Open-source alternative to Doodle, Calendly, and LettuceMeet
A modern, self-hosted polling and scheduling platform for teams. Create surveys, schedule meetings, and manage event signups with ease. Multi-language support (German & English), GDPR-compliant, accessibility-tested (WCAG 2.1 AA), and fully self-hosted.
# Clone & Start - No configuration needed!
git clone https://github.com/manfredsteger/polly.git
cd polly
docker compose up -d
# OR: All-in-one with Makefile (includes seed data)
make completeThat's it! Open http://localhost:3080 and start exploring.
| Field | Value |
|---|---|
| Username | admin |
| Password | Admin123! |
admin@polly.local |
โ ๏ธ Security Warning: After first login, create a new admin account and delete the default admin!
- โ Database auto-configured (PostgreSQL included)
- โ Schema auto-applied on first start
- โ Initial admin account created automatically
- โ
Works out of the box - no
.envfile needed - โ Demo data shows all three poll types
Create your first poll in under 30 seconds โ no login required
Manage users, polls, and system settings from one central dashboard
๐ Schedule Poll Find the best meeting time |
๐ Survey Collect opinions & feedback |
๐ Organization List Slot booking with capacity |
๐ฅ๏ธ Admin Dashboard Screenshots (click to expand)
| Overview | User Management |
|---|---|
![]() |
![]() |
| System stats, recent activity, quick actions | Manage users, roles, and permissions |
| Branding & Theming | Settings |
|---|---|
![]() |
![]() |
| Customize logo, colors, and site name | Email, security, and system configuration |
| Monitoring | Test Suite |
|---|---|
![]() |
![]() |
| System health and performance | Built-in security and integration tests |
| Type | German Name | Description |
|---|---|---|
| ๐ Schedule | Terminumfrage | Find the best date/time with Yes/Maybe/No voting |
| ๐ Survey | Umfrage | Classic polls with text options and optional images |
| ๐ Organization | Orga-Liste | Slot booking with capacity limits and comments |
- Multi-Language Support: Full German (de) and English (en) interface with automatic browser detection. Easily extensibleโadd new languages by creating a translation JSON file in
client/src/locales/ - Anonymous & Authenticated Voting: Works for guests and registered users
- Real-Time Updates: Live voting with WebSocket connections and fullscreen presentation mode
- Email Notifications: Vote confirmation, edit links, and expiry reminders via email
- Matrix Results View: Visual participant ร options grid with color-coded responses
- Export Options: CSV and PDF exports with QR codes
- Calendar Integration: ICS export and webcal:// subscription for schedule polls
- QR Code Sharing: Easy poll distribution via QR codes
- Full Customization: Theme colors, logo, site name via admin panel
- Dark Mode: System-wide dark mode with admin defaults
- Transactional Slot Booking: PostgreSQL row-level locking prevents overbooking in organization polls
- Local Login: Email/password for registered users
- Keycloak OIDC: Enterprise SSO integration (optional)
- Role-Based Access: User, Admin, Manager roles
# Clone the repository
git clone https://github.com/manfredsteger/polly.git
cd polly
# Copy and customize environment
cp .env.example .env
nano .env # Add your SMTP, Keycloak settings
# Start with Docker Compose
docker compose up -d
# The app auto-configures on first start!# Prerequisites: Node.js 20+, PostgreSQL 16+
# Clone and install
git clone https://github.com/manfredsteger/polly.git
cd polly
npm install
# Set up environment
cp .env.example .env
# Edit .env with your database URL and settings
# Push database schema
npm run db:push
# Start development server
npm run dev
# Open http://localhost:3080DATABASE_URL=postgresql://user:password@localhost:5432/polly
SESSION_SECRET=your-secure-random-string-min-32-charsSMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your-email@example.com
SMTP_PASSWORD=your-email-password
EMAIL_FROM=noreply@yourdomain.comKEYCLOAK_REALM=your-realm
KEYCLOAK_CLIENT_ID=polly
KEYCLOAK_CLIENT_SECRET=your-client-secret
KEYCLOAK_AUTH_SERVER_URL=https://keycloak.example.comAPP_URL=https://your-app-url.com
VITE_APP_URL=https://your-app-url.com| Layer | Technology |
|---|---|
| Frontend | React 18, TypeScript, Vite |
| UI | Shadcn/ui, Radix UI, Tailwind CSS |
| State | TanStack Query v5 |
| Backend | Express.js, TypeScript |
| Database | PostgreSQL, Drizzle ORM |
| Auth | Passport.js, express-session |
โโโ client/ # React frontend
โ โโโ src/
โ โ โโโ components/ # Reusable UI components
โ โ โโโ pages/ # Route components
โ โ โโโ hooks/ # Custom React hooks
โ โ โโโ lib/ # Utilities
โโโ server/ # Express backend
โ โโโ routes.ts # API endpoints
โ โโโ storage.ts # Database operations
โ โโโ auth.ts # Authentication
โโโ shared/ # Shared types
โ โโโ schema.ts # Drizzle schemas
โโโ Dockerfile # Production container
โโโ docker-compose.yml # Local development
npm run dev # Start development server (frontend + backend)
npm run build # Build for production
npm start # Start production server
npm run db:push # Push schema changes to database
npm run db:studio # Open Drizzle Studio (DB viewer)Access the admin panel at /admin to customize:
- Theme Colors: Primary, secondary, and feature-specific colors
- Branding: Logo, site name, footer text
- Dark Mode: Set system default (light/dark/system)
- Registration: Enable/disable user registration
- Email Settings: Configure SMTP for notifications
| Feature | Default Color | Description |
|---|---|---|
| Schedule | Orange #F97316 | Terminumfragen |
| Survey | Green #7DB942 | Umfragen |
| Organization | Teal #72BEB7 | Orga-Listen |
- Session-based authentication with secure cookies
- Server-side validation of all inputs with Zod
- Email ownership verification for registered users
- Role-based access control
- CSRF protection
- Secure password hashing with bcrypt
# Show all available commands
make help
# Quick setup (first time)
make setup
# Start production
make prod
# Start development with hot-reload
make dev
# View logs
make logs
# Push database schema
make db-push
# Open database shell
make shell-db
# All-in-one: Build, start, migrate & seed (first time or after updates)
make complete
# Build and publish to Docker Hub
make publish IMAGE_NAME=yourusername/polly# Build and run
docker-compose up -d --build
# View logs
docker-compose logs -f app
# Stop
docker-compose downdocker-compose -f docker-compose.yml -f docker-compose.dev.yml upPull the official image:
docker pull yourusername/polly:latestAll API endpoints use the /api/v1/ prefix. Full OpenAPI specification available in docs/openapi.yaml.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/polls/public/:token |
Get poll by public token |
| POST | /api/v1/polls/:publicToken/vote |
Submit vote |
| GET | /api/v1/polls/:token/results |
Get poll results |
| GET | /api/v1/polls/:publicToken/calendar.ics |
ICS calendar export |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/polls |
Create poll |
| PATCH | /api/v1/polls/:id |
Update poll |
| DELETE | /api/v1/polls/:id |
Delete poll |
| GET | /api/v1/users/me |
Get current user |
| PATCH | /api/v1/users/me/language |
Update language preference |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/admin/polls |
List all polls |
| GET | /api/v1/admin/users |
List all users |
| PUT | /api/v1/admin/settings |
Update settings |
| GET | /api/v1/admin/email-templates |
Manage email templates |
Connect to /ws for live vote updates during presentations. Events: vote_update, slot_update.
Polly is currently in Beta Phase (Q1-Q2 2025). Our focus areas:
| Priority | Feature | Status |
|---|---|---|
| ๐ | Keycloak SSO (OIDC) - Enterprise single sign-on integration | In Progress |
| ๐ค | AI Voice Control - Create polls via speech with GWDG KISSKI Free Tier | Planned |
| ๐ | OpenAI-Compatible API - Support for custom AI providers | Planned |
| ๐ฌ | Matrix / Element Chatbot - Create and manage polls directly from Matrix chat | Version 1.0 |
| ๐ช๐บ | European DC Focus - Simplified deployment for EU data centers | Version 1.0 |
|
|
GWDG โ Gesellschaft fรผr wissenschaftliche Datenverarbeitung mbH Gรถttingen The GWDG is the joint computing and IT competence center for the Georg-August-Universitรคt Gรถttingen and the Max Planck Society. As infrastructure partner, they provide the hosting and computing resources that power Polly's self-hosted deployment capabilities. |
|
|
KISSKI โ KI-Servicezentrum fรผr sensible und kritische Infrastrukturen KISSKI is a BMBF-funded AI service center operated by the GWDG, providing free AI inference capabilities for research and public infrastructure. Polly uses KISSKI's OpenAI-compatible API to offer AI-powered agentic control for poll creation โ hosted in Germany, GDPR-compliant, and offers a free AI tier for every Polly user (please get in touch with GWDG/KISSKI for an AI production licence). |
| Document | Description |
|---|---|
| ROADMAP.md | Development roadmap and future plans |
| CHANGELOG.md | Version history and release notes |
| SECURITY.md | Security policy and vulnerability reporting |
| docs/openapi.yaml | OpenAPI 3.0 API specification |
| docs/SELF-HOSTING.md | Production deployment guide |
| docs/FLUTTER_INTEGRATION.md | Mobile app integration guide |
We welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow existing code style and conventions
- Write TypeScript with proper types
- Use Tailwind CSS for styling
- Test changes before submitting PR
- Update documentation as needed
This project is open source and available under the MIT License.
Made with โค๏ธ for teams everywhere














