Skip to content

Tier System

All features live in their access tier, not by component type. This enables code splitting (admin code never ships to a logged-out visitor), security isolation, and predictable structure.

src/tiers/
  landing/   ← Marketing / landing pages (eager-loaded)
  user/      ← Authenticated dashboard features — LARGEST TIER
  admin/     ← Admin-only (role admin / super_admin)
  public/    ← Unauthenticated public renderers (/b /s /w)

Features by tier (current)

TierFeatures
userbiolink, business-card, dashboard, digital-menu, engagements, onboarding, profile, qr-generator, reminders, settings, website-builder
publicdigital-menu, feedback-forms
admin(tier scaffolded; features being built)
landingpages/ only (no feature dirs)

A feature with both a dashboard and a public display owns both halves in parallel dirs (e.g. tiers/user/features/digital-menu + tiers/public/features/digital-menu); shared data-model types go in the shared core.

Feature directory structure

Every feature is tiers/{tier}/features/{name}/:

pages/        ← Route-level page components
components/   ← Feature-specific UI
hooks/        ← Feature data hooks (supabase.rpc reads live here)
services/     ← EF call wrappers (supabase.functions.invoke lives here)
utils/        ← Pure computation
tests/        ← Co-located Vitest suites
types/        ← (TS-first) domain types
schemas/      ← (TS-first) Zod schemas
constants/    ← (TS-first) incl. the EDGE_FN map

digital-menu is the reference feature — model new features on it.

Routing

Top-level routing in src/routes/index.jsx:

RouteLoadingGuard
/, /login, /signup, /admin/logineager
/b/:slug, /s/:slug, /w/:sluglazypublic
/onboardinglazyProtectedRoute
/dashboard/*eager shell, lazy featuresProtectedRoute → user tier
/admin/*lazyAdminRoute (admin / super_admin)

Public feature routes are mounted from tiers/public/features/{feature}/routes/index.jsx — follow this pattern for new public routes.

Cross-tier import rules [ENFORCED]

  • public/user/, admin/
  • user/admin/
  • All tiers may import global src/components, src/lib.
  • Features import UI from their tier's components/ui/, not the global directly.

Auth & route guards (current)

  • src/contexts/SupabaseAuthContext.jsxuseAuth/useSupabaseAuth: user, session, loading, userRole, roleLoading, signIn/Up/Out. Role from profiles.role (fallback metadata, default 'user').
  • src/components/ProtectedRoute.jsx — gates /dashboard/*; admins bypass the onboarding redirect.
  • src/components/AdminRoute.jsx — gates /admin/*.

Two "shared" locations [TRANSITIONAL]

src/shared/ (intended-canonical) vs legacy top-level src/{components,contexts,hooks,lib,pages,stores}/ (still live — SupabaseAuthContext.jsx, ProtectedRoute.jsx, AdminRoute.jsx are here). Prefer src/shared/; reconcile the two .../components/ui folders into the UI Hybrid System during retrofit.