Architecture
How Sajt fits together — the load-bearing pillars and where to find things.
Sajt is an opinionated, bilingual (sv/en) website builder for small businesses, built on Next.js (App Router), React, TypeScript, Tailwind, Clerk and Convex, deployed on Vercel.
The six pillars
- Two-world model — draft edits live in normalized, mutable tables; publishing
writes an immutable snapshot (
siteVersions). The public site reads only snapshots, so editing can never corrupt a live site. - One shared renderer —
components/site-sections/SectionRenderer.tsxrenders the editor canvas,/preview, share links (/p/<token>) and the public/site. Preview equals production; never fork it. - Structured content — section
contentis a discriminatedv.unionkeyed bytype, validated on every write. No raw HTML, no raw hex. - Constrained theme — themes are pre-validated, AA-safe tokens (palette, font, density, radius, button) mapped to CSS variables.
- SEO as system output — metadata, JSON-LD, sitemap, robots, hreflang and canonical are derived from business data at publish time and frozen in the snapshot.
- Plain language, bilingual — every admin string goes through
lib/i18n.ts(sv/en/pl).
See the rest of this section for Routes, Data model, Auth and permissions, Publishing and the AI system.
This reference is generated from the repo's internal docs (
docs/ARCHITECTURE.mdand friends). Code wins over docs — when they disagree, trust the code.