Skip to main content

FuneralWiseAI — Dashboard Command Center Expected Output Spec

STATUS: DRAFT — NOT APPROVED. CLAUDE.md Rule #17 (HARD GATE) is NOT satisfied.

Stage-1 agent draft, pre-populated from the approved realtor design system (design-direction.md), the shipped "Grace bento" Home body (FuneralDashboardBody.tsx, commits ccf0727c6 + 119b1ddbf), the funeral vertical spec (funeralwiseai-vertical.md), and the approved plan (PLAN_FUNERALWISE_DASHBOARD_REVAMP_2026-07-02.md). Do not build until the founder approves and the §11 open items are confirmed in a Stage-2 interview.

AI Bridge Principle applies to every AI-authored surface in this spec. The agent is a bridge to the funeral director, never a replacement; the dashboard surfaces that bridge honestly (labelled AI vs human, "flag for director" everywhere, no fabricated activity). See architecture/ai-bridge-principle.md.


0. Scope — what this spec covers, and what it does NOT

In scope (Phase 1 + Phase 3 of the plan):

  1. The funeral-only application shell — a persistent left nav rail + top bar + scrollable content area (the realtor "Workflow-Rail" pattern, dressed in the FuneralWiseAI brand). Rail collapse, mobile off-canvas drawer, per-destination badge counts, top-bar setup-progress pill + Grace launcher + notification bell.
  2. The restyled per-screen archetypes: Home (bento — already shipped, kept), Inbox (3-pane), At-Need Calls (list + right drawer with crisis-urgency treatment), Pre-Planning (list + drawer).
  3. The funeral token mapping (realtor structural roles → FuneralWiseAI colors).
  4. The honest-metrics + demo-seeded empty-state contract for every tile/list.
  5. ?tab= deep-link compatibility (existing tab param keeps working under the new rail) + AODA (status never conveyed by color alone).

Explicitly OUT of scope (deferred / other specs):

  • Grace concierge behavior — its own spec (grace-onboarding-concierge-mvp.md); this spec only defines its launcher affordance in the top bar / tiles.
  • Setup-screen restyle (Train AI, Service Catalog, Website, Subscription) — Phase 4, a later same-series PR; day-1 those bodies render unchanged inside the new frame.
  • Church / vet admin restyle — the rail is funeral-gated; church + vet keep the existing tab shell, pixel-unchanged (§7 is a hard regression gate).
  • Voice-agent runtime / deploys (LIFE-SAFETY, voice-agent-engineer + founder go), dark mode (specced in the realtor system, not implemented), a working Cmd+K beyond a display affordance, and any email/notification send.

Build posture (do-not-reinvent): the funeral dashboard is the shared church admin shell (admin/[token]/page.tsxAdminShellAdminDashboard), hostname-switched to the funeral vertical (middleware.ts + resolveFuneralToken() against premium_funeral_homes) with funeral tab bodies swapped in when verticalProfile.key === 'funeral'. This spec wraps that existing dashboard in a new funeral-gated frame and restyles the tab bodies — it does not fork a second dashboard, and it does not touch the church/vet path. The realtor shell (src/components/realtor/shell/) is the pattern source, read for reference; the funeral shell is a build-to-spec port with funeral tokens (the realtor components use inline hex and realtor IA — do not import them).


1. Design tokens — FuneralWiseAI mapping (realtor role → funeral value)

The realtor design system assigns three brand roles — chrome (navy), the single primary action accent (teal), and highlight/celebration (gold) — and lets neutrals carry 90% of the structure ("color as punctuation"). FuneralWiseAI keeps that structure and swaps the three brand values:

Role (realtor)Realtor valueFuneral valueNotes
Rail / chromenavy #0B1F3Aslate #1E293B, active/deep #0F172AThe rail, top bar chrome, headers.
Primary action (the ONE accent)teal #0F766Edeepened sage #3F685C (fill, white text), tint #EDF5F1Buttons, active-nav marker, links-on-white. Deepened from brand sage #4D7C6F for AA. See contrast note below.
Highlight / celebration ONLYgold #C49A3Acopper #B45309, tint #FEF3E2, text-on-tint #8A4A0BLeft-edge accent / badge only. NEVER body text, never a plain label color (realtor anti-pattern #4).
Neutrals / semantic / type / spacing / radius / densityidentical to the realtor specbg #FAFAFA, surface #FFFFFF, border #E6E8EB, text #18181B, muted #6B7280; Inter; 14px body; tabular-nums on all metrics; border-first low-shadow; comfortable (~44px) rows with a compact toggle.

Sage contrast (AODA gate, verified). The primary action color must reach ≥4.5:1 for white text (WCAG AA normal text). Brand sage #4D7C6F measures ~4.75:1 on white — a bare pass with no margin. This spec adopts the deepened sage #3F685C, which measures ~6.3:1 on white (comfortable AA, and AA-large headroom), as the action fill. #4D7C6F may still be used for the sage tint #EDF5F1 and non-text accents. The build must not ship a sage that a contrast checker scores below 4.5:1 for its white-text usage.

Arrangement / pipeline stages (chip + list header, always label + color, colorblind-safe — realtor rule): New inquiry = blue, Arrangements = sage/teal, Service set = amber, Completed = green, Aftercare = violet. A stage is never conveyed by color alone (AODA §6).

Anti-patterns (from design-direction.md, apply verbatim): no tab-sprawl (one record, AI summary on top); size tiles by importance (≤12, curate to 5–9); density toggle (no 27" assumption); highlight color is never text (copper ban); same IA across breakpoints; no blank empty states (demo-seeded + one CTA — §6); skeletons not spinners; color as punctuation; drawers/command-palette over modal-on-modal; border-first flat chrome (no gradients/glossy).


2. The application shell (funeral-gated frame)

2.1 — Gating (funeral only; church/vet untouched)

Should see / NOT see:

  • The FuneralShell renders only when the resolved vertical is funeral (verticalProfile.key === 'funeral', i.e. a premium_funeral_homes-backed token on the funeralwiseai.com host). Church and vet admin render the existing tab shell, byte-for-byte unchanged (§7 regression gate).
  • The funeral dashboard owns its chrome — no ChurchWiseAI marketing header, no sacred-gold/navy, no PewSearch panel (matches funeralwiseai-vertical.md D1).

2.2 — Left nav rail (slate)

Should see:

  • A persistent left rail (slate #1E293B, ~248px), collapsible to a ~64px icon rail. The collapse state is remembered (localStorage) and hydration-safe (read via useSyncExternalStore — no server/client mismatch flash; realtor hydration pattern).
  • A brand tile at the top (FuneralWiseAI lockup / funeral home name), the primary destinations promoted from the existing 8 funeral tabs to rail items (Home, Inbox, At-Need Calls, Pre-Planning, Train AI, Service Catalog, Website, Subscription — final IA confirmed in the Stage-2 interview, §11), and a Settings footer item.
  • The active destination marked with the sage accent (fill or left-edge marker) + a non-color cue (bold label / filled icon) — never color alone (AODA).
  • Badge counts on the destinations that have actionable volume: At-Need (open at-need calls needing a director), Inbox (unhandled threads). Counts are live and honest — a real count from the data, 0 shown as no badge (never a fabricated number; §6).

Should NOT see:

  • A rail item that routes nowhere / a "coming soon" dead link (every rail item resolves to a real screen; setup bodies render even if unstyled on day 1).
  • A badge count that does not reflect real rows.

2.3 — Top bar

Should see:

  • The current-screen title (+ a brief date/greeting), a setup-progress pill (e.g. "Setup 60%") that reflects the tenant's real onboarding completeness and deep-links into the setup flow, a Grace launcher ("Ask Grace") that opens the concierge panel (behavior → grace-onboarding-concierge-mvp.md), a notification bell, and a mobile hamburger (<lg).
  • A search/Cmd+K affordance is display-only (honest — it is not wired; realtor posture). It must be reported as not-yet-functional, not presented as working.

Should NOT see:

  • A setup pill showing a fabricated/hardcoded percentage (it must derive from real setup state, or be omitted).
  • A notification bell that claims unread counts it cannot substantiate.

2.4 — Rail collapse + mobile drawer (behavior, not DOM)

Should see (verify at ≥2 timepoints — feedback_verify_behavior_not_dom_presence):

  • Clicking collapse shrinks the rail to the icon rail and the content area reflows wider; the choice persists across reloads.
  • Under lg, the rail is an off-canvas drawer: the hamburger opens it, a backdrop tap or Esc closes it, focus is trapped while open and restored on close. Same IA as desktop (no web/mobile divergence — anti-pattern #5).

Should NOT see:

  • A hydration flash (rail momentarily expanded then collapsing) — the pattern must read the persisted state before first paint.
  • A mobile drawer that leaves the page scrollable behind it or loses focus.

3. Screen archetype — Home (bento, already shipped, kept)

Status: SHIPPED (the "Grace bento" Home body, FuneralDashboardBody.tsx). This spec keeps it and only asks that it now render inside the new frame and honor the token mapping (§1).

Should see:

  • A bento command center: a hero tile (the one daily number — e.g. today's at-need calls) top-left at ~2× scale, then ≤10 tiles sized by importance (recent activity, calls this week, callbacks pending, setup progress, a Grace entry tile).
  • Metrics use tabular-nums; the hero tile is the largest.
  • Honest empty/onboarding state when there is no activity yet (§6).

Should NOT see:

  • A uniform card wall (anti-pattern #2) or a fabricated KPI (§6).

4. Screen archetype — Inbox (3-pane)

Mirrors the realtor Conversation Inbox archetype (realtor-inbox-mvp.md), funeral terminology.

Should see:

  • A 3-pane split: Pane 1 — filters / saved views (At-Need · Pre-Planning · Family Contact · Crisis · General · Callback · All, with live counts) + channel filter (Voice / Chat); Pane 2 — the thread list (caller name, relationship-to-deceased snippet, timestamp, a type chip + urgency badge where applicable, AI-handled rows muted with an "AI" badge); Pane 3 — the thread + a right context rail (AI call summary, caller facts, "flag for director" / take over actions).
  • Thread bubbles label AI vs human vs caller; an escalation appears as a system row that states why the agent handed off ("wants to arrange a service today — waiting for a director"), never a bluffed answer (AI Bridge).
  • Nothing auto-sends; a human presses any reply (no unattended sends).

Should NOT see:

  • Church filters (prayer request, care/broadcast, denomination) — funeral taxonomy only (matches funeralwiseai-vertical.md §6 banned terms).
  • A blank 3-pane (demo-seeded preview + onboarding nudge — §6), or a spinner (skeleton rows/thread instead).

5. Screen archetypes — At-Need Calls & Pre-Planning (list + drawer)

5.1 — At-Need Calls (list + right drawer, crisis-urgency treatment)

Should see:

  • A list of at-need calls (family calling within hours/days of a death), each row: caller name, relationship, time, and an urgency indicator that is text + color, never color alone (e.g. an "URGENT — family in crisis" label with a copper left-edge accent; copper is the highlight edge, the word "URGENT" is the readable status — copper is not the label text, §1).
  • A right drawer on row-open: the transcript + an AI summary header, caller contact, nature of call, and a "director takes over" action. Opening the drawer does not lose the list (two-tier: list triage + drawer detail, no tab-sprawl).
  • A genuine crisis disclosure (self-harm / acute distress) surfaces the universal 988 pathway and a "connect to a director" offer — never handled as a routine lead (AI Bridge + funeralwiseai-vertical.md §8).

Should NOT see:

  • Urgency shown by color only (AODA), or a "family in crisis" row that reads the same as a routine callback.
  • The AI presented as having counselled the family or promised confidentiality.

5.2 — Pre-Planning (list + drawer, next-action emphasis)

Should see:

  • A list of pre-planning inquiries + a right drawer with the inquiry detail, contact, and a clear next action (schedule a consult / flag for director). Next-action is emphasized (the realtor "next-best-action" pattern), calm and unhurried in tone (this is planning, not crisis).

Should NOT see:

  • The same crisis-urgency treatment as At-Need (pre-planning is not time-critical); a fabricated inquiry (§6).

6. Honest-metrics & empty-state contract (hard gate)

Every tile, list, badge, and pill on every screen obeys the portfolio "honest metrics, never theater" rule (CLAUDE.md) + realtor anti-pattern #6:

SituationExpected output
No calls / no activity yetA demo-seeded preview + one CTA + onboarding nudge ("Your families' calls will appear here once your line is live") — never a blank panel.
A metric with no real dataShow an honest empty/zero state or omit the tile — never a fabricated number (no "Delivered/Opened" theater; no invented call counts).
A badge count of 0No badge (not a "0" that implies activity). A badge shows only a real actionable count.
Setup pillReflects the tenant's real onboarding completeness; if it can't be computed, omit it — never hardcode a percentage.
LoadingSkeletons, not spinners (anti-pattern #7).
ErrorInline "Couldn't load — retry"; the rest of the shell stays usable.
Not-provisioned (no line connected)Honest "AI front office not yet connected — calls not measured yet," not fabricated conversations.

Demo content is seeded (the Moelker Family Funeral Home demo tenant, plan Phase 0) and clearly demo — it never masquerades as a real family, and nothing in this UI path may email anyone (plan §5 safety rail).


7. Church / vet regression gate (funeral-gated — pixel-unchanged)

Because AdminShell / AdminDashboard are shared, the single most important regression guard:

  • CH-1 — A church demo admin token renders the existing church tab shell, visually unchanged (no funeral rail, no slate chrome, no sage/copper). Verify with a click-through on a church demo token.
  • CH-2 — A vet admin token renders the existing vet shell, unchanged.
  • CH-3 — The FuneralShell code path is entered only for verticalProfile.key === 'funeral'; the church/vet branch is provably untouched (diff shows the funeral frame is additive/gated, not a rewrite of the shared shell).
  • CH-4 — Check knowledge/tests/registry.yaml for admin/[token] critical-path overlap before touching shared files; a shared-shell change climbs the verification ladder (deployed-URL Playwright, not build-passes).

  • DL-1 — Existing deep links (funeralwiseai.com/admin/[token]?tab=inbox, ?tab=training, etc.) still resolve to the correct screen under the new rail (the rail destinations map onto the same tab keys; the param is not broken).
  • DL-2 — Selecting a rail destination updates the URL/tab state so a deep link can be copied/shared (parity with the pre-rail behavior).
  • DL-3 — An unknown ?tab= value falls back to Home (no crash), matching the pre-existing behavior.

9. Accessibility (AODA → WCAG 2.1 AA)

  • Landmarks: rail = nav; top bar = banner/header; content = main; the 3-pane inbox panes are navigable regions; lists expose selectable rows.
  • Status never color-only: arrangement stages, urgency ("URGENT — family in crisis"), AI-vs-human authorship, and badge meaning are conveyed by text + icon, not color alone. Copper is a highlight edge, never the readable status.
  • Contrast: ≥4.5:1 for all text; the sage action = #3F685C (~6.3:1 on white); copper text-on-tint uses #8A4A0B on #FEF3E2 (verify ≥4.5:1); slate chrome text meets AA.
  • Keyboard: rail collapse, drawer open/close (Esc), destination nav, row → drawer, take-over/flag, and the Grace launcher are all keyboard-operable with visible focus; the mobile drawer traps + restores focus.
  • Motion: rail/drawer transitions and skeletons respect prefers-reduced-motion.
  • Screen-reader: the setup pill, badge counts, and notification bell expose their meaning as text (e.g. "Setup 60% complete", "3 at-need calls need a director").

10. Acceptance checklist (QA runs on the deployed URL)

Behavioral verification on https://funeralwiseai.com (the real host — the host-alias middleware is skipped on preview hosts, plan §Verification) against the Moelker demo token; never "build passes". Sample at ≥2 timepoints; assert change. Any voice-path touch additionally requires voice-agent-engineer review.

// Shell + gating
test.fixme('funeral admin renders the slate left-rail shell + top bar (setup pill, Ask Grace, bell)', () => {});
test.fixme('rail collapses to a 64px icon rail and the choice persists across reload (no hydration flash)', () => {});
test.fixme('under lg the rail is an off-canvas drawer: hamburger opens, Esc/backdrop closes, focus trapped+restored', () => {});
test.fixme('At-Need and Inbox rail badges show REAL counts; a 0 shows no badge (no fabricated number)', () => {});

// Token mapping / a11y
test.fixme('primary action color is sage #3F685C measuring >=4.5:1 on white; copper is edge/badge only, never text', () => {});
test.fixme('arrangement stages + at-need urgency are text+color, never color alone (AODA)', () => {});

// Screens
test.fixme('Home renders the bento inside the new frame (hero tile 2x, <=10 tiles, tabular-nums, honest empty state)', () => {});
test.fixme('Inbox is a 3-pane split with funeral filters (At-Need/Pre-Planning/Family Contact/Crisis/General/Callback)', () => {});
test.fixme('At-Need is list + right drawer; a crisis row shows URGENT text + copper edge + transcript/AI summary + director take-over', () => {});
test.fixme('Pre-Planning is list + drawer with next-action emphasis (calm, not crisis-styled)', () => {});

// Honesty + deep links + regression
test.fixme('every tile/list/badge shows a demo-seeded/honest empty state — never blank, never a fabricated metric', () => {});
test.fixme('?tab=inbox (and other existing deep links) still resolve under the new rail', () => {});
test.fixme('a church demo token renders the existing church tab shell PIXEL-UNCHANGED (no funeral rail/slate/sage)', () => {});
test.fixme('a vet admin token renders the existing vet shell unchanged', () => {});

11. Open items (Stage-2 founder validation)

#QuestionBlocksPriority
1Final rail IA — exact rail destinations + order + labels (the 8 tabs promoted; is "At-Need Calls" its own destination or an Inbox filter?).§2.2, §4, §5P0
2Badge-count sources — which tables/queries back the At-Need + Inbox badges (verify exact table/column names via information_schema, Rule #18).§2.2, §6P0
3Setup-progress computation — what defines the funeral tenant's onboarding % (which setup steps count)?§2.3, §6P0
4Inbox filter set — confirm the exact funeral filter chips (At-Need / Pre-Planning / Family Contact / Crisis / General / Callback / All).§4P1
5Arrangement stages — are the 5 stages (New inquiry / Arrangements / Service set / Completed / Aftercare) correct, and where do they surface (a pipeline screen, or a status field on inbox rows)?§1, §5P1
6Notification bell — is there a real notification feed to back it, or is it display-only for now (must be honest either way)?§2.3P1
7Compact/density toggle — carry the realtor compact toggle into funeral, or comfortable-only at launch?§1P2

12. Guardrails for agents building against this spec

  • Rule #17 not satisfied — do not build the shell/screens until founder approval.
  • Funeral-gated, church/vet pixel-unchanged — the shared AdminShell/ AdminDashboard change is additive + gated; §7 is a hard regression gate (verify a church demo token on the deployed URL).
  • Honest metrics, never theater — no fabricated counts, no hardcoded setup %, no blank panels (demo-seeded states).
  • AI Bridge — AI-authored surfaces are labelled AI, "flag for director" is always present, no confidentiality promises, crisis surfaces 988 + a human.
  • Build-to-spec port, not component reuse — port the realtor shell with funeral tokens; do not import realtor components into the funeral path.
  • Verify on the real host (funeralwiseai.com), behavior not DOM presence, reduced-motion + mobile emulation, evidence attached (CLAUDE.md ladder).
  • Nothing in this path may email anyone (plan §5); nothing references Kolssak.
  • If code diverges, update this spec first (founder approval), then the code.

End of spec. STATUS: DRAFT — NOT APPROVED.