Skip to content

Features: shared vs role pages

Default: one shared feature page, gated by permissions. Split into role-specific pages only when the workflow itself is different — not when a button should be hidden.

Related: Domains · Permissions · Shared pages.


Decision

ChooseWhen
Shared pageMultiple roles use the same workflow; only actions / fields differ
Role pageSemantics or layout are genuinely unique to one role (e.g. a role dashboard)

Use shared pages when

  • The same list/detail/create flow serves several roles
  • Differences are “can approve” vs “can only view” — permission IDs, not separate routes
  • You would otherwise copy-paste three near-identical pages

Use role pages when

  • The primary job of the screen is role-specific (admin ops dashboard vs employee home)
  • Shared CRUD would force awkward conditionals that obscure the UX

Current state

KindExamples
SharedUsers, maintenance, departments, system (monitor / logs / audit / settings), shared account surfaces
Role-specificRole dashboards (admin, hod, developer, employee, …)

Shared page structure

Under domains/shared/pages/<feature>/:

text
list/index.tsx
list/skeleton.tsx
detail/index.tsx
detail/skeleton.tsx
create/index.tsx
create/skeleton.tsx
  • Keep skeletons local so loading UI matches that page and stays permission-aware
  • Data: TanStack Query hooks + lib/services/* — not ad-hoc fetch in the page
  • Actions: hasPermission('…') before showing privileged controls

Anti-patterns

  • /admin/users and /hod/users as two copies of the same list
  • Hiding a whole shared feature behind a role folder “for convenience”
  • Checking user.role === 'administrator' in the page when a permission ID exists