Directory overview
OpenCouncil follows a standard Next.js 14 App Router structure with clear separation of concerns.App directory
Theapp/ directory contains all routes using Next.js App Router conventions.
Locale-based routing
OpenCouncil usesnext-intl for internationalization. All routes are nested under [locale]/ to support multiple languages:
API routes
API endpoints are organized by domain:Components directory
Components are organized by domain with a specialui/ directory for base components.
Base UI components
Located incomponents/ui/, these are built with Radix UI primitives and Tailwind CSS:
These components use
class-variance-authority for component variants and follow the Radix UI design system.Domain components
Domain-specific components are organized by feature:Dev-only components
Components incomponents/dev/ must never be imported statically in production code:
Lib directory
Thelib/ directory contains all business logic, utilities, and external service integrations.
Data access layer
All database queries are centralized inlib/db/. See the Data Access guide for detailed patterns.
Service integrations
Each external service has its own file:AI
lib/ai.ts - Anthropic Claude for summaries and chatSearch
lib/search/ - Elasticsearch full-text searchStorage
lib/s3.ts - DigitalOcean Spaces for medialib/email/ - Resend for authentication and notificationsDiscord
lib/discord.ts - Admin alerts and notificationsCalendar
lib/google-calendar.ts - Event schedulingUtilities
Utility functions are organized by purpose:Technology stack
OpenCouncil is built with modern, type-safe technologies:Framework: Next.js 14
Framework: Next.js 14
- App Router for file-based routing
- Server Components by default
- Server Actions with
"use server"directive - TypeScript in strict mode
Database: PostgreSQL + Prisma
Database: PostgreSQL + Prisma
- PostgreSQL 14+ with PostGIS extension for geographic data
- Prisma ORM for type-safe queries
- Composite keys for multi-tenant isolation:
(cityId, id)
Authentication: Auth.js (NextAuth v5)
Authentication: Auth.js (NextAuth v5)
- Resend email provider for passwordless authentication
- Prisma Adapter for session storage
- Role-based access control (superadmin, city admin)
Styling: Tailwind CSS + Radix UI
Styling: Tailwind CSS + Radix UI
- Tailwind CSS utility-first approach
- Radix UI primitives for accessible components
- Framer Motion for animations
- class-variance-authority for component variants
Forms & Validation
Forms & Validation
- React Hook Form for form handling
- Zod schemas for validation
- @hookform/resolvers for integration
Testing
Testing
- Jest with jsdom environment
- React Testing Library for component tests
- Testcontainers for integration tests with PostgreSQL
Import conventions
Path aliases
Use the@/ alias for imports from the src/ directory:
Import organization
Group imports logically:Code organization principles
Don’t Repeat Yourself (DRY)
Check for duplicated logic
If two components have similar code blocks (>10 lines), extract to a shared utility.
Common extraction targets
- Filtering/sorting logic → Extract to
lib/utils/orlib/sorting/ - URL parameter handling → Extract to utilities
- Data transformation logic → Extract to utilities
- Complex calculations → Extract to helper functions
Component organization
Functional components only
Functional components only
- Use functional components with hooks
- PascalCase for component names
- camelCase for functions/variables
Server vs Client Components
Server vs Client Components
- Server Components by default (no
"use client") - Client Components only when needed (
"use client"directive) - Use Server Actions with
"use server"directive
Type safety
Type safety
- Never cast to
anyor useanyas a type - Use interfaces/types for data structures
- Proper error typing in catch blocks
Development environment
Nix shell
OpenCouncil uses Nix to manage development dependencies. All shell commands must be run inside the Nix development shell:Build commands
Next steps
Contributing
Learn the contribution workflow
Authentication
Understand authentication patterns
Data access
Explore data access patterns
Architecture
Review the architecture overview