Comcal is a decentralized community management and calendar platform built on the Nostr protocol. It enables communities to create events, coordinate activities, and share calendars without relying on centralized services. All data is sovereign and stored on Nostr relays—your community maintains full control.
- What is Comcal?
- Key Features
- Technology Stack
- Quick Start (Development)
- Development Guide
- Deployment
- Architecture
- Resources
Comcal (Community Calendar) provides communities with a sovereign, decentralized alternative to centralized calendar and community management tools. Built on the Nostr protocol, it implements:
- NIP-52: Calendar Events standard for event management
- Communikey NIP: Community operations and management
Communities maintain full autonomy—no central server, no data lock-in, no platform dependency. Users authenticate with their private keys, ensuring complete control over their identity and data.
- Community Organizers: Manage events and coordinate activities
- Educational Institutions: Coordinate study groups, lectures, and events
- Interest-Based Communities: Share calendars and coordinate meetings
- Any Group: Needing sovereign event coordination without centralized infrastructure
- ✅ Community Management: Create, join, and manage communities with full autonomy
- ✅ Calendar System: Decentralized calendar events with NIP-52 compliance
- ✅ Multi-Calendar Support: Personal and community-level calendars
- ✅ Calendar Sharing: Multiple sharing mechanisms (webcal, QR codes, direct links)
- ✅ Private Key Authentication: Secure, sovereignty-preserving authentication
- ✅ Social Features: Community feeds, member profiles, and interaction
- ✅ Map Integration: Location-based event discovery
- ✅ Markdown Support: Rich text content in events and profiles
| Category | Technology | Version |
|---|---|---|
| Runtime | Node.js | v22.16.0 |
| Frontend Framework | SvelteKit | 2.1.2 |
| Svelte Version | Svelte | 5.0.0 |
| Styling | TailwindCSS | 3.4.10 |
| Components | DaisyUI | 4.12.10 |
| State Management | Svelte 5 Runes | Native |
| Protocol | Nostr | NIP-52, Communikey NIP |
| Nostr Libraries | Applesauce Suite | Latest |
| Deployment | Docker + Traefik | Production-ready |
| Adapter | @sveltejs/adapter-node | 6.0.0 |
- Node.js: v22.16.0
- pnpm: Package manager
- Git: For cloning the repository
If you use NixOS or have Nix installed, the project includes a flake.nix that provides the exact development environment:
# Clone the repository
git clone <repository-url> comcal
cd comcal
# Allow direnv (auto-activates the environment)
direnv allow
# Install dependencies
pnpm installThe flake provides Node.js 22 and pnpm. With direnv configured, the environment activates automatically when you enter the project directory.
First-time Nix setup: Ensure you have direnv and nix-direnv installed, and flakes enabled in your Nix config (experimental-features = nix-command flakes).
# Clone the repository
git clone <repository-url> comcal
cd comcal
# Use correct Node version (if using nvm)
nvm use
# Install dependencies
pnpm install# Start the dev server (runs on http://localhost:5173)
pnpm run dev
# Or open automatically in browser
pnpm run dev -- --open# Build the application
pnpm run build
# Preview production build locally
pnpm run preview# Development
pnpm run dev # Start dev server with hot reload
# Production
pnpm run build # Build for production (Node adapter)
pnpm run preview # Preview production build
# Code Quality
pnpm run lint # Run ESLint
pnpm run format # Format code with Prettier
# Docker
docker compose build # Build Docker image
docker compose up -d # Start containers in background
docker compose logs -f # View logs- Start the dev server:
pnpm run dev - Make changes: Edit components, stores, or helpers
- See hot reload: Changes apply instantly in the browser
- Run linting:
pnpm run lintto check code quality - Format code:
pnpm run formatto maintain style consistency
- SvelteKit: Full-stack framework with server routes and API endpoints
- Svelte 5 Runes: Reactive state management with
$state,$derived,$effect - TailwindCSS: Utility-first CSS for styling
- DaisyUI: Component library on top of Tailwind
- Nostr Protocol: Decentralized event protocol
- Applesauce: Suite of libraries for Nostr interaction
Comcal supports customizable themes for institutional branding:
| Theme | Description |
|---|---|
light |
Default light theme |
dark |
Default dark theme |
stil |
STIL institutional branding (orange accent) |
stil-dark |
STIL dark variant |
Users can choose between theme families and light/dark/system color modes via Settings.
Configuration (.env):
THEME_DEFAULT_LIGHT=stil # Default theme for light mode
THEME_DEFAULT_DARK=stil-dark # Default theme for dark modeIcons are organized in src/lib/components/icons/ by category (ui, actions, social, calendar) with a consistent wrapper pattern using currentColor for theme compatibility.
See CLAUDE.md for detailed developer documentation on theming and icons.
Comcal is designed for production deployment using Docker and Traefik. This section covers deploying to a VPS or self-hosted server.
- OS: Ubuntu 20.04+ or similar Linux distribution
- Docker: Latest version
- Docker Compose: v2+ with plugin support
- Domain Name: For SSL certificates via Let's Encrypt
- Ports: 80 and 443 publicly accessible
- Resources: 512MB RAM minimum (1GB recommended), 1-2GB storage
See Quick Start section above.
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Install Docker Compose v2+
sudo apt install docker-compose-plugin
# Add user to docker group (optional, for non-root docker access)
sudo usermod -aG docker $USER
newgrp docker# Clone the repository
git clone <repository-url> comcal
cd comcalComcal uses a 12-factor app approach with runtime environment variables for configuration. This allows you to use the same Docker image across different environments (development, staging, production) by simply changing environment variables.
# Copy environment template
cp .env.example .env
# Edit environment variables
nano .env# Your domain (required for SvelteKit CSRF protection)
ORIGIN=https://your-domain.com
# Internal service port (usually 3000)
PORT=3000
# Node environment
NODE_ENV=productionThe .env.example file contains all available configuration options. Key categories:
App Branding
APP_NAME: Application name (default: "ComCal")APP_LOGO: URL to application logoAPP_GIT_REPO: Git repository URL
Nostr Relays
FALLBACK_RELAYS: Fallback relays for event discovery (used when gated mode is off)CALENDAR_RELAYS: App-specific relays for calendar events (kinds 31922-31925)COMMUNIKEY_RELAYS: App-specific relays for community events (kinds 10222, 30222, 30382)AMB_RELAYS: Educational content relays with NIP-50 search support (kind 30142)LONGFORM_CONTENT_RELAY: App-specific relay for articles (kind 30023)
Gated Mode
GATED_MODE_DEFAULT: Default state for gated mode (true/false). When enabled, app fetches only from app-specific relaysGATED_MODE_FORCE: When true, users cannot disable gated mode - useful for institutional deployments
Curated Mode
CURATED_PUBKEYS_SETS: Comma-separated NIP-19 naddr identifiers pointing to kind 30000 follow sets. When set, only content from pubkeys in these follow sets is shown for primary content (calendar events, AMB resources, articles, community definitions). Social content (reactions, comments, chat, targeted publications) is not filtered. Leave empty to disable.CURATED_PUBKEYS: Comma-separated hex pubkeys or npub-encoded pubkeys for direct curated author filtering. These are unioned with pubkeys fromCURATED_PUBKEYS_SETS. If either has entries, curated mode is active. Simpler than follow sets for small deployments.
Calendar Settings
CALENDAR_WEEK_START_DAY: Week start day (0=Sunday, 1=Monday)CALENDAR_LOCALE: Date/time locale (e.g., de-DE, en-US)CALENDAR_TIME_FORMAT: Time format (12h or 24h)
Signup
SIGNUP_SUGGESTED_USERS: Suggested users to follow (comma-separated npubs)
Media Uploads (Blossom)
BLOSSOM_UPLOAD_ENDPOINT: Blossom server upload endpointBLOSSOM_MAX_FILE_SIZE: Maximum file size in bytes
Geocoding (OpenCage API)
GEOCODING_API_KEY: SECRET - OpenCage API key (never expose to client)GEOCODING_CACHE_DURATION_DAYS: Cache duration for geocoded resultsGEOCODING_MIN_ADDRESS_LENGTH: Minimum address length for geocodingGEOCODING_MIN_CONFIDENCE_SCORE: Minimum confidence score (0-10)GEOCODING_REQUIRE_ADDRESS_COMPONENTS: Require address components (true/false)GEOCODING_ACCEPTED_COMPONENT_TYPES: Accepted component types (comma-separated)
Imprint/Legal Information
IMPRINT_ENABLED: Enable/disable imprint pageIMPRINT_ORGANIZATION: Organization nameIMPRINT_ADDRESS_*: Address fieldsIMPRINT_CONTACT_*: Contact informationIMPRINT_*: Other legal information
Educational Content
EDUCATIONAL_SEARCH_DEBOUNCE_MS: Search debounce delayEDUCATIONAL_VOCAB_*: SKOS vocabulary keys
See .env.example for complete documentation of all variables with descriptions and defaults.
- Never commit
.envfiles - They are in.gitignoreby default - Protect API keys - The
GEOCODING_API_KEYis kept server-side only - Use strong values - Especially for production deployments
- Rotate secrets regularly - Update API keys periodically
- Environment-specific configs - Use different
.envfiles for dev/staging/production
Edit docker-compose.yml and update:
- Service name (if needed): Default is
comcal - Domain: Replace
your-domain.comwith your actual domain in Traefik labels - Traefik network: Ensure
traefik_webmatches your Traefik setup
Example Traefik configuration:
labels:
- 'traefik.http.routers.comcal.rule=Host(`your-domain.com`)'
- 'traefik.http.routers.comcal.entrypoints=websecure'
- 'traefik.http.routers.comcal.tls.certresolver=letsencrypt'# Build the Docker image
docker compose build
# Start the application in detached mode
docker compose up -d
# View real-time logs
docker compose logs -f- Nostr Protocol: Overview of the Nostr protocol
- NIP-52: Calendar Events: Calendar event standard
- Communikey NIP: Community operations specification
- SvelteKit Documentation: Full framework documentation
- SvelteKit Node Adapter: Node.js deployment
- Svelte 5 Documentation: Latest Svelte features
- TailwindCSS: Utility-first CSS framework
- DaisyUI: Tailwind component library
- Docker Documentation: Containerization platform
- Traefik Documentation: Reverse proxy and load balancer
- Let's Encrypt: Free SSL/TLS certificates
- Check Troubleshooting: See Troubleshooting section above
- Review Logs: Use
docker compose logsfor application logs - Open Issues: Report bugs on the repository
- Community: Join Nostr communities discussing comcal
This project was funded by the BMBSFJ.
Förderkennzeichen: 01PZ24007
Further development happens under funding of Stiftung Innovation in der Hochschullehre:
Contributions are welcome!
Built with ❤️ on the Nostr protocol.

