Zum Inhalt springen

sveltekit-app-setup

Type Skill
Plugin awl-web · v0.0.6
Invoke /awl-web:sveltekit-app-setup
Tools Read, Write, Edit, Bash, Glob, Grep
Source plugins/awl-web/skills/sveltekit-app-setup/SKILL.md

Wires a new or existing SvelteKit app with the internal @awl/* packages in the order the docs imply - registry, OIDC login, session, i18n, OpenTelemetry metrics, HTTP client, Tailwind theme and a Playwright smoke test. Use for “set up sveltekit app”, “new awl web project”, “wire @awl packages”, “add oidc login”, “awl session”, “sveltekit i18n”, “opentelemetry sveltekit”, “hooks.server.ts”, “+layout.server.ts guard”, “awl registry npmrc”. NOT for a single package’s API (use awl-npm-packages), Payload CMS plugins (use payload-plugins) or writing the test suite itself (use awl-testing testing-web).

Trigger phrases: set up sveltekit app · new awl web project · wire @awl packages · add oidc login · awl session · sveltekit i18n · opentelemetry sveltekit · hooks.server.ts · +layout.server.ts guard · awl registry npmrc

Layers go in this order because each one reads what the previous one puts on event.locals: session before OIDC, session before i18n’s fromSession() detector, metrics before anything that records. Every snippet below is copied from the Storybook at https://npm-packages.staging.appswithlove.net; when a detail isn’t there, this skill says so instead of guessing. Per-package API tables live in awl-npm-packages/references/<package>.md.

Need Package Read
Login, logout, token refresh, route guards @awl/oidc (/sveltekit) + @awl/session, or @awl/sveltekit-oidc + @awl/sveltekit-utils references/auth-oidc.md
Server session, flash messages, typed session data @awl/session references/session-and-i18n.md
Translations, locale detection, <html lang> @awl/i18n references/session-and-i18n.md
Run a handle hook on some routes only only from @awl/sveltekit-utils/hooks references/auth-oidc.md
Counters and gauges exported to VictoriaMetrics or Prometheus @awl/opentelemetry references/observability-and-request.md
Typed HTTP client with bearer auth and JSON:API @awl/request references/observability-and-request.md
Error messages, safe tuples, cookies, search params, proxy @awl/utils references/observability-and-request.md
px-based Tailwind theme and AWL breakpoints @awl/tailwindcss references/env-and-config.md
URL-synced state (ReactiveSearchParam) @awl/svelte-utils references/env-and-config.md
Hydration and a11y matchers for Playwright @awl/playwright-sveltekit, @awl/playwright-a11y references/env-and-config.md

Skip a layer the project doesn’t need. A content site without login needs no OIDC or session; an internal tool without translations needs no i18n.

Check package.json, src/hooks.server.ts, src/app.d.ts and src/routes/+layout.server.ts before writing anything. An existing hook sequence has to be extended, not replaced, and App.Locals has to be merged into one declaration.

Point the @awl scope at the GitLab package registry (project 3919) in the user-level .npmrc, so the token stays out of the repo. CI uses CI_JOB_TOKEN, Docker builds mount .npmrc as a secret. Commands and the Dockerfile block: references/env-and-config.md.

Terminal-Fenster
pnpm add @awl/oidc @awl/session @awl/i18n @awl/opentelemetry @awl/request @awl/utils @awl/tailwindcss
pnpm add -D @awl/playwright-sveltekit @awl/playwright-a11y

The docs use npm install; the registry config applies to pnpm as well. Pick the OIDC package first (step 3) and drop the ones you don’t use.

Decide between the two documented integrations, see the comparison table in references/auth-oidc.md. With @awl/oidc, the hook order is fixed:

src/hooks.server.ts
import { sequence } from "@sveltejs/kit/hooks";
import { session } from "$lib/config/session";
import { oidc } from "$lib/config/oidc";
export const handle = sequence(
session.handler, // make sure this runs before
oidc.authenticate, // refreshes access token silently on expiry
);

authenticate only refreshes tokens. Guard routes from the server file that owns them, because a guard protects only what calls it:

// src/routes/(app)/+layout.server.ts
import { oidc } from "$lib/config/oidc";
export const load = async (event) => {
const user = await oidc.protect(event);
return { user };
};

Form actions and +server.ts handlers call oidc.protect(event) themselves. The catch-all action route is src/routes/oidc/[action]/+server.ts with export const GET = oidc.actionHandler.

With @awl/sveltekit-oidc the hook is oidc.authenticate() and guards are only(oidc.protect()).path('/admin*') in the same sequence.

Already done in step 3 when using @awl/oidc. Standalone, the handler is createSession({ storage }) from @awl/session/sveltekit and the session is locals.session with get, set, once, remember, destroy. Use MemoryStorage in dev and RedisStorage in production.

Build the instance in src/lib/i18n.ts with createI18n<typeof en>(), the nesting, interpolation and sveltekit plugins, and .hook({ detect, create }). Then wire the two exports and the %locale% placeholder:

// src/hooks.server.ts (add to the sequence after session.handler)
import { handle as i18nHandle } from '$lib/i18n'
src/routes/+layout.server.ts
export { layoutServerLoad as load } from '$lib/i18n'
src/app.html
<html lang="%locale%">

The docs show export { handle } from '$lib/i18n' as the only hook; the combined sequence and the alias above follow from that. Keep the root layout as this re-export and put the OIDC guard in a group layout, because the docs don’t show how to merge layoutServerLoad with another load.

Create src/lib/server/metrics.ts with createMetrics({...}, { namespace, service, environment, readers }) and import it at the top of hooks.server.ts. Readers must exist before the first measurement, and setReaders replaces all earlier readers. Use @awl/opentelemetry/otlp-proto for VictoriaMetrics and install the matching @opentelemetry/exporter-* peer dependency. The package covers metrics only.

Compose request(url).plugin(vars).plugin(options).plugin(auth).plugin(fetchPlugin) in src/lib/server/api.ts and call .bearer(token).fetch() in loads. Catch RequestError for status and URL, getMessage from @awl/utils/errors for a display string, safe from @awl/utils for tuple-style handling.

Replace @import "tailwindcss" with @import "@awl/tailwindcss" in the global CSS. Add optimizeDeps.exclude: ['@awl/svelte-utils'] to vite.config.ts when that package is installed.

Extend expect with toBeHydrated and toBeAccessible, open /, assert both. The Playwright config itself is in the awl-testing plugin’s testing-web skill.

  1. pnpm install resolves every @awl/* package from the GitLab registry.
  2. pnpm check passes with the merged App.Locals (session, i18n, or user and accessToken).
  3. pnpm dev, then open /oidc/login: the browser is redirected to the issuer. After login, a guarded page renders and /oidc/logout clears it.
  4. A page under the guard returns 302 for a browser request and 401 for fetch without a session.
  5. Switching the locale cookie changes the server-rendered lang attribute and the translated strings.
  6. The metrics reader exports at least one counter (VictoriaMetrics, Prometheus scrape, or the debug log).
  7. The Playwright smoke test passes against pnpm preview.
Variable Used by
OIDC_CLIENT_ID, OIDC_CLIENT_SECRET both OIDC packages
OIDC_SECRET cookie encryption, secret option or CookieDataStorage
NODE_ENV @awl/opentelemetry environment
issuer URL, Redis URL, API base URL, OTLP endpoint not named in the docs, pick your own

Read them via $env/dynamic/private in SvelteKit server modules. Full table and reasons: references/env-and-config.md.

  • Which OIDC package the team prefers for greenfield apps. Neither is marked deprecated.
  • With @awl/oidc, how to read the access token for outbound API calls.
  • The combined hook sequence with session, OIDC and i18n; only pairs are shown.
  • Merging layoutServerLoad with your own root layout load.
  • OTLP endpoint and Prometheus port configuration for the exporter wrappers.
  • Tailwind version and Vite plugin prerequisites for @awl/tailwindcss.
  • Playwright config, webServer and CI job.

When one of these blocks you, check the live page: https://npm-packages.staging.appswithlove.net/?path=/docs/<id> with ids general-oidc--readme, sveltekit-sveltekit-oidc--readme, general-session--readme, general-i18n--readme, general-opentelemetry--readme, utils-request--docs, readme--docs.