A daily coding practice app with spaced repetition to help you master the Blind 75.
Open source. Self-host it, fork it, make it yours.
- Python 3.13+
- Node.js 18+
- Docker & Docker Compose
- Supabase CLI
- uv (Python package manager)
-
Start Supabase (PostgreSQL database)
supabase start
Copy the
DB URLfrom the output and update.env:# Change postgresql:// to postgresql+asyncpg:// DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:54322/postgres -
Start Judge0 (Code execution engine)
# Start Judge0 in background docker-compose up -d # Verify it's running curl http://localhost:2358/ # View logs if needed docker-compose logs -f judge0-server
See DOCKER.md for detailed Docker commands and troubleshooting.
-
Set up Backend
cd backend uv venv uv sync # Run database migrations uv run alembic upgrade head # Seed problems (first 15 Blind 75) uv run python scripts/seed_problems.py # Start backend server uv run uvicorn app.main:app --reload
-
Set up Frontend
cd frontend npm install npm run dev -
Access the app
- Frontend: http://localhost:5173
- Backend API: http://localhost:8000
- API Docs: http://localhost:8000/docs
- Default login:
admin@acodeaday.local/changeme123
acodeaday/
├── backend/ # FastAPI backend
│ ├── app/
│ │ ├── config/ # Settings & logging
│ │ ├── db/ # Database models & connection
│ │ ├── routes/ # API endpoints
│ │ ├── services/ # Business logic
│ │ └── middleware/ # Auth & request handling
│ ├── migrations/ # Alembic database migrations
│ ├── scripts/ # Seed data & utilities
│ └── tests/
├── frontend/ # React + TanStack frontend
│ ├── src/
│ │ ├── pages/ # Route components
│ │ ├── components/ # UI components
│ │ ├── hooks/ # Custom React hooks
│ │ └── lib/ # API client & utilities
│ └── public/
├── supabase/ # Supabase configuration
├── docker-compose.yml # Judge0 & services
└── .env # Environment variables
| Component | Technology |
|---|---|
| Frontend | React 19 + TanStack Router + React Query |
| Code Editor | Monaco Editor |
| Backend | FastAPI (Python 3.13+, async) |
| Database | PostgreSQL (via Supabase) |
| ORM | SQLAlchemy 2.0 (async) |
| Migrations | Alembic |
| Code Execution | Judge0 CE |
| Auth | Supabase Auth (JWT Bearer tokens) |
| AI Chat | litellm (Gemini, OpenAI, Anthropic) |
| Logging | Structlog |
cd backend
# Install dependencies
uv sync
# Run tests
uv run pytest
# Run with auto-reload
uv run uvicorn app.main:app --reload --port 8000
# Create new migration
uv run alembic revision --autogenerate -m "description"
# Apply migrations
uv run alembic upgrade head
# Rollback migration
uv run alembic downgrade -1cd frontend
# Install dependencies
npm install
# Run dev server
npm run dev
# Build for production
npm run build
# Run tests
npm test# Start Supabase
supabase start
# Stop Supabase
supabase stop
# Reset database (WARNING: deletes all data)
supabase db reset
# View Supabase Studio
# URL shown in 'supabase start' output (usually http://localhost:54323)# Start all services
docker-compose up
# Start only Judge0
docker-compose up judge0
# Stop all services
docker-compose down
# View logs
docker-compose logs -f judge0Copy .env.example to .env and configure:
| Variable | Description | Default |
|---|---|---|
DATABASE_URL |
PostgreSQL connection (asyncpg) | postgresql+asyncpg://... |
SUPABASE_URL |
Supabase project URL | http://localhost:54321 |
SUPABASE_KEY |
Supabase anon/public key | - |
DEFAULT_USER_EMAIL |
Default user email | admin@acodeaday.local |
DEFAULT_USER_PASSWORD |
Default user password | changeme123 |
JUDGE0_URL |
Judge0 API endpoint | http://localhost:2358 |
LLM_SUPPORTED_MODELS |
Comma-separated LLM models | gemini/gemini-2.5-flash |
ENVIRONMENT |
Environment (development/production) | development |
DEBUG |
Enable debug mode | true |
LOG_LEVEL |
Logging level | INFO |
Once the backend is running, visit:
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/problems |
List all problems |
| GET | /api/problems/{slug} |
Get problem details |
| POST | /api/run |
Run code against test cases |
| POST | /api/submit |
Submit solution (all tests) |
| POST | /api/rate-submission |
Rate difficulty (Anki SM-2) |
| GET | /api/today |
Get today's session |
| GET | /api/progress |
Get user progress |
| GET | /api/mastered |
Get mastered problems |
| POST | /api/mastered/{id}/show-again |
Re-add to rotation |
| POST | /api/code/save |
Save code (auto-save) |
| GET | /api/submissions/{id} |
Get submission history |
| POST | /api/chat/sessions |
Create AI chat session |
The app uses the Anki SM-2 spaced repetition algorithm:
Rating System: After successful submission, rate difficulty:
- Again: Reset to 1 day, decrease ease factor
- Hard: Slower growth (×1.2), decrease ease
- Good: Normal growth (×ease factor)
- Mastered: Immediately exit rotation
Algorithm: Interval grows based on ease factor (default 2.5, min 1.3). Auto-mastery when interval reaches 30+ days.
"Show Again": Manually re-add mastered problems to rotation (resets ease factor).
Each day presents up to 3 problems:
- Review #1: Oldest overdue problem (if any)
- Review #2: Second oldest overdue problem (if any)
- New Problem: Next unsolved in Blind 75 sequence
User writes code in Monaco Editor
↓
Frontend sends to /api/submit
↓
Backend wraps code with test harness
↓
Sends to Judge0 for execution
↓
Judge0 runs code in sandbox
↓
Returns results (pass/fail per test case)
↓
Backend updates user_progress if all passed
↓
Frontend displays results
- README.md (this file) - Quick start and overview
- TASKS.md - Detailed implementation tasks and patterns
- DOCKER.md - Docker commands and troubleshooting
- spec.md - Complete product specification
- CLAUDE.md - Project instructions for Claude Code
MIT — do whatever you want with it.
"A code a day keeps rejection away"
Focus on understanding through consistent practice, not cramming. One problem at a time, reviewed at optimal intervals for long-term retention.