hotmeteor/inertia-statamic
Inertia.js adapter for Statamic that lets you build Statamic-powered sites with Vue or React instead of Antlers. It bridges Statamic content and routing with Inertia responses, enabling modern SPA-style frontends while keeping Statamic’s CMS.
hotmeteor/inertia-statamic bridges a Statamic site and an Inertia.js front end, letting Statamic's routing/content model resolve URLs while rendering Vue/React/Svelte page components instead of Antlers views.
composer require hotmeteor/inertia-statamic and publish the config (php artisan vendor:publish --tag=inertia-statamic-config or the tag listed in the README).config/inertia-statamic.php first. This is where the mapping between Statamic content (collections, taxonomies, the page tree) and your Inertia page components lives. It is the single most important file to understand.resources/js/app.js resolves the same component paths you reference in config — a mismatch here produces a blank page, not an error.Map content types to components, not routes. Prefer one component per collection/blueprint shape (e.g. Blog/Show, Blog/Index, Pages/Show) over trying to build a catch-all router inside the component. Statamic already owns URL structure; let it.
Use the page tree for marketing pages. The most common day-to-day pattern in this setup is a single Pages/Show component that branches on blueprint/layout field, so editors can create pages in the CP without a developer touching code.
Pass data as props, keep the component dumb. Resolve entries, related entries, and taxonomy terms server-side and hand them over as plain arrays. Avoid calling Statamic's REST/GraphQL API from the client just to hydrate a prop you could have passed for free.
Share global props once. Site settings, navigation trees, and the current user belong in Inertia's shared props (middleware or HandleInertiaRequests), not repeated in every controller/route closure.
Handle augmenting deliberately. If you need computed/processed field values (assets with URLs, Bard-rendered HTML), augment the entry before passing it and be explicit about it — dumping a raw Entry object into props gives you a serialized object your JS component can't rely on.
Forms round-trip through normal Laravel routes. Statamic's CP-driven forms and submissions are separate concerns; for Inertia form handling, post to controller routes and return redirect()->back() with with('success', ...), then read flash from shared props.
Test the URLs, not just the components. Because routing is delegated to Statamic, a broken route is invisible to a Vitest/Vue test. Add a handful of HTTP tests asserting assertInertia() against representative entries (nested page, collection entry, localized URL if applicable).
Upgrade to v0.2.1 if you were seeing spurious 404s. This release changes entry resolution to use an actual lookup rather than deriving the entry some other way, so entries that previously 404'd — particularly nested URIs, non-root mounts, or anything where the URL doesn't trivially map back to an entry — should now resolve correctly. This is a bug fix, not a breaking change; there's no migration or config change, but do clear caches after upgrading (php artisan optimize:clear) and re-run your URL smoke tests to confirm the 404s are actually gone rather than just masked by a stale cache.
Route/config caching bites here more than usual. After editing the config mapping, run php artisan optimize:clear. A stale cached route/config is the most common cause of "my new collection is still 404'ing."
Statamic's static caching and Stache caching interact with this package. If content changes aren't reflected, suspect the Stache/static cache before you suspect the package.
Asset versioning must track builds. Inertia's version hash plus Statamic caching can serve a stale component tree; make sure npm run build runs as part of deploy, and that your deploy clears caches after the build, not before.
Serialization surprises. Statamic entries and augmented values can contain objects (dates, assets, Carbon, collections) that won't survive JSON cleanly or will arrive in an unexpected shape. Dump the props (dd($page->props)) once per content type and normalize early.
Don't fight the page tree. If a developer finds themselves writing custom Laravel routes for content editors could otherwise create in the CP, that's a sign the config mapping (or the blueprint) should change instead.
Extension points: the config file and Laravel's normal route/controller layer. There's no need for heavy customization — if a mapping can't express what you want, prefer a dedicated Statamic route or a controller returning Inertia::render() directly over patching package internals.
How can I help you explore Laravel packages today?