Die SvelteKit-App liegt unter frontend/, das Backend unter backend/ als eigenständige PocketBase-Instanz mit Dockerfile, docker-compose und versioniertem Schema. - PocketBase-URL über PUBLIC_PB_URL konfigurierbar, Default bleibt die produktive Instanz https://api.stammtisch-hersbruck.de - Schema als Snapshot-Migration der sechs fachlichen Collections (users, teams, events, runs, riders, times), abgezogen von der produktiven Instanz. Verifiziert: ein Erststart gegen leere pb_data legt alle sechs an, Felder und API-Rules stimmen überein. - pb_data und pb_migrations als Bind-Mounts, damit Daten persistieren und im Admin-UI erzeugte Migrationen im Repo landen - Veraltete Dokumentation entfernt: pocketbase_schema.json nannte Collections (stages, results, organizers), die es nicht gibt Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
stammtisch-hersbruck.de is a SvelteKit 5 application using Svelte 5's new runes syntax ($state, $props, etc.) with PocketBase as the backend. The app manages events, runs, riders, times and teams for a motorsport/cycling event organization.
The repository is a monorepo: the SvelteKit app lives in frontend/, the PocketBase instance in backend/.
Development Commands
Alle Frontend-Befehle laufen aus frontend/:
cd frontend
# Start development server (runs on http://stammtisch-hersbruck.de.localhost:31337)
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
# Type-check Svelte files
npm run check
# Type-check with watch mode
npm run check:watch
# Generate TypeScript types from PocketBase schema
npm run generate-pocketbase-types
Backend (PocketBase) aus backend/:
cd backend
# PocketBase lokal starten (Admin-UI auf http://127.0.0.1:8090/_/)
docker compose up -d --build
# Stoppen
docker compose down
Architecture
Backend Integration (PocketBase)
- API Base URL: konfigurierbar über
PUBLIC_PB_URLinfrontend/.env. Default ist die produktive Instanzhttps://api.stammtisch-hersbruck.de; für das lokale Backend ausbackend/aufhttp://127.0.0.1:8090umstellen. - Schema: versioniert als Migration in
backend/pb_migrations/. Änderungen im Admin-UI erzeugen dort neue Dateien, die committet werden müssen. - Type-safe client: The PocketBase client is typed using auto-generated types in
frontend/src/lib/types.d.ts - Collections: users, teams, events, runs, riders, times
- Authentication: Handled through
src/lib/stores/pocketbase.svelte.tswith theAuthStoreclass - File handling: Use
getFileURL(record, file, options)helper for PocketBase file URLs
State Management Pattern
The app uses Svelte 5 runes for state management with a custom store pattern:
-
Global stores in
src/lib/stores/:pocketbase.svelte.ts: PocketBase client, auth, and collection operationsapp.svelte.ts: Global app state (theme, navigation, confirm dialogs, hotkeys)teams.svelte.ts: Example of collection-specific store pattern
-
Collection store pattern:
- Each collection has a context-based store (see
teams.svelte.tsas template) - Use
setTeamContext()in parent andgetTeamContext()in children - Stores provide:
records,refresh(),create(),edit(),remove() - The
collectionshelper inpocketbase.svelte.tsprovides reusable CRUD operations
- Each collection has a context-based store (see
-
Auth flow:
- Auth state lives in
authstore frompocketbase.svelte.ts - Cookie-based persistence available via
auth.cookieflag - Auth store syncs with PocketBase
authStore.onChange()
- Auth state lives in
UI Components
- UI Library: Using shadcn-svelte components (bits-ui based)
- Component path alias:
@/components/ui/*maps to$lib/components/ui/* - Styling: Tailwind CSS 4.x with custom configuration
- Dark mode: Handled by
mode-watcherpackage, toggle withtoggleMode() - Tooltips: Global
tooltipaction available fromapp.svelte.tsusing tippy.js
Important Patterns
Svelte 5 Runes: This project uses Svelte 5 syntax exclusively:
$state()for reactive state (notletwith$:)$props()for component props$derived()for computed values{@render children?.()}for slot content
Type Generation: After modifying PocketBase schema, run npm run generate-pocketbase-types to update TypeScript types.
Async Data Loading: Root layout (src/routes/+layout.svelte) shows pattern:
{#await load()}
<!-- loading state -->
{:then _}
<!-- main content -->
{/await}
Confirm Dialogs: Use app.confirm.request() for user confirmations (see events.svelte.ts remove pattern).
Hotkeys: Use app.hotkey(event, condition, callback) which auto-ignores input fields and contenteditable elements.
Project Configuration
- Repo-Struktur: Monorepo mit
frontend/(SvelteKit) undbackend/(PocketBase). Ein einziges Git-Repo im Root. - Dev server port: 31337 (strict mode, custom domain:
stammtisch-hersbruck.de.localhost) - Path alias:
@/*resolves to./src/lib/*(configured in frontend/svelte.config.js) - Adapter: @sveltejs/adapter-auto (auto-detects deployment platform)
File Structure Notes
- Routes are in
src/routes/following SvelteKit conventions - Reusable components in
src/lib/components/ - Stores use
.svelte.tsextension for Svelte 5 runes - Static assets in
static/ components.jsonconfigures shadcn-svelte CLI
When Working with This Codebase
- Always use Svelte 5 runes syntax, never legacy Svelte syntax
- Use the official Svelte MCP server to validate Svelte code
- Collection stores should follow the pattern in
teams.svelte.ts - PocketBase operations go through the
collectionshelper for consistency - UI components should use the shadcn-svelte imports from
@/components/ui/