1f695d3932
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
77 lines
4.4 KiB
Markdown
77 lines
4.4 KiB
Markdown
# 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, languages
|
||
- `statusLine` (trace-dot tooltip: "open to work" / "åpen for muligheter")
|
||
- `aboutParagraphs[]` (3), `interestsLine`
|
||
- `photo` [inv]: asset ref + per-locale `alt`, `caption`
|
||
- `links` [inv]: email, linkedinRedirect (`/Linkedin`), gitea, phone
|
||
- `cv` [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`, `next`
|
||
- `decisions[]`: structured `{ n, choice, alternative, rationale }` (rendered as the numbered trade-off blocks)
|
||
- `diagram` [inv]: SVG asset ref + per-locale `title`, `desc` (a11y), `nodes[]` label overrides per locale
|
||
- `media[]` [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 | compact`
|
||
- `progression?` [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>.png` source 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)
|
||
|
||
1. Locale parity (I18N_SPEC §4.1).
|
||
2. Every `media[]` entry has dimensions + both alts.
|
||
3. Every project has ≥3 `decisions[]` and a `security` section (the site's promise to P2 is structural).
|
||
4. `status` transitions logged in git only — no "archived" entry may appear on the homepage cards (query rule).
|
||
5. Description lengths, title lengths enforced (SEO).
|
||
6. All external `links[].url` respond 200 in a scheduled link-check workflow (not per-commit).
|