laravel/blank-svelte-starter-kit
Laravel + Svelte starter kit for building modern Laravel apps with an Inertia-powered Svelte frontend. Includes Svelte, TypeScript, Tailwind, and fast Vite builds with classic Laravel routing/controllers. No authentication scaffolding included.
Installation
composer create-project laravel/blank-svelte-starter-kit my-app
cd my-app
npm install
npm run dev
php artisan serve in a separate terminal to start the Laravel backend.First Use Case: Create a Svelte Page
resources/js/Pages/ and create a new Svelte file (e.g., Welcome.svelte).routes/web.php:
Route::get('/', function () {
return Inertia::render('Welcome');
});
http://localhost:8000 to see your new page.Key Directories to Explore
resources/js/Pages/ – Svelte components (Inertia pages).resources/js/Layouts/ – Shared layouts (e.g., AppLayout.svelte).resources/js/app.ts – Global Inertia/Svelte setup.vite.config.ts – Vite configuration (frontend build tool).Inertia + Svelte Routing
routes/web.php) to define server-side routes, which Inertia maps to Svelte components.Route::get('/dashboard', [DashboardController::class, 'index']);
<!-- resources/js/Pages/Dashboard.svelte -->
<script lang="ts">
import AppLayout from '@/Layouts/AppLayout';
</script>
<AppLayout>
<h1>Dashboard</h1>
</AppLayout>
visit() method in Svelte for client-side navigation:
<button on:click={() => visit('/dashboard')}>Go to Dashboard</button>
State Management
npm install pinia) for frontend state.Inertia.render():
return Inertia::render('Welcome', ['user' => auth()->user()]);
<script lang="ts">
export let user: { name: string };
</script>
<p>Hello, {user.name}!</p>
API Integration
routes/api.php) for backend endpoints.fetch or Axios:
<script lang="ts">
let posts: any[] = [];
async function fetchPosts() {
const response = await fetch('/api/posts');
posts = await response.json();
}
</script>
<button on:click={fetchPosts}>Load Posts</button>
Authentication (Manual Setup)
composer require laravel/sanctum.auth() helper in Svelte:
<script lang="ts">
import { auth } from '@inertiajs/inertia-svelte';
</script>
<p>User: {auth.user?.name}</p>
Tailwind CSS
tailwind.config.js:
module.exports = {
content: [
'./resources/**/*.svelte',
'./resources/**/*.ts',
],
};
<div class="bg-blue-500 text-white p-4">Styled with Tailwind</div>
TypeScript Support
.svelte files use <script lang="ts">. Define types in resources/js/types/ or globally in app.ts.Inertia Page Loading States
resources/js/app.ts:
import { InertiaProgress } from '@inertiajs/progress';
InertiaProgress.init({ color: '#4F46E5' });
Vite HMR (Hot Module Replacement)
npm run dev and refresh manually.vite.config.ts includes:
server: {
hmr: {
host: 'localhost',
},
},
TypeScript Errors
auth()). Extend app.ts:
declare global {
interface Window {
Laravel: {
csrfToken: () => string;
};
}
}
export let user).CORS Issues
fruitcake/laravel-cors):
composer require fruitcake/laravel-cors
Add to App\Http\Kernel.php:
\Fruitcake\Cors\HandleCors::class,
Shared Layouts
AppLayout.svelte for consistent headers/footers. Pass slots:
<!-- resources/js/Layouts/AppLayout.svelte -->
<slot />
<AppLayout>
<h1>Page Content</h1>
</AppLayout>
Environment Variables
.env and accessed via import.meta.env:
<script lang="ts">
const apiUrl = import.meta.env.VITE_API_URL;
</script>
VITE_ for Vite to expose them.Debugging Inertia Props
<script lang="ts">
export let data: any;
console.log('Props:', data);
</script>
Custom Inertia Responses
Inertia::render() with middleware:
Inertia::share(['flash' => function () { return session('flash'); }]);
<script lang="ts">
export let flash: { message?: string };
</script>
{#if flash.message}
<div>{flash.message}</div>
{/if}
Svelte Stores for Global State
resources/js/stores/index.ts:
import { writable } from 'svelte/store';
export const theme = writable<'light' | 'dark'>('light');
<script lang="ts">
import { theme } from '@/stores';
</script>
<button on:click={() => theme.update(v => v === 'light' ? 'dark' : 'light')}>
Toggle Theme
</button>
Plugin Integration
svelte-preprocess) via vite.config.ts:
import { svelte } from '@sveltejs/vite-plugin-svelte';
export default defineConfig({
plugins: [
svelte({
preprocess: [sass()], // Example: Add Sass support
}),
],
});
Testing
@inertiajs/svelte for frontend:
// tests/Feature/PageTest.ts
import { render } from '@testing-library/svelte';
import Welcome from '@/Pages/Welcome.svelte';
test('renders welcome page', () => {
const { getByText } = render(Welcome, { user: { name: 'John' } });
expect(getByText('Hello, John!')).toBeInTheDocument();
});
How can I help you explore Laravel packages today?