Privacy-first scheduling built on Solid Pods. The open-source Calendly alternative.
Your calendar data belongs to you. SolidScheduler stores scheduling data in your personal Solid Pod — you own your data, always.
- Solid Pod storage — Your Pod is the source of truth for all scheduling data
- Passkey MFA — Optional WebAuthn second factor (Touch ID, Windows Hello, YubiKey)
- Persistent sessions — Redis-backed sessions survive server restarts
- Public booking page — Share a link for others to book time with you
- Email notifications — Booking confirmations and organizer alerts via SMTP
- CalDAV calendar sync — Sync bookings to Nextcloud, Radicale, or any CalDAV server
- ICS export — Download .ics calendar files for any booking
- Self-hosted — Run on your own infrastructure, MIT licensed
git clone https://github.com/zerolimit-es/solid-scheduler.git
cd solid-scheduler
cp .env.example .env # then edit .env
docker compose up -dFor HTTPS (required in production), add Caddy:
docker compose -f docker-compose.yml -f docker-compose.caddy.yml up -dSee SELF-HOSTING.md for the full guide — SMTP, CalDAV, Solid Pod providers, SSL with nginx, and more.
git clone https://github.com/zerolimit-es/solid-scheduler.git
cd solid-scheduler
# Install dependencies
cd proton-scheduler-backend && npm install && cd ..
cd proton-scheduler-frontend && npm install && cd ..
# Configure
cp .env.example .env
# Edit .env with your settings
# Start development servers
# Terminal 1 — Backend
cd proton-scheduler-backend && npm run dev
# Terminal 2 — Frontend
cd proton-scheduler-frontend && npm run devOr with Docker:
make dev-up # Start backend + Redis
make dev # Start frontend dev server (Vite)solid-scheduler/
├── proton-scheduler-backend/ # Express API (Node 20, ESM)
│ ├── src/
│ │ ├── config/ # Configuration
│ │ ├── middleware/ # auth, validate (Zod), rateLimit
│ │ ├── routes/ # auth, availability, bookings, public
│ │ ├── services/ # solid, calendar, email
│ │ └── utils/ # ics, recurrence, rdf
│ └── package.json
│
├── proton-scheduler-frontend/ # React frontend (Vite + Tailwind v4)
│ ├── src/
│ │ ├── App.jsx # Main application
│ │ ├── hooks/ # useAuth, useBookings
│ │ ├── services/api.js # API client
│ │ ├── styles/ # app.css, tokens.css
│ │ └── components/
│ │ ├── booking/ # BookingView, BookingForm, ConfirmationView
│ │ ├── common/ # Icons, PasskeyChallenge, TimezoneSearch
│ │ ├── dashboard/ # DashboardView
│ │ └── layout/ # Header, LoginScreen
│ └── package.json
│
├── docker/
│ ├── nginx/ # Nginx reverse proxy config
│ └── caddy/ # Caddy reverse proxy config
├── docker-compose.yml # Base (frontend + backend + redis)
├── docker-compose.caddy.yml # HTTPS via Caddy (automatic certs)
├── docker-compose.nginx.yml # HTTPS via nginx + Certbot
├── docker-compose.dev.yml # Development
├── Makefile
├── SELF-HOSTING.md # Deployment guide
├── CONTRIBUTING.md
└── README.md
| Layer | Technology |
|---|---|
| Runtime | Node.js 20 LTS, Express (ESM) |
| Frontend | React, Vite, Tailwind CSS v4 |
| Sessions | Redis (write-through + in-memory fallback) |
| Auth | Solid OIDC + optional WebAuthn/Passkey MFA |
| Any SMTP provider | |
| Calendar Sync | CalDAV (Nextcloud, Radicale, Baikal) |
| Containers | Docker + Docker Compose |
See .env.example for all options. Minimum for development:
NODE_ENV=development
PORT=3001
BASE_URL=http://localhost:3001
FRONTEND_URL=http://localhost:3000
SESSION_SECRET=any-random-string-for-dev
DEFAULT_SOLID_IDP=https://login.inrupt.comSee CONTRIBUTING.md for development setup, commit style, and PR process.
MIT — see LICENSE.
Zero Limit (SASU) — Paris, France