Skip to content

Project Structure Guide

Mahid Ahmad edited this page Aug 16, 2025 · 1 revision

This document is a companion to the Development Guide. It focuses exclusively on the codebase layout and how to work within each directory of the LangRoute monorepo.


1. Purpose & Scope

This guide helps both new and existing contributors understand how the LangRoute project is structured. It aims to:

  • Clarify the directory and file organization philosophy
  • Explain where different types of logic (UI, API, DB, validation, etc.) should go
  • Describe how to extend the system with new routes, services, or utilities

What this guide covers:

  • Routing (UI and API) with Next.js App Router
  • Cross-cutting utilities and shared runtime logic
  • Suggested structure for backend business logic and future expansion

What this guide does not cover:

  • Code formatting, linting, commit conventions
  • GitHub workflows, branching, or PR standards

These remain in the Development Guide.


2. Bird’s-Eye Directory Map

├── src
│   ├── app                   # Next.js routes (UI + API)
│   │   ├── (client)/         # Client routes, layouts, UI, providers
│   │   │   ├── (auth)/       # Auth routes (login, register, forgot-password)
│   │   │   ├── (dashboard)/  # Dashboard routes
│   │   │   ├── layout.tsx    # Client layout (navbar, auth guards)
│   │   │   ├── page.tsx      # Home page
│   │   │   └── providers/    # App-wide providers
│   │   └── (server)   				# Server routes, API endpoints, services
│   │       ├── api/          # API routes
│   │       └── services/     # Backend-only business logic
│   ├── db/                   # Prisma client
│   ├── lib/                  # Shared runtime helpers (config, middleware, validation, models, utils)
│   ├── shadcn-ui/            # UI primitives
│   ├── types/                # Global TS declarations
│   └── ...

Note: Some planned directories like ws/ and workers/ are not yet created. Others like services/ are still evolving and may be restructured significantly. Treat the current layout as suggested, not final.

Each folder is explained in detail below.


3. src/app/ — Route Layers

This is the heart of the frontend routing system, powered by Next.js App Router. Pages and layouts are defined by the file system.

3.1 Route Groups

LangRoute uses named route groups like:

  • src/app/(client)/(auth)/...
  • src/app/(client)/(dashboard)/...

These help logically separate routes (e.g. login/register vs dashboard) while keeping clean URLs like /login, /dashboard.

Inside each group:

  • layout.tsx defines layout wrappers (navbar, auth guards, etc.)
  • page.tsx defines route content
  • loading.tsx or error.tsx (optional) handle async and error states

Example:

src/app/(client)/(auth)/login/page.tsx  →  /login
src/app/(client)/(dashboard)/dashboard/page.tsx   →  /dashboard

3.2 API Routes

Next.js App Router supports API endpoints under:

```src/app/(server)/api/{resource}/route.ts```

LangRoute follows these API conventions:

  • RESTful structure (/apikeys, /usage)
  • Zod validation inside handlers
  • Keep handlers thin: delegate to services

4. Providers

4.1 Folder Purpose

src/app/(client)/providers/ contains individual React context providers, such as:

  • AuthProvider
  • QueryProvider
  • ToastProvider

4.2 Composition Pattern

A single AppProviders component composes all individual providers.

src/app/(client)/providers/Providers.tsx wraps the app like this:

export default function Providers({ children }) {
  return <AppProviders>{children}</AppProviders>
}

4.3 Adding a New Provider

  1. Create a file in src/app/(client)/providers/{YourProvider}.tsx
  2. Export the provider component
  3. Add it to AppProviders in the correct order

5. Components

5.1 Global Components

Located in: src/app/(client)/components/

  • Use for reusable UI (buttons, tables, modals)
  • Should follow PascalCase file naming
  • Export from components/index.ts for shorter imports

Example: import { Button } from '@/app/(client)/components'

5.2 Route-Scoped Components

UI specific to a page should live next to the page inside: src/app/(client)/(group)/feature/components/

Only promote components to global if they’re reused across multiple, unrelated routes.

5.3 Styling

  • Tailwind CSS is preferred
  • Use cn() utility from @/lib/utils for conditional classes
  • For Shadcn UI variants, use cva() via class-variance-authority (if/when added)

6. Hooks

6.1 Folder Sub-structure

Current hook categories:

  hooks/
  	├── data/     → React Query hooks (API calls)
  	├── forms/    → React Hook Form + Zod
  	└── ...

Future categories (optional):

  • ui/ for Zustand-based UI state
  • utils/ for generic hooks like useDebounce

6.2 Guidelines

  • Hooks should always begin with useX
  • Do not use Zustand for server/remote data fetching
  • Avoid duplication between hooks and services

7. lib/ — Shared Runtime Helpers

This folder houses all utilities, validators, and singleton clients.

7.1 @/db/prisma — Prisma Client

import { prisma } from '@/db/prisma'
  • Only import into backend files
  • Avoid instantiating Prisma multiple times (handled internally)

7.2 lib/redis/ — Redis Client

import { redis } from '@/lib/redis/redis'
  • Used for rate limits, pub/sub, live logs
  • More logic will be added here later

7.3 lib/config/

  • routesConfig.ts → defines public routes & middleware matchers
  • More config files like defaults.ts may be added
  • Always export from lib/config/index.ts

7.4 lib/validation/

  • For shared Zod schemas
  • Keeps frontend and backend validation in sync

7.5 lib/models/ — Domain Interfaces & DTOs

This folder contains core TypeScript types:

  • User.ts, ApiModels.ts, etc.
  • DTOs like CreateKeyPayload.ts, UsageReport.ts
  • Enum-like types (ProviderName, Role)

Usage:

import { User, ApiModels } from '@/lib/models'

Rules:

  • No runtime logic inside
  • Export everything through lib/models/index.ts
  • Keep in sync with Prisma schema and API contracts

8. Services (backend-only)

⚠️ Disclaimer: The services structure is early and may change. This section reflects the current state only.

  • Encapsulates backend business logic
  • Should never be imported in frontend code

Current Subfolders

services/
  ├── adapters/       # Logic for external integrations
  ├── auth/           # Auth-related services (e.g., token validation)
  ├── proxy/          # Proxy-related services (e.g., API request forwarding)
  ├── usage/          # Usage tracking services
  ├── keys/           # API key management services (e.g., create, revoke, rotate)
  ├── logs/           # Log-related services (e.g., Redis pub/sub for live logs)
  ├── analytics/      # Analytics services (e.g., cost, tokens, latency tracking)

These may contain logic for:

  • Token proxying
  • API key validation
  • Usage logging

Service Guidelines

Each service should be:

  • Pure (no req/res objects)
  • Callable from routes or jobs
  • Tested in isolation if possible
  • Export from services/index.ts

workers/ and ws/

May eventually house:

  • Background workers (usage alerts, key revocation)
  • WebSocket log stream publisher

9. Middleware

9.1 Root Middleware (src/middleware.ts)

This file runs on every request and handles:

  • Auth enforcement
  • Rate-limiting (future)
  • Skips public routes via matcher config

9.2 Helpers (src/lib/middleware/)

Shared functions (e.g., verifyApiKey, rateLimit) go here and are used by:

  • Middleware
  • API handlers
  • Services

10. Realtime & Workers

These directories don’t exist yet, but will be added soon.

  • ws/ — WebSocket gateway (e.g. logs via Redis pub/sub)
  • workers/ — background jobs (usage alerts, email queue)

These will be wired via Docker Compose services.


11. Types

11.1 Declarations Layout

  • src/types/next-auth.d.tsNextAuth module augmentation (User/Session/JWT types).
  • src/types/global.d.tsproject-wide ambient types (e.g., custom globals, env-safe helpers).

11.2 Guidance

  • Extend NextAuth types only in next-auth.d.ts to keep auth concerns isolated.
  • Keep global.d.ts minimal; use it for true ambient declarations that don’t fit a feature module.
  • Prefer colocated, exported interfaces/types in src/lib/models/ for domain types and import them where needed (avoid leaking runtime logic into models).

12. Environment & Config

12.1 Environment files

  • Template lives at env/.env.example.
  • The root .env is generated/updated by project scripts:
    • npm run dev → prepares the root .env (via scripts/prepare-env.mjs) and starts the dev server.
    • You generally should not edit the root .env directly; update your local values under env/ and re-run the dev script.

See scripts/dev.mjs and scripts/prepare-env.mjs for the exact flow.

12.2 YAML Config (Future)

Currently included: sample-config-yaml-file-for-models

This will evolve into a proper config.yaml for:

  • Provider metadata
  • Rate/cost tables
  • GitOps seeding (first boot → populate DB)

13. Frontend vs Backend Summary

Frontend Backend
Feature folders under src/app/(client)/(group)/{feature}/ API routes under src/app/(server)/api/{resource}/route.ts
Global UI components in src/app/(client)/components/ Business logic in src/app/(server)/services/
Typed fetch hooks in src/app/(client)/hooks/data/ (TanStack Query) Database access via Prisma (db/prisma.ts)
Route-specific UI lives alongside the page in src/app/(client)/(group)/feature/components/ Root middleware in middleware.ts (auth, public-route matcher)
Forms in src/app/(client)/hooks/forms/ using Zod + RHF Input validation via shared Zod schemas in lib/validation/
Tailwind CSS via utility classes; custom classes via @apply in globals.css (if reusable) Redis helpers and rate limiting logic in lib/redis/ (planned)
Shared types/interfaces in lib/models/ Config and constants in lib/config/
App-wide providers in src/app/(client)/providers/ and composed in src/app/(client)/providers.tsx Pure service functions — no req/res — callable from jobs or routes

14. FAQ

  • Pre-commit hook fails? Use git commit --no-verify
  • Component tries to import a service? That’s a layering violation — move logic to a hook.
  • WebSocket not connecting? Make sure Redis is running in dev mode.

This guide is a living document. As the LangRoute project evolves, so will the structure and conventions. Please contribute updates or suggestions to keep it relevant for all developers.