Project Page V2 — Migration Plan¶
Status: PARTIALLY COMPLETE
- All 8 project slugs have
v2: trueinprojectV2Data✅ (PR #485)useProjectPageCMShook implemented ✅ (fetches from Strapiproject-pagecollection)- Strapi
project-pagecollection seeded foriac-platform-framework; remaining slugs use staticprojectV2Datafallbackproject-detail.tsxstill exists as V1 fallback — not yet deletedprojectV2Datastill inprojects.ts— kept asinitialDatafallback; delete once all Strapi entries confirmedRemaining work: Populate Strapi
project-pageentries for remaining 7 slugs, then deleteprojectV2Dataandproject-detail.tsx.
Covers two migrations: (1) moving projectV2Data CMS fields into Strapi, and
(2) migrating all existing projects from the V1 layout to the V2 layout.
Context¶
ProjectPageV2 (client/src/pages/project-page-v2.tsx) is the new project page
layout. It is API-first: structured facts (title, client, technologies,
challenge, solution, results, timeline, etc.) come from the existing
projects API. Bespoke editorial content is currently hardcoded in
projectV2Data (client/src/data/projects.ts) and needs to move into Strapi.
The V2 layout renders for a project slug when projectV2Data[slug] exists and
has v2: true. V1 (project-detail.tsx) is the fallback for all other slugs.
Part 1 — Move projectV2Data into Strapi¶
Fields that move to Strapi¶
| Field | Type | Notes |
|---|---|---|
tagline |
Short text | One-liner shown in the hero |
year |
Short text | Display year (e.g. "2024") |
featured |
Boolean | Controls "Featured Project" badge |
titleLines |
Two short text fields (titleLine1, titleLine2) |
Line 1 is white, line 2 is pink |
overviewHeading |
Short text | e.g. "One scaffold, every project." |
overviewBody |
Rich text / repeatable text blocks | The bespoke overview paragraphs |
metaFields |
Repeatable component {label, value} |
CMS-only sidebar facts |
architectureSection |
Component | eyebrow, heading, body, bullets, diagramType |
repoTree |
JSON / nested component | File tree for the repo structure section |
codeSnippets |
Repeatable component {tab, language, code} |
YAML code examples |
secondaryRepo |
Component | Terraform repo tree + module cards |
diagramCallout |
Component | heading, body, ctaLabel, ctaHref |
designDecisions |
Repeatable component {icon, title, body} |
Decision cards |
Strapi content type¶
Create a collection type project-page (one entry per project slug):
project-page
slug UID (linked to projects API slug)
tagline String
year String
featured Boolean
titleLine1 String
titleLine2 String
overviewHeading String
overviewBody RichText (or repeated Text blocks)
metaFields Component (repeatable): label String, value String
architectureSection Component (single): eyebrow, heading, body, bullets[], diagramType
repoTree JSON
codeSnippets Component (repeatable): tab, language, code (Long text)
secondaryRepo JSON
diagramCallout Component (single): heading, body, ctaLabel, ctaHref
designDecisions Component (repeatable): icon, title, body
Frontend changes¶
- Add
useProjectPageCMS(slug)hook — fetches fromGET /api/project-pages?filters[slug][$eq]={slug}&populate=* - Replace
projectV2Data[id]lookup inproject-page-v2.tsxwith the hook result - Keep
projectV2DataasinitialDatafallback during migration so pages render immediately from static data while the CMS fetch is in flight - Once all slugs have Strapi entries and the hook is stable, delete
projectV2Data
Migration order¶
- Wire up the Strapi collection and hook with
iac-platform-frameworkas the pilot — it has the most bespoke content and is the best test case - Verify parity between static and CMS-rendered output
- Migrate remaining slugs one at a time
- Delete
projectV2Dataentries as each slug is confirmed working
Part 2 — Migrate all projects to V2 layout¶
Current state¶
| Slug | Layout |
|---|---|
iac-platform-framework |
V2 ✅ |
genai-framework |
V2 ✅ (PR #485) |
data-platform |
V2 ✅ (PR #485) |
realtime-bi-integration |
V2 ✅ (PR #485) |
metadata-driven-ingestion |
V2 ✅ (PR #485) |
azure-batch-optimisation |
V2 ✅ (PR #485) |
healthcare-cost-analysis |
V2 ✅ (PR #485) |
frozen-potato-prediction |
V2 ✅ (PR #485) |
What each project gets for free on V2¶
Every project that has API data populated gets the following V2 sections automatically — no extra CMS content needed:
- Hero with gradient + grid texture, tech tags, optional image
- Overview section with API-sourced sidebar (Client, Category, Status, Duration, Team, Stack)
- Project Record section: Challenge, Solution, Results, Responsibilities, Lessons Learned, and Timeline cards — all from the API
Steps per project¶
- Add a minimal entry to
projectV2Data(or Strapi once Part 1 is done):
The page renders immediately with the full V2 layout using API data.
-
Add
titleLinesif the title needs a specific two-line split with the second line in pink. Otherwise the title renders as a single line. -
Add
overviewHeading+overviewBodyfor bespoke narrative copy. If omitted, the overview body falls back toproject.overviewfrom the API. -
Add bespoke CMS sections (
architectureSection,repoTree,codeSnippets,designDecisions, etc.) only where the project warrants it. These are fully optional — a project with none of them still renders a complete page. -
Verify the Project Record section renders correctly — check that
challenge,solution,results,responsibilities,lessonsLearned, andtimelineare populated inprojectDetailsfor the slug.
Suggested migration order¶
genai-framework— high-traffic, has rich API data, good candidate for a bespoke architecture section (Hub-Spoke diagram)data-platform— similar profile- Remaining projects in any order
V1 deprecation¶
Once all slugs are on V2, delete project-detail.tsx and remove its route
from App.tsx. The V2 page already handles the not-found and loading states.
Definition of done¶
- [x] Strapi
project-pagecollection type created and documented - [x]
useProjectPageCMShook implemented and tested - [x]
iac-platform-frameworkrendering from Strapi (not static data) - [x] All project slugs have a V2 entry (PR #485)
- [x]
project-detail.tsxdeleted — V1 fallback removed;ProjectRoutenow rendersProjectPageV2for all slugs when flag is on - [ ]
projectV2Datadeleted fromprojects.ts— still used asplaceholderDatafallback inuseProjectPageCMS; delete once all Strapi entries are confirmed populated - [ ] V2 pages smoke-tested in prod for all slugs