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 imagesKey app-level files
| File | Purpose |
|---|---|
app/app/layout.tsx | True root for all authenticated users; wires <Providers> + <AppShell> (layout.tsx:1–21) |
app/(auth)/layout.tsx | Auth-specific layout; centred card + <AlertContainer> (layout.tsx:6–18) |
app/(marketing)/layout.tsx | Standalone marketing layout; loads Gilroy + DM Mono fonts |
app/api/ext/v2/snippet/route.ts | Embed 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 membershipcore.ts internals worth knowing
buildWorkspaceAwareEndpoint— appends?workspace_id=<id>to any endpoint, reading the active workspace fromworkspaceStore(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 onPOST,PUT,PATCH, andDELETErequests (core.ts:91–111). - On a
401response the wrapper callsauthStore.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, resumeImportBatchIdSee 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, useProcessMonitoruseProcessMonitor 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–25Mounted 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 layerNever 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).
Related pages
- Overview — tech stack, route groups, key conventions
- Routing — full route inventory and middleware
- State management — Zustand stores + TanStack Query patterns ★
- Finder Builder v2 — section components, history reducer, dispatch pattern ★
- Architecture overview