Admin Dashboard
The admin package is the Green Goods operator canvas. This page is the single UI contract for packages/admin.
Purpose
packages/adminowns canvas shell composition and admin-only workflows.@green-goods/sharedowns reusable UI primitives, shared config helpers, hooks, providers, stores, and Storybook-backed foundations.- If a pattern is reusable across admin surfaces, move it to shared instead of creating a package-local copy.
Canonical Routes
- Primary canvas surfaces:
/hub,/garden,/community,/actions - Hub canonical deep links:
/hub/work/:workId,/hub/work/submit,/hub/assess/create,/hub/certify/:assessmentId,/hub/certify/create,/hub/history/:historyEventId - Secondary garden flows:
/garden/create,/garden/impact/hypercerts/:hypercertId,/community/treasury/vault,/community/governance/strategies,/community/governance/signal-pool/:poolType - Team campaign flows:
/cookies,/cookies/deploy - Removed admin top-level routes intentionally fall through to the admin 404 unless they are listed in the redirect policy below.
Redirect Policy
- Canonical admin bookmarks stay inside the admin app:
/hub,/garden,/community,/actions, and their documented nested routes. - Public garden URLs redirect to the client app:
/gardens,/gardens/:gardenId, and/gardens/:gardenId/*map to the same path ongreengoods.app. - The admin SPA keeps a client-side fallback for public garden URLs so local and static preview environments match production redirects.
- Removed admin route families are not blanket-redirected. Add a specific destination here before preserving any legacy admin bookmark.
Shell Contract
CanvasLayoutis the canonical shell.- The shell is
AppBar + .workspace-canvas + MainSheet + NavigationBar. AppBaris the stickyz-sticky h-14context region withGardenChipon the left and search, settings, notifications, and profile controls on the right.NavigationBaris navigation only. The canonical items areHub,Garden,Community, andActions.- Controlled Chrome is the admin material boundary: subtle liquid glass is permitted on NavigationBar/FAB and sheet shells. The AppBar root stays transparent so the workspace canvas tone reads behind it. Route cards, forms, tables, lists, and dense content stay solid.
ConnectShellis the disconnected full-screen state with a centered connect prompt and no navigation.- Admin owns
CanvasLayout,CommandPalette,AccountProfilePanel,AccountSettingsPanel,AccountSurface,UserAvatar,UserMenu,ConnectShell, andPageHeader. - Desktop account sheets render
AccountProfilePanelandAccountSettingsPanelas separate right-sheet contents.AccountSurfaceremains the route-level tabbed account surface for mobile profile navigation. - Shared owns
AppBar,NavigationBar,GardenChip,MainSheet,LeftSheet,RightSheet,BottomSheet, andSheetErrorBoundary.
Preferred Primitives
AppBarNavigationBarMainSheetGardenChipCommandPaletteAccountSettingsPanelUserAvatarConnectShellLeftSheetRightSheetBottomSheetPageHeaderListToolbarSortSelectCardAlertStatusBadgeFormFieldAdminDialogAdminConfirmDialog
Surface Primitives
.workspace-canvasis the default canvas workspace treatment..surface-sectioncreates a rounded full-width section wrapper..surface-insetcreates nested panels inside a section..surface-cardcreates interactive tiles.
Dialog Contract
- Admin dashboard modals use
AdminDialogfor form and command-palette surfaces andAdminConfirmDialogfor destructive or confirmation flows. AdminDialogrenders a centered M3 dialog on desktop and a bottom-sheet presentation on mobile.- Dialog actions belong in the pinned
actionsslot. Keep cancel, save, confirm, retry, and close controls outside the scrollable body. - Form and detail content scrolls inside the dialog body, not on the page behind the scrim.
- Every admin dialog must expose a visible surface above the scrim, a non-zero panel rect, accessible title and description wiring, a close or cancel affordance, reduced-motion-safe behavior, and visible pinned actions when there is something to commit or cancel.
- The command palette uses the
palettevariant ofAdminDialogso search behavior and keyboard navigation live inside the same admin modal contract. DialogShellremains available for shared or non-admin surfaces. Do not use it for admin dashboard dialogs.
Canvas UI Heuristics
- Admin is an operator canvas. Use utility copy and operational hierarchy over marketing language.
- Default page sequence is
PageHeader, then the primary workspace, then any secondary inspector or side sheet. - Start with layout and flow before introducing cards or elevated panels.
- Cards and elevated surfaces are for discrete records, action targets, and bounded interaction zones. They are not the default page structure.
- Prefer one dominant workspace surface per route and plain layout within it. Avoid nested stacks of rounded bordered panels.
- Avoid hero sections, decorative promo callouts, and decorative gradients behind routine product UI.
- Use route-tint atmosphere, transparent AppBar continuity, Controlled Chrome depth on navigation/sheets, and high-contrast state accents to establish hierarchy without turning the UI into a promo surface.
- Use
/hubas the reference implementation for canvas composition and interaction density. bun run check:design-tokensenforces the material boundary: admin source must not add glass, backdrop blur, or decorative gradients outsidepackages/admin/src/index.cssandadmin-m3-overrides.css.- Route content, canvas tone changes, FAB menus, sheets, and interaction state use the admin motion role aliases (
--admin-motion-*) layered on top of the canonical--spring-*tokens.
Unified Canvas Route Contract
- Every primary route must answer one operator question, not three.
- The first viewport must show: route title, one short scope sentence, current garden context when applicable, one control row, and the first actionable content.
- Default page anatomy is
PageHeader-> one dominant workspace canvas -> optional secondary inspector (LeftSheet,RightSheet,BottomSheet, or a single rail). - Use one control grammar per route. Choose one of: stage tabs, view tabs, or a list toolbar. Do not stack multiple competing switchers and banners above the workspace.
- Use at most one strong CTA in the header. If a FAB exists for the route, the header should not duplicate the same creation action.
- View-level actions must flow through
ViewAction+AdminViewActionson desktop and the same action set throughuseViewActionsfor tablet/mobile FAB speed dial. Do not add duplicate inline edit buttons inside route bodies for the same action; contextual row actions are allowed when the row is the only discoverable setting control. - Summary metrics are optional and should appear only when they improve decisions. Cap summary strips at three items for operational routes.
- Prefer layout, rows, and sections over card mosaics. Use cards only for discrete records, bounded workflows, or detail modules that need separation.
- Default detail behavior is an inspector or secondary pane, not a new pile of inline cards.
- Use utility copy. Titles identify the workspace. Descriptions explain scope, freshness, or what the operator can do next.
- Keep imagery subordinate to status, title, and actions unless the operator is explicitly reviewing media itself.
- Reduced-motion support is mandatory. Stage changes, row selection, and sheet open/close must retain state clarity without relying on travel or spring lift.
- Route and tab changes should animate only the named route content group. AppBar, Navigation/FAB, and the canvas root stay visually stationary.
Route Roles
/hubis the primary canvas workspace. Its primary object is the Hub workbench with Work, Assess, Certify, and History modes./hubis the gold-standard canvas route for composition, depth, responsive adaptation, and tactile state behavior./hubdefaults to one dominant workbench surface under the stage rail. Detail, review, submit, and read-only handoff flows belong in boundedLeftSheet,RightSheet, orBottomSheetinspectors./hub/work/:workId,/hub/work/submit,/hub/assess/create,/hub/certify/:assessmentId,/hub/certify/create, and/hub/history/:historyEventIdare canonical Hub deep links, not separate full-page detours. They must render through the same Hub controller and preserve shareablegardenAddressandsortquery state. Hub mode belongs to the path, not aviewquery parameter.Certifystays visible for evaluator-only users as a read-only handoff state. Owner or operator authority unlocks mint actions./gardenis the situational overview of a single garden. Its primary object is health, activity, and impact state./communityis the operations workspace for membership, treasury, pools, and yield. Only one of those modes should dominate the canvas at a time./actionsis the action registry and lifecycle workspace. It should feel like a managed catalog, not a marketing gallery.
Route Smells To Reject
/hub: stage navigation should reflect real operating modes rather than placeholder pipelines./hub: header chrome should keep the first actionable queue content within immediate reach./garden: large summary card grids before the operator reaches the actual overview or impact workspace./garden: mixing overview, impact, and settings as visually equivalent tabs without clearly changing page mode./community: a stat strip plus tab switcher plus contextual CTA banner plus card stack before the user reaches the active mode./community: treating treasury, members, pools, and yield as one blended page instead of four focused operational modes./actions: image-led card galleries that make the route read like a promotional browse surface instead of an admin registry./actions: filters that change presentation but never establish a clear “default management view” for scanning and editing records.
Page Families
- List pages:
PageHeader + ListToolbar + filters/sort + loading/empty/error + results - Detail and workbench pages:
PageHeaderor garden hero plus main/rail composition - Operational pages:
PageHeader + stage/tabs + primary workspace + optional inspector
Migration Rules
DashboardLayout,Sidebar, andHeaderare legacy references, not starting points for new work.- Do not add admin-local primitive shims such as
components/ui. - Do not add admin-local config helpers when the behavior belongs beside shared React Query or other shared config.
- Do not introduce package-local
utils/for logic that should live in shared. - Keep reusable components consumed through the
@green-goods/sharedbarrel.