Local Development & Mock Auth
The application uses Google OAuth 2.0 for authentication in production. During local development and automated testing (e.g. AI-assisted visual inspection, Playwright E2E), the OAuth popup cannot be driven by an automated agent.
Mock Auth mode bypasses Google entirely: both the backend and frontend boot with a pre-authenticated dev user, no browser popup required.
How it works
Section titled “How it works”| Layer | Flag | Effect |
|---|---|---|
| Backend (FastAPI) | MOCK_AUTH=true | get_current_user resolves a DB-backed mock user by email (get-or-create) — no JWT validation |
| Frontend (Vite/Svelte) | VITE_MOCK_AUTH=true | authStore initialises synchronously with the same mock user — no fetchMe() HTTP call, no loading flash |
Default mock identity:
email: dev@localname: Dev Userrole: ADMINis_approved: true-
Configure the backend
Copy
.env.exampleto.envinsidebackend-api/and add:backend-api/.env MOCK_AUTH=trueMOCK_AUTH_EMAIL=dev@localMOCK_AUTH_NAME=Dev User -
Configure the frontend
Create
frontend-pwa/.env.local(gitignored by Vite) and add:frontend-pwa/.env.local VITE_MOCK_AUTH=true -
Start the development servers
Terminal window # Install runtimes, install all dependencies, and start both serversmise installmise run setupmise run dev# → Access locally on http://localhost:5173Terminal window cd backend-apiuv sync --all-extrasuv run uvicorn dicechess_trainer.main:app --reload --host 0.0.0.0 --port 8000# → http://localhost:8000Terminal window cd frontend-pwanpm install --legacy-peer-depsnpm run dev# → http://localhost:5173 -
Verify
Open http://localhost:5173. The app should display the main UI immediately — no Google login popup.
You can also confirm the backend returns the mock user:
Terminal window curl http://localhost:8000/api/auth/me# {"id":<mock_user_id>,"email":"dev@local","name":"Dev User","role":"ADMIN","is_approved":true,...}
Syncing with Production Data
Section titled “Syncing with Production Data”To test features locally with actual game data and puzzles, you can synchronize your local SQLite database with the latest production backup using our automated synchronization helper scripts.
These scripts use the GitHub CLI (gh) to securely download the latest production database backup artifact from GitHub Actions, verify its integrity, and replace your local development database (backend-api/data/dicechess.db) safely.
Prerequisites
Section titled “Prerequisites”- Install the GitHub CLI (
gh) (e.g.brew install ghon macOS). - Authenticate with GitHub by running:
Terminal window gh auth login
Running the refresh script
Section titled “Running the refresh script”The recommended way to refresh your database is using the unified mise task, which automatically detects your operating system and calls the appropriate helper script:
mise run db:refreshAlternatively, depending on your preferred terminal shell, you can manually run the scripts from the repository root:
./scripts/ops/refresh_local_db.sh./scripts/ops/refresh_local_db.ps1Automated testing (AI agents & E2E)
Section titled “Automated testing (AI agents & E2E)”When running Playwright or AI-assisted inspections, set both flags in the test environment before launching the servers. The frontend will render authenticated content on the first paint, making visual assertions predictable.
Troubleshooting: “Failed to save position” in mock mode
Section titled “Troubleshooting: “Failed to save position” in mock mode”If UI shows a generic save error in mock mode, check these in order:
- Backend really runs with mock auth (
backend-api/.envhasMOCK_AUTH=true, then restart backend). - Frontend really runs with mock auth (
frontend-pwa/.env.localor.envhasVITE_MOCK_AUTH=true, then restart frontend). - Mock user identity is stable (
MOCK_AUTH_EMAILis unchanged while testing bookmarks/training data). - Shared game exists in
gamestable (bookmarks have FK togames.game_id). - Bookmark is not duplicate (
user_id + game_id + plyunique key).
Example SQL checks:
SELECT id, email, role, is_approved FROM users WHERE email = '<mock_auth_email>';SELECT COUNT(*) FROM games WHERE game_id = '<game_id>';SELECT id FROM bookmarked_positionsWHERE user_id = <resolved_user_id> AND game_id = '<game_id>' AND ply = <ply>;