Development Guide
This guide covers day-to-day development for FVN.li's Laravel 13 + Svelte 5 + Inertia frontend.
Prerequisites
- Docker and DDEV
- Composer through DDEV
- Bun through DDEV
The web container currently runs PHP 8.5, and dependencies are managed from the repo lockfiles.
Initial Setup
ddev start
ddev composer install
ddev bun install
cp .env.example .env
ddev artisan key:generate
ddev artisan migrate
Start the Vite dev server:
ddev bun dev
Open the app at https://fvn-li.ddev.site.
Frontend Stack
- Svelte page components live in
resources/js/pages/**/*.svelte. - Reusable Svelte components live in
resources/js/components/. - Inertia layouts live in
resources/js/layouts/. - Reusable state helpers live in
resources/js/hooks/*.svelte.tsor plain TypeScript modules. - Browser JSON endpoints use
/browser-apiandbrowser-api.*route names. - Stateless external APIs remain under
/api.
Creating Components
Create Svelte components in resources/js/components/:
<script lang="ts">
let {
title,
description = '',
}: {
title: string;
description?: string;
} = $props();
</script>
<section class="space-y-2">
<h2 class="text-lg font-semibold">{title}</h2>
{#if description}
<p class="text-sm text-gray-600 dark:text-gray-400">{description}</p>
{/if}
</section>
Create Inertia pages in resources/js/pages/ and return them from Laravel with Inertia::render().
Browser API Calls
Components call typed functions from resources/js/api; the shared Axios transport in resources/js/utils/http.ts is private to that layer (enforced by lint). Inside an api module, prefer Ziggy route names over hard-coded paths when the route is named:
import http from '@/utils/http';
export async function updateGameViewMode(gameId: number, showCustom: boolean) {
const { data } = await http.put(route('browser-api.games.content.view-mode', { game: gameId }), {
show_custom: showCustom,
});
return data;
}
File uploads pass FormData to http.post directly; Axios sets the multipart boundary itself.
Code Quality
ddev bun types
ddev bun lint
ddev bun format:check
ddev composer lint
ddev bun types runs svelte-check; it is the primary frontend type gate.
Testing
Run PHP tests through DDEV:
ddev composer test
Run Svelte/TypeScript unit tests:
ddev bun test:js
Run Playwright through the DDEV sidecar:
ddev playwright test
ddev playwright test tests/e2e/specs/accessibility.spec.ts --grep @accessibility
Coverage:
ddev composer test:coverage:clover
ddev composer test:coverage:audit
Do not run PHP feature tests concurrently against the shared db_test database unless each process has isolated database state.
Build
Client build:
ddev bun build
Client + SSR build:
ddev bun build:ssr
The SSR entry point is resources/js/ssr.ts, and the browser entry point is resources/js/app.ts.
Debugging
- Use browser DevTools for Svelte component output and network requests.
- Inertia page props are visible in the page payload and browser globals during development.
- Source maps are enabled in development.
- Laravel logs are in
storage/logs/laravel.log. - Browser API requests should hit
/browser-api; do not add new endpoints under old framework-specific prefixes.