Modern POS and club management UI built with SvelteKit 5 runes, Supabase, Tailwind CSS v4, and a11y‑first UI primitives.
users profile table and roles: admin, staff, secretary.src/lib/i18n.ts with t()/tt() utilities and en/el locales.src/lib/components/ui/*.$state, $derived, $bindable)Prerequisites: Bun 1.1+ (or Node 20+), Supabase CLI, Git.
Clone and install
git clone https://github.com/dacrab/clubOS-svelte.git
cd clubOS-svelte
bun install
Environment Copy example env and edit:
cp .env.example .env.local
Keys used by the app: PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_PUBLISHABLE_KEY (or legacy PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY). Local-only: SUPABASE_SERVICE_ROLE_KEY (for bun run db:seed).
Optional: local Supabase
supabase start
supabase db reset # loads schema from supabase/migrations
bun run db:seed # seeds demo tenant, users, categories, products, orders
Run the app
bun run dev
Quality & tests
bun run check # svelte-check + biome + knip
bun run test # vitest
bun run dev # start dev server
bun run build # production build
bun run preview # preview production build
bun run check # typecheck + svelte-check + biome + knip
bun run check:watch # watch mode (svelte-check + ultracite fix)
bun run test # run unit tests (vitest)
bun run db:seed # seed database (requires service role key locally)
bun run db:reset # supabase db reset + seed
bun run db:restart # supabase stop && supabase start
src/lib/supabase-client.ts – Supabase client (browser) via $env/dynamic/public.src/lib/user.ts – current user store and profile/tenant loader.src/lib/i18n.ts – i18n utilities and translations (en, el).src/lib/components/ui/** – reusable UI; import from barrels.src/routes/** – SvelteKit routes (pages + endpoints): admin/*, staff/*, secretary/*, reset/*, api/*.scripts/seed.ts – idempotent database seeding (service role key, local only).supabase/** – CLI config and migrations.svelte.config.js, vite.config.ts, biome.jsonc, knip.json, tsconfig.json.$state for local mutable state, $derived for pure computed values, $bindable for two‑way bindable props.import { Card, CardContent, CardHeader, CardTitle } from "$lib/components/ui/card";
import { Button } from "$lib/components/ui/button";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "$lib/components/ui/table";
$lib/*, $app/*, $env/* (see knip.json). Avoid namespace imports.title, button type, valid ARIA only, no positive tabIndex).noUncheckedIndexedAccess, exactOptionalPropertyTypes, verbatimModuleSyntax, etc.). Use import type for types.PUBLIC_SUPABASE_URL and one of PUBLIC_SUPABASE_PUBLISHABLE_KEY or PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY are required. The app throws if missing.SUPABASE_SERVICE_ROLE_KEY. On hosted projects, prefer an sb_secret_... key. For local Supabase CLI, you must use the legacy JWT service_role key (the sb_secret_... key is not supported by the local Auth server for admin endpoints).SUPABASE_SERVICE_ROLE_KEY is used by scripts/seed.ts to bypass RLS for seeding. Never expose this key to browsers or deploy hosts.script-src 'self', style-src 'self'). Add hosts explicitly if you embed external resources.users, categories, products, register_sessions, orders, order_items, tenant_members, facilities, appointments, football_bookings, tenant_settings, user_preferences.bun run test.vitest-env-public.ts, vitest-setup-client.ts.Workflows in .github/workflows:
ci.yml – install, typecheck, lint, tests.codeql.yml – code scanning.dependabot.yml – dependency updates (Actions + npm).Recommended repository secrets:
GITGUARDIAN_API_KEY (if using a secrets scan workflow)@sveltejs/adapter-vercel.PUBLIC_SUPABASE_URL and PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY on the host.vercel.json defines a cron to hit /api/keep-alive every 6 days at 03:17 UTC..env.local (dev) or host env (prod).svelte.config.js CSP directives.127.0.0.1:54321 and Vite HMR; ensure CLI is running.This repository enforces strict a11y and code quality via Ultracite + Biome and strict TypeScript. Prefer barrel imports and typed-only imports for a clean, tree‑shakable surface.