This is the github repository for the artisanal website made by standup comedian / former physicist Alex Kaufman. You can use this repo to find out about shows ahead of time, or request features I am likely not technically competent enough to implement.
The site is maintained from the road, often from the GitHub mobile app between shows. The principles below exist to keep that possible.
These are the rules-of-thumb the site is built around. When in doubt, lean on these.
-
Git is the CMS. Content lives as plain files in this repo. No database, no admin panel, no external dashboards. One commit is one update. Everything is versioned and rollback-able.
-
One file, one change. A routine update — adding a show, editing the bio — should touch exactly one file. If you have to remember to also update X, Y, and Z, that's a bug to fix.
-
Phone-editable wins. Every format choice is judged against: can I do this from the GitHub mobile app, in an airport, with one hand? No required tooling beyond a text editor.
-
Fail loud at deploy, not silent at runtime. A typo in a show file should break the build with a clear error, not quietly disappear from the live site. Catch it while you still remember what you meant.
-
Boring code beats clever code. Future-me is a jet-lagged comedian, not a full-time engineer. Prefer obvious Flask/Jinja patterns, vanilla CSS, minimal JS. If a trick saves ten lines but takes ten minutes to re-understand, it isn't worth it.
-
Small surface area. Every new file, format, config option, or dependency is a thing to remember. Justify additions. Prune ruthlessly.
-
Deploys are boring.
git pushtomainis the whole deploy. No manual rituals, no "don't forget to X." If it needs a step, automate it or write it down in the one place we'll look. -
Performance is part of the product. Bookers decide in seconds. Images optimized, third-party scripts deferred, fonts preloaded. Cheaper than hiring a designer.
-
Documentation lives next to the thing. How to add a show → CONTENT.md. How to deploy → DEPLOYMENT.md. What we're working on → TODO.md. Don't make future-me grep.
- Flask + Jinja2 — small Python web app, server-rendered HTML. App factory in alexkaufmanlive/init.py.
- Markdown + YAML frontmatter for all content. Show files in alexkaufmanlive/content/shows/, pages in alexkaufmanlive/content/. Loaded into memory at startup by content.py.
- Responsive image pipeline — drop originals in
content/static/originals/, scripts/build_images.py generates AVIF/WebP/JPEG at multiple widths on deploy. - Hosted on PythonAnywhere, deployed via GitHub webhook to
/git_update→update-site.sh→ WSGI reload. - Secrets via 1Password SDK in production. Dev uses safe defaults — see config.py.
# Install in editable mode (uses flit)
pip install -e .
# Generate image derivatives so the site renders without warnings
python scripts/build_images.py
# Run the dev server
FLASK_APP=alexkaufmanlive flask runFLASK_ENV defaults to dev, so 1Password isn't needed locally.
For production setup (1Password service account, webhook
config), see DEPLOYMENT.md.
- Adding shows or editing content → CONTENT.md
- Setting up the deploy pipeline → DEPLOYMENT.md
- Roadmap and known wins → TODO.md