Privacy-Friendly Form Builder For Conscious Companies
What is bettercollected? 🔗
bettercollected is an open-source, privacy-friendly form builder. It lets you show responders that you care about their data: creators declare the purpose of the data they collect, responders consent before submitting, and they can later view their submission and request its deletion (a GDPR-style flow baked into the product).
It provides a workspace to host all your forms in one place — forms built with the native drag-and-drop builder, or imported from Google Forms and Typeform.
More at bettercollected.com.
- 🧩 Drag-and-drop form builder with a rich set of field types
- 🔐 Consent + purpose declaration, response viewing, and deletion requests
- 🔗 Import forms and responses from Google Forms and Typeform
- 🏢 Multi-tenant workspaces with members and custom domains
- 📊 Form analytics powered by self-hosted Umami — no responder data leaves your infrastructure — plus CSV export
- 🤖 AI-assisted form generation
Cloud: the hosted version is at bettercollected.com.
Self-host / develop locally: see the setup below.
bettercollected is a polyglot microservices monorepo:
| Service | Stack | Role |
|---|---|---|
webapp/ |
Next.js + TypeScript | Frontend (builder, dashboards, responder portal) |
backend/ |
FastAPI + MongoDB (Beanie) | Core API |
auth/ |
FastAPI + Stripe | Identity (OAuth / OTP / JWT) + billing |
integrations/ |
FastAPI + Google/Typeform APIs | Form-provider integrations |
temporal/ |
Temporal workers | Background jobs (imports, deletion, CSV, previews) |
common/ |
Shared Python package | Models, enums, crypto, JWT |
Infra: MongoDB, Redis, PostgreSQL + Temporal, nginx, and Umami (self-hosted analytics, with its own PostgreSQL). A deep dive lives in docs/ARCHITECTURE.md.
Prerequisites: uv, Node 20+ (see
.nvmrc), Yarn 1.x, and Docker.
# 1. Start infra (MongoDB + seed data, nginx, Mailpit email inbox)
docker compose -f docker-compose.local.yml up --build -d
# 2. Copy and fill env files (see the developers guide for required secrets)
cp backend/.env.example backend/.env
cp auth/.env.example auth/.env
cp webapp/.env.example webapp/.env
# 3. Install & run
(cd backend && uv sync && uv run python -m uvicorn backend.app:get_application --port 8000 --reload)
(cd auth && uv sync && uv run python -m uvicorn auth.app:get_application --port 8001)
(cd webapp && yarn install && yarn dev) # http://localhost:3000The full walkthrough — env vars, shared secrets, provider OAuth, Temporal, and common gotchas — is in docs/DEVELOPERS_GUIDE.md. Integration setup (Google/Typeform apps) is in docs/RUNNING_INTEGRATIONS.md.
The entire stack — including analytics — runs on your own machine, so no third-party service ever sees responder data:
./deploy.sh # everything except form-provider integrations
./deploy.sh googleform # ... with Google Forms import
./deploy.sh typeform # ... with Typeform import
./deploy.sh both # ... with both
./deploy.sh down # stop the stackdeploy.sh brings up the full stack from
docker-compose.deployment.yml with health
checks and correct startup ordering: webapp (:3000), backend (:8000),
auth, MongoDB (+ seed data), Temporal + workers, nginx (:3001/:3002), and
Umami analytics (:3003, default login admin/umami —
change it). On first run it also generates a random UMAMI_APP_SECRET into a
gitignored root .env. The backend auto-provisions the Umami website on
startup, so analytics needs no manual setup.
Configuration lives in .env.deployment. The tracked
defaults (including secrets) are for local evaluation only — generate fresh
secrets before exposing an instance to the internet, and put TLS or a
reverse proxy in front of it yourself.
GitHub Actions deploys updated service images through Docker Stack and Docker Manager. Set these repository variables before enabling the workflow:
| Environment | Ref | Manager variable | Stack variable |
|---|---|---|---|
| Development | develop |
DEVELOP_MANAGER |
DEVELOP_STACK |
| Staging | master |
STAGING_MANAGER |
STAGING_STACK |
| Production | a Git tag | PROD_MANAGER |
PROD_STACK |
Each manager variable must contain that environment's Docker Manager URL. The workflow authenticates with GitHub OIDC, so the matching Docker Manager must trust this repository as an OIDC client.
Contributions are very welcome! Please read CONTRIBUTING.md and our Code of Conduct. Good places to start:
- Issues labelled
good first issue - The per-service
AGENTS.mdfiles for context on the code you're touching
Found a security issue? Please follow our Security Policy — do not open a public issue.
Licensed under the Apache License 2.0.
