Onboarding: your first bug-fix¶
A practical, step-by-step walkthrough for a new contributor. Unlike the Architecture and Setup pages (which explain what the system is), this page walks you through doing your first bug-fix end to end — from a fresh clone to a merged pull request.
1. Set up the development environment¶
Prerequisites: Python 3.11+ (3.12 recommended — plugins test against 3.12), Node 24+ (required by Vite 8), Poetry, npm, and GNU Make.
# Clone
git clone https://github.com/astrapi69/adaptive-learner.git
cd adaptive-learner
# Install everything: Poetry backend + plugin path-deps + npm frontend
make install
# Establish a green baseline before you change anything
make test
# Run the app (backend on :18001, frontend on :15174)
make dev
The frontend dev server runs at http://localhost:15174, the
backend at http://localhost:18001. Both ports are overridable via
ADAPTIVE_LEARNER_FRONTEND_PORT / ADAPTIVE_LEARNER_PORT. Press
Ctrl-C once to stop both.
If make install fails, the usual culprit is Poetry picking the wrong
Python — run poetry env use python3.12 in backend/ and re-install.
For the full configuration chain (secrets, AI keys, the mandatory
ADAPTIVE_LEARNER_SECRET_KEY) see Setup.
2. Find a bug¶
Issues are the work queue. Every fix needs an issue first
(GITHUB-ISSUE-PFLICHT).
Or on GitHub: https://github.com/astrapi69/adaptive-learner/issues?q=is%3Aissue+is%3Aopen+label%3Abug
Pick something small to start — look for good first issue or a
low-effort bug. If no issue exists for the bug you found, create
one before you touch code — and file a separate issue for any new
bug you discover along the way.
3. Understand the issue¶
- Read the description and reproduce the bug locally.
- Note which storage mode it occurs in. Adaptive Learner ships dual storage (API/SQLite and Dexie/IndexedDB); a bug may live in one mode, the other, or both. See Storage layer.
- If you cannot reproduce it, ask in the issue rather than guessing.
4. Create a branch¶
Adaptive Learner uses gitflow: develop is the active branch;
main holds releases only. Branch from develop and open your PR
against develop.
Branch naming:
| Prefix | For |
|---|---|
fix/... |
bug fixes |
feature/... |
new features |
refactor/... |
refactors |
docs/... |
documentation |
chore/... |
tooling / housekeeping |
5. Fix the bug¶
Tips for finding the code:
- Frontend errors: open the browser DevTools console.
cd frontend && npx vitest --watch <file>gives live test feedback while you edit (always run vitest fromfrontend/, not the repo root).- Styling: Tailwind utility classes only, no inline color styles
and no new rules in
global.css. Colors go through design tokens (CSS variables) — see Theme system. - Both storage modes must keep working. A feature that ships in API mode without a Dexie path (or a graceful "not available in browser mode" message) is a release blocker.
6. Write a regression test¶
Every fix needs at least one test that fails before the change and passes after it.
# Frontend (Vitest) — run from frontend/
cd frontend && npx vitest run src/path/to/file.test.ts
# Backend (pytest)
cd backend && poetry run pytest tests/path/ -v
# A single plugin
make test-plugin-gamification
For backup-touching changes there is an extra gate: a real
Export → Import round-trip in make dev with real data (the
BACKUP-AKZEPTANZTEST). Unit tests alone never justify a backup
merge.
7. Run the full gate locally¶
make test # backend + plugins + frontend Vitest
make check-types # mypy + tsc --noEmit
make test-dexie-smoke # GH-Pages-shape build, every route, no backend
cd frontend && npm run build
Everything must be green before you open a PR.
8. Commit and push¶
Conventional Commits. Reference the issue with a closing keyword so the merge auto-closes it.
git add -A
git commit -m "fix(area): short description
Longer description of what the problem was and how it was fixed.
Closes #123"
git push -u origin fix/short-description
Keep commits atomic — each commit leaves the tree green
(make test passes). Combine a source change with its test change in
the same commit when splitting them would create a red intermediate.
9. Open a pull request¶
gh pr create --base develop \
--title "fix(area): short description" \
--body "Closes #123
## What changed
- ...
## Tests
- ..."
Always target develop, never main (main is the release
branch). For a sub-issue of an umbrella/epic, cite the sub-issue
with Closes #<sub-issue>, plus Refs #<umbrella> for traceability.
10. Wait for CI¶
CI runs the correctness gates on every PR:
- Frontend tests (Vitest) + Backend / plugin tests (pytest)
- TypeScript (
tsc --noEmit) + mypy + ruff + ESLint - Pre-commit hooks
- Complexity gate (baseline ratchet — new functions must stay under the cyclomatic-complexity threshold)
- Folder-size + file-size guards (god-file / god-folder prevention)
- i18n parity (all 11 languages must define every key)
- Design-token guard (no hardcoded colors / fixed-palette utilities)
- Docs-drift verifier
Heavier checks (Dexie-mode E2E, coverage, mutation testing, security scan, content-stats drift) run nightly + at release, not on every PR.
11. Review and merge¶
Wait for review (or self-merge if you have maintainer rights). PRs are
squash-merged into develop, so your branch's commits collapse to
one clean commit on the trunk.
Project rules (short version)¶
| Rule | Meaning |
|---|---|
GITHUB-ISSUE-PFLICHT |
every fix/feature needs an issue first |
| Tailwind-only | no global.css additions, no inline color styles |
| Design tokens | colors via CSS variables, never hex literals |
| Dexie-mode parity | everything works in Dexie and API mode |
| Library-first | native API > framework > library > custom code |
| Conventional Commits | fix(), feat(), refactor(), docs(), ... |
| i18n | all UI strings in all 11 languages |
| 44px touch targets | mobile-friendly interactive elements |
Full rule set: .claude/rules/.
Common commands¶
make dev # start backend + frontend
make test # all tests (backend + plugins + Vitest)
make test-dexie-smoke # Dexie-mode release gate (no backend)
make check-types # mypy + tsc --noEmit
make check-complexity-gate # complexity ratchet
make check-folder-size # god-folder guard
make sync-i18n # regenerate frontend i18n from backend YAML
make sync-versions # propagate the canonical version
cd frontend && npm run build # build the frontend
make help lists every target; the
Makefile
is the source of truth for build commands.
Architecture in one screen¶
frontend/src/
api/ FastAPI client (the only place fetch() lives)
components/ UI components, grouped by concern (dashboard/, lesson/, ...)
features/ feature-strategy gating (useFeatureAvailable)
hooks/ React hooks
lib/ business logic, grouped by domain (lesson/, srs/, ai/, ...)
pages/ route components (+ content/, dashboard/, lesson/ subdirs)
shared/ app-independent reusable components
storage/ dual storage: getStorage() -> IStorageService
styles/ design tokens + per-theme CSS
backend/app/
routers/ thin FastAPI endpoints (delegate to services)
services/ business logic (no FastAPI imports)
repositories/ data layer (Session-free contracts)
models/ SQLAlchemy models (single-file domain model)
hookspecs.py the 10 plugin hooks
plugins/ 13 PluginForge plugins (one package each)
Details: Architecture.
Where do I find...?¶
| What | Where |
|---|---|
| Project rules | .claude/rules/ |
| Architecture | Architecture |
| Storage layer | Storage layer |
| Plugin system | Plugin guide |
| AI integration | AI integration |
| Testing | Testing |
| Release workflow | Release workflow |
| Lesson content format | Authoring lesson content |
| i18n | i18n |
| Deployment | Deployment |
| Roadmap | docs/ROADMAP.md |