# Brentwood Migration — Internal Build Plan (team detail)

> **This is the team's working plan — assignments, critical path, and engineering detail.**
> The **executive / client-facing** version is [`10-WEEK-PLAN.md`](./10-WEEK-PLAN.md). Granular tasks live
> in [`TASK-BREAKDOWN.md`](./TASK-BREAKDOWN.md) + [`TASK-TRACKER.md`](./TASK-TRACKER.md); editor-facing
> block thinking in [`manual-thought-on-web-dev.md`](./manual-thought-on-web-dev.md).

**Status:** DRAFT — authored 2026-06-02/03 by Adi (with Claude). Not yet reviewed by Rian/client.
**Anchor:** Hard launch **August 1, 2026**. **Budget guidance:** ~450h ceiling (first draft ~300–400h).
**Authoritative scope:** `PROJECT-BRIEF.md` > `notes/Scope of Work (from proposal).md`.

---

## Date framing
Counting Monday-start weeks from this week, **Aug 1 falls in Week 9**: **9 weeks build → launch (Aug 1) →
Week 10 post-launch stabilization** (first week of the 30-day bug-fix window, through early September).

## Budget reality
Four developers at ~25h/wk for 10 weeks alone would be ~1,000h — well past the ~450h ceiling. The team
is **not** fully loaded the whole time; the plan sequences *who is active when*. Pair with the
hours-vs-budget burn-down in `TASK-TRACKER.md`.

---

## Team & lanes
| Code | Who | Primarily does |
|---|---|---|
| **AP** | Adi Pramono — lead, 11y | **~90% of the lead role.** Architecture, migration extractor, custom blocks (esp. T3 dynamic), Calendar, Livestream module, tracking/plugin work, redirect map, code review |
| **ZR** | Zeina Randa — **Adi's Assistant** | AP's deputy: planning support; **Kadence template work** (header/footer/patterns); **leads & QAs the junior page-assembly team**; Tier-B + non-bespoke Tier-C pages. Not a substitute for AP on architecture/custom blocks |
| **IJ / RQ / YM** | Indra Jaya · Rahman Qolby · Yohana Marpaung — juniors, ~1y | **One shared pool — no fixed per-person lanes.** Page assembly, content cleanup, media, QA; ZR assigns/reviews. ~20–30h/wk each, Indonesia/WFH |
| **RB** | Rian Bowden — Canada | Business & client comms, FinalSite discovery call, stakeholder reviews, asset gathering, training delivery |
| **AI** | AI-assist | Scripted extraction/transforms, redirect-map generation, schema, QA scanning, doc drafting, block scaffolding |

In the weekly plan, **J** = the junior team collectively (IJ · RQ · YM).

---

## Critical path & a key build decision

**Critical path — blocks gate everything the juniors do.** Juniors rebuild pages by *assembling blocks*,
so they can't start real page work until blocks exist. **Week 2 is a block sprint** (first week after
planning): AP + AI build the **T1 + T2** block library and the placement-behavior wrapper *before*
juniors ramp in Week 3. Any slip in block delivery pushes the whole junior workstream — so blocks are
scheduled first and protected. T3 dynamic blocks follow Weeks 3–5 and gate only the pages that use them.

**Build decision — the custom header (decide W1, build W2).** Brentwood's header is custom (deep nav /
sub-menus). Tie-breaker per design-latitude = **what's easiest for the client to maintain**:

| Option | Client maintainability | Fit to current design | Notes |
|---|---|---|---|
| **Kadence Header Builder / Elements** *(preferred)* | **High** — marketing edits in UI | Good for most; mega-menu edge cases need CSS | Keeps us out of the maintenance loop |
| **Child-theme template-part override** | Low — every change needs a dev | Exact / full control | Only where Kadence can't express it |

**Recommendation:** hybrid — Kadence header for editability, child-theme override only where Kadence
can't match. Footer same. ZR builds the Kadence side; AP the child-theme parts. Confirm with RB in W1.

---

## Build approach (decided 2026-06-03)

How we split the work between scripted import and human building:

- Courses and blog posts — and the other record-based content (staff bios, photo library, livestream
  entries) — are done by scripted DB import. They're structured database rows, so a deterministic
  extractor is faster, cheaper, and more consistent. Hand-keying 700+ blogs / 168 bios / 141 courses
  would blow the hour budget.
- Pages are built by humans (juniors). The reason is QA / human eyes: hand-building puts a person on
  every page as it's made, reviewed against the live site during construction. That catches layout drift,
  visual-parity gaps, and odd content that an automated page migration would carry through silently. QA is
  baked into the build, then Adi does final QA on top (layered: junior builds → ZR reviews → AP signs off).
  The per-page featured-image / Hero Media variance (slider / static image / YouTube / MP4) a script could
  probably handle too — but since pages are hand-built anyway, the person just sets the right hero in the
  same pass. (It also trains the team.)
- AI/Claude is tooling behind the scenes (extractor, transforms, redirect map, QA scanning) — not the
  page-builder.

Open sub-question: do juniors build pages fully from scratch, or does the extractor pre-fill the page
body (text/photos from `text_blocks`, `photos`, etc.) as a draft while humans own the hero and final
layout? The draft-then-polish path saves re-keying a lot of text; decide per page tier.

Permissions note: Adi is a developer on this server (no sudo, no direct docker, can't reach the Laravel DB
directly, owner-only paths off-limits). Bulk/elevated steps — DB access for the Week-1 counts and the
extractor, exposing the Laravel MySQL, container-level work, broad migration scripts — will exceed Adi's
permissions. For those, Adi + Claude draft a self-contained, ready-to-run request and ask Rian (owner) to
execute it, rather than working around the server's security model.

---

## 10-week plan (with assignments)

### Week 1 — Jun 1–7 · Discovery, kickoff & foundations
**🏁 Milestone:** Kickoff · FinalSite discovery call · scope + tracking approach confirmed.
- **AP:** Stand up the task tracker; spec the extractor; run the DB tiering counts + finalize the block catalog (see Pages deep-dive); define block/template architecture & dev workflow.
- **J:** Onboard to WP target + Kadence/ACF; review the site page-by-page; build the **page inventory** (each page → tier A/B/C + blocks used).
- **RB:** Co-lead FinalSite discovery call (with Tracy); confirm add-ons; gather brand assets; confirm livestream "old way" with Brentwood IT.
- **🔑 Decision:** header/footer approach (Kadence vs child-theme).
- **⚠️ Gate:** FinalSite answers unlock tracking add-on detail.

### Week 2 — Jun 8–14 · 🧱 Block sprint + template framework (critical path)
**🏁 Milestone:** Template framework preview + first blocks demoable.
- **AP:** Block sprint — **T1 + start T2** + placement-behavior wrapper; first extractor (pages → T1); child-theme header parts.
- **ZR:** Kadence header/footer + template framework (palette/typography/patterns); help shape the block catalog.
- **J:** Build UI patterns under AP/ZR; hand-rebuild 5–10 Tier-C landmark pages to validate template + blocks.
- **RB:** Provision DO staging box (security pass on creds); review framework with client.

### Week 3 — Jun 15–21 · Custom post types + migration dry-run
**🏁 Milestone:** Staging live for client; Staff/Courses/Blog structures with sample content.
- **AP:** CPTs (Staff, Courses, Livestream) + taxonomies + templates; extractor dry-run; start redirect map.
- **J:** Build the 7–8 locked core admissions/brochure pages first; QA sample content.
- **RB:** Client checkpoint on staging.

### Week 4 — Jun 22–28 · Full content migration + custom features start
**🏁 Milestone:** First complete content draft — all pages, 700+ blogs, 168 bios, 141 courses, photos.
- **AP:** Full extractor run; start Calendar + Video Hero; baseline GA4/GTM/Meta Pixel.
- **J:** Content cleanup pass begins — verify URLs, tag→section, alt/captions.
- **RB:** Progress report; schedule editor training.

### Week 5 — Jun 29–Jul 5 · Custom features + cleanup
**🏁 Milestone:** Calendar + Livestream demo; core pages reviewed for visual parity.
- **AP:** Finish Calendar; Livestream CPT + List block + migrate entries; footer images (ACF); Google Login.
- **J:** Cleanup on high-traffic pages; campaign landing-page template; responsive checks.
- **RB:** Stakeholder review of core pages (Erin/Tracy).

### Week 6 — Jul 6–12 · Tracking, SEO, performance
**🏁 Milestone:** Tracking live on staging; campaign FinalSite forms demo; structural SEO pass.
- **AP:** Campaign forms + thank-you + conversion events; BW Lead AI journey tracking; Looker Studio; SEO (schema/sitemap/OG/site search); image-opt profiles; caching + CDN; backups.
- **J:** Finish cleanup; heading/SEO checks; populate redirect map; QA.
- **RB:** Review tracking with Brentwood; confirm Looker Studio access.

### Week 7 — Jul 13–19 · Feature complete + full QA pass
**🏁 Milestone:** Feature-complete staging; big stakeholder review round.
- **AP:** Finalize features; redirect map verified; fix QA findings.
- **J:** Full QA — cross-browser, responsive, links, forms, redirects → punch list.
- **RB:** Schedule training; collect review feedback.

### Week 8 — Jul 20–26 · Feedback, polish, pre-launch QA
**🏁 Milestone:** Sign-off candidate; editor training delivered (recorded); admin docs draft.
- **AP:** Burn down punch list; tracking validation; backups verified restorable.
- **J:** Page polish; final content QA; training-prep support.
- **RB:** Deliver 2-hr editor training + photojournalism blog video; gather sign-off.

### Week 9 — Jul 27–Aug 2 · 🚀 Launch (Aug 1)
**🏁 Milestone:** LAUNCH — Aug 1. Production cutover on DigitalOcean.
- **AP:** Pre-launch checklist; DNS cutover; smoke test; monitor.
- **J:** Launch-day QA sweep; verify redirects + forms on live.
- **RB:** Go/no-go sign-off; client launch comms.

### Week 10 — Aug 3–9 · Post-launch stabilization
**🏁 Milestone:** Stable live site; weekly bug-fix reporting; living admin docs final.
- **AP:** Monitor analytics/errors; fix launch issues; finalize docs.
- **J:** Monitor + fix real-traffic content issues.
- **RB:** Client check-in; begin 30-day bug-fix window + ongoing-support discussion.

---

## Deep-dive: Pages migration (the part that needs breaking down)

"~200 pages → Gutenberg/ACF" understates the work. A page is **not a document** — it's a **hierarchy
node** (parent/child, nested slug, breadcrumbs, sub-menu, sort order, view permissions) **+ an ordered
stack of polymorphic content-elements**, each rendered via `view('content-elements.{type}')` with its own
per-placement behavior. So Pages splits into **three work-streams estimated separately**:

### A. Block library — build once, reuse on every page  *(AP-led + AI)*
~18 content-element types → Gutenberg/ACF blocks, tiered by effort (blade + model inspected):

| Tier | Element types | WP target | Effort |
|---|---|---|---|
| **T1 — Static** | text-block, quote, titles/heading, photo, embed-code, youtube-video, embed-video, timetable\* | Core blocks / simple ACF / raw-HTML wrapper. *\*timetable descoped to static image/PDF.* | **Low** |
| **T2 — Composite** | photo-block (+ `-text`), slideshow, inquiry-form, course-description, social-media-feed | Custom block: layout + fields; slideshow carousel JS; inquiry-form = FinalSite embed *(constrained)* | **Medium** |
| **T3 — Dynamic** | content-filter, course-list, staff-profile-list, livestream-list, publication-list, calendar | Custom block + WP query against CPTs/taxonomies **+ front-end filtering JS**. **Vue today → rebuilt, not restyled** | **High** |

**Cross-cutting placement behaviors** (pivot flags, *not* blocks): `expandable` (inline + modal), tag
`filter`, `randomize`, `no_margin`, `hide_print`, `guest`-only, `unlisted`/anchor. One shared
wrapper-pattern + small JS reused across blocks. Budget explicit time.

### B. Migration extractor — scripted, re-runnable  *(AP + AI)*
Per page: walk `content_elements` in pivot `sort_order`, **published version only**, map `content_type` →
block, emit block markup / ACF payload; carry pivot settings → block attributes, tags, photos
(alt/caption), internal links (replicate `PageLink`). Preserve hierarchy (`parent_page_id` → WP
parent/child + slug); build the **301 redirect map** from `PageSlug`/`PageRedirect`. Re-runnable.

### C. Page assembly & cleanup — apply many  *(juniors, ZR lead)*
**Good news:** bespoke per-page view overrides are *few* — only `hub`, `parents`, the `live/*` set, and
system pages. Majority are generic content-element stacks → bulk-migratable. Tier pages:

| Tier | What | Who | Approach |
|---|---|---|---|
| **A — Simple** | Mostly text / photo / quote stacks | Juniors (bulk) | Extractor output + light cleanup |
| **B — Composite** | Mixed blocks, slideshows, embeds | Juniors + AP spot-check | Migrate + moderate cleanup; parity check |
| **C — Landmark/bespoke** | Home, admissions hub, athletics, arts, /live, /giving, calendar, `hub`/`parents` | AP + strongest junior | Hand-built / heavy cleanup |

### Lock the tiering in Week 1 (exact counts)
MySQL isn't exposed to the host, so live counts couldn't be pulled. **Week-1 task (AP):** run against the
mirror to turn tiers into real numbers + per-tier hour estimates:

```sql
SELECT content_type, COUNT(*) FROM content_elements GROUP BY content_type ORDER BY 2 DESC;
SELECT contentable_id, COUNT(*) els FROM contentables
  WHERE contentable_type='App\\Models\\Page' GROUP BY 1 ORDER BY 2 DESC;
SELECT SUM(expandable IS NOT NULL) expandable, SUM(filter) filterable, SUM(randomize) randomize FROM contentables;
SELECT COUNT(*) FROM page_slugs;  SELECT COUNT(*) FROM page_redirects;
```
*(Confirm table/column names against `database/migrations`.)*

### Pages track across the 10 weeks ("block library first")
- **W1:** tiering counts + block catalog; juniors build page inventory.
- **W2:** Extractor v1 (T1 blocks); build T1 + start T2; juniors validate via 5–10 Tier-C pages.
- **W3:** Finish T2; CPTs ready → T3 list blocks begin; extractor dry-run; juniors start Tier-A.
- **W4:** Full extractor run; T3 underway; juniors Tier-A cleanup + behavior testing.
- **W5:** Finish T3 + calendar; placement-behavior wrapper done; juniors Tier-B.
- **W6:** Tier-C bespoke pages; redirect map wired + verified.
- **W7:** Full page QA — parity, links, redirects, responsive.

---

## Open follow-ups
- [ ] Rian/client review of the plan + Week-9 launch framing.
- [ ] Build the hours-vs-budget burn model (450h ceiling) — in `TASK-TRACKER.md`.
- [ ] Run the Week-1 DB tiering counts.
- [ ] **Ask Rian (before Week-2 block sprint):** consolidate Video + Interlink layout variations to a few standard layouts?
- [ ] **Ask Rian:** drop the lightbox "+" zoom icon → plain Kadence Row (saves a custom block)?
- [ ] **Ask Rian:** dark mode anywhere (only on `/arts/arts-gallery`)? Recommend skip.

## Editor-facing block plan
See [`manual-thought-on-web-dev.md`](./manual-thought-on-web-dev.md) for the consolidated ~6–8 custom
blocks (with layout options) derived from the page-by-page survey in `tmp/Block planning @brentwood.pdf`.
