# Robot U Site Agent Guide ## Purpose This repository contains the Robot U community site. It is a thin application layer over Forgejo: - Forgejo is the source of truth for authentication, public content repos, and issue-backed discussions. - This app provides the web UI, course/lesson browsing, markdown rendering, and ICS calendar ingestion. - The current live Forgejo instance is `https://aksal.cloud`. ## Stack - Backend: FastAPI - Frontend: Preact + TypeScript + Vite - Python tooling: `uv`, `ruff` - Frontend tooling: `bun`, Biome ## Important Files - `app.py`: FastAPI app and SPA/static serving - `live_prototype.py`: live payload assembly for courses, lessons, discussions, and events - `prototype_cache.py`: server-side cache for the public Forgejo content payload - `update_events.py`: in-process SSE broker for content update notifications - `forgejo_client.py`: Forgejo API client - `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`. Recommended local flow: ```bash cp .env.example .env ``` Useful variables: - `FORGEJO_BASE_URL=https://aksal.cloud` - `APP_BASE_URL=http://kacper-dev-pod:8800` - `AUTH_SECRET_KEY=...` - `AUTH_COOKIE_SECURE=false` - `FORGEJO_OAUTH_CLIENT_ID=...` - `FORGEJO_OAUTH_CLIENT_SECRET=...` - `FORGEJO_OAUTH_SCOPES=openid profile` - `FORGEJO_TOKEN=...` - `FORGEJO_GENERAL_DISCUSSION_REPO=Robot-U/general_forum` - `FORGEJO_WEBHOOK_SECRET=...` - `FORGEJO_CACHE_TTL_SECONDS=60.0` - `CALENDAR_FEED_URLS=webcal://...` - `HOST=0.0.0.0` - `PORT=8800` Notes: - 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. - API clients can query with `Authorization: token ...` or `Authorization: Bearer ...`. - `CALENDAR_FEED_URLS` is optional and accepts comma-separated `webcal://` or `https://` ICS feeds. - Do not commit `.env` or `.env.local`. ## Main Start Command Use this for the normal local app flow: ```bash ./scripts/start.sh ``` What it does: 1. Loads `.env` and `.env.local` if present. 2. Builds the frontend with `bun`. 3. Starts FastAPI with `uvicorn`. Override host/port when needed: ```bash HOST=0.0.0.0 PORT=8800 ./scripts/start.sh ``` ## Development Commands ### Backend only ```bash .venv/bin/python -m uvicorn app:app --reload ``` ### Frontend only ```bash cd frontend ~/.bun/bin/bun run dev ``` ### Frontend production build ```bash cd frontend ~/.bun/bin/bun run build ``` ## Quality Checks Run both before pushing: ```bash ./scripts/check_python_quality.sh ./scripts/check_frontend_quality.sh ``` ## Product/Data Model Background - Public non-fork repos are scanned. - A repo with `/lessons/` is treated as a course repo. - A repo with `/blogs/` is treated as a post repo. - Lessons are discovered from `lessons///`. - Each lesson folder is expected to contain one markdown file plus optional assets. - Frontmatter is used when present for `title` and `summary`. - Discussions are loaded from Forgejo issues and comments. - Issue bodies are scanned for canonical post/lesson URLs and Forgejo file URLs to connect discussions back to content. - Calendar events are loaded from ICS feeds, not managed in-app. ## UI Expectations - The UI should not expose Forgejo as a user-facing implementation detail unless necessary for debugging. - Course cards should open course pages. - Lesson rows should open lesson pages. - Discussion pages should focus on one thread at a time. - Markdown should render as readable content, not raw source. ## Push Workflow The site source repo currently lives at: - `git@aksal.cloud:Robot-U/robot-u-site.git` Typical push flow: ```bash git status git add ... git commit -m "..." git push origin main ```