Rounds is a self-hostable interview prep workspace for system design, coding, behavioral prep, and job-search tracking.
Current release: v1.0.0
Hosted demo: https://rounds.keyurgolani.name
Demo login:
- Email:
demo@rounds.keyurgolani.name - Password:
RoundsDemo123!
The demo account is seeded on first PocketBase deployment, can run one custom coding snippet and one test-suite evaluation per session, and resets its profile, progress, drafts, applications, todos, preferences, and local caches when it logs out.
- System design practice with question lists, API-backed cheat-sheet guides, diagrams, trade-off panels, and senior follow-up topics.
- Coding practice with Monaco editor, local drafts, focus mode, custom runs, full-suite evaluation, curated runnable question sets, and structured problem metadata.
- AI Assisted Coding rounds with multi-file Monaco workspace, AI chat (Ask mode) using your configured provider, per-checkpoint test runner, and a rubric-grade submission flow.
- Behavioral prep with competency-tagged questions, STAR story guidance, personal anecdotes, and question-to-story linking.
- Application tracking with companies, roles, statuses, rounds, offers, campaign context, and todos.
- Resume Studio with four templates, per-section editors, drag-and-drop reordering, JD-aware tailoring, ATS scoring, version history, AI bullet rewrites, server-rendered PDFs, exports to DOCX / HTML / Markdown / plain text / JSON Resume, and public share links.
- Command center, theme controls, streak tracking, and dashboard widgets for day-to-day prep.
| Layer | Tech |
|---|---|
| Frontend | React 18, TypeScript, Vite, Tailwind CSS |
| Auth + data | PocketBase + SQLite |
| Code runner | FastAPI + Python/Node subprocess drivers |
| Deployment | Docker Compose or Kubernetes manifests |
| Tests | Vitest + Testing Library, pytest on Python 3.12 |
.
├── frontend/ React + Vite SPA, production nginx config
├── backend/ FastAPI code runner + AI/PDF/share routers
├── backend/pdf_renderer/ Node + Puppeteer sidecar for high-fidelity PDFs
├── pocketbase/ PocketBase image, migrations, hooks, seeds
├── docs/ Deployment notes
├── k8s/ Kustomize manifests
├── docker-compose.yml Local development stack
└── docker-compose.prod.yml Single-box production stack
cp .env.example .env
docker compose up -dServices:
- Frontend:
http://localhost:3001 - PocketBase:
http://localhost:8090, admin UI athttp://localhost:8090/_/ - Runner:
http://localhost:3099
Dev compose bootstraps a PocketBase admin from PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD when set. The .env.example defaults are for local development only.
cp .env.example .env
# edit .env for your domain, admin credentials, CORS, OAuth, and signup policy
docker compose -f docker-compose.prod.yml up -dOnly the frontend port is exposed. nginx routes runner endpoints to FastAPI and all other /api/* plus /_/* traffic to PocketBase.
Production compose pulls published images from Docker Hub by default:
keyurgolani/rounds-frontendkeyurgolani/rounds-pocketbasekeyurgolani/rounds-runner
Equivalent images are also published to GHCR as ghcr.io/keyurgolani/rounds-frontend, ghcr.io/keyurgolani/rounds-pocketbase, and ghcr.io/keyurgolani/rounds-runner.
PocketBase data lives in the pb_data Docker volume. Back it up regularly.
Hosted instances can disable public signups:
VITE_DISABLE_SIGNUPS=true
ROUNDS_DISABLE_SIGNUPS=trueVITE_DISABLE_SIGNUPS hides signup UI in the frontend. ROUNDS_DISABLE_SIGNUPS blocks direct PocketBase user creation through a server-side hook.
Fresh deployments run these migrations in order:
1700000000_init_collections.jscreates the final schema.1700000100_seed_data.jsloads all shared questions, categories, coding question sets, and guide cheat sheets.1700000500_bootstrap_admin.jsoptionally creates the first PocketBase admin from environment variables.1700000600_demo_user.jscreates the hosted demo user and demo-run limiter fields.1700000700_resume_studio.jsadds resume, resume version, and bullet-library collections.1700000800_ai_providers.jsadds the per-user AI provider credential collection (keys stored encrypted at rest).1700000900_share_links_resume_rel.jsextendsshare_linkswith a relation to resumes for public read-only views.
npm --prefix frontend test
npm --prefix frontend run build
python3.12 -m venv /tmp/rounds-backend-venv
/tmp/rounds-backend-venv/bin/python -m pip install -r backend/requirements.txt
/tmp/rounds-backend-venv/bin/python -m pytest backendSee .env.example and frontend/.env.example for the complete list.
| Variable | Purpose |
|---|---|
HTTP_PORT |
Production frontend host port |
POCKETBASE_PORT |
Dev PocketBase host port |
RUNNER_PORT |
Dev runner host port |
FRONTEND_PORT |
Dev frontend host port |
CORS_ALLOW_ORIGINS |
Runner CORS origins |
PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD |
PocketBase admin bootstrap; also used by the runner's public-share endpoint to bypass owner rules |
PDF_RENDERER_URL |
Internal URL of the headless-Chromium PDF renderer (defaults to the sidecar service) |
AI_KEY_SECRET |
Symmetric secret used to encrypt user-supplied AI provider keys at rest |
VITE_POCKETBASE_URL |
Browser PocketBase base URL; blank means same-origin |
VITE_API_PROXY_TARGET |
Vite dev runner proxy target |
VITE_POCKETBASE_PROXY_TARGET |
Vite dev PocketBase proxy target |
VITE_DEV_ALLOWED_HOSTS |
Comma-separated Vite dev allowed hosts |
VITE_OAUTH_GOOGLE_ENABLED, VITE_OAUTH_GITHUB_ENABLED |
Render OAuth buttons |
VITE_DISABLE_SIGNUPS, ROUNDS_DISABLE_SIGNUPS |
Disable signup UI and server-side user creation |
MIT. See LICENSE.