Skip to content

06 — Phase 1 Prototype

Status: shipped 2026-04-30. Live preview at genesis-admin.adventive.dev (deploys as adv-ui-admin-dev Worker with Static Assets).

Phase 1 ships a visually functional UI prototype before the API is built. The goals are pragmatic, not architectural:

  1. Validate the brand language and information architecture with the operator team before Phase 2 commits to a backend contract.
  2. Prove the chosen stack (Vite + React + TS + Tailwind + shadcn primitives + TanStack Router/Query) works end-to-end at Cloudflare Worker scale.
  3. Surface the surfaces — give Phase 2 a concrete UI shape to reverse-engineer the API contract from, instead of speccing endpoints in the abstract.
  4. Establish brand tokens, component primitives, and the layout shell that production will inherit verbatim.

The prototype is not a throwaway. It IS the v1 of adventive-admin-ui. Phase 2 swaps the data layer (src/lib/mock/* → TanStack Query hooks against adventive-admin-api) and adds Cloudflare Access; everything else carries forward.

15 routes, all rendering against in-memory mock fixtures:

Dashboard (/) — Operator landing page. Four KPI tiles (MTD/QTD/YTD/LTD revenue), a 12-month stacked-area revenue trend (Recharts), recent invoices list, managed-services queue snapshot, and a Quick Actions panel with deep links into open invoices, delinquent, Cognito sync, and user lookup.

Accounts list (/accounts) — Status-filter chips (active / trial / delinquent / paused / cancelled / all) with running counts, search box, exportable table with MRR, open balance, delinquent total, user count, activation date, and a per-row open link to detail.

Account detail (/accounts/$accountId) — Header KPI tiles (MRR, LTV, open invoices, delinquent) plus a tabbed surface with all 9 tabs the legacy Account/detail page exposes:

  • Settings — Customer info, billing address, main contact, billing & payment terms, Adventive team
  • Users — table of account users with role, created/activated/last-login dates
  • Campaigns — list with advertiser, status, dates, ad-unit count, 30-day impressions and clicks
  • Ad Units — list with format, advertiser, recipe UUID, status, 30-day impressions
  • Advertisers — list with campaign count, created date
  • Billing History — invoice list with status, dates, amount, PDF/CSV links
  • Permissions & Entitlements — entitlement catalog with per-account override state
  • Plan Info — tier, monthly price, contract dates, auto-renew, seats vs. seat limit, feature bundle
  • Managed Services — job list with type, assignee, status, hours logged vs. budgeted, due date

Billing surfaces — Overview with KPIs + trend/breakdown chart toggle + collections progress bar + aging snapshot; Invoices list with status filters and search; Account Revenue History (12-month per-account grid with MTD, average, lifetime sales); Processing Controls (test invoice, real cycle, QB export, commission report, dunning sweep, year-end rollover) with destructive-action badges and last-run timestamps; Delinquent invoices with dunning batch and call-log actions; Aging Summary with bucketed bar chart and per-account aging matrix.

Tools — Preview Link Lookup (with QR + open buttons per result), User Lookup (cross-account search), Ad Type Utilization (horizontal bar chart + table with trend arrows), Ad Type Performance (impressions, viewability, CTR, video completion, engagement), Cognito Sync (with discrepancy callouts and per-row reconcile actions), Special Permissions catalog.

ConcernChoiceWhy locked
BuildVite 8Already used elsewhere in the org; rolldown bundler
FrameworkReact 19Aligns with existing engineering skills
LanguageTypeScriptRequired for OpenAPI-driven type generation in Phase 2
StylingTailwind 3 (NOT Tailwind 4)shadcn/ui ecosystem still on v3; v4 migration deferred
Component primitivesshadcn-flavored on RadixDirect lift from brandguide.adventive.com/dashboard
RoutingTanStack Router (code-based)Type-safe, file-based optional, no build-step required for prototype
Server stateTanStack QueryPhase 2 swap target; mocks today, hooks tomorrow
ChartsRechartsUsed in dashboard, billing overview, aging
Iconslucide-reactshadcn/ui’s standing pair
FontInter (via rsms.me CDN)Brand guide standard

The prototype’s tokens are HSL CSS variables lifted directly from brandguide.adventive.com/dashboard via DOM inspection. They live in src/index.css and Tailwind reads them through the tailwind.config.ts theme block.

--background: 230 25% 7%; /* deep navy-black */
--foreground: 210 40% 98%; /* near-white */
--primary: 250 100% 70%; /* Adventive purple */
--card: 230 25% 10%;
--accent: 230 25% 15%;
--border: 230 25% 18%;
--radius: 0.75rem;
--stripe-purple: 250 100% 66%;
--stripe-pink: 330 100% 71%;
--stripe-blue: 217 91% 60%;

The dark theme is the default and only theme for now. A light variant is deferred until operator preference data is collected post-rollout.

Mock fixtures live in src/lib/mock/:

  • types.ts — TypeScript types matching the API contract (Account, Invoice, Campaign, AdUnit, etc.)
  • accounts.ts — 8 fully-realized accounts across all status tiers, with related users, campaigns, ad units, advertisers, managed-services jobs, permissions, and plan info
  • billing.ts — invoices, KPIs, 12-month revenue trend, aging buckets, processing controls, account-history rows
  • tools.ts — ad type utilization/performance, Cognito sync samples, preview link samples
  • operator.ts — current operator and roster

Pages import from these modules directly today. Phase 2’s swap pattern:

// Phase 1
import { accounts } from "@/lib/mock/accounts";
const data = accounts.filter((a) => a.status === "active");
// Phase 2
import { useAccounts } from "@/lib/api/hooks";
const { data, isLoading, error } = useAccounts({ status: "active" });

The mock module shape is intentionally aligned with the API contract — same field names, same types, same nullability. The swap is mechanical, not architectural.

Worker name: adv-ui-admin-dev. Hostname: genesis-admin.adventive.dev (AAAA pre-creation required). Built with npm run build, deployed with npm run deploy:dev. Cloudflare Access is not yet enforced on the dev preview — the URL is unprotected during the team-review window. Access is added when the API lands and Phase 2 promotes to staging.

  • Layout shell (src/components/admin/admin-shell.tsx, sidebar.tsx, top-bar.tsx, page-header.tsx)
  • All 15 route components — each one is the production view, just with mock data
  • All shadcn-flavored primitives (src/components/ui/*)
  • KpiCard, StatusPill — domain-specific composites that already encode brand and copy
  • Brand tokens, font, CSS variables
  • The OpenAPI-shape mock contract
  • The typed API client at src/lib/api/client.ts (generated from adventive-admin-api’s openapi.json)
  • TanStack Query hooks at src/lib/api/hooks/* replacing src/lib/mock/*
  • Cloudflare Access integration on the UI Worker route
  • Auth context provider that reads /api/me once on mount and caches the operator role for RBAC-conditional UI
  • An “as-built” pass updating brand tokens from any review feedback that lands during the meeting
  • Real authentication — Cloudflare Access defers to Phase 2 promotion
  • Real data — every list, detail, KPI is a fixture
  • Mutating actions — buttons render but trigger no network calls. The “Run April billing” button on the dashboard, for example, is decorative
  • The full Reports surface — those endpoints are not in admin-api’s scope and the corresponding UI is intentionally omitted (decision in §02)
  • Dark/light theme toggle — dark only
  • Mobile breakpoints below lg — sidebar disappears, but the prototype is desktop-first by design

Local: ~/Repositories/GitHub/Adventive/adventive-admin-ui/ — initial commit 2026-04-30. Pushed to GitHub by Jeffrey post-review.