How apps/web turns generated content into prerendered SvelteKit pages, and where to change routes, SEO and runtime integrations.

Reference Value
Subject Routes, content catalog, rendering and caching, SEO surfaces, locales, runtime integrations; for web contributors
Verified source apps/web on main at 950ba889, checked 2026-11-07; media resolution, project share copy, image blocks, section defaults, the analytics relay and Blog redirects re-verified on main at 0461e045, checked 2026-11-10
Support state Application contracts checked against main 950ba889; main 0461e045 (#692) pins design v0.40.0. Public requests on November 7, 2026 returned the 950ba889 revision's project redirect and robots tag

Stack

SvelteKit 3 with Svelte 5 runes, TypeScript, Tailwind CSS 4, Vite and @sveltejs/adapter-vercel pinned to the nodejs22.x runtime. GSAP and Embla drive motion and carousels. Configuration lives in vite.config.ts. Its ssr.noExternal list bundles packages whose module format breaks Vercel's Node runtime, including sanitize-html and its ESM-only parser chain (htmlparser2, domhandler, domutils, domelementtype, dom-serializer, entities).

flowchart LR
  G["src/lib/content<br/>21 generated modules"] --> A["catalog<br/>availability rules"]
  A --> L["+layout.server.ts<br/>+page.server.ts loaders"]
  G --> D["Direct reads<br/>chrome, CTAs, fallbacks"]
  L --> P["Prerendered pages<br/>EN, FR, ES"]
  D --> P
  P --> B["Browser"]

Route map

Route Source Notes
Home, about, contact, projects, services, blog, blog/personal src/routes/[[lang=locale]]/ Optional locale segment: EN has no prefix, /fr and /es match through src/params.ts
projects/[slug], blog/[slug], services/[id], legal/[slug] Same tree Detail pages for CMS rows; [email protected] resets the layout for article pages
/sitemap.xml, /robots.txt src/routes/ Functions; host-aware
/og/[type=ogType]/[slug].png src/routes/og/ Prerendered Blog and Project cards
/llms.txt, /llms-full.txt src/routes/, src/lib/server/llms.ts Prerendered crawler text from generated content
/api/weather src/routes/api/weather/ Function with a 30 minute shared cache
/relay/e src/routes/relay/e/+server.ts POST function, never prerendered: forwards each Plausible event once with the visitor's address; 404 when PUBLIC_PLAUSIBLE_DOMAIN is empty
/work → /projects (English path only, src/routes/work/). In every locale: /tech-stack → /services; /services/internal-tooling → /services/data-pipeline; /services/sql-development → /services/database-engineering; /projects/yesid-dev-design → /projects/yesid-design +server.ts redirects Permanent redirects kept on functions so CDN cache headers survive
blog/one-brain-for-five-ai-tools-t3-code-and-notion and its FR and ES former slugs → the requested locale's "four AI tools" post blog/<old-slug>/+server.ts, server/four-ai-tools-redirect.ts Permanent; every old spelling follows the URL's locale (#676)

Content catalog and SEO

Routes read the synchronous catalog from src/lib/catalog/index.ts. It reads generated modules; it never fetches editorial content at request time.

Interface Contract
projects bySlug, locale-aware available, featured, byService; listings project away case-study bodies
services byId, available, adjacent
blog Available language rows, slug/body/category and the post's topic icon: one of 21 SVGs in src/lib/assets/blog-icons/, read raw by name. The exporter sets the name from the post's Directus svg_illustration, or a stable post-id hash over four topics per category when none is set. catalog/icon-assets.test.ts checks the library and every fixture post's icon
meta, nav, legal, content Site defaults, route overrides, navigation, legal copy and page blocks
catalog/availability.ts One site-page, entity-status and locale policy for routes, prerender, sitemap, OG and LLM text
adapters/page-seo.ts resolvePageSeo composes catalog data through static defaults or route factories; validates PageSeo

createContentCatalog(source) injects rows and locale/page policy for tests. Layout chrome and client fallbacks may read generated modules directly.

Rendering, gating and caching

Concern Contract Source
Prerender Root layout sets prerender = true; every page prerenders with explicit entries per published locale and slug. Endpoints opt out individually src/routes/+layout.server.ts, src/lib/server/prerender-entries.ts
Page registry A page renders only if site_pages publishes its path or its listing prefix; otherwise 404. The sitemap uses the same predicate src/lib/catalog/availability.ts
Layout fallbacks Layouts resolve catalog defaults and route SEO; errors use status-specific or generic generated copy +layout.server.ts, +layout.ts
Cache headers HTML and __data.json get s-maxage=86400, stale-while-revalidate=604800 on the CDN and max-age=0 in the browser, set only in hooks.server.ts hooks.server.ts
Theme and fonts @yesid/ui/head injects the theme boot script before paint; Link preload headers carry the self-hosted fonts Same
Errors handleError logs non-404 failures to the function log and resolves localized CMS error copy Same
Media The generated media-assets module maps each referenced file UUID to a committed mirror under static/images or a file the live export wrote to static/images/cms/<file-uuid>/ (Git-ignored); fixture builds map unmirrored UUIDs to a labelled placeholder. An ID missing from the map falls back to Directus only in Vite dev and fails in production src/lib/directus/assets.ts, apps/cms/scripts/lib/build-media.ts
Metric display Home Service cards, Service listings/details and Project impact cards show values and labels. Optional CMS source/date fields are not displayed or included in metric text in llms-full.txt HomeServices.svelte, ServiceCard.svelte, ServiceDetailPage.svelte, ProjectImpactCard.svelte, server/llms.ts

SEO and locales

compose-page-seo.ts and route-seo-factories.ts merge site metadata, SEO defaults and per-route route_seo rows into one PageSeo, so canonical, OG, JSON-LD and sitemap agree. The <html lang> value comes from the URL path. Published locales are EN, FR and ES. Entity availability also checks its site page and entity status; Blog uses separate language rows. Missing optional FR or ES localized fields fall back to English. Indexable pages carry a max-image-preview:large robots tag (pageRobots in utils/seo-defaults.ts); noindex pages get theirs from SeoHead. Project descriptions come from og/project-copy.ts: the localized one-liner (English fallback) with the call to action, the one-liner alone, then leading complete overview sentences with the call to action when it fits; a result outside 50 to 200 characters uses the site default. Blog descriptions close with their card's call to action when the result stays within 200 characters (withShareCta in og/share-copy.ts).

Runtime integrations

Integration Contract Source
Contact Browser POST to Web3Forms with a 15 second abort; submit enabled only after hydration; drafts persist per tab src/lib/components/contact/ContactPage.svelte
Analytics @yesid/analytics Plausible client, started once from the root layout; host-gated, cookieless, eight allowlisted events, posted to same-origin /relay/e, which forwards them to Plausible; Vercel Web Analytics and Speed Insights start on the same production host. Cloudflare's injected beacon is provider configuration src/lib/analytics/, src/routes/relay/e/
Weather /api/weather?lang= returns Montreal weather or null (no key, prerender, or provider failure) src/lib/utils/weather.ts
Transit KPIs Home hero polls https://transit.yesid.dev/api/v1/kpis every 45 seconds while visible; LIVE requires complete finite aggregate lanes and a usable route; retain the last real reading through one failure with its age advancing, then DEMO after a second consecutive failure src/lib/live/live-kpis.ts

Code layout

Need Where
Page components by area src/lib/components/{home,about,blog,projects,services,contact,shared,brand,cms}
Motion actions and scroll scrubs src/lib/motion/ (policy from @yesid/motion); utils/morphGate.ts lets a running SVG entrance or morph finish before the latest input plays, actions/morphHover.ts is the one path morph and actions/pointerHover.ts the touch-safe hover
Share cards src/lib/og/: card.ts layout, render.ts resvg rasterizer, share-copy.ts calls to action, project-copy.ts project card line and description, validate-project-lines.ts and glyph-coverage.ts export-time fit and font checks
Utilities, locale routing, SEO defaults src/lib/utils/
Server-only helpers (Markdown, Shiki, LLM text, redirects, indexing) src/lib/server/
Static assets and committed mirrors static/ (images, OG cards, the six service SVGs named by CMS services.svg, favicons)
Release gate scripts scripts/ (check-client-payload.mjs, check-csp.ts, check-ssr-runtime.mjs, check-svelte-warnings.mjs, generate-og-cards.ts) and tools/ (design gates)

Reading position and link activation