Development Pipeline
What is built, what is next, what is deferred. MAJ items are multi-day phases, MED items are single-feature builds, SML items are sub-day tweaks. Last updated 2026-05-09 (Phase 6a).
Major (multi-day, architectural, or cross-cutting)
| # | Item | Status | Target | Notes |
|---|---|---|---|---|
| MAJ-001 | Phase 2 — Frontend shell (all 9 routes from design handoff) | Done 2026-05-04 | May 2026 | All 9 user-facing routes shipped. Today, Tasks, BC, TQC, TCE, Personal Finance, Personal & Health, Lists, Brand demo. Brand primitives complete. Mobile breakpoint via Tailwind responsive utilities. |
| MAJ-002 | Phase 3 — Data layer (Supabase CRUD, cross-org API routes) | Planned | May-Jun 2026 | Run migrations, connect Personal Supabase, wire BC/SM proxies. |
| MAJ-003 | Phase 4 — Integrations (M365 SSO, Basiq, HubSpot x5, LMS) | Planned | Jun-Jul 2026 | Requires Integration Spec (see MED-003). Blocked until Phase 3 stable. |
| MAJ-004 | Phase 5 — Polish (notifications, Cmd+K search, performance) | Planned | Jul 2026 | Today page live data, tag release. |
Medium (1-3 days, single feature or screen)
| # | Item | Status | Target | Notes |
|---|---|---|---|---|
| MED-001 | Today page — full build from design handoff | Done 2026-05-04 | Hero, calendar strip, cash tiles, priority list, waiting-on, changed feed, 7-day events. All 5 brand primitives + LogoMark/Quadrant/Spark. Demo at /brand-demo. Mobile responsive via Tailwind (collapse below lg). | |
| MED-002 | Tasks/Covey page — full build from design handoff | Done 2026-05-04 | Quadrant/Delegation tab toggle, entity filter, 2x2 quadrant grid with reg-marks + italic 0N numbers, OwnerChip primitive (agent vs human), DelegationTable. | |
| MED-003 | Integration Spec document (pre-Phase 4) | Planned | Bank account mapping, HubSpot dashboard specs (x5), LMS auth coordination, Vanguard investigation, Entra ID MFA config. | |
| MED-004 | Bright Connect entity tab — full build | Done 2026-05-04 | Hero with LogoMark + balance, bank balance/projection chart with period toggle, OKRs with progress bars, HubSpot revenue-by-rep + pipeline-by-stage HBars, 30-day events. Spark gained responsive prop. HBar + Progress primitives added. | |
| MED-005 | TQC entity tab | Done 2026-05-04 | Same shape as BC: chart, OKRs, lead flow, LMS placeholder pending Steven Miles, 30-day events. | |
| MED-006 | TCE entity tab | Done 2026-05-04 | Same shape as BC: chart, OKRs, sales manager (3 reps), install lead flow, 30-day events. Runway flagged red. | |
| MED-007 | Personal Finance tab | Done 2026-05-04 | Net wealth hero, chart with period toggle, OKRs, bank accounts list, investments list, 60-day finance calendar. | |
| MED-008 | Personal & Health tab | Done 2026-05-04 | Health upcoming, household tasks, 60-day personal events. | |
| MED-009 | Lists tab | Done 2026-05-04 | Books / Films / Restaurants 3-column layout with NOW/NEXT/DONE status. | |
| MED-010 | Cmd+K command palette (Phase 5 polish, brought forward) | Done 2026-05-05 | Global ⌘K/Ctrl+K palette, fuzzy search across 100 items, brand-styled dialog, navigates to result route. Polish backlog: improve ranking so direct entity matches outrank task-text matches (cmdk default scoring favours where in the value string the match lands; entity rows could lead with their own keywords). | |
| MED-011 | Vitest scaffolding + lib/fmt.ts test coverage | Done 2026-05-05 | Vitest 4 + jsdom installed, npm test exposed. 33 assertions covering all 11 formatters; caught a real bug in fmtDateLong on first run. Pattern logged in DECISIONS D16. Future-friendly: lib/**/*.test.ts and components/**/*.test.{ts,tsx} already in the include glob. | |
| MED-012 | Extract shared entity-tab components (BC/TQC/TCE/PF refactor) | Done 2026-05-06 | components/entity/ now hosts EntityHero, ProjectionChartCard, OkrsCard, EventsCard. The 4 entity pages drop from ~290 LOC each to ~120 LOC. Client bundle ~50% smaller (3.5 kB → 1.8 kB) — pages are now server components, only ProjectionChartCard is 'use client'. Visual parity verified vs pre-refactor screenshots. Future entity tabs (Solar Market split, Source Energy) inherit the shape. | |
| MED-013 | Pixel-precise mobile pass for /today (port of A_TodayMobile) | Done 2026-05-06 | Forest-deep hero, scrollable cash row with fmtAUDCompact, compact calendar / priority / waiting lists with truncation footer ("+ N more →"). Mobile + desktop trees both server-rendered, swapped via Tailwind lg:hidden / hidden lg:flex. Other routes still rely on the responsive-grid collapse from the original pass — bespoke mobile design is /today-only for now. | |
| MED-014 | Component test coverage for entity shells + search index | Done 2026-05-06 | @testing-library/react adopted (D17 refines D16). 40 new assertions across 5 files: search index (15) + EntityHero (5) + ProjectionChartCard (8) + OkrsCard (6) + EventsCard (6). Suite total now 77/77 in <2 s. Locks in period-toggle state, split-colour caption handling, search index shape, route assignments. | |
| MED-015 | Accessibility hardening (WCAG AA + Lighthouse target) | Done 2026-05-06 | 69 axe violations → zero on 8 user-facing routes. ARIA roles + labels + landmarks + skip-link. Brand co-designed with a11y per D18: small-caption copper → copper-2, fg-4 → fg-3, sidebar monograms → plain squares, LogoMark bold by default. 3 new GOTCHAS. | |
| MED-016 | Pre-commit + pre-push hooks (husky + lint-staged) | Done 2026-05-09 | pre-commit runs lint-staged (eslint --fix --max-warnings=0 on staged TS/TSX); pre-push runs npm run typecheck && npm test. ESLint 9 flat config (eslint.config.mjs) consuming next/core-web-vitals + next/typescript. Baseline sweep cleared 2 errors + 3 warnings. .gitkeep cleanup in dirs that now hold real components. Pattern logged in D19. Future autonomous chunks can't land lint warnings, type errors, or red tests in main. | |
| MED-017 | Projects tab — /projects list + /projects/[slug] detail | Done 2026-05-10 | Phase 6a (2026-05-09): card grid + detail page rendering live markdown from the dashboard's own docs/ folder via a server-side mock-data layer; sidebar nav wired. Phase 6b (2026-05-10): lib/projects/fetch.ts switched to Supabase queries against ref jxbxqjpzcuovnmsmkhjq, gated behind NEXT_PUBLIC_USE_MOCK_PROJECTS for offline dev; 002_projects.sql migration applied with anon SELECT RLS + commit_etag column; sync-project-docs Edge Function deployed, runs on pg_cron every 15 min, first-run upserted 9 docs in ~5s. Full spec at the bottom of this file. |
Small (< 1 day, single task or tweak)
| # | Item | Status | Target | Notes |
|---|---|---|---|---|
| SML-001 | Generate deploy SSH key + add GitHub secrets | Done 2026-05-23 | DROPLET_HOST + DROPLET_SSH_KEY added to repo secrets; auto-deploy workflow re-enabled on push to main (commit 72ffe78). | |
| SML-002 | Run setup-droplet.sh on droplet | Done 2026-05-23 | Systemd service, .env.local, and cron job in place on the droplet. | |
| SML-003 | First deploy — verify blank app loads at dashboard.finchmax.com | Done 2026-05-23 | Deploy workflow runs on every push to main and SSHes into the droplet to git pull && npm ci && npm run build && systemctl restart aj-dashboard. | |
| SML-004 | Run Supabase migrations (3 orgs) | Planned | Personal, BC, SM — SQL files ready in supabase/ | |
| SML-005 | Configure Supabase Auth (M365 SSO provider) | Planned | Personal org only — aj@finchmax.com allowlist | |
| SML-006 | Coordinate Steven Miles on LMS token auth (~20 lines PHP) | Planned | Dependency for LMS iframe in TQC tab | |
| SML-007 | Inline edit for project names on /projects cards | Done 2026-05-22 | Hover-revealed pencil swaps the Newsreader name into an input; Enter saves, Escape cancels; blur cancels. Optimistic UI with rollback on server error. New server action app/projects/actions.ts#updateProjectName + new supabasePersonalAdmin service-role client in lib/supabase/server.ts (anon RLS is SELECT-only). Auth gate validates Supabase session cookie when present (only aj@finchmax.com); allows local dev with no session until SSO lands. New env var SUPABASE_PERSONAL_SERVICE_ROLE_KEY. |
Bugs
| # | Item | Severity | Status | Notes |
|---|---|---|---|---|
| — | No known bugs | — | — | — |
Completed Archive
- MAJ-001 — Phase 2 Frontend shell (closed 2026-05-04): All 9 user-facing routes built end-to-end against
design/handoff/option-a.jsx. Stack: Next.js 15 App Router, Tailwind, next/font wired to--ar-font-*tokens. 12 brand primitives (ExtensaMark, Card+Header+Body, EntityBadge soft/solid/dot, StatusDot, Eyebrow, RegMarks, LogoMark, Quadrant, Spark withresponsivemode, HBar, Progress, OwnerChip), 2 layout primitives (Sidebar withusePathnameactive-route detection, MetaStrip). All routes compile to 102 kB shared First Load JS + 3-3.7 kB per client page..claude/settings.jsonallowlists routine ops for autonomous work. - MED-001 — Today page (closed 2026-05-04): Full Direction A build at
/today. Sidebar, meta strip, hero, calendar strip with NOW indicator, priority tasks, cash tiles 2×2, waiting-on, since-yesterday feed, 7-day events. Brand primitive demo at/brand-demo. Mobile responsive. - MED-002 — Tasks/Covey page (closed 2026-05-04): Full Direction A build at
/tasks. Quadrant/Delegation tab toggle, entity colour filter (multi-select), 2x2 quadrant grid with quadrant-coloured reg-marks and italic Newsreader 0N numbers. Task cards with entity-coloured left border, OwnerChip showing agent (italic copper "a") vs human (sand initial). DelegationTable for the second view. - MED-004 — Bright Connect entity tab (closed 2026-05-04): Full Direction A build at
/bright-connect. Hero with BC LogoMark + heading + balance + delta. Bank balance/projection chart (forest line + copper area + dashed copper projection) with 7D/1M/3M/6M/12M period toggle. OKRs with italic copper numbers and KR progress bars. HubSpot revenue-by-rep HBars (copper-tipped leader). HubSpot pipeline-by-stage HBars (copper Closed Won). 30-day events 4-column grid with italic Newsreader date numbers. - MED-005 — TQC entity tab (closed 2026-05-04): Same shape as BC at
/tqc. Hero "The Quote Company + LMS" (LMS in copper italic). Declining-trend chart projecting to $69k. OKRs (cashflow, conversion, referral). HubSpot lead flow 5 stages. LMS-iframe placeholder card pending Steven Miles' PHP token-validation hook. - MED-006 — TCE entity tab (closed 2026-05-04): Same shape as BC at
/tce. Hero "Take Charge Energy" (Energy in copper italic). Recovery-trend chart projecting to $85k. OKRs (Karratha backlog, install margin, WA fleet). HubSpot sales manager (3 reps with copper-tipped leader). HubSpot install lead flow. Runway pill in red (19 days). - MED-007 — Personal Finance (closed 2026-05-04): At
/personal-finance. Net wealth $959,090 = cash $160,390 + investments $798,700. Net wealth chart with period toggle. Personal OKRs (super cap, emergency fund). Bank accounts list (Westpac/Macquarie/ANZ Amex). Investments list (Vanguard Family Trust + SMSF) with 30D deltas. 60-day finance calendar. - MED-008 — Personal & Health (closed 2026-05-04): At
/personal-life. Hero "Off-the-clock, still tracked". Upcoming health appointments. Household task list with done items struck through. 60-day personal events. - MED-009 — Lists (closed 2026-05-04): At
/lists. Books / Films / Restaurants 3-column with NOW/NEXT/DONE status pills. - MED-010 — Cmd+K command palette (closed 2026-05-05): Global ⌘K/Ctrl+K palette mounted in root layout; backed by
cmdkfor fuzzy filtering.lib/search.tsflattens 100 items across tasks (priorities + COVEY q1-q4), meetings, entities, contacts, waiting-on, since-yesterday, events (7-day + entity-specific), and lists. Dialog styled in brand language: forest-deep header, copper-rail focus, Newsreader input, Plex Mono captions, registration marks. Esc / backdrop close. - MED-011 — Test scaffolding (Vitest) (closed 2026-05-05): Vitest 4 + jsdom installed,
vitest.config.tsaliases@to repo root,npm test/test:watch/typecheckscripts exposed. 33 assertions inlib/__tests__/fmt.test.tscovering every formatter; caught a real bug infmtDateLongon first run (missing canonical comma due to Node's en-AU ICU behavior — helper rewritten to compose manually). Decision logged in D16. - MED-012 — Entity-tab shared components (closed 2026-05-06): Extracted
EntityHero/ProjectionChartCard/OkrsCard/EventsCardintocomponents/entity/. Refactored BC, TQC, TCE, PF to compose them. Pages dropped from ~290 LOC avg to ~120 LOC avg; client JS dropped from 3.46-3.79 kB to 1.82 kB on each page because they're now server components (onlyProjectionChartCardis'use client'for its period-toggle state). Visual parity verified against pre-refactor screenshots. Net change: 1171 → 809 lines across the 4 pages + shared components. - MED-013 — Pixel-precise mobile pass for
/today(closed 2026-05-06): Six new components incomponents/today/mobile/portA_TodayMobilefrom the design handoff. Forest-deep hero with greeting + Extensa wordmark + lede; paper meta strip; horizontal-scrolling cash row usingfmtAUDCompact(≥$100k → "$Xk", smaller stays full); compact 4-meeting calendar with "+N more →"; trimmed priority and waiting-on lists. Mobile + desktop trees both server-rendered, swapped via Tailwindlg:hidden/hidden lg:flex. Also fixedfmtKnegative-handling, surfaced by the new test. - MED-014 — Component test coverage (closed 2026-05-06): Adopted
@testing-library/reactand@testing-library/jest-dom(D17, refining D16). 40 new assertions across the search index builder and the 4 entity-shell components. Brings suite total to 77 across 6 files; all green; <2 s wall time. Locks in period-toggle state, split-colour caption handling, search index shape and route assignments — exactly the behaviours that would silently regress on the next refactor without tests. - MED-015 — Accessibility hardening (closed 2026-05-06): Took the codebase from 69 axe-core WCAG AA violations to zero on all 8 user-facing routes. Skip-link,
<main>id,role="tab"+aria-selected,aria-labelledbypalette,aria-labelChase buttons + CashTile,role="img"NOW indicator. Brand-and-a11y co-design (D18) — small captions step from copper to copper-2 and fg-4 to fg-3, sidebar monogram letters dropped, LogoMark bold by default to qualify for WCAG "large text" 3:1. - MED-017 — Projects tab (closed 2026-05-10): Two-phase build. Phase 6a (2026-05-09) shipped
/projects+/projects/[slug]against anode:fsmock-data layer that reads the dashboard's owndocs/folder so the renderer was exercised on real markdown from day one. Newlib/projects/module (types.ts,parse-leading-paragraph.ts,parse-index.ts,mock-data.ts,fetch.ts), newcomponents/projects/(card, grid, detail header, doc rail, doc renderer with brand-token component overrides, entity badge, status badge), two newlib/fmt.tshelpers (fmtTimestamp,fmtRelativeTime). Phase 6b (2026-05-10) flipped the data layer to live Supabase. Migration002_projects.sqlapplied to refjxbxqjpzcuovnmsmkhjqwith two amendments to the drafted file — anon SELECT RLS policies and acommit_etagcolumn for the GitHub conditional-request fast-path. Edge Functionsync-project-docs(status filter:active-only) deployed withverify_jwt: true, scheduled viapg_cronevery 15 min; first-run upserted 9 docs in ~5s.lib/projects/fetch.tsswapped to Supabase queries gated behindNEXT_PUBLIC_USE_MOCK_PROJECTS=truefor offline dev;/projectsroutes flaggedforce-dynamicso doc edits surface on the next request after a sync. New.env.example(placeholder values) documents the flag. Latency probe (proxy via forced row-resync — couldn't push to main from droplet because the deploy_key is read-only): 4.95s function round-trip + 0.47s page render = ~5.4s total surfacing on manual invoke; cron-driven worst case is 15 m + 5 s. - MED-016 — Pre-commit + pre-push hooks (closed 2026-05-09): husky + lint-staged wired (D19).
pre-commit→npx lint-staged(eslint --fix --max-warnings=0on staged TS/TSX);pre-push→npm run typecheck && npm test. Createdeslint.config.mjs(flat config, ESLint 9 / Next 15) consumingnext/core-web-vitals+next/typescriptviaFlatCompat; tightenedno-unused-vars(_-prefix allowed); ignoreddesign/handoff/**.package.jsonlintswitched from deprecatednext linttoeslint .. Baseline sweep cleared 2 errors + 3 warnings (typedunknownnarrowing in tce-revenue route; unescaped apostrophe; two unused imports; named the eslint config default export). Cleanup: removed redundant.gitkeepfiles incomponents/{brand,layout,tasks,today}/(those dirs hold real components now). Suite still 77/77; typecheck clean.
MED-017 — Projects Tab
A new top-level section of the dashboard that surfaces the state of every software project AJ is working on, sourced live from each project's GitHub repo. The dashboard project itself is the first project indexed.
Acceptance criteria
- New sidebar item "Projects" after "Lists" in the sidebar nav
/projectsroute shows a card grid of all registered projects/projects/[slug]route shows project detail: doc index on the left rail, rendered markdown on the right, last-synced timestamp, "Open in GitHub" link- All content sourced from the
docs/folder of each registered project's GitHub repo - Phase 6a: ships against mock data (Supabase migration drafted but not run)
- Phase 6b: real data via Supabase + Edge Function sync (runs after droplet is configured and Supabase migrations are run)
- Brand-compliant: forest/copper, sharp corners, Newsreader for display, Inter for body, Plex Mono for timestamps. No emoji, no exclamation marks.
Pre-flight (Claude Code: do this first)
Before writing any code, verify these against the actual repo:
- Confirm
lib/mock-data.tsexists and check the existing pattern for typed mock data - Confirm
lib/fmt.tsexists and check existing format helpers (will needfmtRelativeTimeandfmtTimestamp— the repo'sfmt*prefix convention) - Confirm the route layout: the repo uses flat routes (
app/today/,app/tasks/, etc.) — noapp/(routes)/group — so projects routes live atapp/projects/page.tsxandapp/projects/[slug]/page.tsx - Check
components/structure — confirm where shared shadcn-wrapped primitives live vs page-specific components - Check sidebar component to identify the file where nav items are declared
- Check
package.jsonfor existing markdown dependencies — likely none yet - Confirm Tailwind config token names match
--ar-*/--ent-*CSS variable names exactly
If any assumption below conflicts with the live repo, follow the repo's pattern, not this spec. Note the deviation in the final report.
Data model
Lives in the Personal Supabase org (cross-entity, not tied to a single business).
-- supabase/personal/002_projects.sql
create type project_status as enum (
'active',
'paused',
'archived',
'planning'
);
create type project_entity as enum (
'personal',
'bc',
'sm',
'tqc',
'tce',
'cross-entity'
);
create table projects (
id uuid primary key default gen_random_uuid(),
slug text unique not null,
name text not null,
description text,
status project_status not null default 'active',
entity project_entity not null default 'personal',
primary_repo text not null,
additional_repos text[] default '{}',
default_branch text not null default 'main',
docs_path text not null default 'docs',
deploy_url text,
deploy_status text,
tech_stack text[] default '{}',
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
create table project_doc_snapshots (
id uuid primary key default gen_random_uuid(),
project_id uuid not null references projects(id) on delete cascade,
path text not null,
filename text not null,
content text not null,
leading_paragraph text,
last_commit_sha text not null,
last_commit_at timestamptz not null,
last_commit_message text,
fetched_at timestamptz not null default now(),
unique (project_id, path)
);
create index project_doc_snapshots_project_id_idx
on project_doc_snapshots (project_id);
create index projects_status_idx
on projects (status);
create or replace function set_updated_at()
returns trigger language plpgsql as $$
begin
new.updated_at = now();
return new;
end $$;
create trigger projects_set_updated_at
before update on projects
for each row execute function set_updated_at();
Seed row (run after migration)
Lives at supabase/personal/002_projects_seed.sql — flat layout matches the existing 001_core_tables.sql pattern, no migrations/ subfolder.
-- supabase/personal/002_projects_seed.sql
insert into projects (
slug, name, description, status, entity,
primary_repo, default_branch, docs_path,
deploy_url, tech_stack
) values (
'aj-dashboard',
'AJ Dashboard',
'Personal productivity dashboard across Bright Connect, Solar Market, Take Charge Energy, and personal life.',
'active',
'personal',
'aj-225/aj-dashboard',
'main',
'docs',
'https://dashboard.finchmax.com',
array['Next.js 15','TypeScript','Tailwind','shadcn/ui','Supabase','Recharts']
);
Routes
app/projects/
page.tsx List view: card grid
loading.tsx Skeleton
[slug]/
page.tsx Detail view: doc index + rendered markdown
loading.tsx Skeleton
not-found.tsx
Components
All under components/projects/ unless noted:
project-card.tsx— card primitive: name, entity badge, status badge, deploy URL, leading paragraph, last commit relative timeproject-grid.tsx— wraps card list, handles empty stateproject-detail-header.tsx— name, entity, status, deploy URL, "Open in GitHub" button, last synced timestampproject-doc-rail.tsx— left rail listing docs from INDEX.md, with active-doc highlightproject-doc-renderer.tsx— right pane, renders selected markdown viareact-markdownproject-entity-badge.tsx— thin wrapper around the existing brandEntityBadge(components/brand/entity-badge.tsx) that adds the project-onlypersonalandcross-entitykinds. The repo has nocomponents/shared/; the brand-level badge already lives undercomponents/brand/.status-badge.tsx— reusable project-status indicator. Namedstatus-badge(notstatus-pill) because the brand bans capsule pills (BRAND.mdrule 6,AGENTS.mdban list); the component renders with the standard 2px corner radius.
Lib helpers
lib/
projects/
types.ts Project, ProjectDocSnapshot, ProjectDocIndex types
fetch.ts getProjects(), getProjectBySlug(), getProjectDocs()
parse-index.ts parseDocsIndex(content): returns ordered list of {path, label}
parse-leading-paragraph.ts extractLeadingParagraph(content): returns first paragraph after H1, max 250 chars
mock-data.ts Mock projects + doc snapshots for Phase 6a
fetch.ts reads from Supabase in production. In Phase 6a it returns mock data. The component imports the same function name in both phases — only the implementation switches.
Markdown rendering
Add dependencies:
npm install react-markdown remark-gfm rehype-raw rehype-sanitize
project-doc-renderer.tsx config:
remark-gfm— tables, task lists, strikethroughrehype-sanitize— XSS protection (docs come from external repos eventually)- Custom component overrides for
h1-h6,code,pre,a,table— all styled with brand tokens, no inline styles
Code blocks use Plex Mono. H1 uses Newsreader 300. Body uses Inter. No drop shadows, 2px radius on the code block surface.
Sync job (Phase 6b — defer until droplet + Supabase are live)
Supabase Edge Function sync-project-docs, scheduled via pg_cron every 15 minutes.
supabase/personal/functions/sync-project-docs/
index.ts Main handler
github.ts Thin wrapper around GitHub Contents API
parser.ts Re-uses logic from lib/projects/parse-leading-paragraph.ts
Algorithm:
for each project where status = 'active':
call GitHub API: list contents of {project.docs_path} on {project.default_branch}
for each .md file returned:
get file's latest commit SHA via /repos/{repo}/commits?path={path}&per_page=1
if SHA matches existing snapshot's last_commit_sha:
skip
else:
fetch file content
extract leading paragraph
upsert into project_doc_snapshots
delete snapshots where path no longer exists in the repo
Secrets needed:
GITHUB_PAT— fine-grained PAT with read access to all repos that will be registered as projects (start with just aj-dashboard)
Set via:
supabase secrets set GITHUB_PAT=ghp_xxx --project-ref <personal-project-ref>
Schedule:
select cron.schedule(
'sync-project-docs',
'*/15 * * * *',
$$ select net.http_post(
url := 'https://<project-ref>.supabase.co/functions/v1/sync-project-docs',
headers := jsonb_build_object('Authorization', 'Bearer ' || current_setting('app.cron_secret'))
); $$
);
Mock data shape (Phase 6a)
lib/projects/mock-data.ts — return one project (the dashboard itself) with mock snapshots for STATUS.md, PIPELINE.md, DECISIONS.md, ARCHITECTURE.md, GOTCHAS.md, BRAND.md, CHANGELOG.md, INDEX.md. Use the actual current content of those files as fixtures so the renderer is exercised on real markdown.
Order of work
Phase 6a (build against mock data, no droplet/Supabase needed):
- Add deps:
pnpm add react-markdown remark-gfm rehype-raw rehype-sanitize - Write
lib/projects/types.ts,parse-leading-paragraph.ts,parse-index.ts - Write
lib/projects/mock-data.tsandfetch.ts(mock implementation) - Write
components/projects/* - Write
app/projects/page.tsxandapp/projects/[slug]/page.tsx - Add "Projects" to sidebar nav
- Visual review: confirm cards, detail page, markdown rendering all match brand
- Write
supabase/personal/migrations/00X_projects.sqland the seed SQL — do not run yet - Update
docs/STATUS.mdanddocs/CHANGELOG.mdto record Phase 6a complete
Phase 6b (real data — defer until droplet is live):
- Run the migration in the Personal Supabase org
- Run the seed insert
- Write the Edge Function
sync-project-docs - Set the
GITHUB_PATsecret - Deploy the function
- Schedule via
pg_cron - Switch
lib/projects/fetch.tsfrom mock to Supabase - Manual trigger to populate, then verify dashboard shows live data
Open questions for AJ
- Should the Projects tab show archived projects by default, or hide them behind a filter? (Default: hide.)
- Multiple repos per project — needed now or later? (Spec includes the column. UI ignores it for v1.)
- Public read-only mode for sharing project status with collaborators (Charly, Steven)? (Out of scope for v1.)