Contributing¶
Get involved¶
Start with an issue, so we can agree on the approach before you write code:
| You want to… | Open |
|---|---|
Report a studio command that fails, crashes or produces the wrong output |
Bug report |
| Suggest a new command, setting, scene template or house-style change | Feature request |
| Ask a question or raise anything else | Blank issue |
Or pick from every template.
Check Troubleshooting and the
open issues first. To fix something
yourself, fork the repository, branch from main and open a
pull request. Use the commit prefixes
below, and make sure CI passes.
Layout¶
| Path | What it is |
|---|---|
tools/studio/ |
The Python CLI |
tests/ |
pytest suite for the CLI |
brand/ |
House style: design spec, CSS, fonts, GSAP, pronunciations |
templates/ |
Starter script, scene patterns and thumbnail |
episodes/<slug>/ |
One HyperFrames project per video |
docs/ |
This site |
Tests¶
uv run pytest # all tests, with a coverage table
uv run pytest --cov-report=html # browsable report in htmlcov/index.html
uv run pytest tests/test_script.py -k pause # one file, or tests matching a name
The suite needs no TTS model or HyperFrames: narration goes through a fake engine
(fake_tts in tests/conftest.py), transcripts are stubbed, and scene renders are stubbed. The
mix tests run real ffmpeg, mastering a test tone and measuring that it lands on the loudness target;
they skip when ffmpeg isn't installed (CI installs it). Paths in
studio.common are fixed at import time, so tests that write files point the module attributes
they use at tmp_path with monkeypatch. test_demo_episode_timing_is_reproducible checks that
the committed episodes/demo-paris-commune/timing.json still follows from its script and
narration, so a change to timing maths shows up as a failing test, not a silently re-timed video.
Coverage settings are under [tool.coverage] in pyproject.toml. The run fails below the
fail_under floor; raise it as coverage grows.
Documentation site¶
The site is built with MkDocs Material from docs/
and mkdocs.yml, and published to GitHub Pages by .github/workflows/docs.yml on every push to
main that touches them.
uvx --with mkdocs-material==9.7.7 mkdocs serve # live preview at http://127.0.0.1:8000
uvx --with mkdocs-material==9.7.7 mkdocs build # strict build into ./site
The build is strict, so broken links fail it. In the repository settings, set Pages → Source to GitHub Actions once.
Development works the same way on Windows, Linux and macOS: install the tools, clone,
and uv sync. Keep both platforms working: pass encoding="utf-8" to every text read and write, run
npx through hf() in common.py, and keep absolute paths out of ffmpeg filter arguments
(a drive colon splits options).
CI¶
ci.yml runs
on every push to main and every pull request:
pytestwith coverage on Python 3.12 and 3.13; the coverage table goes in the run's summary, andcoverage.xmlplus the HTML report are uploaded as thecoverageartifact. On pull requests from this repository, python-coverage-comment-action posts one comment with the total and the coverage of the changed lines (updated on each push), and pushes tomainrefresh the README badge, stored on thepython-coverage-comment-action-databranchuv sync --locked,ruff check tools/ tests/, and a CLI smoke test (statuson every episode, plusnew)hyperframes checkon every episode, at the pinned HyperFrames version
CI never narrates or renders, so commit audio/vo/, timing.json and index.html after sync.
Commit messages and releases¶
release-please reads
Conventional Commit messages on main and keeps a release PR
open that bumps the version in pyproject.toml and uv.lock and updates CHANGELOG.md. Merging it
tags vX.Y.Z and publishes a GitHub release. Never hand-edit the version or the changelog.
| Prefix | Changelog section | Bump (while < 1.0) |
|---|---|---|
feat: |
Features | patch |
fix:, perf: |
Bug fixes, Performance | patch |
episode:, brand:, docs:, deps: |
Episodes, House style, Documentation, Dependencies | patch |
refactor:, test:, ci:, chore: |
hidden | none |
feat!: or a BREAKING CHANGE: footer |
minor |
The repository needs Settings → Actions → General → Allow GitHub Actions to create and approve pull requests turned on. Release PRs opened with the default token don't trigger CI; close and reopen the PR to run checks before merging.
Upgrading HyperFrames¶
Bump HF_VERSION in tools/studio/common.py, run studio check on an episode, and compare a draft
render.
Licence¶
The studio software is released under the MIT licence.
Editorial content (everything under episodes/ and scripts/) is © World Socialist Web Site, all
rights reserved. Fonts (SIL OFL 1.1), GSAP (GreenSock Standard License) and third-party photographs
keep their own terms.