2026-01-09 00:51:25 +01:00
# Calendar Application Architecture
## Overview
2026-01-11 02:28:04 +01:00
The Calendar application is a modern, self-hosted calendar solution that combines a Django REST API backend with a separate CalDAV server for standards-compliant calendar data storage and synchronization. This architecture provides both a modern web interface and full CalDAV protocol support for compatibility with standard calendar clients.
2026-01-09 00:51:25 +01:00
## System Architecture
```
┌─────────────────┐
│ Frontend │
│ (Next.js) │
└────────┬────────┘
│
│ HTTP/REST API + CalDAV Protocol
│
┌────────▼─────────────────────────────────────┐
│ Django Backend │
│ ┌──────────────────────────────────────┐ │
│ │ REST API Endpoints │ │
│ │ - /api/v1.0/calendars │ │
│ │ - /api/v1.0/users │ │
│ └──────────────────────────────────────┘ │
│ ┌──────────────────────────────────────┐ │
│ │ CalDAV Proxy │ │
│ │ - /api/v1.0/caldav/* │ │
│ │ - /.well-known/caldav │ │
│ └──────────────────────────────────────┘ │
│ ┌──────────────────────────────────────┐ │
│ │ Authentication (OIDC/Keycloak) │ │
│ └──────────────────────────────────────┘ │
└────────┬───────────────────────────────────┘
│
│ HTTP/CalDAV Protocol
│
┌────────▼─────────────────────────────────────┐
2026-01-11 02:28:04 +01:00
│ CalDAV Server │
2026-01-09 00:51:25 +01:00
│ (CalDAV Protocol Implementation) │
│ - Calendar storage │
│ - Event storage (iCalendar format) │
│ - CalDAV protocol handling │
└────────┬─────────────────────────────────────┘
│
│ PostgreSQL
│
┌────────▼─────────────────────────────────────┐
│ PostgreSQL Database │
│ - Django models (users, calendars metadata) │
2026-01-11 02:28:04 +01:00
│ - CalDAV server schema (calendar data) │
2026-01-09 00:51:25 +01:00
└──────────────────────────────────────────────┘
```
## Component Responsibilities
### Django Backend
The Django backend serves as the **orchestration layer ** and **business logic engine ** for the application.
**Primary Responsibilities:**
- **User Management & Authentication**: OIDC authentication via Keycloak, user profiles, sessions, authorization
- **Calendar Metadata Management**: Calendar creation/deletion, sharing, visibility settings, display preferences
- **REST API Layer**: Modern RESTful API for the web frontend (JSON, standard HTTP methods, versioned at `/api/v1.0/` )
2026-01-11 02:28:04 +01:00
- **CalDAV Proxy**: Proxies CalDAV requests to CalDAV server, handles authentication translation, URL routing, discovery endpoint
2026-01-09 00:51:25 +01:00
- **Business Logic**: Calendar sharing logic, permission checks, data validation, integration coordination
**Data Storage:**
- User accounts
- Calendar metadata (name, color, visibility, owner)
- Sharing relationships
- Application configuration
2026-01-11 02:28:04 +01:00
**Important**: Django does NOT store actual calendar events. Events are stored in the CalDAV server.
2026-01-09 00:51:25 +01:00
2026-01-11 02:28:04 +01:00
### CalDAV Server
2026-01-09 00:51:25 +01:00
2026-01-11 02:28:04 +01:00
The CalDAV server is a **standards-compliant CalDAV server ** that handles all calendar data storage and protocol operations.
2026-01-09 00:51:25 +01:00
**Primary Responsibilities:**
- **Calendar Data Storage**: Stores actual calendar events in iCalendar format, manages calendar collections
- **CalDAV Protocol Implementation**: Full RFC 4791 implementation (PROPFIND, REPORT, MKCALENDAR, PUT, DELETE)
- **iCalendar Format Management**: Parses and generates iCalendar files, validates syntax, handles VEVENT/VTODO components
- **Database Schema**: Uses PostgreSQL with its own schema for calendar data
**Authentication Integration:**
2026-01-11 02:28:04 +01:00
- Uses Apache authentication backend which reads `REMOTE_USER` environment variable
- Django proxy sets `X-Forwarded-User` header, which the CalDAV server converts to `REMOTE_USER`
- All communication is via HTTP - no direct database access from Django
2026-01-09 00:51:25 +01:00
### Frontend (Next.js)
The frontend provides the user interface and interacts with both REST API and CalDAV protocol:
- Modern React-based UI
- Uses REST API for calendar metadata operations
- Uses CalDAV protocol directly for event operations
- Supports multiple languages and themes
## Why This Architecture?
### Design Decision: CalDAV Server Separation
2026-01-11 02:28:04 +01:00
The decision to use a separate CalDAV server rather than implementing CalDAV directly in Django was made for several reasons:
2026-01-09 00:51:25 +01:00
2026-01-11 02:28:04 +01:00
1. **Standards Compliance ** : Using a mature, well-tested CalDAV server that fully implements RFC 4791. Implementing CalDAV from scratch would be error-prone and time-consuming.
2026-01-09 00:51:25 +01:00
2026-01-11 02:28:04 +01:00
2. **Protocol Complexity ** : CalDAV is built on WebDAV, involving complex XML handling, property management, and collection hierarchies. A dedicated CalDAV server handles all of this complexity.
2026-01-09 00:51:25 +01:00
3. **Maintenance ** : Using a proven, maintained CalDAV server reduces maintenance burden and ensures compatibility with various CalDAV clients.
2026-01-11 02:28:04 +01:00
4. **Focus ** : Django backend can focus on business logic, user management, and REST API, while the CalDAV server handles calendar protocol operations.
2026-01-09 00:51:25 +01:00
2026-01-11 02:28:04 +01:00
5. **Shared database ** : The CalDAV server stores its data into Postgres, which we use in all LaSuite projects.
6. **Clean separation ** : All communication between Django and the CalDAV server is via HTTP, ensuring clean separation of concerns and no direct database access.
2026-01-09 00:51:25 +01:00
### Benefits
1. **Standards Compliance **
- Full CalDAV protocol support enables compatibility with any CalDAV client (Apple Calendar, Thunderbird, etc.)
- Users can sync calendars with external applications
- Follows industry standards (RFC 4791)
2. **Separation of Concerns **
- Django handles business logic and user management
2026-01-11 02:28:04 +01:00
- CalDAV server handles calendar protocol and data storage
2026-01-09 00:51:25 +01:00
- Each component focuses on its core competency
3. **Flexibility **
- Can expose both REST API (for web app) and CalDAV (for external clients)
- Different clients can use different protocols
- Future-proof architecture
4. **Maintainability **
- Clear boundaries between components
- Easier to test and debug
- Can update components independently
5. **Performance **
2026-01-11 02:28:04 +01:00
- CalDAV server is optimized for CalDAV operations
2026-01-09 00:51:25 +01:00
- Django can focus on application logic
- Database can be optimized separately for each use case
## Data Flow
### Creating a Calendar
TODO: should this only be via caldav too?
1. **Frontend ** → POST `/api/v1.0/calendars` (REST API)
2026-01-11 02:28:04 +01:00
2. **Django Backend ** : Validates request, creates `Calendar` model, calls CalDAV server to create calendar collection
3. **CalDAV Server ** : Receives MKCALENDAR request, creates calendar collection, returns calendar path
4. **Django Backend ** : Stores CalDAV server path in `Calendar.caldav_path` , returns calendar data to frontend
2026-01-09 00:51:25 +01:00
### Creating an Event
Events are created directly via CalDAV protocol:
1. **Frontend ** → PUT `/api/v1.0/caldav/{user}/{calendar}/{event_uid}.ics` (CalDAV)
2026-01-11 02:28:04 +01:00
2. **Django Backend ** : `CalDAVProxyView` authenticates user, forwards request to CalDAV server with authentication headers
3. **CalDAV Server ** : Receives PUT request with iCalendar data, stores event in calendar collection
2026-01-09 00:51:25 +01:00
4. **Django Backend ** : Forwards CalDAV response to frontend
### CalDAV Client Access
1. **CalDAV Client ** → PROPFIND `/api/v1.0/caldav/` (CalDAV protocol)
2026-01-11 02:28:04 +01:00
2. **Django Backend ** : Authenticates user via Django session, forwards request to CalDAV server with `X-Forwarded-User` header
3. **CalDAV Server ** : Processes CalDAV request, returns CalDAV response
2026-01-09 00:51:25 +01:00
4. **Django Backend ** : Forwards response to client
## Integration Points
### User Synchronization
2026-01-11 02:28:04 +01:00
Users are automatically created in the CalDAV server when they first access it. The CalDAV server's Apache authentication backend reads the `REMOTE_USER` environment variable, which is set from the `X-Forwarded-User` header sent by Django. No explicit user creation is needed - the CalDAV server will create principals on-demand.
2026-01-09 00:51:25 +01:00
### Calendar Creation
When creating a calendar via REST API:
1. Django creates `Calendar` model with metadata
2026-01-11 02:28:04 +01:00
2. Django calls CalDAV server via HTTP to create calendar collection
3. Django stores CalDAV server path in `Calendar.caldav_path`
2026-01-09 00:51:25 +01:00
### Authentication Translation
2026-01-11 02:28:04 +01:00
Django sessions are translated to CalDAV server authentication:
2026-01-09 00:51:25 +01:00
- Django adds `X-Forwarded-User` header with user email
2026-01-11 02:28:04 +01:00
- CalDAV server converts `X-Forwarded-User` to `REMOTE_USER` environment variable
- CalDAV server's Apache authentication backend reads `REMOTE_USER` for authentication
- All communication is via HTTP - no direct database access
2026-01-09 00:51:25 +01:00
### URL Routing
CalDAV clients expect specific URL patterns. The CalDAV proxy handles path translation:
- Discovery endpoint at `.well-known/caldav` redirects to `/api/v1.0/caldav/`
2026-01-11 02:28:04 +01:00
- Proxy forwards requests to CalDAV server with correct paths
2026-01-09 00:51:25 +01:00
## Database Schema
2026-01-11 02:28:04 +01:00
Both Django and the CalDAV server use the same PostgreSQL database in a local Docker install, but maintain separate schemas:
2026-01-09 00:51:25 +01:00
**Django Schema (public schema):**
- `calendars_user` - User accounts
- `caldav_calendar` - Calendar metadata
- `caldav_calendarshare` - Sharing relationships
- Other Django app tables
2026-01-11 02:28:04 +01:00
**CalDAV Server Schema (public schema, same database):**
- `users` - CalDAV server user records (for digest auth, not used with Apache auth)
- `principals` - CalDAV server principals
- `calendars` - Calendar collections
- `calendarinstances` - Calendar instance metadata
- `calendarobjects` - Calendar resources (events)
- `calendarchanges` - Change tracking
- Other CalDAV server-specific tables
2026-01-09 00:51:25 +01:00
2026-01-11 02:28:04 +01:00
This allows them to share the database locally while keeping data organized. Note that Django never directly accesses CalDAV server tables - all communication is via HTTP.