1f695d3932
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4.4 KiB
4.4 KiB
DATA_MODEL.md
Content model for the bilingual content collections. All schemas zod-validated at build; a schema violation fails CI. (Conceptual field lists — not code.)
1. Collections overview
content/
├── profile/ singleton per locale (hero, chips, about)
├── projects/ 3 entries × 2 locales (jobtrack, inboxintel, homelab)
├── experience/ 5 entries × 2 locales (council, side roles, education, 2023-now)
├── skills/ 3 group entries × 2 locales
└── meta/ colophon page, 404 copy, contact page copy × 2 locales
Locale-invariant fields live on the EN entry and merge into NO at load (I18N_SPEC §3). Below, fields marked [inv] are invariant; everything else is per-locale prose.
2. profile (singleton)
name[inv],roleLine,heroTagline(the one-sentence claim),heroSummary(≤ 2 lines)chips[]:{ id [inv], label }— location, permit, availability, languagesstatusLine(trace-dot tooltip: "open to work" / "åpen for muligheter")aboutParagraphs[](3),interestsLinephoto[inv]: asset ref + per-localealt,captionlinks[inv]: email, linkedinRedirect (/Linkedin), gitea, phonecv[inv]:{ en: {path, sizeKb, updated}, no: {...} }
3. projects
id/slug[inv, per-locale slug via slug map],name[inv],order[inv]status[inv]:active | in-development | archived(drives chip semantics per COLOUR_SYSTEM §3.4)valueProp(one-liner),cardTeaser(2 lines for homepage card)stack[][inv]:{ name, contextLine? per-locale }(chip + tooltip)links[][inv]:{ type: repo|live|docs, url, public: bool }(repo links only if/when repos are public — publish decision is content, not code)tldr:{ what, why, stack, role }(4 strings)sections[]: ordered{ anchorId per-locale, heading, body (markdown) }— canonical section kinds:problem,architecture,decisions,security,screenshots,nextdecisions[]: structured{ n, choice, alternative, rationale }(rendered as the numbered trade-off blocks)diagram[inv]: SVG asset ref + per-localetitle,desc(a11y),nodes[]label overrides per localemedia[][inv refs]:{ image, width, height, per-locale alt + caption, order }— dimensions mandatory (CLS 0)template[inv]:case-study | capability(homelab uses the lighter template)summaryOnly?(NO-side flag per I18N_SPEC §4.2)
4. experience
id[inv],employer[inv],location[inv],period[inv]:{ from, to|null }role,summary,highlights[](featured only)emphasis[inv]:featured | compactprogression?[inv]: for the council entry —[{from: 2015, to: 2017, label-per-locale: "Apprentice"}, {from: 2017, to: 2023, label: "System Developer"}]anchor?— the confirmed concrete bullet (streetlight/highways system) is content, phrased per CANONICAL_CONTENT- Entries:
warwickshire(featured),royal-vapes,hodcarrier,nuffield(compact,alongside: true[inv] flag renders the "alongside" grouping),education,norway-now(2023–, norskkurs + products)
5. skills
id[inv],order[inv],title,contextLine,skills[]:{ name [inv], tooltip? }- Groups:
development,devops-infrastructure,practices
6. Page-meta (every routable page)
title,description(≤155 chars),ogImage[generated per locale],pageId[inv → slug map join]- Case studies additionally emit structured-data fields (SEO_SPEC §3)
7. Asset conventions
- Screenshots:
assets/projects/<id>/<capture>.pngsource of truth at 2×, seeded demo data only (Phase 3 prerequisite); pipeline emits AVIF/WebP/fallback + srcset. - Diagrams: hand-authored SVGs following the design-system diagram style; text within diagrams uses per-locale label injection at build (single SVG source, two rendered outputs) — avoids maintaining twin diagrams.
- Fonts/CVs/favicons in
public/(unprocessed, stable URLs).
8. Validation rules (CI)
- Locale parity (I18N_SPEC §4.1).
- Every
media[]entry has dimensions + both alts. - Every project has ≥3
decisions[]and asecuritysection (the site's promise to P2 is structural). statustransitions logged in git only — no "archived" entry may appear on the homepage cards (query rule).- Description lengths, title lengths enforced (SEO).
- All external
links[].urlrespond 200 in a scheduled link-check workflow (not per-commit).