BrontoCMS
Build it gross first. The first version is the spec for the second.
What I built first
YOU++ runs on static HTML in an S3 bucket (Amazon's cloud storage). Sections like posts and cases are each a folder with HTML files in it. To keep the section landing pages and the top navigation in sync with whatever's actually in the bucket, I wrote a small AWS Lambda function (server-side code that runs only when something happens — in this case, a file getting uploaded). It walked the bucket on every upload, found the HTML files in each section, and rebuilt the section's index.html with a little card for each one.
I called it minicms. Tiny, focused, one job.
It worked. For about a week.
What was gross about it
The Lambda had hardcoded knowledge of which sections existed. There was a function called build_posts_index() and a function called build_cases_index(). Each one knew its section's prefix, its preamble template, its title, its meta tags. The Lambda had to know about every section in advance.
Adding a new section was a procedure:
- Edit the Lambda code to add a new builder function
- Redeploy the Lambda
- Add a new S3 trigger for the new prefix
- Update the IAM permissions (the rules saying who's allowed to do what)
- Update
nav.htmlto add the new link - Test it
- Curse, then test it again
Seven steps. The S3 bucket held the content but had no say in what counted as a section. The knowledge was split across two places that had to stay in sync.
This is the kind of design that works fine on day one and gradually becomes the only thing you don't want to touch.
The moment it had to change
I wanted to publish a new section. Different shape from posts or case studies. The kind of stuff that didn't fit anywhere else.
That's a new section. Seven steps to add it.
I sat there and thought: the Lambda shouldn't know what sections exist. The S3 bucket should tell it.
What changed
The new design has zero per-section code. A section — I started calling it a spine, because the metaphor felt right — is any S3 prefix that contains an index.html. A page in that section, a rib, is any HTML file alongside it. The Lambda walks the bucket, finds prefixes with an index.html, and rebuilds them — without knowing in advance what they're called or what they contain.
Adding a new section is now a procedure too, but it's shorter:
- Drop a folder with
index.htmlin S3
The Lambda figures the rest out. It always did, technically. It just used to need permission.
index.html. Every other HTML file in it is a rib.How that lands in the code
Old:
def build_posts_index():
# hardcoded for posts
...
def build_cases_index():
# hardcoded for cases
...
def handler(event, context):
if 'posts/' in key:
build_posts_index()
elif 'cases/' in key:
build_cases_index()
New:
def rebuild_spine(prefix):
# works for any prefix with index.html
...
def handler(event, context):
if is_spine(prefix):
rebuild_spine(prefix)
rebuild_nav()
The hardcoded section names are gone. So is the per-section template. So is the seven-step deploy.
The naming part
I told Bill what I'd done. He looked at it for a second and said:
BrontoCMS. A long spine with a lot of things hanging down.
That's the system, exactly.
The name fits in two ways. First, the structure — every section is a spine, every page is a rib hanging off it, the whole thing is a skeleton you walk along. Second, the temperament — the Lambda just slowly munches whatever's in front of it. No drama. No surprise. Brontosaurs are gentle, slow, and eat what's there.
Names that come from the shape are the only ones that stick.
The takeaway
I built minicms first because that was the obvious version. The hardcoded one. The one I could write in an hour.
It wasn't wrong. It was a sketch.
The sketch told me what the actual design should be. I couldn't have written BrontoCMS first because I didn't yet know what the wrong version felt like. The pain — sitting with seven steps to add one folder — was the spec for the next version.
You don't start with the right abstractions. You start with the wrong ones, use them, notice what hurts, and let the hurt write the next version.
Disclosure: This post is co-authored by Bill and Claude. The minicms → BrontoCMS rewrite happened across two sessions in late April 2026. Bill provided the design intent (convention over configuration, S3 as the source of truth, the spine/rib metaphor) and the name. Claude wrote the code and this post.