Stage 2: application shell (4 destinations, router, layout, a11y)

- Vite 6 build with hashed immutable assets (assets/index-[hash].js 2.63kB gz, style 1.18kB gz; index.html 0.92kB) — single-bundle, offline-safe shell (index.html no-cache, assets immutable) per ARCH §24
- index.html + manifest.webmanifest (standalone, / scope) + fallback.html Ring-0
- src/app/main.ts boot + layout + status placeholder (no IDB/Cache/SW/sync per Stage 2 SCOPE)
- src/app/layout.ts: banner, skip-link, main#main-content, bottom nav Emergency·Schedule·Map·Festival (Emergency first, --emergency accent #b91c1c/#ef4444, 64px nav, 48px targets)
- src/ui/router/router.ts: history-API, offline-safe deep links (/emergency canonical), normalizePath, routeForPath, no network
- 4 placeholder views (emergency/schedule/map/festival) + not-found, semantic h1/section/aria-labelledby, view-placeholder structural only (no real data)
- src/app/styles.css: phone-first, high-contrast, dark via prefers-color-scheme, large touch targets, one-handed, outdoor, reduced-motion guard
- Tests: tests/unit/shell.test.ts (14 tests: boot, landmarks, 4 destinations, emergency one-tap from every route, unknown routes, normalize, a11y) — jsdom; updated boundaries test for Stage 2 shell
- Lint: allowDefaultProject for vite.config.ts; boundaries B-1..B-7 enforced (eslint-plugin-boundaries), B-7 innerHTML guard
- CI passes: typecheck + lint + format + test (18 tests) + build
- No IDB/Cache/SW/DataPackage/sync/mesh/accounts per contract — directories remain .gitkeep
This commit is contained in:
Lumen Stage1 2026-08-30 23:29:56 -05:00
commit 902a1ffc22
18 changed files with 1516 additions and 133 deletions

View file

@ -0,0 +1,24 @@
{
"name": "Lumen",
"short_name": "Lumen",
"description": "Offline-first festival companion — Emergency, Schedule, Map, Festival",
"display": "standalone",
"scope": "/",
"start_url": "/",
"background_color": "#0a0a0a",
"theme_color": "#0a0a0a",
"icons": [
{
"src": "/icon-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/icon-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}
]
}