Skip to content

Domain placement rules

Frontend feature code is organized by domain ownership, not by “which role logged in.” Shared workflows live once; role folders keep only unique experiences.

Related: Features · Routing · Shared pages.


Layout (high level)

text
apps/web/src/
  domains/
    shared/pages/     # multi-role workflows (users, maintenance, system, …)
    admin/pages/      # admin-only experiences (e.g. dashboard)
    hod/pages/        # department-head-only surfaces
    …                 # other roles as needed
  lib/services/       # HTTP (not UI)
  context/            # app shell state
  query/              # TanStack keys + shared query helpers
  router/             # routes + guards

Rules

  1. Shared by default — If more than one role uses the same workflow, put the page under domains/shared/pages/<feature>/.

  2. Gate with permissions — Visibility of actions differs by permission; do not copy the whole page per role.

  3. Role folders are exceptions — Dashboards or flows that are semantically unique to one role stay under domains/<role>/pages/.

  4. Folder-per-page — Shared features use:

    text
    users/list/index.tsx + skeleton.tsx
    users/detail/index.tsx + skeleton.tsx
    users/create/index.tsx + skeleton.tsx

    Same pattern for maintenance (and other shared CRUD). Skeletons stay local to the page so loading UI matches that surface.

  5. No server lists in context — Lists/details go through TanStack Query; context is app shell only (context).


Current placement (examples)

FeatureLocation
Users managementdomains/shared/pages/users/*
Maintenancedomains/shared/pages/maintenance/*
Departmentsdomains/shared/pages/departments/*
System (monitor, logs, audit, settings)domains/shared/pages/system/*
Admin dashboarddomains/admin/pages/dashboard/* (role-specific)

Why this shape

  • One implementation of each workflow → fewer bugs when permissions change
  • Clear ownership for contributors (“edit shared users list, not three role copies”)
  • Matches backend permission IDs instead of hard-coded role branches in every page

When in doubt: shared page + permission checks, then extract a role page only if the UX truly diverges.