Skip to main content
CharleOS uses Next.js 16 App Router with a feature-based organization. This guide explains how the codebase is structured and where to find (or add) code.

Overview

App Directory (/app)

The app/ directory contains all routes and pages using Next.js App Router.

Route Groups

CharleOS uses route groups to organize pages without affecting URLs:

(dashboard)/ - Main App

The authenticated team member application:
Key features:
  • Shared layout with sidebar navigation
  • Role-based access control
  • Real-time updates via Pusher

client-portal/ - Client Portal

Separate app for clients to view their work:
Separate from main app:
  • Different authentication (Better Auth with client context)
  • Different branding and navigation
  • Restricted to client-facing features only

(auth)/ - Authentication Pages

Team member authentication flow:

api/ - API Routes

All backend API endpoints:
Convention:
  • Each route exports GET, POST, PUT, PATCH, DELETE handlers
  • Use lib/services/ for business logic (keep routes thin)
  • Return structured responses with proper error handling

Special Files

Components Directory (/components)

All React components organized by feature:

Feature-Based Organization

Component Naming

  • PascalCase for components: TaskCard.tsx
  • Feature prefixes for clarity: TaskStatusBadge, QuoteApprovalCard
  • Index files for clean imports: components/tasks/index.ts

UI Components (/components/ui)

Base components from shadcn/ui:
  • Built on Radix UI primitives
  • Styled with Tailwind CSS
  • Fully customizable
  • Don’t edit directly - use composition
Example usage:

Lib Directory (/lib)

Shared utilities, business logic, and configuration:

Services (/lib/services)

Business logic layer - keeps API routes thin:
Pattern:
  • Functions accept validated input
  • Return typed results or throw errors
  • Used by API routes and server components
Example:

Database (/lib/db)

Database schema and client:
Key files:
  • schema.ts - Single source of truth for database structure
  • Types auto-generated from schema
  • All tables, relations, enums defined here

Utils (/lib/utils)

Utility functions grouped by purpose:

Constants (/lib/constants)

Configuration and constants:

Schemas (/lib/schemas)

Zod validation schemas for forms and API:
Usage:

AI (/lib/ai)

AI features (Alan assistant):

Hooks Directory (/hooks)

Custom React hooks for data fetching and state:
Pattern (SWR-based):

Tests

Unit Tests (/__tests__)

Vitest tests for utilities and logic:
Run tests:

E2E Tests (/e2e)

Playwright tests for critical flows:
Run tests:

Other Directories

Drizzle (/drizzle)

Database migrations (auto-generated):
Don’t edit manually - generate with npm run db:generate

Trigger (/trigger)

Background jobs (Trigger.dev):

Emails (/emails)

React Email templates:

Scripts (/scripts)

Utility scripts:

File Naming Conventions

Code Organization Principles

1. Colocation

Keep related code close together:
  • Task components in components/tasks/
  • Task services in lib/services/tasks.ts
  • Task schemas in lib/schemas/task.ts
  • Task API in app/api/tasks/

2. Feature-Based Structure

Organize by feature, not by type: ✅ Good:
❌ Bad:

3. Shared vs Feature Code

  • Shared codelib/, components/ui/, hooks/
  • Feature code → Feature-specific directories

4. Thin Routes, Fat Services

API routes should be thin wrappers:

Adding New Features

When adding a new feature, follow this structure:
1

Create Database Schema

Add tables to lib/db/schema.ts and run npm run db:push
2

Add Service Layer

Create lib/services/your-feature.ts with business logic
3

Create API Routes

Add routes in app/api/your-feature/route.ts
4

Build Components

Add components in components/your-feature/
5

Create Hooks

Add hooks/use-your-feature.ts for data fetching
6

Add Pages

Create pages in app/(dashboard)/your-feature/

Import Paths

CharleOS uses path aliases for clean imports:
Configured in tsconfig.json:
  • @/* → Root directory
  • @/components/* → Components
  • @/lib/* → Library code

Local Setup

Set up your development environment

Database

Working with the database schema

Authentication

How auth is structured

Testing

Writing and running tests