- Python 51.7%
- JavaScript 18.1%
- CSS 15.3%
- Nix 12.8%
- HTML 2.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| apps/pyquest | ||
| .gitignore | ||
| flake.nix | ||
| README.md | ||
homefree-pyquest
A HomeFree plugin: PyQuest — a guided, self-paced Python course for a kid who wants rigour rather than a tour.
The course itself is CS50P. This app is the rails around it: it answers "what do I do today", records what has actually been finished, and gives a parent a read-only view of where things stand.
Why a harness and not a curriculum
The failure mode of "here are three great resources, off you go" is that it makes a beginner the project manager of their own education. Every session starts with where was I, which tab, what now? — and that overhead is what stalls people before any of the actual learning starts.
So the design goal is narrow:
Open one page, and there is exactly one obvious thing to do.
Rails constrain what to work on next and when — never how hard the problem is. Sequencing is scaffolded; the problems stay difficult. Days unlock in order, and a day is only done when all its tasks are.
The plan is a sequence, not a calendar. "Day 3" is a position, not a date. If a problem set eats six hours across two afternoons, Day 3 simply takes two days and nothing is "late" — the target is depth over coverage.
What runs where
| Laptop (the learner's real dev environment) | Box (this app) |
|---|---|
| Python 3, VS Code, git | Plan engine — today's card |
| Their actual code | Progress tracking, per SSO user |
check50 --local (real CS50 autograding) |
Parent view |
| The terminal | Syllabus + resource links |
| Forgejo — their git remote |
No code executes on the box. This process only reads and writes JSON, which is why there is no sandbox anywhere in it and no need for one.
Why local, and why Forgejo
A local setup is what actual developers use, so that's what this track builds.
It also sidesteps an account problem: submit50 pushes to
github.com/me50/<user>, and GitHub requires users to be 13 or older — so
for a younger learner, CS50's submission path and its browser codespace are both
closed. check50 --local is not: it runs the real check suites from the public
cs50/problems repo with no account at all. The autograding survives; only the
submission-and-certificate path is gated (and the free course tier has no
certificate anyway).
Forgejo on the same box then gives a real git remote with no third-party ToS, no age gate, and nothing leaving the house — plus a natural artifact for the nightly code review: today's commit diff.
Curriculum is data, not code
Everything lives in apps/pyquest/curriculum/*.json — goal, prose, resource
link, exact command, expected output. Adding or rewording a lesson never touches
Python. Four strands run through it:
- spine — CS50P notes and problem sets
- drill — CodingBat, the fluency layer
- toolcraft — shell, git, debugging, venvs. Delivered just-in-time, at the point it's needed, rather than front-loaded
- build / review — projects, and the 15-minute nightly walkthrough
Enable
homefree.services.pyquest = {
enable = true;
# public = false; # LAN-only by default
# subdomain = "pyquest";
};
SSO-gated via Caddy (oauth2 = true). Every authenticated household member gets
their own independent track — a parent can work alongside. Admins additionally
see the Parent tab, gated on the X-Homefree-Role header.
Tests
nix-shell -p 'python313.withPackages(ps: with ps; [fastapi uvicorn pydantic httpx])' \
--run "python3 apps/pyquest/test_smoke.py"
Covers the auth gate, admin-only parent view, day unlock/relock, per-user isolation, identity sanitising, and graceful degradation on a corrupt progress file.