Landing site for Lettr, built with SvelteKit 2, Svelte 5, TypeScript, and Tailwind CSS v4.
- SvelteKit + Svelte 5 (runes)
- TypeScript (strict mode)
- Tailwind CSS v4
- GSAP animations
- Vitest unit tests
pnpm installpnpm dev
# expose dev server on local network
pnpm dev -- --host# static checks (Svelte + TypeScript)
pnpm check
# unit tests
pnpm test:unit
# watch mode for unit tests
pnpm test:unit:watchRun a single test file:
pnpm vitest src/path/to/file.test.tsRun one test by name:
pnpm vitest -t "test name"pnpm build
pnpm previewsrc/routes/+layout.svelte: global layout shell and page metadatasrc/lib/components/SplineFooter.svelte: lazy-loaded Spline footer scene wrappersrc/lib/utils/spline.ts: Spline visibility gating and script loader utilitiessrc/lib/utils/shiki.ts: syntax highlighting setup and singleton highlighter
The /demo flow is instrumented with PostHog events in src/routes/demo/+page.svelte.
book_slot_selected is emitted for both user-driven and auto-selected slots so slot selection is always represented before confirmation.
flowchart TD
A[book_page_viewed] --> B[book_volume_selected]
B --> C[book_routing_decided]
C -->|selfServe| D[book_routed_self_serve]
D --> E[book_self_serve_create_account_clicked]
D --> F[book_self_serve_docs_clicked]
C -->|demo or priorityDemo| G[book_config_loaded]
G --> H[book_slots_loaded]
H -->|auto_initial| J[book_slot_selected]
H --> I[book_day_selected]
I -->|auto_day_pick| J
I -->|manual click| J
J --> K[book_confirm_started]
K --> L[book_reservation_confirmed]
C --> X1[book_routing_validation_failed]
G --> X2[book_config_load_failed]
H --> X3[book_slots_load_failed]
J --> X4[book_confirm_validation_failed]
K --> X5[book_reservation_failed]
Shared event properties are attached to each event:
funnel_name:booking_funnelfunnel_version:1page:/demotimezone: client timezone
book_slot_selected includes an additional property:
selection_source: one ofmanual,auto_initial, orauto_day_pick