37 — Home Dashboard (role-driven "what needs my attention")
▶ PROMOTED TO PROTAGONIST by [doc-50] (2026-06-29): the app's center of gravity is now action-first — Home is the default gravity well, not a sibling tab. It gains a light cross-catalog work-board (the doc-46 pipeline: where work sits by stage) on top of the existing "what needs you" digest. Browse/ Portals (doc-49) become the substrate you land on when you act. First build slice: a pipeline strip on Home (stage counts across the catalog). See
50-UX-PARADIGM-OPTIONS.md§6.▶ REDESIGNED by doc-54 (2026-07-04): Home v2 is NON-SCROLLABLE — one screen, no vertical scroll (stakeholder-locked "bold philosophy"). The §2 sections become a fixed tile budget (count + one-line top signal); depth lives behind the See-all drill-ins — the only scroll escape. Adds a context-aware Resume tile (closes the doc-47 §11 field feedback). See doc-54 §3.1.
Envisioning. Governed by
00-ROADMAP.md; implements20-UI-SIMPLIFICATION.md§4.2 ("dashboard widgets — pin recents, pending approvals, activity"). Opened 2026-06-21 (owner locked this as the phase after the first-load perf slice). iOS-first, then web parity.
0. Value model (owner-raised 2026-06-22) — the perspective that ties it together
Owner QA surfaced the real question: a row that just says "Under review", or a note with no provenance, feels thin — it's data, not decision-support. Three principles fix that and should govern every section:
- Digest → drill-in. The dashboard is a triage surface, not a data screen. Each section shows the top N highest-signal items + a count + "See all →" to a dedicated full screen (filter / sort / history). This is what makes a thin row OK: depth lives one tap away; the dashboard's job is "what should I look at first." So each attention section becomes both a dashboard digest and its own screen (reachable from the digest and from the drawer where it makes sense).
- Per-row context contract:
what · who · when. Every item must answer what happened, by whom, how recently — that's the minimum to decide whether to act. Today we have "what" (and only partially). "who" and "when" are not in the current list payloads — surfacing them is the real reason the/mobile/dashboardaggregate exists: not merely to bundle calls, but to be the dashboard's purpose-built read model that joins author + timestamp and pre-shapes each item. (So the aggregate SHOULD do this enrichment — it's not just a latency play. Owner intuition was right.) - Per-actor perspective — same dashboard, role-driven emphasis. Different actors triage different things; the dashboard orders/weights sections by role, it does not fork into per-type screens (doc-20 §1 still holds). First cut:
- Owner / Admin (label / manager): approvals they owe · release-readiness across projects · team activity. Triaging others' work.
- Editor (producer / artist): changes requested on their tracks · notes left for them · what to fix next. Acting on feedback.
- Viewer (client / A&R): awaiting my review (approve) · shared-with-me. Read-mostly; approval sections render read-only ("Awaiting approval"). The aggregate computes per-actor relevance server-side so the client stays dumb.
Build implication / order: (a) evolve /mobile/dashboard from "bundle" → read model with who·when + per-actor shaping; (b) add "See all" section screens; (c) richer rows (cover, dimension, author, relative time). Slices 1–3 (the digest skeleton + the four sections) are done; this is the enrichment phase on top. Section-level richness beats adding more sections.
1. Decision & guardrail
Turn the iOS home from a grid of artists into an actionable dashboard that foregrounds the Review & Approve loop: what needs my attention right now.
One dashboard, role-driven content — Owner / Admin / Editor / Viewer change what's surfaced and actionable, not which screen you land on. No per-user-type home screens (doc-20 §1 — that's the deferred templates layer). This phase is the single dashboard; "role/workflow templates" stay post-MVP.
The artist/roster grid does not disappear — it becomes one section of the dashboard (or a tab), below the attention surface.
2. What it surfaces (sections, in priority order)
The dashboard is attention + continuity only. Management surfaces (artists/roster, teams, trash, settings) live in the secondary nav (§6), not on the dashboard — so the home stays a focused "do this next" surface, not a navigation hub.
- Needs your approval — versions/covers
Under reviewwhere the viewer can approve (Owner/Admin/ Editor). Source: per-trackreleaseStatus+ per-filereviewStatus; project gate fromGET /project/:id/release-readiness. Viewers see a read-only "Awaiting approval" count, no action. - Unresolved notes & comments (rolled up) — the eagle-level roll-up we already shipped:
GET /comment/rollup+/comment/rollup/counts(unresolved · tagged), breadcrumbed to their track/version. The single highest-signal "attention" feed. - Recent activity —
GET /notification(already the live SSE-backed feed) + the realtime (doc-35) events, framed as "what changed since you looked". - Jump back in (recents) —
GET /track/recent-access. Already built; just surfaced here.
Updated by doc-54 (2026-07-04): these sections persist as tiles (count + top signal) in the one-screen, non-scrollable Home v2; the row lists move wholly into the See-all screens (the §0 what·who·when contract migrates with them). Section 4's recents collapse into a single Resume continuity tile. §2.1's rule is unchanged — and now generalized platform-wide as doc-47 §7 principle 7.
Role gating is per resource (doc-20 §2 — getCollaboratorRole() equivalent): a section/action only shows where the viewer's cascaded role allows it. No new RBAC; reuse the collaborator-array + Role enum that already governs the app. Viewer gets the same dashboard (owner decision 2026-06-21) — approval sections render read-only (status, no action), notes/activity/recents are read as normal.
2.1 Empty / first-run state (progressive disclosure)
A brand-new user has nothing in any section — rendering four empty sections is a wall of nothing. Instead, progressive disclosure:
- All sections empty → collapse to a single first-run hero: "Create your first artist" (primary CTA, promoting today's empty state) + one line explaining the Review & Approve loop. Nothing else.
- Some sections have content → render only the non-empty sections; never show an empty section header. A subtle "finish setting up" nudge can ride along until the workspace has an artist + a track.
- This means the dashboard grows into itself as the user adds content, rather than presenting a skeleton of empty promises on day one. (Owner confirmed the create-artist CTA direction; this is the refinement.)
3. Backend — the one new thing (optional but recommended)
Everything above is already exposed as separate endpoints. The only new backend work is the roadmap-flagged GET /mobile/dashboard aggregate (roadmap §"optional"): one authenticated call returning { pendingApprovals, rollupCounts, notifications, recents } for the viewer, to kill the 4–5 cold round-trips on home open (which is exactly the first-load cost we've been fighting). Build it as a thin composition over the existing services — no new domain state.
- Slice it so the iOS client can ship against the existing endpoints first (fan-out), then switch to the aggregate when it lands — the aggregate is a latency optimization, not a dependency.
4. Build order (slices)
- iOS dashboard + nav shell — restructure
ArtistsHomeViewinto the sectioned attention dashboard (§2) and move the roster grid + other destinations into the avatar drawer (§5.3). Includes the progressive-disclosure empty state (§2.1). ReuseCachedImage,SectionHeader, the roll-up row + breadcrumb components from the Portal. Mostly layout/IA; no new endpoints. The old artist-grid home becomes the "Artists" drawer destination — it isn't deleted, just relocated. - Wire the attention sections to the existing endpoints (rollup/counts, release-readiness per recent project, notifications, recents). Role-gate each section/action.
GET /mobile/dashboardaggregate (backend) + switch the iOS client to one call.- Web parity (later) — same sections in the Next.js app once the single layout is consolidated (doc-20 §3+§5).
Reuses, not rebuilds: roll-up (doc-33), approval dimension (doc-32), activity/realtime (doc-35), notifications, recents. The dashboard is the surface that finally makes them legible together.
5. Navigation & secondary destinations (owner: "home is the dashboard; roster + the rest in a menu")
5.1 The destinations (today's app)
Primary: Dashboard (home). Secondary, behind the menu: Artists / roster, Teams, Shared with me, Search, Trash, Subscription & Storage, Settings, Account / sign-out. (Recents folds into the dashboard; Search may later graduate — see §5.4.)
5.2 Actor lens (who needs what)
- Owner / Admin — the long tail: artists, teams, storage, trash, settings. Benefits most from a grouped menu of destinations.
- Editor — mostly lives in the dashboard + the projects they collaborate on; reaches Artists/Shared occasionally.
- Viewer — dashboard + Shared/Search. Teams/Trash/Storage are hidden (nothing to manage).
So the secondary surface is role-gated: the menu only lists what the viewer can actually use.
5.3 Pattern decision — a Liquid-Glass drawer sheet opened from the avatar, not a tab bar
Why not the iOS-default tab bar. Apple's HIG favors a tab bar for top-level nav — but a tab bar promotes 3–5 co-equal surfaces, which directly contradicts the owner decision that the dashboard is the surface and everything else is secondary. A tab bar would dilute the "one place to look" intent.
Why not a true left-edge slide drawer. It's an Android/web idiom with no native iOS component; hand-rolling it fights the system back-swipe, costs custom gesture code, and is weaker on VoiceOver / Dynamic Type. The "hamburger" concept is right; a literal edge-drawer is the wrong mechanism on iOS.
Recommended (native + matches intent): the account avatar (top-leading) opens a Liquid-Glass sheet (.presentationDetents([.medium, .large]), glass background — native on iOS 26). One affordance merges "where can I go" and "who am I" — a well-established pattern (Gmail/Google). Sheet layout:
- Header — user identity + a storage meter (subscription usage at a glance).
- Workspace — Artists / roster · Teams.
- Library — Shared with me · Search · Trash.
- You — Settings · Subscription · Sign out.
- Each row role-gated; absent rows simply don't render (no disabled clutter).
Keep the trailing + as the create affordance (new artist/project) — distinct from navigation, so "go somewhere" (leading avatar) and "make something" (trailing +) stay cleanly separated. This also retires the current separate trailing profile menu (folded into the drawer) — one menu, not two.
▶ Queued (owner-raised 2026-06-26): the
+should create any hierarchy node, not just an artist. Today the home+only makes an artist. Turn it into a create menu spanning the whole hierarchy — Roster · Artist · Project · Track · Version — so creation isn't gated by where you are. Open question: whether items requiring a parent (Project needs an Artist; Track needs a Project; Version needs a Track) prompt a parent-picker inline or are disabled until context exists. The CRUD sheets already exist (CreateArtistSheet/CreateProjectSheet/CreateTrackSheet); this is a menu + parent-resolution layer over them. Build after the current Sort/Filter/Search + records work (doc-40/41). Pairs with doc-25 CRUD. Also (owner-raised 2026-06-26): the same+create affordance must appear on the section screens reached from Home — Artists, Projects (.albums), Tracks — not only the home root. Each section pre-selects the relevant type (e.g. Tracks → "New track" with a project-picker). One shared create-menu component, surfaced in each section's toolbar.
Native, accessible, Liquid-Glass by default, minimal custom code. A literal edge-swipe drawer can be a later feel enhancement if wanted — flagged, not assumed.
5.4 Escape hatch (don't over-commit)
If usage later shows people can't find a section, promote the 2–3 most-used (likely Search + Shared) to a minimal iOS-26 Liquid-Glass tab bar and leave the long tail in the drawer. The drawer scales down gracefully; we don't need to decide now. The dashboard stays the primary surface either way.
6. Resolved decisions (owner, 2026-06-21) + remaining
- ✅ Home is the dashboard. Roster + other sections move to the secondary menu (§5).
- ✅ Empty state = progressive disclosure with a promoted "create your first artist" hero (§2.1).
- ✅ Viewer gets the same dashboard, approval sections read-only (§2).
- ⏳ Remaining (decide during the shell slice): exact menu glyph/position (avatar-leading recommended); whether Search lives in the drawer or graduates to a tab early; storage-meter detail in the drawer header.