Self-hosted scheduling tool for booking meetings. Simple alternative to Calendly with Google Calendar integration.
- Meeting types - Create multiple meeting types with configurable duration, buffers, and daily limits
- Weekly availability - Set recurring availability per day of week
- Google Calendar sync - Automatic free/busy check and event creation
- Public booking links - Share
/book/{slug}URLs for each meeting type - Guest timezone selection - Guests see times in their timezone
- Calendar export - .ics file download after booking
- Simple admin UI - Server-rendered HTML, no JavaScript framework
-
Set up Google OAuth credentials (see Configuration)
-
Set environment variables:
export TEMPRIX_ENCRYPTION_SECRET="your-32-character-secret-key!!"
export TEMPRIX_GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"
export TEMPRIX_GOOGLE_CLIENT_SECRET="your-client-secret"- Run the server:
make build
./bin/temprix- Visit
http://localhost:8080/adminand login with Google
# Clone the repository
git clone https://github.com/bigbag/temprix.git
cd temprix
# Build
make build
# Or install to GOPATH/bin
make install# Build image
make docker-build
# Run container
docker run -d \
-p 8080:8080 \
-v temprix-data:/app/data \
-e TEMPRIX_BASE_URL=https://your-domain.com \
-e TEMPRIX_ENCRYPTION_SECRET=your-32-character-secret-key!! \
-e TEMPRIX_GOOGLE_CLIENT_ID=your-client-id \
-e TEMPRIX_GOOGLE_CLIENT_SECRET=your-client-secret \
temprixRequired:
TEMPRIX_ENCRYPTION_SECRET- 32+ character secret for token encryptionTEMPRIX_GOOGLE_CLIENT_ID- Google OAuth Client IDTEMPRIX_GOOGLE_CLIENT_SECRET- Google OAuth Client Secret
Optional:
TEMPRIX_PORT- Server port (default:8080)TEMPRIX_BASE_URL- Public URL for OAuth callback and booking links (default:http://localhost:8080)TEMPRIX_DB_PATH- SQLite database path (default:./data/temprix.db)
- Go to Google Cloud Console
- Create a new project or select existing one
- Enable the Google Calendar API
- Go to Credentials > Create Credentials > OAuth 2.0 Client ID
- Set Application type to Web application
- Add authorized redirect URI:
http://localhost:8080/auth/callback(or your production URL) - Note the Client ID and Client Secret
New OAuth apps are in "Testing" mode and require adding test users before they can login:
- Go to Google Cloud Console
- Select your project
- Go to APIs & Services > OAuth consent screen > Audience
- In the Test users section, click + Add users
- Add your email address
- Save
You can add up to 100 test users in testing mode. For production use with any Google account, submit for Google verification (requires privacy policy, terms of service, etc.).
+------------------+ +------------------+ +------------------+
| Public User | | Admin User | | Google Calendar |
+--------+---------+ +--------+---------+ +--------+---------+
| | ^
| /book/{slug} | /admin |
v v |
+--------------------------------------------------+ |
| Temprix Server | |
| | |
| +-------------+ +-------------+ +-----------+ | |
| | Handlers | | Auth | | Calendar |-+-------+
| | | | (Google | | (Event |
| | - Admin | | OAuth) | | create, |
| | - Booking | | | | free/ |
| | - Auth | +-------------+ | busy) |
| +------+------+ +-----------+
| | |
| v |
| +-------------+ +-------------+ +-----------+ |
| | Availability| | Models | | ICS | |
| | Engine | | | | Generator | |
| | | | - Meeting | | | |
| | - Slots | | - Booking | | - RFC5545 | |
| | - Filters | | - User | | | |
| +------+------+ +-------------+ +-----------+ |
| | |
| v |
| +----------------------------------------------+|
| | SQLite Database ||
| | ||
| | - meeting_types - bookings - users ||
| +----------------------------------------------+|
+--------------------------------------------------+
- Visit
/admin- redirected to Google OAuth - After login, see dashboard with meeting types
- Create meeting types with name, duration, buffers, schedule
- View and manage bookings
- Guest visits
/book/{slug}(e.g.,/book/30min-call) - Selects their timezone
- Picks a date - available time slots are shown
- Selects a time slot
- Enters name and email
- Confirms booking - event created in your Google Calendar
- Downloads .ics file to add to their calendar
- Get weekly schedule for the meeting type
- Generate all possible slots for selected date
- Query Google Calendar free/busy API
- Remove slots that conflict with existing events
- Remove slots that conflict with existing bookings
- Check max bookings per day limit
- Apply buffer times (before/after)
- Return available slots
SQLite stores all data:
CREATE TABLE users (
id TEXT PRIMARY KEY,
google_id TEXT UNIQUE NOT NULL,
email TEXT NOT NULL,
access_token TEXT NOT NULL, -- AES-GCM encrypted
refresh_token TEXT NOT NULL, -- AES-GCM encrypted
calendar_id TEXT DEFAULT 'primary'
);
CREATE TABLE meeting_types (
id TEXT PRIMARY KEY,
slug TEXT UNIQUE NOT NULL, -- URL-friendly identifier
name TEXT NOT NULL,
description TEXT,
duration_minutes INTEGER NOT NULL,
buffer_before_minutes INTEGER DEFAULT 0,
buffer_after_minutes INTEGER DEFAULT 0,
max_per_day INTEGER DEFAULT 0, -- 0 = unlimited
meeting_link TEXT, -- manual Zoom/Meet link
timezone TEXT NOT NULL,
weekly_schedule TEXT NOT NULL, -- JSON: {"mon": [{"start": "09:00", "end": "17:00"}]}
active INTEGER DEFAULT 1
);
CREATE TABLE bookings (
id TEXT PRIMARY KEY,
meeting_type_id TEXT NOT NULL,
guest_name TEXT NOT NULL,
guest_email TEXT NOT NULL,
start_time DATETIME NOT NULL, -- stored in UTC
end_time DATETIME NOT NULL,
guest_timezone TEXT NOT NULL,
google_event_id TEXT,
status TEXT DEFAULT 'confirmed' -- confirmed, cancelled
);Google OAuth tokens are encrypted at rest using AES-256-GCM:
- 32-byte key derived from
TEMPRIX_ENCRYPTION_SECRET - Random 12-byte nonce per encryption
- Base64 encoded for storage
- Meeting type timezone: used to interpret weekly schedule
- Guest timezone: for display in booking UI
- Storage: all times stored in UTC
- Conversion: handled at display time using Go's
time.LoadLocation
temprix/
├── main.go # Entry point, routes
├── internal/
│ ├── config/config.go # Environment variable loading
│ ├── db/
│ │ ├── db.go # SQLite connection, migrations
│ │ └── queries.go # All SQL operations
│ ├── models/models.go # Data structures
│ ├── auth/google.go # OAuth flow, token encryption
│ ├── calendar/google.go # Calendar API wrapper
│ ├── availability/slots.go # Slot calculation
│ ├── handlers/handlers.go # HTTP handlers
│ └── ics/generator.go # .ics file generation
├── templates/
│ ├── admin/ # Admin UI templates
│ └── booking/ # Public booking templates
├── static/style.css # Styling
├── Dockerfile
├── Makefile
└── README.md
make build # Build binary to bin/temprix
make test # Run tests
make clean # Remove build artifacts
make install # Install to GOPATH/bin
make tidy # Tidy Go modules
make vet # Run go vet
make run # Build and run
make build-all # Build for linux/darwin amd64/arm64
make docker-build # Build Docker image
make docker-run # Run Docker containerMIT License - see LICENSE file.