Agent-readable docs index: /llms.txt. Full docs in one file: /llms-full.txt. Download /docs.zip to grep all markdown files locally.

Self-hosting

OpenSession runs as a single Cloudflare Worker with D1 (SQLite database), R2 (file storage), and the send_email binding for transactional emails. The entire stack fits within Cloudflare's free tier for most conference workloads.

Prerequisites

  • A Cloudflare account (free tier works)
  • Node.js 18+ and pnpm
  • Google OAuth credentials (optional, for Google login)
  • A domain pointed at Cloudflare (for email sending)

Architecture

┌──────────────────────── Cloudflare Worker ────────────────────────┐ │ │ │ Spiceflow app (React Server Components) │ │ ├── Admin dashboard /org/:orgId/e/:eventId/* │ │ ├── Public CFP /submit/:eventSlug/:formSlug │ │ ├── Speaker portal /portal/:eventSlug/* │ │ ├── Embeds /embed/:eventSlug/* │ │ ├── API /api/auth/* (BetterAuth) │ │ └── Cron close forms, reminders, outbox drain │ │ │ └────────┬──────────────┬──────────────┬────────────────────────────┘ │ │ │ v v v D1 database R2 bucket send_email binding (SQLite) (files) (transactional mail)

Setup steps

    Clone the repository

    git clone https://github.com/remorses/opensession cd opensession pnpm install

    Create Cloudflare resources

    Create a D1 database and R2 bucket in your Cloudflare dashboard or via Wrangler:
    cd website npx wrangler d1 create opensession-db npx wrangler r2 bucket create opensession-files
    Update wrangler.jsonc with your database ID.

    Configure Google OAuth (optional)

    Create OAuth credentials in the Google Cloud Console:
    1. Create a new OAuth 2.0 Client ID
    2. Set the authorized redirect URI to https://your-domain.com/api/auth/callback/google
    3. Note the Client ID and Client Secret

    Set secrets

    Store your auth secrets using Wrangler or your preferred secrets manager. Add the Google credentials only when you want to offer Google login:
    npx wrangler secret put BETTER_AUTH_SECRET npx wrangler secret put GOOGLE_CLIENT_ID npx wrangler secret put GOOGLE_CLIENT_SECRET
    Set BETTER_AUTH_URL to your production domain (e.g. https://opensession.dev).

    Run migrations

    pnpm db:migrate:remote

    Deploy

    pnpm deploy

Local development

For local development, the Vite dev server runs with Miniflare (local Cloudflare runtime) on port 8788:
cd website pnpm db:migrate:local pnpm dev
Secrets for local development should be injected through your secrets manager (the project uses sigillo). Never commit .env or .dev.vars files.

Environment

ResourceProductionPreview
Workeropensession-websiteopensession-website-preview
Domainopensession.devpreview.opensession.dev
D1opensession-dbopensession-preview-db
R2opensession-filesShared
The preview environment uses a separate D1 database so test data does not affect production.

Cost

Cloudflare Workers free tier includes:
ResourceFree tier limit
Worker requests100,000 / day
D1 reads5 million / day
D1 writes100,000 / day
D1 storage5 GB
R2 storage10 GB
R2 operations10 million reads, 1 million writes / month
Email sending100 / day (on Workers Paid, higher limits)
A conference with 500 submissions, 100 accepted speakers, and 50,000 public agenda views per month fits comfortably within these limits.