Skip to main content

Founder HQ — Expected Output Spec

1. Why this exists

Founder request, verbatim (2026-09-11): "I don't want to look up stuff in files. for whatever i might need for testing, i need all links available in some UI screen... a robust dashboard like the realtor one with an ARIA that knows my system and everything inside out... tabs for sections and all the links I would need as CEO."

This is NOT a replacement for the existing /founder/[token] operations dashboard (metrics, watchtower, outreach, QA — FounderDashboard.tsx). Founder HQ is a link directory + assistant: a single page that answers "where do I click to test/see/manage X" without opening a file or asking an agent. It is linked from the existing dashboard header.

2. Non-goals (v1)

  • No writes to prod data. Every action on this page either navigates away (a link) or answers a question in a chat box. Nothing on /hq itself mutates premium_churches, churches, Stripe, or any customer table.
  • No customer data display beyond counts. No church names, no contact PII, no transcripts. The assistant may state aggregate facts already public in PRICING.md/knowledge/data/*.yaml/ product_knowledge, never per-customer records.
  • No secrets committed. Any link containing FOUNDER_TOKEN or an admin token is built server-side at render time from env/DB. The registry source file never contains a literal token.
  • Not a second QA tool. It links to /ensure-solid output and readiness docs; it does not reimplement them.
  • Not host-aliased. /founder/* is not rewritten by any brand-host middleware branch (verified — no pathname.startsWith('/founder') branch exists in src/middleware.ts). One canonical URL: churchwiseai.com/founder/[token]/hq, reachable from any host that resolves to the deployment (including *.vercel.app previews) since nothing here depends on host-based rewriting.

3. Auth model

Same pattern as every other /founder/[token]/* page (morning-brief, root dashboard):

  • Server component reads params.token, compares to process.env.FOUNDER_TOKEN.
  • Mismatch or unset env var → notFound() (Next.js 404), not a 403 — indistinguishable from a route that doesn't exist, matching demo-record-mode's stated rationale.
  • export const dynamic = 'force-dynamic' (no ISR/caching of a token-gated page).
  • robots: 'noindex, nofollow' inherited from the existing founder/[token]/layout.tsx.
  • The chat API route (/api/founder/hq-chat) re-validates the token independently — a page render passing auth does not imply the API trusts the same request. Token accepted via Authorization: Bearer <token> header or JSON body { token }; either must equal FOUNDER_TOKEN.

4. Data model — the registry is the product

src/lib/founder/hq-links.ts exports a typed, static structure:

type StaticHqLink = { kind: 'static'; label: string; url: string; note?: string; badge?: string };
type ResolvedHqLink = {
kind: 'resolve';
label: string;
resolve: (token: string) => string | null; // null = cannot resolve server-side
note?: string;
badge?: string;
fallbackNote: string; // shown when resolve() returns null
};
type HqLinkEntry = StaticHqLink | ResolvedHqLink;
type HqSection = { id: string; label: string; description: string; links: HqLinkEntry[] };
export const HQ_SECTIONS: HqSection[];
  • static entries are literal, public URLs (property homepages, docs portal, GitHub).
  • resolve entries are for anything that must embed FOUNDER_TOKEN or another secret — the function takes the already-validated founder token and returns a live URL, or null if the required env/DB value is missing (rendered with fallbackNote instead of a dead link, never a broken href).
  • The page (hq/page.tsx) is a server component: it calls a resolveHqSections(token) helper that walks HQ_SECTIONS, calls every resolve(), and passes the fully-resolved plain-URL structure to the client component. No resolve function or token ever reaches client-side JS — the client component receives only strings.
  • This registry doubles as the daily QA sweep's link-liveness source (future work, not v1): any automated "check every founder-facing link" job should import HQ_SECTIONS rather than maintaining a second list. v1 ships the registry + a unit test that every static url parses as a valid URL and the source file contains no literal token value (grepping for the env var name FOUNDER_TOKEN being used, never a token string).

5. Tabs — what each shows

Six tabs, tab bar mirrors the ChurchWiseAI design system (.btn-gold active state, navy/gold/cream cards) at the same visual bar as /realtor/app and the existing FounderDashboard.tsx.

5.1 Test & Demo

  • churchwiseai.com/demo — live browser voice+chat demo.
  • /s/gospel-fellowship-b1d6 — the church Pro Website demo tenant referenced in demo-record-mode's own instructions page.
  • /realestate-demo — the real-estate demo chooser index.
  • /wiseaiagency/playground — multi-vertical demo playground (funeral/vet/dental/restaurant/etc.).
  • Demo dial-in numbers, sourced from src/lib/phone-registry.ts PHONE_REGISTRY, filtered to entries with agent !== null (i.e. actually routed) — demoUS (469) 615-2221 and demoCA (365) 825-4095, both Grace Community Church. spareCA (+13658253552) is EXCLUDED even though the source file's own comment calls it "unassigned" — per founder-confirmed fact (2026-09-10), that number is now Team Beckett's real production line and must never be listed as a test/demo number. This is a deliberate override of a stale code comment, noted inline in the registry source.
  • Sales/support toll-free (888) 603-0316 — listed as "call the AI sales agent yourself," not a demo line.
  • Demo recording-mode toggle: two resolve links, /api/founder/demo-record-mode?token=… (ON, 24h) and the same with &off=1 (OFF), each labelled with what it does per the route's own docstring.
  • /book on each live host with a voice/chat demo path: churchwiseai.com, wiseaiagency.com, funeralwiseai.com, veterinarywiseai.com (booking calendar + copy is host-aware per src/lib/booking-calendars.ts).

5.2 Properties

One row per property in knowledge/readiness/*.yaml, production_url field, with the yaml's status rendered as a badge (live / coming_soon / pre-launch):

PropertyURLStatus
ChurchWiseAIchurchwiseai.comlive
PewSearchpewsearch.comlive
IllustrateTheWordillustratetheword.comlive
SermonWisesermonwise.ailive
ShareWiseAIsharewiseai.comcoming_soon
WiseAI Agencywiseaiagency.comlive
FuneralWiseAIfuneralwiseai.comlive
VetWiseAIveterinarywiseai.compre-launch
Pro Websitechurchwiseai.com/pro-websitelive
RealtyWiseAIrealtywiseai.comlive — see §6
CompareLocal.cacomparelocal.calive (3 markets)
johnmoelker.comjohnmoelker.comlive

Each row's static child links (pricing/contact/blog) are only added where the page is confirmed to exist in src/app/<brand>/*; wiseaiagency.com/chamber gets its own row per the founder's Sept 17 event. No child link is invented from a URL pattern guess — every one is verified against a page.tsx in the current tree before being added to the registry (Hard Guardrail: "don't guess URLs, verify in code").

5.3 Admin

  • /admin/[token] (resolve, church admin dashboard, FOUNDER_TOKEN used only if it happens to equal a real admin token — see §6 open item) — actually resolves against the demo church admin token, not FOUNDER_TOKEN (they are different secrets); documented as an open item since the page cannot look up a real customer's admin token without a DB read the spec's non-goals forbid wiring in v1. Rendered with fallbackNote pointing at the DB query to run instead.
  • Every existing /founder/[token]/* sibling page, enumerated from the current directory tree: morning-brief, daily-ops, demo-tour, growth (+ growth/geo, growth/campaigns), guide-review, internal-contacts, outreach, outreach-engine, sermon-quality, submissions, voice-clients, webhook-inbox.
  • /realtor/app — WiseAI Realtor customer dashboard (for QA'ing the customer experience directly).
  • wiseaiagency.com/business/<admin_token> — noted as resolve-shaped but not resolvable server-side without a DB lookup (out of v1 scope) → rendered with a "look up in local_business_setup_profiles" fallback note rather than a guessed/dead link.

5.4 Sales & CRM

  • GoHighLevel login (app.gohighlevel.com) + one deep link per sub-account (app.gohighlevel.com/v2/location/<locationId>/dashboard) using the three location IDs on record: churchwiseai 45se8cO8HtXSwLmCL9vw, wiseaiagency 5JXMml9xsYhsk2bLsNYN, johnmoelker gfmy9CQ3wB52trxeWL9T.
  • Both Google Business Profiles + their official public review links: WiseAI Agency g.page/r/CRj28zWUWiC_EBM/review, ChurchWiseAI LTD g.page/r/CZ4BxRKaQfhJEBM/review.
  • Stripe live dashboard (dashboard.stripe.com/acct_1SSPz2FaoK5IPzNo/dashboard).
  • All five GHL booking calendar public widget URLs, derived by calling bookingWidgetUrl() from src/lib/booking-calendars.ts on CHURCHWISEAI, WISEAIAGENCY, funeralwiseai, vetwiseai, and THIRTY_MIN — never retyped as literal calendar IDs, so a future calendar rebuild (like the 2026-09-08 round-robin migration) cannot leave this page stale.

5.5 Ops

  • Vercel dashboard, GitHub repo (github.com/ChurchWiseAI/churchwiseai-web) + open-PRs filter, Supabase project dashboard (wrwkszmobuhvcfjipasi), LiveKit Cloud project (cwa-voice-9x077mph / p_5u9xu5ysoly), docs.churchwiseai.com.
  • Daily Brief artifact (the standing URL: https://claude.ai/code/artifact/6baf7fc5-b237-4aa7-a773-e1afd186b5cd).
  • C:\dev (the knowledge/ops monorepo) does have a remote — github.com/ChurchWiseAI/DEV, default branch master — so DECISION_LOG.md, BACKLOG.md, and the QA sweep outputs get real github.com/ChurchWiseAI/DEV/blob/master/<file> links, not local-path placeholders.

5.6 Chamber (Sept 17)

  • wiseaiagency.com/chamber (live page).
  • Runway checklist rendered as static text (not links): Sept 12 print, Sept 14 run-throughs, Sept 16 Angela/AV check, Sept 17 arrive 11:15.
  • Packet file list rendered as plain text (local paths under C:\dev\CHAMBER_PACKETS\), explicitly NOT as clickable links (they are local files, not URLs — a fake link would violate the "don't-guess-URLs" guardrail).

6. Open items — could not resolve server-side (flagged for founder/lead decision)

  1. RealtyWiseAI status contradiction. The task brief that requested this page described realtywiseai.com as "DORMANT (DNS unpointed)." Live verification in knowledge/readiness/realtywise.yaml (dated 2026-09-10) found the OPPOSITE: the domain resolves, returns HTTP 200, and serves real marketing page code (src/app/realtywiseai/page.tsx). This spec and the registry mark it live, per the more recent, code-verified source. Needs founder/lead reconciliation on which claim was stale.
  2. /admin/[token] and wiseaiagency.com/business/<admin_token> cannot be resolved to a working URL without a live DB read (which admin token for which church?) — out of scope for a registry that must not perform DB writes/reads at import time. Rendered with a fallback note, not a dead or guessed link.
  3. GHL sub-account deep-link URL shape (app.gohighlevel.com/v2/location/<id>/dashboard) is the standard GHL pattern but was not click-verified in this session (no browser session available to the agent building this). Flagged as best-effort, not verified.