zekythewolf/list-starter
A Laravel starter package for quickly building list-based features. It gives you a clean foundation for managing lists and their items, including models, migrations, and CRUD scaffolding for todo lists, checklists, and other ordered collections, so you can focus on your app's unique logic.
LIST-Starter is a starter kit, not a runtime dependency — you consume it once at project creation, then the code is yours. There is no composer require step and no upstream upgrade path.
Minimum path to a running app:
git clone [email protected]:ZekyTheWolf/LIST-Starter.git my-app
cd my-app && rm -rf .git
composer install
cp .env.example .env && php artisan key:generate
php artisan migrate # V11 defaults to SQLite; accept the prompt to create the file
bun install # or: npm install
bun run dev # or: npm run dev
php artisan serve
Prerequisites for V11.0.0: PHP 8.2+, Composer 2, Node 18+ (needed by Vite 5) or Bun 1.x.
Where to look first, in this order:
composer.json / package.json — confirms Laravel 11, Inertia 1.x, and whether Svelte is 4 or 5. This single check prevents most confusion later.bootstrap/app.php — under Laravel 11 this is the new application configuration file (middleware, exceptions, routing), replacing Http/Kernel.php and Exceptions/Handler.php.routes/web.php — every page is an Inertia::render('PageName', [...props]) call.resources/js/app.js — the Inertia + Svelte bootstrap (createInertiaApp, page resolution, layout wiring).resources/js/Pages/ — one .svelte file per Inertia page.First real use case: add a page. Create the route, render a page, add the component, pass props.
// routes/web.php
Route::get('/posts', fn () => Inertia::render('Posts/Index', [
'posts' => Post::latest()->paginate(20),
]))->name('posts.index');
<!-- resources/js/Pages/Posts/Index.svelte -->
<script>
export let posts
</script>
{#each posts.data as post}
<article>{post.title}</article>
{/each}
Because props are plain serialized data, any Eloquent paginator or API resource can be handed straight to a Svelte component — that is the core workflow of the whole kit.
Data flow is one-way. Controller → Inertia::render → Svelte export let props. Do not fetch data with fetch() in onMount for initial page content; put it in the controller so the page renders complete on first load and benefits from Inertia's history/back-button cache.
Forms use the Inertia form store, not Svelte state. @inertiajs/svelte exposes useForm, which returns a Svelte store — prefix with $:
<script>
import { useForm } from '@inertiajs/svelte'
const form = useForm({ title: '', body: '' })
</script>
<form on:submit|preventDefault={() => $form.post('/posts')}>
<input bind:value={$form.title} />
{#if $form.errors.title}<p>{$form.errors.title}</p>{/if}
<button disabled={$form.processing}>Save</button>
</form>
This gives you validation errors, processing, recentlySuccessful, and reset() for free — hand-rolled fetch + errors state is the most common reinvention in this stack.
Shared props live in app/Http/Middleware/HandleInertiaRequests.php. Auth user, flash messages, and app name belong in share(), not duplicated per controller. Every Inertia response inherits them.
Validation lives in FormRequests. A StorePostRequest returning ['title' => 'required|max:255'] surfaces automatically as $form.errors because Laravel redirects back with the error bag. No extra glue needed.
Persistent layouts. Register a layout in resources/js/app.js's resolve (or via a layout prop on the page) so the sidebar/nav does not remount between navigations — this is what makes the SPA feel instant and preserves scroll position on the layout's scroll container.
Named routes in JS. If Ziggy is wired up (ziggy-js + the @routes Blade directive in app.blade.php), use route('posts.index') instead of string URLs in Svelte. Otherwise you will be hardcoding paths in every component and breaking them on rename.
Bun workflow. Bun is a drop-in for the npm scripts already in package.json — bun run dev, bun run build. Use bunx vite for one-off binaries. Vite itself still runs on Node semantics; Bun is only the package manager and script runner here, so nothing in vite.config.js needs to change.
Upgrading from v1.1.5 is a port, not a merge. The V11.0.0 jump crosses a Laravel major. Create a fresh V11.0.0 checkout, then port your domain code (app/Models, database/migrations, routes/, resources/js/Pages, resources/js/Components) across. Do not git merge — you will inherit deleted skeleton files and a broken middleware pipeline. Reserve a half-day for the port and diff bootstrap/app.php against your old Kernel.php to catch custom middleware.
Version numbers encode the Laravel major. V11.x.x means "requires Laravel 11 / PHP 8.2+". This is a deliberate convention, but it means the jump from v1.1.5 → V11.0.0 looks like a routine minor bump in a changelog reader and is actually a breaking platform move. Pin your fork to a tag and treat starter-kit bumps as deliberate upgrade projects.
Laravel 11 deleted files your muscle memory will look for. There is no app/Http/Kernel.php, no app/Exceptions/Handler.php, and most config/*.php files are gone. Registering middleware in the wrong place is silently ineffective — you will get 419s or missing session data with no error. All of it goes in bootstrap/app.php:
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [YourMiddleware::class]);
})
To get a pruned config file back: php artisan config:publish session.
Mismatched Inertia versions produce opaque errors. inertiajs/inertia-laravel 1.x must pair with @inertiajs/svelte 1.x. A mix of 0.x JS with 1.x PHP typically throws "All Inertia requests must receive a valid Inertia response" — which actually means the server returned plain HTML (often a 500 or a redirect) rather than an Inertia payload. Check the raw network response before touching the JS.
Svelte 4 vs 5 is not cosmetic. Inspect package.json before writing components. Svelte 5 runes replace export let with $props() and on:click with onclick; @inertiajs/svelte needs a v2-era release for Svelte 5. Mixing syntaxes in one project yields confusing reactivity failures. Pick the style the kit ships with and be consistent.
409s on navigation are version conflicts, not bugs. Inertia compares an asset version between client and server. After a deploy or a bun run build, an open tab sends a stale version and receives a 409; Inertia hard-reloads. If users report "random page refreshes", this is why — expected behavior, not a defect.
Bun lockfile hygiene. Run rm package-lock.json before the first bun install, then commit only bun.lockb. Ship both lockfiles and CI becomes non-deterministic. In CI use bun install --frozen-lockfile. Note that Bun blocks postinstall scripts for untrusted packages by default — if a native dependency (e.g. an image or CSS tooling package) fails to build, add it to trustedDependencies in package.json rather than disabling the safety net globally.
Non-interactive migrations. Laravel 11 prompts to create the SQLite database file. In Docker entrypoints or CI, that prompt hangs the pipeline — pass php artisan migrate --force --no-interaction.
Asset 404s in production almost always mean a missing build. laravel-vite-plugin resolves through public/build/manifest.json with a hot file overriding in dev. If public/build is absent (gitignored, forgot the CI build step), you get a ViteManifestNotFoundException or unstyled pages. Make bun run build part of the deploy script, not a manual step.
Debugging props. dump() inside a controller surfaces in the JSON payload in the network tab, not in the browser UI. For a cleaner loop, install Laravel Debugbar and Inertia DevTools (browser extension), which show the page component name and prop tree per request.
Best extension points, in rough order of leverage: HandleInertiaRequests::share() for global data, resources/js/app.js for plugins/progress bar/layout resolution, bootstrap/app.php for middleware and exception rendering, and tailwind.config.js for design tokens — restyling via Tailwind config beats editing components when you want the kit to look like your product rather than a template.
How can I help you explore Laravel packages today?