Monorepo: SvelteKit PWA Workspace Architecture
Section titled “Monorepo: SvelteKit PWA Workspace Architecture”Date: 2026-03-06
Session: Extend monorepo with apps/ workspace for SvelteKit PWAs
Status: ✅ Complete
Commit: be9b5fe
Summary
Section titled “Summary”Extended the existing Astro monorepo with a new apps/ pnpm workspace for SvelteKit PWAs. The first app (apps/sd-demo) is a working debt payoff calculator built with SvelteKit 2, Svelte 5 runes, Tailwind CSS, and vite-plugin-pwa. Design tokens are consumed directly via workspace link — no publishing friction.
Tasks Completed
Section titled “Tasks Completed”- Added
apps/*topnpm-workspace.yaml - Added
eslint-plugin-svelte(flat/recommended) to root ESLint config - Added
prettier-plugin-svelteto root Prettier config (formatting disabled in lint-staged — see Known Issues) - Scaffolded
apps/sd-demo/— complete SvelteKit PWA with working calculator page - Updated
README.mdanddocs/ARCHITECTURE.mdwith new structure and SvelteKit decision rationale
Files Modified
Section titled “Files Modified”Root config:
pnpm-workspace.yaml— addedapps/*eslint.config.mjs— added svelte plugin, added.svelte-kit/**andbuild/**to ignorespackage.json— addedeslint-plugin-svelte,prettier-plugin-svelte; added*.sveltelint-staged rule (ESLint only).prettierrc— added svelte plugin + parser override
Documentation:
README.md— updated Project Structure + Tech Stackdocs/ARCHITECTURE.md— updated structure diagram, workspace config, component philosophy, added “Why SvelteKit for Apps?” ADR block
New app:
apps/sd-demo/.gitignoreapps/sd-demo/package.json— SvelteKit 2 + vite-plugin-pwa + @smart-debt/design-tokens workspace depapps/sd-demo/svelte.config.js— adapter-static (pure static, Cloudflare Pages ready)apps/sd-demo/vite.config.ts— sveltekit + VitePWA (autoUpdate, workbox)apps/sd-demo/tailwind.config.js— CSS variable pattern (matches Template site)apps/sd-demo/postcss.config.jsapps/sd-demo/tsconfig.json— extends .svelte-kit/tsconfig.json + skipLibCheckapps/sd-demo/src/app.html— PWA HTML shell (manifest link, theme-color #005c2e)apps/sd-demo/src/app.css— Tailwind directives + SmartDebt CSS custom properties (light/dark)apps/sd-demo/src/app.d.ts— SvelteKit global typesapps/sd-demo/src/design-tokens.d.ts— ambient types for @smart-debt/design-tokensapps/sd-demo/src/routes/+layout.svelte— imports app.cssapps/sd-demo/src/routes/+page.svelte— debt payoff calculator (Svelte 5 runes)apps/sd-demo/static/favicon.svg— copied from Template SD brandapps/sd-demo/static/manifest.json— PWA manifest (standalone display)
Architecture Decisions
Section titled “Architecture Decisions”Same Monorepo (not separate repo)
Section titled “Same Monorepo (not separate repo)”@smart-debt/design-tokensconsumed viaworkspace:*— no npm publishing needed- One lockfile = consistent versions across all sites and apps
- Brand assets (
src/brand/) shared directly - Each app still deploys independently to its own Cloudflare Pages project
SvelteKit for Apps (not Astro)
Section titled “SvelteKit for Apps (not Astro)”- Astro optimized for content; SvelteKit for interactive PWAs with client-side routing
- Svelte 5 runes compile to minimal vanilla JS
adapter-static→ pure static output, CDN-ready, no server neededvite-plugin-pwaintegrates natively with SvelteKit’s Vite pipeline
Embedding Strategy
Section titled “Embedding Strategy”- Apps deploy to
*.pages.devsubdomains - Astro marketing pages embed via
<iframe src="https://sd-demo.pages.dev"> - Iframes = isolated, sandboxed, portable to third-party sites
Verification Results
Section titled “Verification Results”| Check | Result |
|---|---|
pnpm build (sd-demo) | ✅ Builds to build/ with service worker + workbox |
pnpm lint (monorepo root) | ✅ 0 errors (7 pre-existing warnings only) |
pnpm check (sd-demo svelte-check) | ✅ 0 errors, 0 warnings |
pnpm test (design-tokens unit) | ✅ 26/26 pass |
| Pre-commit hook | ✅ Passes (lint-staged ESLint on .svelte files) |
Known Issues
Section titled “Known Issues”prettier-plugin-svelte incompatible with Svelte 5 syntax
Section titled “prettier-plugin-svelte incompatible with Svelte 5 syntax”- Error:
TypeError: getVisitorKeys is not a function or its return value is not iterable - Cause:
prettier-plugin-sveltev3.5.1 (latest) doesn’t handle Svelte 5 rune syntax ($state,$derived,$props) in Prettier v3.8 - Mitigation:
.sveltefiles excluded from prettier formatting in lint-staged (ESLint-only) — same pattern as.astrofiles in this repo - Resolution: Watch for
prettier-plugin-sveltev4 which will support Svelte 5
Next Steps
Section titled “Next Steps”- Deploy sd-demo — create Cloudflare Pages project, run
pnpm build+ wrangler deploy - Embed teaser — add iframe embed on Template site (components showcase or dedicated page)
- Add more routes — avalanche vs. snowball comparison, amortization schedule table
- Color generation — optionally wire up
pnpm colors:sdequivalent for the app - CI — add sd-demo to GitHub Actions matrix when ready for continuous deployment
Commands Reference
Section titled “Commands Reference”# Developmentpnpm --filter @smart-debt/sd-demo dev # Start dev server
# Buildpnpm --filter @smart-debt/sd-demo build # Static build → apps/sd-demo/build/
# Type checkpnpm --filter @smart-debt/sd-demo check # svelte-check
# Lint (from monorepo root)pnpm lint # ESLint across all sites + apps