Files
landing/AGENTS.md
mifi c963e34766
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
Proper 410/404 pages
2026-02-16 01:18:38 -03:00

7.1 KiB

Agent guide: mifi Ventures landing

This file helps LLM agents work in this repo without introducing anti-patterns. Follow the architecture and conventions below.

Purpose

  • Audience: LLM agents (e.g. Cursor, Codex) making code or content changes.
  • Goal: Preserve a minimal static site: SvelteKit prerender, no client-side app JS, shared theming, critical CSS inlining, and clear separation between app routes and static error pages.

Stack and architecture

  • Framework: SvelteKit with adapter-static. All routes are prerendered; there is no client-side router or hydration (csr: false in src/routes/+layout.ts).
  • Build: pnpm run build = vite buildnode scripts/critters.mjsnode scripts/minify-static-js.mjsnode scripts/copy-410-paths.mjs. Output is dist/ (static files only).
  • Runtime: nginx serves dist/ (mounted as /usr/share/nginx/html in the container). No Node at runtime.
  • Theming: CSS only. Light/dark follows system preference via @media (prefers-color-scheme: dark) in src/app.css. There is no JS theme toggle or data-theme; do not add one unless explicitly requested.
  • Fonts: Local only. Inter and Fraunces are served from static/assets/fonts/ (e.g. inter-v20-latin-*.woff2, fraunces-v38-latin-*.woff2). Preloads are in src/routes/+layout.svelte. Do not add Google Fonts or other external font URLs for the main site or error pages.

Key paths

Path Role
src/app.css Single global stylesheet: CSS variables (light/dark), base styles, components. Source of truth for theme tokens.
src/app.html SvelteKit HTML shell. Rarely edited.
src/routes/+layout.svelte Root layout: head (meta, fonts, favicon, scripts), skip link, slot. Imports app.css.
src/routes/+layout.ts Exports prerender = true, ssr = true, csr = false. Do not enable CSR.
src/routes/+page.svelte Home page; composes sections from src/lib/components/.
src/lib/data/*.ts Content and meta (home-meta, content, experience, engagements, json-ld). Edit here for copy or SEO.
src/lib/seo.ts SEO defaults (baseUrl, theme colors, etc.) and mergeMeta().
static/ Copied as-is into dist/ by SvelteKit. Favicon, robots.txt, fonts, images, 404.html, 410.html, and assets/error-pages.css live here.
scripts/critters.mjs Post-build: inlines critical CSS into every dist/*.html (including 404 and 410). Resolves stylesheet URLs relative to dist/.
scripts/minify-static-js.mjs Post-build: minifies JS in dist/assets/.
scripts/copy-410-paths.mjs Post-build: copies 410.html to each 410 URL path as index.html so static preview (e.g. serve dist) shows the 410 page at those URLs; nginx still returns 410 via explicit location blocks.
nginx.conf Serves static files; try_files $uri $uri/ /index.html for SPA-style fallback; error_page 404 /404.html and error_page 410 /410.html for custom error pages.

Static error pages (404, 410)

  • Files: static/404.html, static/410.html. They are standalone HTML (not Svelte). Do not convert them to Svelte routes.
  • Styling: Both link to one shared stylesheet: <link rel="stylesheet" href="/assets/error-pages.css">. All error-page CSS lives in static/assets/error-pages.css (theme variables for light/dark, local @font-face for Inter/Fraunces, layout for .error-page). Do not duplicate theme tokens or add inline <style> in the HTML; keep a single source in error-pages.css.
  • Critical CSS: The build runs Critters on all dist/*.html. Critters inlines critical CSS from linked stylesheets (including /assets/error-pages.css) into 404.html and 410.html. So:
    • Do keep the <link rel="stylesheet" href="/assets/error-pages.css"> in 404.html and 410.html; Critters will inline it at build time.
    • Do not add error-page-only CSS in src/app.css; the app bundle is not loaded on error pages.
  • Theme alignment: When changing light/dark colors or typography in src/app.css, update static/assets/error-pages.css so 404/410 stay visually consistent (same --ep-* tokens and, if needed, @media (prefers-color-scheme: dark)).
  • Local fonts: Error pages use the same font paths as the main site (/assets/fonts/...) via @font-face in error-pages.css. Do not use Google Fonts or other external font URLs on error pages.
  • Preview vs production: In preview (serve dist), the 410 URLs (e.g. /pt/, /feed/) are served by copying 410.html to each path as index.html (see scripts/copy-410-paths.mjs). In production, nginx returns HTTP 410 for those paths and serves the same content via error_page 410 /410.html. If you add or remove 410 paths, update both nginx.conf and the PATHS array in scripts/copy-410-paths.mjs.

Anti-patterns to avoid

  1. Enabling client-side rendering
    Do not set csr: true or add a client-side router. The site is intentionally static and JS-minimal.

  2. Adding app JavaScript for the main shell
    The only scripts are small, purposeful ones (e.g. copyright-year.js, ga-init.js, mobile-menu-helper.js) in static/assets/js/. Do not introduce a Svelte hydration bundle or large runtime for the main pages.

  3. External fonts
    Do not add <link> to Google Fonts (or similar) in layout or error pages. Use local fonts in static/assets/fonts/ and reference them via preload (layout) or @font-face (error-pages.css).

  4. Skipping Critters for new HTML
    Any new .html in static/ is copied to dist/ and must be processed by Critters (the script already runs on all dist/*.html). Do not add static HTML that bypasses the build or that uses only inline styles without a linked stylesheet (linked styles get inlined by Critters).

  5. Diverging error page theme
    Do not change 404/410 styling in a way that ignores static/assets/error-pages.css or that duplicates theme tokens from src/app.css in ad-hoc form. Keep one error-page stylesheet and align its variables with app.css when you change the main theme.

  6. Breaking static export
    Do not add routes or behavior that require server-side rendering at request time (e.g. dynamic routes without prerender). The app is fully prerendered and served as static files.

  7. Scattering SEO or theme defaults
    Keep SEO defaults and theme-color values in src/lib/seo.ts and in layout/error pages that need them. Do not duplicate or hardcode them in many places.

Quick reference

  • Change copy or structure (home): src/lib/data/*.ts, src/lib/components/*.svelte, src/routes/+page.svelte.
  • Change global styles or theme: src/app.css. Then sync static/assets/error-pages.css if tokens or dark mode change.
  • Change error page copy or structure: static/404.html, static/410.html. Style changes: static/assets/error-pages.css only.
  • Add a new static HTML page: Add it under static/, link to /assets/error-pages.css (or a dedicated stylesheet that Critters can inline). Ensure scripts/critters.mjs runs over all dist/*.html (it already does).
  • Change nginx behavior: nginx.conf (e.g. cache headers, error_page, try_files).