mifi.dev one-page static landing — plan 1. Tech stack (locked): SvelteKit (static) Chosen stack: SvelteKit with the static adapter (@sveltejs/adapter-static). Output is pure static HTML with no client-side framework bundle or rendering; minimal JS (theme toggle, copy-link, a11y, copyright year) compiles to a small vanilla-like bundle from Svelte components. Why SvelteKit: Components + scoped CSS; static adapter = pre-rendered HTML; data-driven at build time via load in +page.server.ts or +layout.server.ts; no React runtime; you've used it recently for another static site with good results. Critical CSS: Implement during scaffold (not bolted on later). Use a Vite plugin (e.g. vite-plugin-critical or equivalent) or a post-build step with the critical npm package to inline critical CSS in , add in , and place at end of . Content: Data-driven JSON (e.g. src/lib/data/links.json or content/links.json); load in +page.server.ts (or +page.ts with export const prerender = true) and pass to the page—all content rendered into HTML at build time. Package manager: pnpm (lockfile pnpm-lock.yaml); all install/build/test scripts assume pnpm. Language: TypeScript (always); all app and config code in TypeScript. CSS: PostCSS for nesting and future CSS features (e.g. postcss-nested, postcss-preset-env); integrate with Vite/SvelteKit so component and global CSS are processed consistently. 2. Repo, deploy, and infrastructure Repo: git.mifi.dev/mifi-holdings/mifi-dev-landing. Deploy: Webhook from Gitea to Portainer stack; stack defined by docker-compose in repo. docker-compose (in repo): Service: nginx (small footprint, low memory) serving the built static site. Traefik labels for: Hosts: mifi.dev, www.mifi.dev Use existing Docker network: marina-net No client-side rendering; container just serves pre-built HTML/CSS/JS and assets. CI (Woodpecker) will run on the same server as Gitea: lint, unit tests, e2e/visual regression, and build (using pnpm); deploy can be “build artifact + webhook triggers Portainer to pull and redeploy stack.” Local development: Dev Containers (.devcontainer/) so local development matches a consistent, reproducible environment (Node, pnpm, browsers/tools as needed). Playwright in the dev container must use the same Linux build as the CI pipeline so visual-regression snapshots are the same size and comparable. Document how to open the project in a dev container in README; CI can mirror the same stack where relevant. 3. Tooling and quality Prettier: Format HTML, CSS, JS/TS, JSON, YAML (config in repo). Lint: ESLint and TypeScript for TS—strict, no unsafe patterns; align with CSP (e.g. no eval, no inline event handlers in generated HTML). Stylelint for CSS—scoped to project rules, WCAG-related rules where helpful. Unit tests: Vitest (latest), 100% coverage for all JS (theme toggle, copy-link, a11y helpers, copyright year). No framework runtime in output = tests run against plain JS (or Svelte-compiled output). E2E / visual regression: Playwright (latest)—e2e flows plus visual regression (screenshot diffing) for layout/design. Run in CI (Woodpecker). Dev container must use the same Linux Playwright build as CI so snapshots are the same size. Packages: Use latest stable versions; lockfile in repo (pnpm-lock.yaml). 4. Build pipeline Critical CSS: Inline critical CSS in . Non-critical styles: in , actual at end of (your preferred pattern; Critters or alternative implements this). Content: JSON data file(s) (e.g. src/lib/data/links.json) defining links, labels, and any copy; consumed at build time and rendered into HTML. No client-side data fetching or rendering. JS: Single small bundle (or one script) for: theme switch, copy-link, a11y enhancements, copyright year. Script referenced via