Skip to content

Instantly share code, notes, and snippets.

@wsydney76
Created September 24, 2026 08:24
Show Gist options
  • Select an option

  • Save wsydney76/d9cf101d41cf31425e5c18edb5d080f4 to your computer and use it in GitHub Desktop.

Select an option

Save wsydney76/d9cf101d41cf31425e5c18edb5d080f4 to your computer and use it in GitHub Desktop.
Craft 6 Inertia - Proof of concept only - Do not use in production
import '../css/app.css';
import './bootstrap';
// import './navigation-warning.js';
import { createApp, h } from 'vue';
import type { DefineComponent } from 'vue';
import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from 'ziggy-js';
// Don't create the app if there is no #app element, to prevent errors in non-Inertia pages.
// app is the default when using @inertia directive without a value.
if (document.getElementById('app'))
createInertiaApp({
resolve: (name) =>
resolvePageComponent(
`./Pages/${name}.vue`,
import.meta.glob<DefineComponent>('./Pages/**/*.vue')
),
setup({ el, App, props, plugin }) {
createApp({ render: () => h(App, props) })
.use(plugin)
.use(ZiggyVue)
.mount(el);
},
});
// Accept HMR as per: https://vitejs.dev/guide/api-hmr.html
if (import.meta.hot) {
import.meta.hot.accept(() => {
console.log('HMR');
});
}
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Inertia\Middleware;
class HandleInertiaRequests extends Middleware
{
/**
* The root template that's loaded on the first page visit.
*/
public function rootView(Request $request): string
{
return config('inertia.root_view');
}
/**
* Determine the current asset version.
*/
public function version(Request $request): ?string
{
return parent::version($request);
}
/**
* Define the props that are shared by default.
*
* @return array<string, mixed>
*/
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'flash' => [
'success' => fn() => $request->session()->get('success'),
'error' => fn() => $request->session()->get('error'),
],
]);
}
}
@php
// These are simple defaults for the Inertia root view.
// Individual Inertia pages can override the title via <Head>.
// The @inertia directive will create a <div id="app" data-page="..."> element by default.
// If the id is changed, also update app.ts to match, avoiding errors on non-inertia pages.
$title = $title ?? config('app.name');
@endphp
<x-layouts::app :$title>
@routes
@inertiaHead
@inertia
</x-layouts::app>
public function show(string $site, string $slug): Response
{
$entry = Entry::find()->section('article')->slug($slug)->one();
if (!($entry instanceof Entry)) {
throw new NotFoundHttpException();
}
return Inertia::render('Article/Show', [
'entry' => $entry->detailsToArray(),
'backUrl' => route('inertia.article', ['site' => $site]),
'translations' => [
'Back to search' => t('Back to search', [], 'site'),
],
]);
}
<script setup lang="ts">
import { Head, Link } from '@inertiajs/vue3';
import Heading from '@/components/Heading.vue';
import { useTranslation } from '@/composables/useTranslation';
const { t } = useTranslation();
type ArticleEntry = {
id: number | string;
title: string;
url: string | null;
image: string | null;
body: string;
email: string | null;
};
type ShowArticleProps = {
entry: ArticleEntry;
backUrl?: string;
};
const props = withDefaults(defineProps<ShowArticleProps>(), {
backUrl: '',
});
</script>
<template>
<Head :title="props.entry.title" />
<Heading :text="props.entry.title" />
<div class="space-y-4">
<div v-if="props.backUrl">
<Link :href="props.backUrl" class="text-blue-600 hover:underline">
&larr; {{ t('Back to search') }}
</Link>
</div>
<img
v-if="props.entry.image"
:src="props.entry.image"
:alt="props.entry.title"
class="h-auto w-full rounded"
/>
<a
v-if="props.entry.url"
:href="props.entry.url"
class="block text-blue-600 hover:underline"
>
{{ props.entry.url }}
</a>
<a
v-if="props.entry.email"
:href="`mailto:${props.entry.email}`"
class="block text-blue-600 hover:underline"
>
{{ props.entry.email }}
</a>
<div class="prose mt-4" v-html="props.entry.body"></div>
</div>
</template>
Route::get('{site}/inertia/article/{slug}', [InertiaArticleController::class, 'show'])
->middleware([ResolveSite::class, HandleInertiaRequests::class])
->name('inertia.article.show');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment