|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +HFLOSSK is the Humanitarian Free/Open Source Software Course website for RIT, built with Flask and Mako templates. It serves course materials (lectures, homework, quizzes) and tracks student participation via YAML files and RSS blog feeds. There is no database β all data is file-based. |
| 8 | + |
| 9 | +## Commands |
| 10 | + |
| 11 | +### Setup (Fedora Linux 43) |
| 12 | +```bash |
| 13 | +sudo dnf install python3 python3-pip git |
| 14 | +git clone git@github.com:FOSSRIT/hflossk.git |
| 15 | +cd hflossk |
| 16 | +python3 -m venv venv |
| 17 | +source venv/bin/activate |
| 18 | +pip install -e . |
| 19 | +``` |
| 20 | + |
| 21 | +### Run locally |
| 22 | +```bash |
| 23 | +python app.py |
| 24 | +# Serves at http://127.0.0.1:5000/ in debug mode |
| 25 | +``` |
| 26 | + |
| 27 | +### Run tests |
| 28 | +```bash |
| 29 | +pip install -e ".[test]" |
| 30 | +pytest # Run tests only |
| 31 | +pytest --tb=short # Shorter traceback output |
| 32 | +ruff check . # Lint only |
| 33 | +``` |
| 34 | + |
| 35 | +### Run full test suite via tox |
| 36 | +```bash |
| 37 | +pip install tox |
| 38 | +tox # Tests (py314) + lint |
| 39 | +tox -e lint # Lint only |
| 40 | +tox -e cover # Tests with coverage |
| 41 | +``` |
| 42 | + |
| 43 | +### Freeze static site |
| 44 | +```bash |
| 45 | +python freeze.py |
| 46 | +# Generates static HTML in build/ |
| 47 | +``` |
| 48 | + |
| 49 | +## Architecture |
| 50 | + |
| 51 | +### Entry Point |
| 52 | +`app.py` imports the Flask app from `hflossk/site.py` and runs the Flask dev server in debug mode. For production, use `gunicorn hflossk.site:app`. |
| 53 | + |
| 54 | +### Template Engine: Mako (not Jinja2) |
| 55 | +Templates use `.mak` extension and Mako syntax (`${variable}`, `<%inherit>`, `<%def>`, `% for`). The Flask-Mako extension bridges Flask and Mako. All templates live in `hflossk/templates/`. |
| 56 | + |
| 57 | +### Core Modules |
| 58 | +- **`hflossk/site.py`** β Flask app creation, route definitions, context processor that injects `site.yaml` config into all templates. Gravatar/Libravatar helper. Routes for pages, syllabus, blog JSON endpoint, participant profiles, resources. |
| 59 | +- **`hflossk/blueprints.py`** β Blueprints for `/assignments/` (homework), `/lectures/`, `/quizzes/`. Each dynamically discovers and serves templates from its subdirectory. |
| 60 | +- **`hflossk/participants.py`** β Blueprint for `/participants/`, `/blogs/`, `/checkblogs/`. Walks `scripts/people/<year>/<term>/*.yaml` to build student roster. Calculates expected blog post counts based on elapsed course weeks. |
| 61 | +- **`hflossk/util.py`** β RSS feed parsing via feedparser. Counts blog posts since course start date. |
| 62 | + |
| 63 | +### Data Flow |
| 64 | +1. **Course config**: `hflossk/site.yaml` (instructor, dates, location) and `hflossk/schedule.yaml` (weekly topics, assignments, due dates) are loaded at request time and injected into templates. |
| 65 | +2. **Student data**: `scripts/people/<year>/<term>/<username>.yaml` β each file has required keys (`blog`, `feed`, `forges`, `irc`, `name`, `rit_dce`) and optional `hw` dict mapping assignment names to blog post URLs. |
| 66 | +3. **Blog tracking**: `/blog/<username>` endpoint parses student RSS feeds and returns JSON post count. Used via AJAX in the participants page. |
| 67 | + |
| 68 | +### Content as Templates |
| 69 | +Course content (lectures, homework, quizzes) are Mako template files in `hflossk/templates/hw/`, `hflossk/templates/lectures/`, `hflossk/templates/quiz/`. They inherit from `master.mak`. |
| 70 | + |
| 71 | +### Static Assets |
| 72 | +`hflossk/static/` contains Bootstrap CSS/JS, course PDFs (`books/`), slide decks (`decks/`), and challenge descriptions (`challenges/`). |
| 73 | + |
| 74 | +### YAML Validation Tests |
| 75 | +`hflossk/tests/test_yaml.py` validates that all student YAML files contain required fields and conform to expected schema. This is the primary test coverage. |
| 76 | + |
| 77 | +## CI/CD |
| 78 | + |
| 79 | +- **CI** (`.github/workflows/ci.yml`): Runs on all branches/PRs in a Fedora 43 minimal container. Installs deps, lints with ruff, runs pytest. |
| 80 | +- **Preview** (part of CI): For non-main branches, freezes the site and uploads a downloadable artifact (retained 7 days). |
| 81 | +- **Deploy** (`.github/workflows/deploy.yml`): On push to `main`, freezes the site via `freeze.py` and deploys to GitHub Pages. |
| 82 | +- **Static site generation**: `freeze.py` uses Frozen-Flask to crawl the app and generate static HTML. Dynamic routes like `/blog/<username>` (live RSS parsing) are excluded. |
| 83 | + |
| 84 | +## Key Constraints |
| 85 | +- Flask-Mako pins the project to Mako templating; migration to Jinja2 would require rewriting 30+ template files |
| 86 | +- No database or ORM β all persistence is YAML files in the repo |
| 87 | +- Python 3.14 on Fedora 43 is the target runtime |
| 88 | + |
| 89 | +## Git Commit Conventions |
| 90 | +- Subject line: emoji prefix + component prefix (e.g., `π§ App:`, `π Docs:`, `π CI:`, `π Fix:`) |
| 91 | +- Trailer: `Assisted-by: Claude Opus 4.6 (1M context)` for AI-assisted commits |
| 92 | +- Trailer: `Signed-off-by:` (always last, via `--signoff`) |
| 93 | +- GPG signed (via `-S`) |
0 commit comments