The web user-interface for the BTClock
- TypeScript 53.8%
- Svelte 38.2%
- CSS 6.4%
- JavaScript 0.7%
- Python 0.6%
- Other 0.3%
Onboarding doc for AI agents touching the SvelteKit WebUI: stack overview, feature-folder map, current home-page features wired to firmware endpoints, conventions to keep, and a punch list of constructive improvements. |
||
|---|---|---|
| .forgejo/workflows | ||
| .github | ||
| .vscode | ||
| doc | ||
| extra/icons | ||
| patches | ||
| project.inlang | ||
| src | ||
| static | ||
| tests | ||
| .gitignore | ||
| .prettierignore | ||
| .prettierrc | ||
| AGENTS.md | ||
| Dockerfile | ||
| eslint.config.js | ||
| gzip_build.py | ||
| package.json | ||
| playwright.config.ts | ||
| playwright.doc-screenshot.config.ts | ||
| playwright.screenshot.config.ts | ||
| pnpm-lock.yaml | ||
| README.md | ||
| renovate.json | ||
| svelte.config.js | ||
| tsconfig.json | ||
| vite.config.test.ts | ||
| vite.config.ts | ||
BTClock WebUI
The web user-interface for the BTClock.
Getting started
This project is managed with pnpm. Install it with
corepack enable pnpm or npm i -g pnpm if you don't have it yet.
pnpm install # runs patch-package for the SvelteKit filename shortening patch
pnpm dev # start the dev server (http://localhost:5173)
Set PUBLIC_BASE_URL in .env to the address of a real BTClock to have
the dev server proxy API requests to it (defaults to
http://192.168.20.97). For a same-origin build that the firmware serves
from LittleFS, set it to an empty string at build time.
Production build
pnpm build # produces dist/ with bundle.js + index.html (post-build rewrap)
python3 gzip_build.py # gzips everything under dist/ into build_gz/
mklittlefs -c build_gz -s 409600 output/littlefs.bin
The post-build rewrap step in vite.config.ts turns SvelteKit's
bundle.html fallback into a self-contained bundle.js that the BTClock
firmware mounts inside the .overlay container. The filename-shortening
patch in patches/ keeps asset names within LittleFS's filename limit.
Tests
pnpm test:unit # vitest unit + component tests
pnpm test:integration # playwright end-to-end suite (chromium + mobile)
pnpm test:screenshots # device/locale screenshot suite
pnpm doc:update-screenshots
Key architectural choices
- Feature-based folders — UI is organised under
src/lib/features/{clock,control,status,firmware,settings,convert}with colocated sub-components and spec tests. Generic primitives live insrc/lib/ui/, data access insrc/lib/api/, and global state insrc/lib/stores/as Svelte 5 runes. - Discriminated-union state —
SettingsStateandStatusStateencodeloading | error | ready, so every consumer handles each phase explicitly instead of falling through nullable props. - Valibot schemas — Runtime validation for every inbound API payload
lives in
src/lib/api/schemas.ts, protecting the UI from firmware drift. - Paraglide JS v2 — Message catalogs in
src/lib/locales/are compiled per-locale and tree-shaken by the Paraglide Vite plugin. - Static output only —
@sveltejs/adapter-staticwith SSR disabled; the WebUI is always mounted on-device by the firmware. - Minimal font footprint — only the
latin-400woff2 files for Ubuntu and Antonio are shipped, keepingbuild_gz/well below the ~420 KB LittleFS partition.

