Skip to content

Project Page V2 — Migration Plan

Status: PARTIALLY COMPLETE

  • All 8 project slugs have v2: true in projectV2Data ✅ (PR #485)
  • useProjectPageCMS hook implemented ✅ (fetches from Strapi project-page collection)
  • Strapi project-page collection seeded for iac-platform-framework; remaining slugs use static projectV2Data fallback
  • project-detail.tsx still exists as V1 fallback — not yet deleted
  • projectV2Data still in projects.ts — kept as initialData fallback; delete once all Strapi entries confirmed

Remaining work: Populate Strapi project-page entries for remaining 7 slugs, then delete projectV2Data and project-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

  1. Add useProjectPageCMS(slug) hook — fetches from GET /api/project-pages?filters[slug][$eq]={slug}&populate=*
  2. Replace projectV2Data[id] lookup in project-page-v2.tsx with the hook result
  3. Keep projectV2Data as initialData fallback during migration so pages render immediately from static data while the CMS fetch is in flight
  4. Once all slugs have Strapi entries and the hook is stable, delete projectV2Data

Migration order

  1. Wire up the Strapi collection and hook with iac-platform-framework as the pilot — it has the most bespoke content and is the best test case
  2. Verify parity between static and CMS-rendered output
  3. Migrate remaining slugs one at a time
  4. Delete projectV2Data entries 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

  1. Add a minimal entry to projectV2Data (or Strapi once Part 1 is done):
"my-slug": {
  v2: true,
  tagline: "...",
  year: "2024",
  featured: false,
}

The page renders immediately with the full V2 layout using API data.

  1. Add titleLines if the title needs a specific two-line split with the second line in pink. Otherwise the title renders as a single line.

  2. Add overviewHeading + overviewBody for bespoke narrative copy. If omitted, the overview body falls back to project.overview from the API.

  3. 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.

  4. Verify the Project Record section renders correctly — check that challenge, solution, results, responsibilities, lessonsLearned, and timeline are populated in projectDetails for the slug.

Suggested migration order

  1. genai-framework — high-traffic, has rich API data, good candidate for a bespoke architecture section (Hub-Spoke diagram)
  2. data-platform — similar profile
  3. 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-page collection type created and documented
  • [x] useProjectPageCMS hook implemented and tested
  • [x] iac-platform-framework rendering from Strapi (not static data)
  • [x] All project slugs have a V2 entry (PR #485)
  • [x] project-detail.tsx deleted — V1 fallback removed; ProjectRoute now renders ProjectPageV2 for all slugs when flag is on
  • [ ] projectV2Data deleted from projects.ts — still used as placeholderData fallback in useProjectPageCMS; delete once all Strapi entries are confirmed populated
  • [ ] V2 pages smoke-tested in prod for all slugs