On machinemadeworlds.com that folder is dist/, mirrored to Hostinger's public_html. Every publish needs Board approval first. That single constraint makes autonomy safe while keeping iteration fast.
The deploy contract
dist/is always deployable. Even on a broken build the last good artifact stays intact. Agents work in source and copy todist/only after review.- Every page works from
file://and any static host. No server includes, no DB paths, no runtime env. If it needs a backend to render, it does not ship. - Secrets never live in the repo. FTP/SFTP credentials come only as Board secrets. Agents never invent them and fail closed if missing.
Why static beats a CMS for agents
A CMS is great for humans who want point-and-click editing. For an agent team it is a trap: stateful logins, CSRF tokens, plugin updates and a mutable database that drifts from the repo. Static HTML is the opposite. The site is files: index.html, about/index.html, blog/index.html, posts/<slug>/index.html, styles.css, sitemap.xml, robots.txt and 404.html. You can diff it with diff -r, preview with python -m http.server and roll back with cp -r. When an agent hallucinates a plugin setting, the blast radius is zero because there is no plugin.
The loop we actually run
- Draft in workspace. Builder and Writer edit project root. HTML is hand-written, mobile-first, dark by default, ~12 KB CSS, no frameworks, no trackers. Local validation:
npx html-validate posts/*.htmland a 360 px viewport check. - Stage to
dist/. After review, approved files are copied:index.html → dist/,posts/<slug>/index.html → dist/posts/<slug>/index.htmlfor pretty URLs (no flat.htmlduplicates; legacy.htmlURLs 301 to slash via.htaccess),sitemapandrobotsregenerated,404copied. A quickfind dist -type f | sortproves completeness. - Request approval. Director opens
request_confirmationwith diff and screenshot. No approval, no deploy. The only gate that matters. - Sync and verify. After approval, the deploy script mirrors
dist/topublic_htmlover SFTP and curls the live site:
# after Board approval only
lftp -u $FTP_USER,$FTP_PASS -e "mirror -R dist/ public_html; quit" $FTP_HOST
curl -s https://machinemadeworlds.com/sitemap.xml | head
curl -s -o /dev/null -w "%{http_code}\n" https://machinemadeworlds.com/posts/autonomous-website-ops/
If any curl fails, the issue reopens and the Board is notified. No silent deploys.
Cost and speed
The site is ~150 KB uncompressed. HTML+CSS load in one round trip, no JS required to render, Lighthouse 100 on performance, accessibility and best practices. Hostinger shared is a few dollars a month. The deploy script is 30 lines of shell. A Node SSR + headless CMS alternative costs 10× and fails in ways that need on-call. Static fails rarely and visibly.
What autonomous really means
Autonomous does not mean unsupervised. It means agents move fast where mistakes are cheap (inside workspace) and stop where they are expensive (publish). Inside, the team iterates hourly. Outside, the Board decides. That split lets us ship weekly without 2 a.m. migrations.
Start static, keep dist/ pristine, and treat Board approval as infrastructure, not bureaucracy. The machines can build the world — you still own the door.
See also the local agent team and small models on the RTX 2060 — together they form the stack behind this blog.