Colophon
What is actually running when you load this page.
The request path
you → Caddy (TLS, :443) → lighttpd (127.0.0.1:1720, CGI) → perl → Loom
Caddy terminates TLS and reverse-proxies the hostname. lighttpd serves
/assets, /media and /tally/tally.js straight off disk, executes the demo
scripts under /demo, and rewrites everything else to public/app.cgi — which
is six lines long and hands the request to Loom.
CGI, genuinely: a fresh perl per request. For a site of flat files it is fast
enough, and it means there is no daemon to babysit and no state to leak between
requests.
The pieces
| Repo | Role here |
|------|-----------|
| perl-loom | Renders every page, runs /admin |
| perl-tally | Counts the visit, serves /tally/dashboard.cgi |
| perl-cookie | The /demo/cookie.cgi demo |
| perl-mailer | The /demo/mailer.cgi demo |
| perl-fileupload | /demo/upload.cgi, and Loom's media manager |
No library was forked to build this. build.sh copies each repo's lib/ into
one tree and overlays this site's content, templates and demo endpoints on top,
so pulling a library and rebuilding picks its changes up.
Zero CPAN dependencies. Not "few" — zero. Everything is core Perl:
Digest::SHA, JSON::PP, MIME::Base64, Time::Local, Fcntl, POSIX,
File::Path, File::Basename, Scalar::Util.
The hourly reset
The admin is open — demo / demodemo — so the site has to be disposable. A
systemd timer runs on the hour and restores content/pages and content/data
from a pristine copy taken at build time, empties public/media, clears saved
demo messages, and drops any admin sessions. Tally's event log is not reset,
so the visitor stats are real.
Edit a page, delete one, upload something dubious. It will be back.
Deliberate constraints
- No outbound connections. Tally's geolocation is a local packed database
binary-searched in process; there is no lookup API. Fonts, CSS and JS are all served from this origin. Nothing here phones anywhere.
- Mail is composed but not sent. The host blocks port 25, so
/demo/mailer.cgi shows you the MIME it built rather than pretending.
- The template playground has limits. It renders text through
Loom::Template, which has no eval and no filesystem access — but input is
capped and the whole thing runs under a timeout regardless.
Colours and type
System font stack, no webfonts. The palette follows prefers-color-scheme, so
this page is dark if your machine is.
Elsewhere
This site is entirely separate from claytongrace.com, which is a Python building- management suite. Different stack, different repos, different server process — they share only a domain and an author.