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%
Find a file
Djuri Baars fe029d8339
Some checks failed
/ check-changes (push) Successful in 56s
/ build (push) Failing after 48s
docs: add agent guide
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.
2026-04-26 17:41:55 +02:00
.forgejo/workflows Revert "ci: upgrade pnpm/action-setup to v6 in build workflow" 2026-04-18 15:13:52 +02:00
.github ci: bump pnpm/action-setup to v5 and fix package_json_file path 2026-04-18 14:20:30 +02:00
.vscode Added WiFi signal status and settings 2023-11-21 16:05:00 +01:00
doc fix(clock): stop BTClock digits from overflowing the Status column 2026-04-17 03:41:28 +02:00
extra/icons Remove icons to save space in image 2024-09-03 12:37:35 +02:00
patches feat(webui): promote webui-v2 to repo root 2026-04-17 02:06:52 +02:00
project.inlang feat(webui): promote webui-v2 to repo root 2026-04-17 02:06:52 +02:00
src feat(settings): user-configurable screen + currency rotation order 2026-04-20 23:29:00 +02:00
static style: run prettier across webui 2026-04-18 14:25:06 +02:00
tests Align WebUI with firmware 3.4.0 API 2026-04-17 23:46:47 +02:00
.gitignore chore: ignore .pnpm-store for Prettier, ESLint, and git 2026-04-17 02:12:31 +02:00
.prettierignore feat(settings): user-configurable screen + currency rotation order 2026-04-20 23:29:00 +02:00
.prettierrc feat(webui): promote webui-v2 to repo root 2026-04-17 02:06:52 +02:00
AGENTS.md docs: add agent guide 2026-04-26 17:41:55 +02:00
Dockerfile chore(docker): bump base image to Node 24 LTS 2026-04-17 14:17:36 +02:00
eslint.config.js chore: ignore .pnpm-store for Prettier, ESLint, and git 2026-04-17 02:12:31 +02:00
gzip_build.py fix(webui): stage gzipped assets under build_gz/www/ 2026-04-23 23:05:27 +02:00
package.json chore(deps): update eslint, typescript-eslint, vite to latest 2026-04-21 00:39:50 +02:00
playwright.config.ts feat(webui): promote webui-v2 to repo root 2026-04-17 02:06:52 +02:00
playwright.doc-screenshot.config.ts refactor(status): let screen and currency buttons reflow to column width 2026-04-17 03:32:16 +02:00
playwright.screenshot.config.ts refactor(status): let screen and currency buttons reflow to column width 2026-04-17 03:32:16 +02:00
pnpm-lock.yaml chore(deps): update eslint, typescript-eslint, vite to latest 2026-04-21 00:39:50 +02:00
README.md feat(webui): promote webui-v2 to repo root 2026-04-17 02:06:52 +02:00
renovate.json Migrate config renovate.json 2024-12-26 14:29:21 +00:00
svelte.config.js perf(webui): bundle into single JS chunk for faster ESP32 load 2026-04-18 13:14:50 +02:00
tsconfig.json feat(webui): promote webui-v2 to repo root 2026-04-17 02:06:52 +02:00
vite.config.test.ts feat(webui): promote webui-v2 to repo root 2026-04-17 02:06:52 +02:00
vite.config.ts perf(webui): bundle into single JS chunk for faster ESP32 load 2026-04-18 13:14:50 +02:00

BTClock WebUI

Latest release BTClock CI

The web user-interface for the BTClock.

Screenshot Screenshot Dark

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 in src/lib/ui/, data access in src/lib/api/, and global state in src/lib/stores/ as Svelte 5 runes.
  • Discriminated-union stateSettingsState and StatusState encode loading | 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-static with SSR disabled; the WebUI is always mounted on-device by the firmware.
  • Minimal font footprint — only the latin-400 woff2 files for Ubuntu and Antonio are shipped, keeping build_gz/ well below the ~420 KB LittleFS partition.