From a84f7d7068810d7a181f4214ab3dcf2163d4c667 Mon Sep 17 00:00:00 2001 From: CrewCircle Date: Tue, 28 Jul 2026 15:21:56 +1000 Subject: [PATCH] Fix admin dashboard status vocabulary and GitHub enrichment mismatches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dashboard showed all 6 projects as "Killed" with 0 active and $0 MRR despite 3 apps being genuinely live. Root cause: registry.json uses a "live"/"coming_soon" status vocabulary, but RegistryProject's type and StatusBadge only understood "active"/"killed" — anything else silently rendered as "Killed" and was excluded from the active count. Extended the vocabulary to a real 3-state model (active/coming_soon/ killed, matching what the Python provisioning script actually writes for newly created projects) instead of forcing coming-soon apps into a binary active/killed choice. Added a "Coming Soon" badge variant. Also fixed the Active Projects stat card, which hardcoded everyone not active as "killed" regardless of their real status. Separately, GitHub star/fork enrichment showed "—" for every project. Root cause was a typo'd org name that no longer exists on GitHub (crewcricle vs crewcircle — this is a local env var fix, not reflected in this diff). While tracing it, also found one registry ID that doesn't match its real GitHub repo name (taxflowai vs taxflow-ai, a hyphen difference GitHub's case-insensitive matching can't paper over). Added a small override map in github.ts rather than renaming the registry ID, which is used as a key across routes/costs/provisioning. Co-Authored-By: Claude Sonnet 5 --- packages/admin-ui/src/status-badge.tsx | 9 ++++++++- src/app/admin/page.tsx | 4 +++- src/app/admin/projects-table.tsx | 2 +- src/lib/admin/github.ts | 12 +++++++++++- src/lib/admin/registry.ts | 2 +- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/admin-ui/src/status-badge.tsx b/packages/admin-ui/src/status-badge.tsx index e315dca..ca3d94a 100644 --- a/packages/admin-ui/src/status-badge.tsx +++ b/packages/admin-ui/src/status-badge.tsx @@ -7,6 +7,7 @@ const badgeVariants = cva( variants: { status: { active: "bg-green-100 text-green-800", + coming_soon: "bg-amber-100 text-amber-800", killed: "bg-red-100 text-red-800", }, }, @@ -20,8 +21,14 @@ interface StatusBadgeProps extends VariantProps { className?: string; } +const STATUS_LABELS: Record = { + active: "Active", + coming_soon: "Coming Soon", + killed: "Killed", +}; + export function StatusBadge({ status, className }: StatusBadgeProps) { - const label = status === "active" ? "Active" : "Killed"; + const label = STATUS_LABELS[status ?? "active"] ?? "Killed"; return ( {label} diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 557deec..811dd37 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -19,6 +19,8 @@ export default async function AdminDashboardPage() { ); const activeCount = projects.filter((p) => p.status === "active").length; + const comingSoonCount = projects.filter((p) => p.status === "coming_soon").length; + const killedCount = projects.filter((p) => p.status === "killed").length; const totalMmr = projects .filter((p) => p.status === "active") .reduce((sum, p) => sum + p.price_cents, 0); @@ -42,7 +44,7 @@ export default async function AdminDashboardPage() { ( - + ), }, { diff --git a/src/lib/admin/github.ts b/src/lib/admin/github.ts index fa2d26b..2db503c 100644 --- a/src/lib/admin/github.ts +++ b/src/lib/admin/github.ts @@ -6,6 +6,15 @@ const GITHUB_API = "https://api.github.com"; const CREWCIRCLE_ORG = process.env.CC_GITHUB_USERNAME ?? "crewcircle"; +/** + * Registry project IDs that don't match their actual GitHub repo name. + * The registry ID stays stable (used as a key across routes, costs, etc.); + * this only redirects the GitHub API lookup. + */ +const REPO_NAME_OVERRIDES: Record = { + taxflowai: "taxflow-ai", +}; + export interface GitHubRepo { name: string; full_name: string; @@ -46,7 +55,8 @@ export async function getRepo(repoName: string): Promise return null; } - const url = `${GITHUB_API}/repos/${CREWCIRCLE_ORG}/${repoName}`; + const resolvedName = REPO_NAME_OVERRIDES[repoName] ?? repoName; + const url = `${GITHUB_API}/repos/${CREWCIRCLE_ORG}/${resolvedName}`; const res = await fetch(url, { headers: { diff --git a/src/lib/admin/registry.ts b/src/lib/admin/registry.ts index 7991d1d..503ee95 100644 --- a/src/lib/admin/registry.ts +++ b/src/lib/admin/registry.ts @@ -6,7 +6,7 @@ export interface RegistryProject { name: string; description: string; price_cents: number; - status: "active" | "killed"; + status: "active" | "coming_soon" | "killed"; created_at: string; killed_at?: string; }