Skip to main content
CharleOS is an agency management system built with modern web technologies. This guide will help you set up your development environment and understand the codebase structure.

Quick Start

Get up and running in minutes:
1

Prerequisites

Ensure you have Node.js 18+, npm, and Git installed
2

Clone & Install

git clone https://github.com/charle-agency/charle-os.git
cd charle-os
npm install
3

Environment Setup

The .env.local file is already in the repository - no need to pull from Vercel
4

Run Development Server

npm run dev
Open http://localhost:3000
See Local Setup for detailed step-by-step instructions.

Tech Stack

CharleOS is built with a modern, type-safe stack optimized for developer experience and performance:

Next.js 16

Framework
  • App Router architecture
  • React 19
  • TypeScript throughout
  • Server components by default

Better Auth

Authentication
  • Google OAuth integration
  • Session management
  • Role-based permissions
  • Client portal access

PostgreSQL + Drizzle

Database
  • Type-safe ORM with Drizzle
  • Hosted on Neon (serverless)
  • Schema-first migrations
  • Drizzle Studio for browsing

Tailwind + shadcn/ui

Styling
  • Utility-first CSS
  • Pre-built components
  • Dark mode support
  • Responsive by default

Full Stack

  • Framework: Next.js 16 (App Router)
  • Language: TypeScript 5
  • Database: PostgreSQL with Drizzle ORM
  • Auth: Better Auth (Google OAuth)
  • Styling: Tailwind CSS 4 + shadcn/ui
  • State Management: SWR for data fetching
  • Forms: React Hook Form + Zod validation
  • Testing: Vitest (unit) + Playwright (E2E)
  • Deployment: Vercel
  • Monitoring: Sentry
  • Search: Algolia

Development Workflow

CharleOS follows a structured development process:
Day-to-day development
  1. Pull latest changes from main
  2. Create a feature branch
  3. Make changes and test locally
  4. Run linters and tests
  5. Push branch and create PR
  6. Deploy preview automatically on Vercel

Project Structure

CharleOS uses Next.js App Router with feature-based organization:
charle-os/
├── app/                      # Next.js App Router
│   ├── (dashboard)/         # Main app (authenticated)
│   ├── client-portal/       # Client-facing portal
│   ├── (auth)/              # Auth pages (sign-in, etc.)
│   └── api/                 # API routes
├── components/              # React components
│   ├── ui/                  # shadcn/ui base components
│   ├── tasks/               # Task-related components
│   ├── quotes/              # Quote-related components
│   └── ...                  # Feature-based organization
├── lib/                     # Shared utilities
│   ├── db/                  # Database schema & queries
│   │   ├── schema.ts        # Drizzle schema
│   │   └── index.ts         # Database client
│   ├── services/            # Business logic services
│   ├── utils/               # Utility functions
│   └── constants/           # App constants
├── hooks/                   # Custom React hooks
├── __tests__/               # Unit tests (Vitest)
├── e2e/                     # E2E tests (Playwright)
└── drizzle/                 # Database migrations
See Project Structure for detailed explanation.

Key Concepts

App Router Architecture

CharleOS uses Next.js App Router with route groups:
  • (dashboard)/ - Main authenticated app for team members
  • client-portal/ - Client-facing portal (separate auth context)
  • (auth)/ - Authentication pages (sign-in, callbacks)
  • api/ - API routes for data fetching and mutations

Server vs Client Components

By default, components are Server Components for better performance:
  • Server Components: Data fetching, static content, no interactivity
  • Client Components: Forms, interactivity, browser APIs
  • Mark with "use client" only when needed

Data Fetching with SWR

CharleOS uses SWR for client-side data fetching:
import useSWR from 'swr';

export function useTaskDetail(id: string) {
  return useSWR(`/api/tasks/${id}`, fetcher);
}
Benefits:
  • Automatic caching and revalidation
  • Optimistic updates
  • Error handling
  • Loading states

Type Safety

Everything is typed with TypeScript:
  • Database schema → Drizzle generates types
  • API routes → Request/response types
  • Components → Props interfaces
  • Forms → Zod schemas for validation

Available Scripts

Common commands you’ll use during development:
CommandDescription
npm run devStart development server at http://localhost:3000
npm run buildBuild production bundle
npm run lintRun ESLint
npm run type-checkRun TypeScript compiler (no emit)
npm run testRun unit tests
npm run test:e2eRun E2E tests
npm run db:pushPush schema changes to database (local dev)
npm run db:generateGenerate migration file (for production)
npm run db:studioOpen Drizzle Studio (visual DB browser)
npm run db:seedSeed development data
See package.json for the full list of scripts.

Getting Help

Documentation

Internal Resources

  • Internal Docs - Check docs/developer/ for technical documentation
  • Code Comments - Complex logic is documented inline
  • Type Definitions - Let TypeScript guide you

Troubleshooting

Common issues and solutions:
Symptom: Error mentioning https://charle.agency when signing in locallyCause: Auth URLs in .env.local are pointing to productionFix: Update .env.local:
BETTER_AUTH_URL="http://localhost:3000"
NEXT_PUBLIC_BETTER_AUTH_URL="http://localhost:3000"
Symptom: Can’t connect to databasePossible causes:
  • DATABASE_URL not set in .env.local
  • VPN interfering with connection
  • Need to re-pull env vars from Vercel
Fix: Run vercel env pull .env.local to get latest credentials
Symptom: Can sign in but see “Pending Approval” messageCause: New accounts start with pending roleFix: Ask an admin to update your role in the database
Symptom: Import errors or missing modulesFix:
# Clear cache and reinstall
rm -rf node_modules .next
npm install

Next Steps