These docs are a work in progress and may not be fully up to date. Some pages may contain internal notes for our team.
Skip to Content

Next.js — directory structure

Annotated map of src/ and the top-level repo layout. All paths are relative to the repo root (dropafinder-app-nextjs/).

Top-level repo layout

dropafinder-app-nextjs/ ├── public/ Static assets served at the root URL (fonts, images, favicon) ├── src/ All application source code ├── AGENTS.md Repo-internal conventions (BEM, API layer, mutation patterns) ├── next.config.mjs Next.js config — path aliases, environment variable exposure ├── package.json Dependencies and npm scripts └── tsconfig.json TypeScript compiler config (strict mode, `@/` path alias → `src/`)

src/app/ — App Router

Next.js App Router tree. Route groups use parenthesised directory names to scope layouts without adding URL segments. See Routing for the full route inventory and middleware detail.

src/app/ ├── (auth)/ Authentication group — own root layout, no dashboard chrome │ ├── login/ /login │ └── register/ │ └── [token]/ /register/:token — invitation-based registration ├── (marketing)/ Public marketing pages — own root layout, no Providers wrapper ├── (preview)/ Internal dev previews — bare layout with overflow:hidden │ ├── finder-builder-v3-poc/ Sandbox for the v3 builder (not customer-facing) │ └── finder-preview/ Standalone finder preview ├── app/ Authenticated dashboard — URL prefix /app/* │ ├── layout.tsx Root layout: imports globals.scss, mounts <Providers> + <AppShell> │ ├── AppShell.tsx Sidebar + top bar chrome │ ├── dashboard/ /app/dashboard — home overview │ ├── finders/ │ │ └── [id]/ │ │ ├── [section]/ /app/finders/:id/:section — section-based builder editing │ │ └── analytics/ /app/finders/:id/analytics │ ├── locations/ /app/locations │ ├── sets/ /app/sets │ ├── maps/ /app/maps │ ├── tags/ /app/tags │ ├── custom-fields/ /app/custom-fields │ ├── workspaces/ /app/workspaces — workspace switcher and management │ ├── billing/ /app/billing — Paddle billing integration │ ├── changelog/ /app/changelog — in-app changelog viewer │ ├── account/ /app/account — user account settings │ └── admin/ /app/admin — internal admin panel (role-gated) └── api/ ├── ext/ │ └── v2/ │ └── snippet/ GET — serves the embed widget JS (local build or CDN proxy) └── map-style-preview/ GET — serves map style preview images

Key app-level files

FilePurpose
app/app/layout.tsxTrue root for all authenticated users; wires <Providers> + <AppShell> (layout.tsx:1–21)
app/(auth)/layout.tsxAuth-specific layout; centred card + <AlertContainer> (layout.tsx:6–18)
app/(marketing)/layout.tsxStandalone marketing layout; loads Gilroy + DM Mono fonts
app/api/ext/v2/snippet/route.tsEmbed widget proxy; prefers local build in dev, falls back to CDN (route.ts:1–44)

src/components/ — React components

Feature-organised component library. BEM class naming is required for all new CSS; violations in existing files must be fixed in the same editing pass (AGENTS.md:13–22).

src/components/ ├── auth/ Login and registration form components ├── billing/ Paddle billing UI (plan selector, usage meters, upgrade prompts) ├── branding/ Brand-related UI elements ├── finders/ │ ├── edit/ Lightweight inline edit controls shared across sections │ ├── v2/ Finder Builder v2 — the current production builder │ │ ├── FinderBuilderV2.tsx Root builder component; owns the section router │ │ ├── BuilderSidebar.tsx Left-side section navigation │ │ ├── LivePreview.tsx Iframe preview pane; communicates via postMessage │ │ ├── aiHub/ AI assistant panel (import + improvement flows) │ │ ├── importFlow/ Guided import wizard │ │ └── sections/ One subdirectory per builder section (appearance, locations, etc.) │ │ └── _shared/ Section-level shared primitives (inputs, toggles, pickers) │ └── v3/ Finder Builder v3 POC — work in progress, not yet customer-facing ├── layout/ Global layout primitives (sidebar, top bar, nav items) ├── map/ MapLibre / react-map-gl wrappers and map-related controls ├── modals/ Modal dialogs (confirmation, delete, create-workspace, etc.) ├── onboarding/ First-run onboarding flow components ├── panels/ │ ├── create/ Slide-out panels for creating resources (location, finder, tag, set…) │ └── update/ Slide-out panels for editing existing resources ├── search/ Global search and autocomplete components ├── settings/ Account and workspace settings forms └── ui/ Low-level design system atoms (Alert, Button, Input, Select, Spinner…)

💡 Tip: The components/finders/v2/ subtree is the most complex area of the codebase. For an in-depth walkthrough of the section component pattern, history reducer, and LivePreview postMessage bridge, see Finder Builder v2.

src/lib/ — utilities and API layer

Business logic, API wrappers, and configuration helpers. All API calls to the backend must go through fetchAPI or fetchExt from core.ts — never raw fetch() (AGENTS.md:42–44).

src/lib/ └── api/ ├── core.ts fetchAPI / fetchExt wrappers; auth headers, workspace scoping, audit headers, 401 auto-logout ├── index.ts Re-exports all domain modules for clean import paths ├── normalizers.ts Response normalizers — convert raw API shapes to typed front-end models ├── payloads.ts Payload transformers — convert front-end state to API request bodies ├── account.ts /account endpoints ├── admin.ts /admin endpoints ├── aiImports.ts AI location import endpoints ├── aiImprovements.ts AI location improvement endpoints ├── auth.ts Login, logout, register, token refresh ├── billing.ts Paddle billing endpoints ├── customFields.ts Custom field CRUD ├── finders.ts Finder CRUD and publish ├── locations.ts Location CRUD and bulk operations ├── maps.ts Map CRUD ├── processes.ts Background process polling and event streaming ├── sets.ts Set CRUD ├── tags.ts Tag CRUD └── workspaces.ts Workspace CRUD and membership

core.ts internals worth knowing

  • buildWorkspaceAwareEndpoint — appends ?workspace_id=<id> to any endpoint, reading the active workspace from workspaceStore (core.ts:24–35). Call this for every workspace-scoped request.
  • Audit headers (X-Audit-Request-Id, X-Audit-Action, X-Audit-Resource-Type, X-Audit-Resource-Id) are appended automatically on POST, PUT, PATCH, and DELETE requests (core.ts:91–111).
  • On a 401 response the wrapper calls authStore.logout() and redirects to /login (core.ts:144–147).

src/stores/ — Zustand client state

Four Zustand stores cover all global client state. All stores are client-side ('use client' directive). authStore and workspaceStore use the persist middleware.

src/stores/ ├── authStore.ts Authenticated user: token, userId, email, role, subscription status, 2FA flags, permissions │ Persists to localStorage key "user" (shared with the legacy Svelte app — authStore.ts:51) ├── workspaceStore.ts Active workspace: activeWorkspaceId + activeWorkspaceName │ Persists to localStorage key "active-workspace" (workspaceStore.ts:30) ├── uiStore.ts Transient UI state: active slide-out panel + panelData, alert queue │ addAlert() is the required way to surface errors to users (AGENTS.md:62) └── processStore.ts Background process tray: isTrayOpen, focusedProcessId, resumeImportBatchId

See State management for the full store API and TanStack Query patterns.

src/hooks/ — custom hooks

src/hooks/ └── useProcessMonitor.ts Background process monitor — polling + SSE event streaming Exports: useProcess, useProcessEvents, useProcessStream, useProcessMonitor

useProcessMonitor is the single hook that manages long-running background jobs (AI import, bulk operations). It combines TanStack Query polling (3-second interval while a process is queued or running) with a ReadableStream SSE connection for real-time event delivery (useProcessMonitor.ts:36–151). When a terminal status (completed, failed, cancelled, waiting_review) arrives via SSE, it invalidates the ['process', processId] query key to sync polling state (useProcessMonitor.ts:121–123).

src/providers/ — context providers

src/providers/ └── Providers.tsx Composes ThemeProvider (next-themes, data-theme attribute) + QueryClientProvider (5-min staleTime, 1 retry) — Providers.tsx:7–25

Mounted at the root of both app/app/layout.tsx and app/(auth)/layout.tsx. The (marketing)/ layout does not use this provider tree.

src/sass/ — global styles and design tokens

src/sass/ ├── globals.scss Entry point imported by app/app/layout.tsx and (auth)/layout.tsx ├── _v2-tokens.scss $v2- prefixed SCSS variables + --color-* custom properties (AGENTS.md:64–66) ├── _colors.scss Base colour palette ├── _typography.scss Type scale definitions ├── _forms.scss Form element base styles ├── _buttons.scss Button base styles ├── _settings.scss Breakpoints, spacing scale, z-index ladder ├── _mixins.scss Reusable SCSS mixins └── _reset.scss CSS normalisation layer

Never hardcode hex values or pixel values that have a corresponding $v2- token or var(--color-*) custom property (AGENTS.md:64–66).

src/types/ — TypeScript type definitions

src/types/ ├── index.ts Re-exports all domain types for clean `@/types` imports ├── auth.ts User, AuthState shapes ├── finders.ts Finder, FinderPayload, section-level config types ├── locations.ts Location, LocationPayload ├── sets.ts Set types ├── maps.ts Map types ├── tags.ts Tag types ├── customFields.ts CustomField types ├── workspaces.ts Workspace, WorkspaceMember ├── processes.ts Process, ProcessEvent (status enum: queued/running/completed/failed/cancelled/waiting_review) ├── search.ts Search result types ├── billing.ts Subscription tier / status types ├── ui.ts Alert, PanelType, and other UI-state types ├── aiImports.ts AI import job types ├── aiImprovements.ts AI improvement job types ├── admin.ts Admin-specific types └── global.d.ts Ambient declarations (e.g. window extensions)

All object shapes use interface; unions and aliases use type. Import type-only with import type (AGENTS.md:36–40).