Development

timewalk is a few files, and it has no build step. The server is one Python file that you run with uv run. uv run reads the dependencies of the server from the file itself. They are Starlette, uvicorn, websockets, and Playwright and pypdf for the PDF. The pages are plain HTML, CSS and JavaScript modules.

File What it is
src/timewalk/__init__.py The server. It holds the git layer (Repo), the readers for notes and slides, the terminals, the edits watcher and the web application
src/timewalk/slides_pdf.py The PDF export, the command timewalk-pdf. The PDF button of the page uses it too
src/timewalk/static/ The page (index.html, app.js), served at /. The old address /presenter sends the browser on to /. Also the print page, common.js and app.css
src/timewalk/static/vendor/ ghostty-web, highlight.js and marked, each with its licence
tests/test_timewalk.py The tests
demo/ The demo submodule, with its notes and slides
docs/ This site. It holds the pages, _smalldocs.yml, the theme Atelier in _extensions/, styles.css, screenshots.py, images/ and style/

Tests and lint

just test            # the git layer, notes and slides, the web application's guards, the terminals
just test -k slides  # extra arguments go to pytest
just lint            # ruff

The tests build small repositories of their own. They check that timewalk never does these things:

  • move the repository that you give it
  • lose an untracked file, an edit or a commit of a learner
  • ask about edits in a replay copy, or move with --in-place without asking
  • write through the file view
  • answer a request without the token

To check a change to the page, drive it in headless Chrome against a clone of the demo. Headless Chrome is Chrome that runs without a window. Open the page in two windows, and check that they agree. Throw the clone away after the check.

The site

just screenshots     # take every picture again, from a clone of the demo
just site            # build the site with smalldocs, and serve it on this machine

The pages are Markdown files in docs/. smalldocs builds them into a website. A theme named Atelier sets the look of the pages, such as the fonts, the colours and the sidebar. docs/_smalldocs.yml lists the pages, and the sections and order of the sidebar. A GitHub Action builds the site on each push to main that changes a file in docs/ or the workflow itself. Then it publishes the site to GitHub Pages.

The theme is in docs/_extensions/atelier/, with a .source file that says where it came from. To take a new version, run uvx --from 'smalldocs>=0.3.3' smalldocs add rahuldave/smalldocs-atelier@TAG --force in docs/, with the tag of the version for TAG, for example v0.2.0. The command copies the theme at that tag into docs/_extensions/atelier/. Without --force, smalldocs asks before it replaces the copy that is there, or stops with an error when it cannot ask. --force replaces it without asking. docs/styles.css holds the site’s own CSS rules, which change parts of the theme’s look.

screenshots.py clones the demo into a temporary folder and serves the clone with timewalk. Then it drives the page in headless Chrome. It uses bash and a short prompt, so nothing personal shows. When the pages change, take the pictures again.

The writing guide

Every page of the site follows the writing guide, docs/style/GUIDE.md. So do the README and the notes and slides of the demo. The glossary of terms is in docs/style/README.md, with the headings that other pages link to. Check the pages with the recipe:

just style                                    # every page, the README and the demo's prose
python3 docs/style/check.py -v docs/edits.md  # one page, with the soft notes

Fix each hard problem. Then read the page, and build the site with just site.

just style then asks Claude Code, through claude -p, to review the prose that changed since the last commit. A problem that Claude finds fails the check. Each file gets at most three such rounds between two commits. After the third, the check passes, and the findings wait for a person in the file’s report in reports/writing/. Without Claude Code, just style skips this review.

The demo

The history of the demo is its own repository. This repository holds it as a submodule, which is a git repository kept inside another one at a fixed commit. To change the demo, do these steps in order:

  1. Work in the submodule.
  2. Keep one commit for each step, with an annotated step-NN tag. An annotated tag stores a message with the tag.
  3. Push its main and its tags.
  4. Commit the new submodule pointer here.
  5. Check demo/notes.md and demo/slides/slides.toml against the steps.

Licence

timewalk uses the MIT licence. The libraries in src/timewalk/static/vendor/ keep their own licences. ghostty-web uses MIT, highlight.js uses BSD 3-Clause and marked uses MIT.