High-level architecture
OpenCouncil is built as a modern web application with a decoupled task processing architecture. The system consists of three main components:Next.js application
User-facing web application with Server Components and API routes
Task server
Background processing server for AI and media tasks
PostgreSQL database
Data persistence with PostGIS for geospatial features
Technology stack
Frontend layer
- Next.js 14: App Router with Server Components and React Server Actions
- TypeScript: Strict mode enabled for type safety
- Tailwind CSS: Utility-first styling with custom design system
- Radix UI: Accessible component primitives
- Framer Motion: Animation library
- React Hook Form + Zod: Form handling and validation
Backend layer
- Prisma ORM: Type-safe database access with migrations
- Auth.js: Session-based authentication with email magic links
- PostgreSQL 14+: Primary database with PostGIS extension
- Elasticsearch: Full-text search and content discovery
AI and media processing
- Anthropic Claude: AI summaries and chat assistant
- Google Cloud Speech-to-Text: Audio transcription
- DigitalOcean Spaces: S3-compatible object storage for media
- Custom task queue: Background job processing with callbacks
Application architecture
Directory structure
Data access patterns
OpenCouncil follows strict data access patterns for maintainability:All database queries use centralized functions in
src/lib/db/. This prevents scattered query logic and ensures consistent data access patterns.- Store shared Prisma types in
src/lib/db/types/{entity}.ts - Re-export from
src/lib/db/types/index.ts - Import from
@/lib/db/typesto prevent circular dependencies
Task workflow architecture
The task system is designed to offload long-running processes from the main application to a dedicated backend server.Task lifecycle
Initiation
User action or cron job triggers
startTask() function:- Creates
TaskStatusrecord in database - Sends POST request to task server with
callbackUrl
Execution
Backend task server processes the job:
- Task added to custom in-memory queue
- Worker process executes the task
- Sends progress updates to callback URL
Completion
Task server sends final result:
- Status:
successorerror - Result data or error message
- Full response stored in
TaskStatus.responseBody
Task architecture diagram
Task types
OpenCouncil supports multiple task types:Transcribe
Transcribe
Converts audio/video to text with speaker recognition:
- Uses Google Cloud Speech-to-Text or Whisper
- Generates speaker segments and utterances
- Creates word-level timestamps
- Identifies speakers using voiceprints
src/lib/tasks/transcribe.tsSummarize
Summarize
Generates AI summaries of speeches:
- Analyzes speaker utterances
- Extracts key topics and subjects
- Creates structured summaries
- Links to existing subjects or creates new ones
src/lib/tasks/summarize.tsGenerate voiceprint
Generate voiceprint
Creates speaker voice profiles:
- Analyzes audio samples
- Generates unique voiceprint
- Enables automatic speaker identification
src/lib/tasks/generateVoiceprint.tsGenerate podcast
Generate podcast
Creates podcast-style audio content:
- Extracts key segments from meetings
- Generates host narration
- Produces structured audio content
src/lib/tasks/generatePodcast.tsPoll decisions
Poll decisions
Fetches decisions from Diavgeia:
- Queries Greek government transparency portal
- Links decisions to meeting subjects
- Progressive backoff to avoid over-polling
src/lib/tasks/pollDecisions.tsTask reprocessing
A key feature is the ability to reprocess task results without re-running the entire task:force flag triggers cleanup:
- Delete existing
SpeakerSegment,Utterance, andWordrecords - Recreate everything from stored
responseBody
Database architecture
Schema overview
OpenCouncil uses PostgreSQL with the PostGIS extension for geospatial features.Composite keys
Many models use composite keys(cityId, id) for multi-tenant data isolation:
Key relationships
City → Meetings → Subjects
City → Meetings → Subjects
Meeting → Transcription
Meeting → Transcription
Task processing
Task processing
Search architecture
OpenCouncil uses Elasticsearch for full-text search across transcripts.Search features
Natural language queries
Parse user queries and extract filters automatically
Filter extraction
Identify city, person, party, topic, date, and location filters
Multi-field search
Search across utterances, summaries, and subjects
Retry logic
Exponential backoff for reliability
Search implementation
Notification system
Multi-channel notification delivery with user preferences:Matching engine
Match notifications to user preferences:
- Topics of interest
- Specific people or parties
- Geographic locations
- Meeting types
Approval workflow
For cities with
NOTIFICATIONS_APPROVAL mode:- Notifications enter pending queue
- Admins review and approve
- Batch sending on approval
Multi-channel delivery
Send via configured channels:
- Email: Resend API
- WhatsApp: Bird API
- SMS: Bird API
Key integrations
Anthropic Claude
AI summaries, chat assistant, and content generation
Elasticsearch
Full-text search and content discovery
Resend
Email authentication and notifications
Bird API
WhatsApp and SMS notifications
DigitalOcean Spaces
S3-compatible object storage for media
Google Calendar
Event scheduling and synchronization
Discord
Real-time admin alerts for system events
Mapbox
Interactive maps and geospatial features
Deployment architecture
Production setup
Scaling considerations
Security architecture
Authentication flow
Authorization patterns
OpenCouncil uses centralized authorization helpers:Performance optimizations
Caching strategy
Database optimization
- Indexes: Strategic indexes on frequently queried fields
- Connection pooling: Prisma connection pool configuration
- Query optimization: Use
selectto fetch only needed fields - Pagination: Cursor-based pagination for large datasets
Monitoring and observability
Discord integration
Admin alerts sent to Discord webhook:Logging
- Structured logging for search analytics
- Task execution logging
- API request logging
- Error tracking with context
Next steps
Database schema
Detailed database schema documentation
API reference
Complete REST API documentation
Task system
Deep dive into task processing
Contributing
Join the development workflow