Skip to Content

← All archived intake epics

Intake: console-ui-polish

breakdown.md

Breakdown: Console UI polish — sidebar shell, then every surface

  • scope-slug: console-ui-polish · source: Jamie's intake interrogation (2026-08-27); no scope.md behind this batch. Rulings quoted per stub.
  • initiative: Scale the bridge / objective: Q2-2026 Objective 1 — Establish Product-Market Fit with Vendor Partners
  • personas: Admin (Sustentus staff), Partner

What I understood

The console shipped functional and plain: a text-link top nav in a narrow max-w-5xl column, no visible theming, sparse empty and loading states, and tables that fight small screens. Both audiences now matter equally — invited partners judge Sustentus by it, and staff live in it — so the polish serves credibility and ergonomics with the same weight, ordered foundation-first rather than by audience. Jamie's rulings (2026-08-27): this batch is visual/UX refinement only — no new capabilities; the shell moves from the top nav to a sidebar shell; there is no external reference design — the sidebar derives from apps/web's own dashboard shell patterns and the brand-guidelines skill; and the cut is shell first, then per-surface, four PRs each reviewable on its own.

The four cross-cutting irritations Jamie confirmed — inconsistent empty/loading states, misbehaviour at tablet/half-screen widths, generic-scaffold typography and colour, and a wired but unsurfaced next-themes toggle — thread through every stub: the shell stub establishes the fixes, the surface stubs apply them to their pages.

Where it sits

Not a product seam — the console is the internal tenant-management surface (apps/console), never tenant-facing. No service-journey step and no feature-role-matrix entity is touched; everything lands in apps/console (plus packages/ui where a refinement is genuinely reusable). Access control (proxy.ts, requireViewer/requireStaff, the console-access marker) is load-bearing and explicitly untouched — polish restyles what renders, never who gets it rendered.

Build order

  1. console-shell-sidebar — replace the top nav with a responsive sidebar shell: theme toggle, brand foundation, sane widths — depends-on: none
  2. console-dashboard-activity-polish — dashboard, activity feed and notifications: states, hierarchy, brand pass — depends-on: console-shell-sidebar
  3. console-tenants-polish — tenant directory, detail, create and deleted views: table readability, states, responsiveness — depends-on: console-shell-sidebar
  4. console-auth-access-polish — sign-in, invitation accept, no-access and access management: the first-impression pass — depends-on: console-shell-sidebar

Parallelizable

Stubs 2–4 all depend only on the shell and are independent of each other — any order or all in parallel once stub 1 lands. The linear order tie-breaks on impact: the dashboard and activity are what both audiences see first and most, the tenant pages are the staff daily driver, and the auth pages are seen once per user but first by every new partner.

Out of scope (whole scope)

  • Any new capability. Jamie's ruling (2026-08-27): visual/UX refinement only. Search or filtering on the tenant list, new pages, new data on existing pages — all route through /pipeline scope as their own story.
  • Access-control mechanics: proxy.ts, requireViewer/requireStaff, the console-access marker shape, live-read-vs-claim semantics, Clerk instance settings.
  • The notifications read model and its layout-freshness caveat — presentation only here.
  • Any surface in apps/web, apps/agent, or the platform's Clerk configuration.

_done/console-auth-access-polish.md

Stub: Sign-in, invitation and access pages polish

  • feature-slug: console-auth-access-polish
  • scope: console-ui-polish
  • personas: Admin (Sustentus staff), Partner
  • initiative: Scale the bridge / objective: Q2-2026 Objective 1 — Establish Product-Market Fit with Vendor Partners
  • depends-on: console-shell-sidebar
  • sequence: 4 of 4

Problem

A partner's very first contact with the console is the invitation accept flow and the sign-in screen, and today they are the least styled surfaces in the app — default Clerk components on a bare page, a terse no-access page, and a plain access-management page for staff. The first impression the console polish exists to fix starts one screen before the console itself.

Proposed change

A presentation pass over the (auth) segment (sign-in, the /accept invitation flow), the no-access page and the staff access page: branded framing around the Clerk components (appearance/theming consistent with the shell's brand baseline, in both themes), a no-access page that explains the invitation-only model in brand voice instead of refusing curtly, and the access page brought up to the same table/state standard as the tenant pages. The auth mechanics do not move: invitation-only stays enforced exactly as it is — no sign-up link appears, /accept still refuses without a Clerk invitation ticket, and nothing touches Clerk instance settings.

Acceptance criteria (rough)

  • Sign-in and accept render the Clerk flows inside branded page framing, correct in both themes; no sign-up affordance appears anywhere.
  • The no-access page states, in brand voice, that access is by invitation and whom to contact — copy only, no new links to gated surfaces.
  • The access page matches the batch's table, empty-state and loading standards.
  • /accept behaviour without a ticket is byte-for-byte the same refusal as today.

Out of scope (this feature)

  • Any change to the invitation lifecycle, the console-access marker, grant/revoke semantics, or Clerk instance configuration.
  • Restricting or restyling the platform's own self-registration — different app, same Clerk instance, explicitly untouchable.

Notes for Define

Jamie's rulings (2026-08-27): visual/UX only; auth + access pages confirmed in scope. The AGENTS.md rule "never restrict sign-up at the Clerk instance level" binds this stub hardest — polish is framing and copy, never gate mechanics. touches: apps/console/app/(auth)/**, apps/console/app/no-access/page.tsx, apps/console/app/(console)/access/page.tsx.

_done/console-dashboard-activity-polish.md

Stub: Dashboard, activity and notifications polish

  • feature-slug: console-dashboard-activity-polish
  • scope: console-ui-polish
  • personas: Admin (Sustentus staff), Partner
  • initiative: Scale the bridge / objective: Q2-2026 Objective 1 — Establish Product-Market Fit with Vendor Partners
  • depends-on: console-shell-sidebar
  • sequence: 2 of 4

Problem

The landing dashboard, the activity feed and the notification surfaces are what both audiences see first and most, and they carry the batch's confirmed irritations hardest: pages pop in with no loading skeletons, empty states are bare text where they exist at all, and the stat cards and feed read as default-shadcn rather than Sustentus.

Proposed change

A presentation pass over (console)/page.tsx (stat cards, welcome copy, email-delivery alert, recent-activity preview), (console)/activity, (console)/notifications and the bell/list components, inside the new shell: brand-consistent hierarchy and spacing per the brand-guidelines skill, designed empty states for every zero-data view, loading skeletons for the server-rendered reads, and dark-mode correctness for all of it. Data shown, scoping, and reads stay exactly as they are — staff see the estate, a partner sees their tenants, and the "counts + activity is the whole of it" ruling from the console batch still stands.

Acceptance criteria (rough)

  • Every zero state on these surfaces (no tenants, no activity, no notifications, no email failures) shows a designed empty state, not bare text or blank space.
  • Navigating to these pages shows loading skeletons rather than an abrupt pop-in.
  • Stat cards, feed entries and notification items follow the brand typography scale and render correctly in both themes.
  • A partner viewer sees the same data they see today — nothing added, nothing widened.

Out of scope (this feature)

  • New dashboard figures (platform health, uptime — still excluded until they have a real definition), new filters, or any new read.
  • The notification read model, mark-read actions, and the layout-freshness caveat.
  • The tenant pages (stub 3) and auth pages (stub 4).

Notes for Define

Jamie's rulings (2026-08-27): visual/UX only; empty/loading states, small screens, brand consistency and theming are the four confirmed irritations to clear on these surfaces. touches: apps/console/app/(console)/page.tsx, apps/console/app/(console)/activity/, apps/console/app/(console)/notifications/, apps/console/components/{stat-card,activity-feed,notification-list,notification-bell,email-delivery-alert}.tsx.

_done/console-shell-sidebar.md

Stub: Console sidebar shell — navigation, theming and responsive foundation

  • feature-slug: console-shell-sidebar
  • scope: console-ui-polish
  • personas: Admin (Sustentus staff), Partner
  • initiative: Scale the bridge / objective: Q2-2026 Objective 1 — Establish Product-Market Fit with Vendor Partners
  • depends-on: none
  • sequence: 1 of 4

Problem

The console shell is a row of text links in a narrow centred column — it reads as an unstyled scaffold to the partners Sustentus invites in, crowds as links accumulate (Email delivery already hides behind a staff check partly for space), fights data-heavy pages with its max-w-5xl cap, and surfaces none of the theming that next-themes already wires. Every other stub in this batch restyles pages inside this frame, so the frame moves first.

Proposed change

Replace the top-nav header in apps/console/app/(console)/layout.tsx with a sidebar shell, derived from apps/web's dashboard shell patterns and the brand-guidelines skill — Jamie's ruling (2026-08-27): no external reference design exists; those two sources are the truth. Functionally the shell keeps exactly today's contents: the same five destinations with the same staff-only gating, the notification bell with its server-rendered list, and the Clerk UserButton. Add a visible dark/light theme toggle, collapse the sidebar sensibly at tablet/mobile widths, and let page content use the width the sidebar frees up — data pages stop being squeezed into the old centred column. Establish the brand typography/spacing baseline the surface stubs (2–4) build on.

Acceptance criteria (rough)

  • Every (console) route renders inside the sidebar shell with a visible active state for the current section; no route loses its place in the nav.
  • Staff-only entries (Access, Email delivery) are still absent for a partner viewer — gating unchanged, only presentation moved.
  • The notification bell and its list work exactly as before, from the new shell.
  • A theme toggle in the shell switches dark/light and persists across navigation.
  • At tablet width the sidebar collapses to an accessible pattern (drawer or icon rail) and no page shows a horizontal scrollbar from the shell itself.

Out of scope (this feature)

  • Restyling the pages inside the shell — stubs 2–4.
  • Adding, removing or re-gating any navigation destination.
  • Any change to proxy.ts, requireViewer, or the layout's notification read.

Notes for Define

Jamie's rulings (2026-08-27 interrogation): sidebar over top-nav; derive from apps/web + brand-guidelines, no mockup to match; visual/UX only. The layout comment about App Router not re-rendering shared layouts on client navigation (notification freshness) still holds in a sidebar shell — keep the comment and the behaviour. touches: apps/console/app/(console)/layout.tsx, apps/console/components/, apps/console/app/globals.css.

_done/console-tenants-polish.md

Stub: Tenant directory and detail polish

  • feature-slug: console-tenants-polish
  • scope: console-ui-polish
  • personas: Admin (Sustentus staff), Partner
  • initiative: Scale the bridge / objective: Q2-2026 Objective 1 — Establish Product-Market Fit with Vendor Partners
  • depends-on: console-shell-sidebar
  • sequence: 3 of 4

Problem

The tenant pages are the console's daily driver for staff, and they inherited the batch's irritations in their most concentrated form: tabular data squeezed into the old narrow column, overflow at tablet/half-screen widths, abrupt loads, and undesigned zero states on the directory, the deleted view and the detail page's sections.

Proposed change

A presentation pass over the tenant directory, tenant detail, new-tenant flow and deleted-tenants views ((console)/tenants/**), inside the new shell: readable, scannable tables that use the width the sidebar shell freed, deliberate responsive behaviour at small widths (column priority or stacking rather than horizontal overflow), loading skeletons, designed empty states (including the happy "no deleted tenants" case), and the brand pass on status badges, cards and forms — tenant-status and subscription-card included. Actions, fields, validation and audience scoping stay exactly as they are.

Acceptance criteria (rough)

  • The tenant list is readable at tablet width with no horizontal page scroll — columns collapse or stack by priority.
  • Directory, deleted view and detail sections each have designed empty and loading states in both themes.
  • The new-tenant and remove flows render the same steps and validations as today, restyled only.
  • A partner still sees only the tenants carrying their id — scoping untouched.

Out of scope (this feature)

  • Search, filtering, sorting, or pagination changes to the directory — capabilities, not polish; they route through /pipeline scope.
  • Any change to tenant actions, server actions, or the create/delete lifecycle.
  • The dashboard/activity surfaces (stub 2) and auth pages (stub 4).

Notes for Define

Jamie's rulings (2026-08-27): visual/UX only; small-screen behaviour and brand consistency are confirmed irritations here. touches: apps/console/app/(console)/tenants/**, apps/console/components/{tenant-status,subscription-card}.tsx.