-`calendar_feeds.py`: ICS/webcal feed loading and parsing
-`settings.py`: env-driven runtime settings
-`frontend/src/App.tsx`: client routes and page composition
-`frontend/src/MarkdownContent.tsx`: safe markdown renderer used in lessons and discussions
-`scripts/start.sh`: main startup command for local runs
## Repo Layout Notes
- The root repository is the site application.
-`examples/quadrature-encoder-course/` is a separate nested git repo used as sample content. It is intentionally ignored by the root repo and should stay that way.
## First-Time Setup
### Python
```bash
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
```
### Frontend
```bash
cd frontend
~/.bun/bin/bun install
```
## Environment
Runtime configuration is loaded from shell env, then `.env`, then `.env.local` through `scripts/start.sh`.
- Browser sign-in uses Forgejo OAuth/OIDC. `APP_BASE_URL` must match the URL opened in the browser, and the Forgejo OAuth app must include `/api/auth/forgejo/callback` under that base URL.
- Browser OAuth requests only identity scopes. The backend stores the resulting Forgejo token in an encrypted `HttpOnly` cookie and may use it only after enforcing public-repository checks for writes.
-`FORGEJO_TOKEN` is optional and should be treated as a read-only local fallback for the public content cache. Browser sessions and API token calls may write issues/comments only after verifying the target repo is public.
-`/api/prototype` uses a server-side cache for public Forgejo content. `FORGEJO_CACHE_TTL_SECONDS=0` disables it; successful discussion replies invalidate it.
- General discussion creation requires `FORGEJO_GENERAL_DISCUSSION_REPO`. Linked discussions are created in the content repo and include canonical app URLs in the Forgejo issue body.
- Forgejo webhooks should POST to `/api/forgejo/webhook`; when `FORGEJO_WEBHOOK_SECRET` is set, the backend validates Forgejo/Gitea-style HMAC headers.