Folder Structure

A guided map of the web/ directory — what lives where, and why.

Every chapter in this handbook refers to folders inside web/ (the web application’s home at the repository root). This page is the map: the whole tree at a glance, then a short tour of each area. The organizing idea is simple — app/ is what the app shows and serves (every folder there is a URL), and everything else is what the app is built from (components, modules, shared logic) or how it is built and checked (configuration, tests, scripts).

The tree at a glance

web/
├── app/                ← the routes: every folder here becomes a URL
│   ├── (public)/         landing page, login, signup
│   ├── (authenticated)/  the product: workspaces, datasets, settings …
│   ├── api/              ← the app's own backend: 97 route handlers
│   ├── api-docs/         the interactive Swagger page
│   ├── auth/             login callbacks, email confirm, password reset
│   └── layout.tsx        root layout — wraps every page in the providers
├── middleware.ts       ← runs before every request: session refresh,
│                         workspace redirects
├── components/         ← reusable UI building blocks (see Component Library)
├── modules/            ← self-contained feature modules (gallery,
│                         photo-map-3d, gas-heatmap, thermal-pair-viewer,
│                         cad-viewer, dataset-onboarding)
├── lib/                ← shared non-UI logic: Supabase clients, AG-UI,
│                         cloud storage, workspace registry, JWT …
├── hooks/              ← shared React behavior (17 use-* hooks)
├── providers/          ← global context providers: session, organization,
│                         theme
├── public/             ← files served as-is: icons, manifest, service
│                         worker, the Swagger spec (api-docs/swagger.yaml)
├── styles/             ← global CSS and the design-system tokens
├── tests/              ← Vitest suites (api, components, integration) and
│                         Playwright end-to-end specs
├── playwright/         ← Playwright's working directory
├── scripts/            ← maintenance scripts: Supabase type generation,
│                         Cesium asset copy, test runners
├── types/              ← extra TypeScript declarations
├── assets/ templates/ stories/   ← demo CAD file, design wireframes,
│                                   component stories
└── package.json, next.config.js, tailwind.config.js, tsconfig.json,
    components.json, vitest*.config.ts, playwright.config.ts,
    Dockerfile, apphosting.yaml          ← build, test & deploy config

app/ — the routes

KAP uses Next.js’s App Router, whose core convention is: the folder tree is the URL structure. A folder app/datasets/[slug]/ with a page.tsx inside renders at /datasets/<some-dataset>; square brackets mark the variable parts. Three special ideas explain the rest:

  • Route groups — folder names in parentheses, like (public) and (authenticated), organize routes without appearing in the URL. Their job here is to give the two halves of the app different wrappers: pages in (public)/ (landing, login, signup) get the marketing chrome, while pages in (authenticated)/ get the signed-in app shell. Inside (authenticated)/ live the product surfaces: w/ — the workspaces (/w/data-explorer, /w/integrity, covered in Workspaces) — plus datasets, organizations, settings, profile, insights, anomalies, and the CAD viewer.
  • app/api/ — the backend. Folders here define API route handlers instead of pages: code the browser calls for data rather than screens a person visits. This is the 97-handler backend documented in Backend API & Swagger; app/api-docs/ is the page that renders its Swagger documentation.
  • layout.tsx files wrap everything below them. The root app/layout.tsx wraps every page in the global providers (session, organization, theme — from providers/); each route group adds its own layout on top.

A few top-level entries (app/dashboard/, app/datasets/create/, app/auth/…, app/onboarding/) predate the route groups and live directly under app/ — same conventions, just outside the two groups.

The complete list of the URLs this tree produces — every page route, in plain English — is the Page Route Inventory.

Alongside app/ sits middleware.ts — not a route, but the code that runs before every request: it refreshes the caller’s Supabase session and redirects users to the right workspace (see the architecture diagram).

components/, modules/ — what screens are built from

  • components/ holds the reusable UI building blocks, from the ~50 generic primitives in components/ui/ up through the workspace shell and feature components. It has its own chapter with the full tree and inventory.
  • modules/ holds the six self-contained feature modules — gallery, photo-map-3d, gas-heatmap, thermal-pair-viewer, cad-viewer, and dataset-onboarding. Each is a mini-application with its own internal core/, ui/, shared/, services/, and overlays/ folders and a single public entry point (index.ts); the heavy 3D/viewer surfaces live here. How modules plug into workspaces is the subject of Workspace Modules.

lib/, hooks/, providers/ — shared logic

  • lib/ is the app’s shared non-UI logic, used by both server and client code. The load-bearing residents: supabase/ (the browser, server, and admin database clients), ag-ui/ and chat/ (the assistant’s client plumbing), workspaces/ (the workspace registry — modules, navigation, permissions, scope), cloud-storage.ts (GCS/Azure access), jwt.ts, tts/, services/, and the generated database types (database.generated.ts).
  • hooks/ holds shared React behavior — 17 use-* hooks (AG-UI client and events, auth tokens, chat history, network status, local storage …). Components stay presentational; stateful behavior lives here.
  • providers/ holds the three global context providers — session, organization, theme — that the root layout wraps every page in.

public/, styles/ — served as-is, and the look

  • public/ is served verbatim at the site root: icons and logos, the PWA manifest.json and service worker sw.js, map markers — and api-docs/swagger.yaml, which is why the raw spec has a stable URL.
  • styles/ holds globals.css and the design-system/ tokens; tailwind.config.js at the root turns those tokens into the utility classes components use.

tests/, playwright/, scripts/ — checking and upkeep

  • tests/ is organized by kind: api/ (route-handler tests), components/, integration/, and e2e/ (Playwright browser specs), with shared mocks/ and setup files. The Vitest configs at the root (vitest.config.ts, vitest.components.config.ts) and playwright.config.ts wire them up.
  • scripts/ holds maintenance tooling — regenerating Supabase types (generate-supabase-types.mjs), copying Cesium’s static assets, test runners, and deploy helpers (apphosting/).

The root config files

File What it controls
package.json Dependencies and the npm run commands (dev, build, test)
next.config.js Next.js build behavior
tsconfig.json TypeScript rules and the @/… import alias
tailwind.config.js The design tokens available as utility classes
components.json Where the shadcn/ui generator puts new primitives
middleware.ts The every-request gatekeeper (see above)
Dockerfile, apphosting.yaml How the app is containerized and deployed

Last Updated: 2026-07-30