National Commerce Docs

Architecture

How the National Commerce web app fits together — stack, structure, and patterns.

This page explains how the code fits together. It helps developers find their way around and follow the team's patterns.

Tech stack

The web app uses these tools:

  • Next.js 15 with the App Router — renders pages and runs server code.
  • React 19 and TypeScript — build the interface.
  • Supabase — stores data in PostgreSQL and signs users in.
  • Cloudflare Workers with Hono — run background and edge jobs.
  • Tremor Raw, Radix UI, and Tailwind CSS — style the interface.
  • TanStack Query — fetches and caches data on the client.
  • React Hook Form and Zod — build and validate forms.
  • Biome — lints and formats the code.
  • Turborepo with pnpm — manages the monorepo.

Monorepo layout

The repo holds several apps and shared packages:

apps/
├── web/          # The Next.js web app (this documentation covers it)
├── worker/       # Cloudflare Worker that builds reports and sends email
├── docs/         # This documentation site (Fumadocs)
├── mcp/          # Model Context Protocol server
└── shipping-audit-tool/

packages/
├── ui/           # Shared UI components
├── supabase/     # Supabase client and generated types
├── emails/       # React Email templates
├── client-config/
└── typescript-config/

Web app structure

The web app splits its code by role:

apps/web/
├── app/          # Pages and API routes (App Router)
├── components/   # Shared components (layout, UI, admin)
├── features/     # Feature modules (the core of the app)
├── lib/          # Shared logic (auth, zones, sku-sync)
├── hooks/        # Shared React hooks
├── utils/        # Supabase client helpers
└── middleware.ts # Protects routes and refreshes sessions

Route groups

The App Router groups routes by access level:

  • app/(auth) — public sign-in and password pages.
  • app/(onboarding) — the setup wizard for new users.
  • app/(authenticated) — every screen behind sign-in.
  • app/api — server endpoints the front end calls.

Feature modules

Each feature lives in apps/web/features/ and follows one shape:

feature-name/
├── components/   # React components for the feature
├── actions/      # Server Actions that write data
├── hooks/        # Custom React hooks
├── types/        # TypeScript types
└── utilities/    # Helper functions

This layout keeps a feature's code in one place. New work usually starts here.

How data moves

The app fetches and writes data three ways:

  1. Server Components load static or slow-changing data on the server.
  2. TanStack Query with Server Actions loads dynamic data and updates it.
  3. API routes serve the client and handle cron and integration calls.

The Data Flows page shows how data moves between ShipHero, the worker, N8N, and Supabase.

Authentication and access

Supabase Auth signs users in. The middleware.ts file guards routes and refreshes each session.

Row-Level Security (RLS) protects every table. Users see only the accounts they may access. Admin-only screens add a second guard in the app.

Key patterns

Follow these rules when you build screens:

  • Put MainLayout in each page.tsx, never in layout.tsx.
  • Show skeleton components while data loads. Never print "Loading...".
  • Truncate text with the TruncatedText component.
  • Add type="button" to every button that does not submit a form.
  • Keep dialogs open during async work.

The repo's CLAUDE.md file lists the full set of rules.

On this page