console-ui-polishbreakdown.mdscope.md behind this batch. Rulings quoted per stub.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.
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.
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.
/pipeline scope as their own story.proxy.ts, requireViewer/requireStaff, the
console-access marker shape, live-read-vs-claim semantics, Clerk instance settings.apps/web, apps/agent, or the platform's Clerk configuration._done/console-auth-access-polish.mdA 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.
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.
/accept behaviour without a ticket is byte-for-byte the same refusal as today.console-access marker, grant/revoke
semantics, or Clerk instance configuration.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.mdThe 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.
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.
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.mdThe 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.
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.
(console) route renders inside the sidebar shell with a visible active state
for the current section; no route loses its place in the nav.proxy.ts, requireViewer, or the layout's notification read.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.mdThe 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.
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.
/pipeline scope.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.