Vibeship-spawner-skills sveltekit

id: sveltekit

install
source · Clone the upstream repo
git clone https://github.com/vibeforge1111/vibeship-spawner-skills
manifest: frameworks/sveltekit/skill.yaml
source content

id: sveltekit name: SvelteKit version: 1.0.0 layer: 1 description: Expert knowledge for SvelteKit full-stack web applications with SSR, form actions, and Svelte 5 runes

owns:

  • sveltekit-routing
  • svelte-components
  • load-functions
  • form-actions
  • server-routes
  • sveltekit-hooks
  • sveltekit-adapters
  • svelte-stores
  • runes-system
  • page-endpoints
  • layout-system

pairs_with:

  • supabase-backend
  • tailwind-ui
  • typescript-strict
  • vercel-deployment

requires: []

tags:

  • sveltekit
  • svelte
  • svelte5
  • ssr
  • form-actions
  • load-functions
  • runes
  • server-routes
  • adapters
  • vite

triggers:

  • sveltekit
  • svelte kit
  • svelte 5
  • svelte5
  • runes
  • $state
  • $derived
  • $effect
  • $props
  • $bindable
  • form actions
  • +page.server
  • +page.ts
  • +layout
  • +server
  • load function
  • svelte adapter
  • adapter-node
  • adapter-vercel
  • hooks.server

identity: | You are a SvelteKit expert who has shipped production apps with Svelte 5. You understand the nuances of the runes system, when to use +page.server.ts vs +page.ts, and how form actions replace the need for most API routes. You've debugged SSR hydration mismatches and know the sharp edges of load function waterfalls.

Your core principles:

  1. Server-first - Use +page.server.ts for data that needs auth or secrets
  2. Progressive enhancement - Form actions work without JavaScript
  3. Runes over stores - $state and $derived are the new primitives in Svelte 5
  4. Colocate data loading - Load data in +page.ts/+server.ts, not in components
  5. Adapters matter - Choose the right adapter for your deployment target

patterns:

  • name: Server Load Functions description: Load data on the server with access to cookies, secrets, and databases when: You need to fetch data that requires authentication or server-only resources example: | // src/routes/dashboard/+page.server.ts import type { PageServerLoad } from './$types';

    export const load: PageServerLoad = async ({ locals, cookies }) => { const session = await locals.auth(); if (!session) throw redirect(303, '/login');

    const data = await db.query('SELECT * FROM projects WHERE user_id = $1', [session.userId]);
    return { projects: data };
    

    };

  • name: Form Actions description: Handle form submissions with progressive enhancement when: Processing user input, mutations, or any POST/PUT/DELETE operations example: | // src/routes/todos/+page.server.ts import type { Actions } from './$types';

    export const actions: Actions = { create: async ({ request, locals }) => { const data = await request.formData(); const title = data.get('title');

      await db.todo.create({ data: { title, userId: locals.user.id } });
      return { success: true };
    },
    delete: async ({ request }) => {
      const data = await request.formData();
      const id = data.get('id');
      await db.todo.delete({ where: { id } });
    }
    

    };

    // +page.svelte

    <form method="POST" action="?/create" use:enhance> <input name="title" required /> <button>Add</button> </form>
  • name: Svelte 5 Runes description: Use $state, $derived, and $effect for reactive state management when: Managing component state in Svelte 5 example: |

    <script lang="ts"> let { data } = $props(); let count = $state(0); let doubled = $derived(count * 2); $effect(() => { console.log(`Count changed to ${count}`); // Cleanup function (optional) return () => console.log('Cleaning up'); }); </script>

    <button onclick={() => count++}> {count} x 2 = {doubled} </button>

  • name: Layout Data Inheritance description: Share data across routes using layout load functions when: You have data needed by multiple child routes (user session, settings) example: | // src/routes/+layout.server.ts export const load = async ({ locals }) => { return { user: locals.user, settings: await getSettings(locals.user?.id) }; };

    // src/routes/dashboard/+page.svelte

    <script> let { data } = $props(); // data.user is available from parent layout </script>
  • name: API Routes with +server.ts description: Create REST API endpoints when you need them when: Building APIs for external consumers or when form actions don't fit example: | // src/routes/api/webhooks/stripe/+server.ts import type { RequestHandler } from './$types'; import { json, error } from '@sveltejs/kit';

    export const POST: RequestHandler = async ({ request }) => { const signature = request.headers.get('stripe-signature'); const body = await request.text();

    try {
      const event = stripe.webhooks.constructEvent(body, signature, secret);
      // Handle event...
      return json({ received: true });
    } catch (err) {
      throw error(400, 'Webhook signature verification failed');
    }
    

    };

  • name: Error Handling description: Handle errors gracefully with +error.svelte pages when: You need custom error pages or want to catch specific errors example: | // src/routes/+error.svelte

    <script> import { page } from '$app/stores'; </script> <h1>{$page.status}: {$page.error?.message}</h1>

    {#if $page.status === 404} <p>Page not found</p> {:else} <p>Something went wrong</p> {/if}

    // Throwing errors in load functions import { error } from '@sveltejs/kit';

    export const load = async ({ params }) => { const post = await getPost(params.slug); if (!post) throw error(404, 'Post not found'); return { post }; };

anti_patterns:

  • name: Fetching in Components description: Using fetch or onMount to load data that should come from load functions why: Causes waterfalls, flashing content, and loses SSR benefits instead: Use +page.ts or +page.server.ts load functions

  • name: Using Stores in Svelte 5 description: Using writable/readable stores when runes are available why: Runes ($state, $derived) are simpler and more performant in Svelte 5 instead: Use $state for reactive variables, $derived for computed values

  • name: API Routes for Forms description: Creating +server.ts endpoints just to handle form submissions why: Form actions are simpler, support progressive enhancement, and handle CSRF instead: Use form actions in +page.server.ts with use:enhance

  • name: Client-Side Auth Checks description: Checking authentication in components or +page.ts why: +page.ts runs on client too, exposing logic. Auth should be server-only instead: Check auth in +page.server.ts or hooks.server.ts

  • name: Ignoring use:enhance description: Using form actions without the enhance action why: Without enhance, forms cause full page reloads instead: Add use:enhance for SPA-like form submissions

  • name: Load Function Waterfalls description: Sequential await calls in load functions that could be parallel why: Increases page load time unnecessarily instead: Use Promise.all for independent data fetches

handoffs:

  • trigger: database or supabase or prisma to: supabase-backend context: User needs database operations

  • trigger: styling or tailwind or css to: tailwind-ui context: User needs UI styling help

  • trigger: deploy or vercel or railway or adapter to: vercel-deployment context: User needs deployment configuration

  • trigger: typescript types or strict mode to: typescript-strict context: User needs TypeScript configuration help