Bilingual Bakery CMS Template
A bilingual (SV / EN) bakery website template, designed from day one as a generic template a bakery owner could pick up and customise without a developer in the loop. The public side covers a hero with seasonal banner and a live 'open now' status pill, a product gallery filterable by category (Tårtor, Kakor, Bröd, Bakverk, Övrigt) and dietary tag (Glutenfri, Laktosfri, Vegansk, Nötfri), a custom-order form with eight fields (name, phone, email, pickup date, portions, occasion, description, allergies), an opening-hours widget that respects holiday closures rendered as 'Kommande avvikelser', a Google Places reviews carousel cached server-side for an hour, a pinnable news banner, and bilingual copy via a no-build-step i18n helper. The admin side is a login-protected dashboard with full CRUD over Sortiment, Beställningar, Öppettider, Nyheter, and Inställningar, including a kanban-style status flow over incoming orders (new, seen, accepted, declined). All brand details are placeholder lorem ipsum so the template stays neutral.
The stack is SvelteKit 2 + Svelte 5 (runes mode) + TypeScript on the front, Tailwind v4 via @tailwindcss/vite for styles, Convex for the database and file storage, Clerk for auth, Resend for transactional email, and the Google Places API for live reviews. Deploys to Vercel + Convex Cloud, runs on Bun.
The design choice that makes it interesting is the demo mode. The site runs with no API keys at all. When env vars are missing, src/lib/server/source.ts falls back to in-memory dummy data from src/lib/server/dummy.ts: ten sample products, five sample reviews, console-logged emails. Three auth modes toggle by env var. Bypass is the default, /admin is open with a visible 'DEMO BYPASS' banner. Password mode kicks in when OWNER_DEMO_PASSWORD is set, gating /admin/login behind a 30-day cookie session. Live mode kicks in when PUBLIC_CLERK_PUBLISHABLE_KEY is set, swapping in real Clerk auth flow. Every Convex-bound function in source.ts is shaped as a swap-in for the dummy version, so going to production is adding env vars and replacing call sites, not rewriting the data layer.
The owner-facing UX is the second deliberate choice. The admin routes use bakery vocabulary (Tårtor, Beställningar, Öppettider, Nyheter, Inställningar), not engineering terms. The Översikt dashboard surfaces three counters at a glance (Nya beställningar, Sortiment, Nyheter) and a Senaste beställningar feed. Featured products auto-promote to the homepage. JSON-LD LocalBusiness markup is rendered on every page for SEO without the owner ever touching it.