All skills
asyrafhussin avatar

/laravel-inertia-react

@ac26821

Laravel + Inertia.js + React integration patterns. Use when building Inertia page components, handling forms with useForm, managing shared data, or implementing persistent layouts. Triggers on tasks involving Inertia.js, page props, form handling, or Laravel React integration.

Use this Skill: https://skilld.dev/gh/asyrafhussin/agent-skills/laravel-inertia-react

This session only. Nothing lands on disk.

ruleslayout-persistent.md

≈1.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Persistent Layouts

Persistent layouts maintain state between page visits. Without them, layouts remount on every navigation, losing state like scroll position, form inputs in navigation, or audio/video playback.

Incorrect

// ❌ Layout wrapping in page - remounts on every navigation
import AppLayout from '@/Layouts/AppLayout'

export default function Dashboard() {
  return (
    <AppLayout>
      <h1>Dashboard</h1>
    </AppLayout>
  )
}

// ❌ Layout in _app.jsx - still remounts
function App({ Component, pageProps }) {
  return (
    <AppLayout>
      <Component {...pageProps} />
    </AppLayout>
  )
}

Problem: Layout remounts on every page change, losing any state.

Correct

Using layout Property

// resources/js/Layouts/AppLayout.tsx
import { Link, usePage } from '@inertiajs/react'
import { ReactNode } from 'react'

interface Props {
  children: ReactNode
}

export default function AppLayout({ children }: Props) {
  const { auth } = usePage().props as any

  return (
    <div className="min-h-screen bg-gray-100">
      <nav className="bg-white shadow-sm">
        <div className="max-w-7xl mx-auto px-4 py-3">
          <div className="flex justify-between items-center">
            <div className="flex space-x-4">
              <Link href="/" className="font-bold">
                Logo
              </Link>
              <Link href="/dashboard">Dashboard</Link>
              <Link href="/posts">Posts</Link>
            </div>
            <span>{auth.user?.name}</span>
          </div>
        </div>
      </nav>

      <main className="max-w-7xl mx-auto py-6 px-4">
        {children}
      </main>
    </div>
  )
}
// resources/js/Pages/Dashboard.tsx
import AppLayout from '@/Layouts/AppLayout'
import { ReactNode } from 'react'

export default function Dashboard() {
  return (
    <div>
      <h1 className="text-2xl font-bold">Dashboard</h1>
      {/* Page content */}
    </div>
  )
}

// Assign persistent layout
Dashboard.layout = (page: ReactNode) => <AppLayout>{page}</AppLayout>

TypeScript Declaration

// resources/js/types/inertia.d.ts
import { ReactNode } from 'react'

declare module '@inertiajs/react' {
  interface PageComponent {
    layout?: (page: ReactNode) => ReactNode
  }
}

Default Layout in app.tsx

// resources/js/app.tsx
import { createInertiaApp } from '@inertiajs/react'
import { createRoot } from 'react-dom/client'
import AppLayout from './Layouts/AppLayout'

createInertiaApp({
  resolve: (name) => {
    const pages = import.meta.glob('./Pages/**/*.tsx', { eager: true })
    const page = pages[`./Pages/${name}.tsx`] as any

    // Set default layout if page doesn't have one
    page.default.layout = page.default.layout || ((page: ReactNode) =>
      <AppLayout>{page}</AppLayout>
    )

    return page
  },
  setup({ el, App, props }) {
    createRoot(el!).render(<App {...props} />)
  },
})

Nested Layouts

// resources/js/Layouts/SettingsLayout.tsx
import { Link } from '@inertiajs/react'
import { ReactNode } from 'react'

interface Props {
  children: ReactNode
}

export default function SettingsLayout({ children }: Props) {
  return (
    <div className="flex">
      <aside className="w-64 border-r p-4">
        <nav className="space-y-2">
          <Link href="/settings/profile">Profile</Link>
          <Link href="/settings/password">Password</Link>
          <Link href="/settings/notifications">Notifications</Link>
        </nav>
      </aside>
      <main className="flex-1 p-6">{children}</main>
    </div>
  )
}
// resources/js/Pages/Settings/Profile.tsx
import AppLayout from '@/Layouts/AppLayout'
import SettingsLayout from '@/Layouts/SettingsLayout'
import { ReactNode } from 'react'

export default function Profile() {
  return (
    <div>
      <h2>Profile Settings</h2>
      {/* Content */}
    </div>
  )
}

// Nested persistent layouts
Profile.layout = (page: ReactNode) => (
  <AppLayout>
    <SettingsLayout>{page}</SettingsLayout>
  </AppLayout>
)

Conditional Layouts

// resources/js/Pages/Login.tsx
import GuestLayout from '@/Layouts/GuestLayout'
import { ReactNode } from 'react'

export default function Login() {
  return (
    <div>
      <h1>Login</h1>
      {/* Login form */}
    </div>
  )
}

// Different layout for auth pages
Login.layout = (page: ReactNode) => <GuestLayout>{page}</GuestLayout>

Layout Without Persistence

// When you DON'T want persistence (rare)
export default function SpecialPage() {
  return <div>No layout</div>
}

// Explicitly no layout
SpecialPage.layout = (page: ReactNode) => page

Benefits

  • State preserved between page navigations
  • Audio/video continues playing
  • Form inputs in navigation preserved
  • Scroll position in sidebars maintained
  • Better perceived performance

Source: SKILL.md on GitHub

1 warning16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides a comprehensive set of best practices and patterns for building applications with Laravel, Inertia.js, and React. The content consists of architectural guidance and code examples that follow official framework standards and do not exhibit any malicious behavior or security risks.

  • Socket16d

    1 alert: gptAnomaly

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    30 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at ac26821. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 7 months ago
Other metadata
metadata
{
  "author": "AsyrafHussin",
  "version": "1.0.2",
  "laravelVersion": "13.x",
  "phpVersion": "8.3+"
}

README badge

README badge for asyrafhussin/agent-skills/laravel-inertia-react