Every project begins with a sentence that sounds small. Ours was: “Build a tool that takes a folder of big photos and turns them into web-sized images.”
That’s a batch image processor. It’s an old, honest idea. Photos straight from a camera are huge, often several megabytes each, and putting them on a website unchanged makes pages slow and bandwidth bills larger. A batch tool shrinks them, makes a small thumbnail for each one, and does it for dozens of files at once instead of one at a time.
This is the first of five posts about how that small idea became bip, the free, self-hosted photo gallery now at version 1.02 Release. You can see the finished product on the project page, but the interesting part is how it got there.
We wrote the idea down as a proper engineering brief rather than a vague wish. The brief said what the tool should do, what it should never do, which technology to use, and how we’d know it was finished. It matters more than anything else in this story, so it’s worth explaining why.
Why a written brief comes first
When you work with an AI coding assistant, the quality of what you get back depends on the clarity of what you hand over. A vague request produces confident-looking code that does something slightly different from what you wanted. A tight brief produces code you can actually review against something.
Ours covered four things:
- The job: read images from an upload folder, produce a web-sized version and a thumbnail of each, and record them.
- The constraints: plain PHP with no framework, a small embedded SQLite database rather than a database server, and the kind of cheap shared hosting most people already have.
- The limits: a batch must stop safely before a host’s time limit cuts it off, so a big upload is processed across several runs instead of failing halfway.
- The definition of done: a person can deploy it, log in, process a batch, and see the results.
Everything that followed was measured against that document.
Choosing boring technology
The constraints were deliberate. Plain PHP and SQLite run almost everywhere and keep working for years without attention. A database in a single file can be backed up by copying it. For a small utility someone might install once and forget, boring is a feature.
The first working version
The first version did what the brief said. You uploaded images by FTP, logged into an admin page, pressed a button, and the tool worked through the files, resized them, made thumbnails, converted them to WebP (a modern format that gives much smaller files for the same visual quality), and wrote a record of each into the database.
There was deliberately no upload form in the browser. Uploading by FTP removes a whole category of risk, because the application never has to accept a file from a stranger.
It worked. It was useful. And that was exactly when the trouble started.
The first temptation
Once images and thumbnails were sitting in a database, the next thought came almost immediately: if everything is already recorded, why not show it? A page that lists the processed photos would be only a small step.
We’ll be honest: that was the first step on a road that would add albums, captions, a public viewer, and a good deal more. Even after the product was feature-complete we kept polishing the public page: a handful of small layout and presentation tweaks to the index page were made during the release-candidate cycle, once real galleries were on screen. More on those in Part 5.
In Part 2 we look at scope creep, and why it’s not always the villain it’s painted as, so long as you keep making decisions about it on purpose.
In short
The project began as a batch image processor with a written engineering brief. A clear brief is what makes AI-assisted coding reviewable, and the first working version did its job, which tempted us to ask for more.
Read next: — Scope creep, on purpose.




Leave a Reply