I walked all 156 beds of the San José Municipal Rose Garden, photographed every rose, and directed an AI build partner to turn a static brochure map into an interactive companion — now officially adopted by the City of San José.
Visit the live companion →I didn't start in a code editor — I started in the garden. Over a full season I walked all 156 beds, one arc at a time, photographing every rose in bloom and the little green sign beside it, and reading each one out loud to be sure I had it right.
That's where the surprises were. Dozens of beds had quietly been replanted, and the City's planting plans hadn't caught up — so if I'd trusted the spreadsheet, half the garden would have been wrong. Every photo on the site is one I took myself. No stock, no shortcuts — because when you're standing in front of a rose, you deserve to know you found the right one.
A dataset is only as true as the last person who went and looked. The garden had quietly changed; the official records hadn't — and no amount of good code fixes bad ground-truth.
Next came the unglamorous part: hundreds of photos that all needed to be matched to the right rose. The names were right there on the signs — but they're angled, sun-washed, weather-worn metal, and no off-the-shelf tool could read them cleanly.
So I built a small OCR pipeline on Apple's Vision framework (compiled down to a tiny Swift binary), which read the raised lettering far better than anything else I tried. It pulled the text off each sign, fuzzy-matched it to a rose in my dataset, and renamed the photo on its own — jump-for-joy.jpg, memorial-day.jpg. The edge cases I did by hand: beds where a new name had been taped over an old sign, and one 2026 pre-release whose card had no name on it at all.
The real win wasn't reading the signs — it was that the pipeline then renamed every photo to the right rose on its own. Hundreds of iPhone shots sorted themselves into a clean archive, and the grunt work quietly disappeared.
Here's the part that surprises people: the clickable map isn't generated. I drew it — every one of the 185 tap-targets, one or more for each of the 156 beds, traced over the garden's original brochure illustration, because that brochure look is the point.
And not for lack of trying to automate it. I tested AI and computer-vision approaches to detect the bed shapes from the artwork — every pass came back merged, ragged, or off by 10 to 30 pixels. Close. But "close" opens the wrong rose when someone taps. So I traced all 185 by hand on an image-map tool, then a Python script converted them to SVG.
Each shape carries its bed number hard-coded right into it (data-bed="72"), so a tap is a one-line lookup with zero coordinate math — the deliberately simple approach that can never return the wrong bed.
<area> polygons, each tying a set of pixel coordinates to one bed number, drawn by hand rather than detected by a model.The least clever solution won. The "smart" version — math that guesses a bed from where you tapped — can quietly point someone at the wrong rose. Baking the answer into each shape can't misfire. Reliability beat cleverness.
This was built with AI — and the part worth talking about isn't that I used it. It's that I knew exactly where it stops. The code moved at the speed of conversation; the judgment couldn't be handed over.
The tool made me faster — it didn't make the decisions. Bringing the vision, the taste, and the parts no model can touch, then directing the rest: that's the creative job now. A physical garden, taken all the way to shipped, maintainable software — without a development team.
Every rose got its own write-up — 156 of them — each one written for the person standing in front of it, not for a botanist. I led with what you actually want to know (its name, where you are, what it should look like, whether it's worth leaning in for) and tucked the breeder, year, and parentage underneath as quiet credibility.
Then I audited all 156 against primary sources and the signs themselves — 38 corrections, and real restraint on fragrance, because visitors will smell the rose and catch an overstatement instantly. On that honest base I added nine themed walking tours (routes auto-optimized from the main gate), a Chinese-zodiac rose matcher, riddle scavenger hunts, an interactive scent wheel, and a tappable history timeline.
slug — the ID that ties the write-up, the photo file, and the map together — followed by bed, breeder, year, type, color, and fragrance.Restraint is a feature. The visitor is standing there with their nose in the rose — one overstated "strong fragrance" and they stop believing all 156. Credibility is a design material, not a disclaimer.
The whole thing is a single, self-contained HTML file — no framework, no build step, no backend. It loads fast on a phone in the middle of a garden with patchy signal, and I can open it, change a rose, and save. The clickable map, all 156 descriptions, the tours, the games, even the brochure illustration — one file, deployed to Netlify with analytics and social-preview cards.
And it keeps itself honest: every time I walk the garden, my field-log and the OCR pipeline turn the visit into an update. Walk → log → auto-tag → apply. A living thing, not a one-time deliverable.
Shipped beats sophisticated. One plain file I can open and fix in the garden will outlive anything that needs a build server and a team. I optimized for the thing surviving me, not for impressing an engineer.
I shared the live site with Councilmember Mulcahy's office — and it moved faster than I expected. The Rose Garden Experience is now officially adopted by the City of San José, championed across Parks & Recreation, Team San José, the Friends of the Rose Garden, and Rotary.
It started as something I made because I love the garden. It's ending up as public infrastructure.
I love the way you describe this as a labor of love. I live in the neighborhood near Rose Garden and I feel your passion and joy. You combined technology, creativity and a genuine commitment to community and then gave the work back to San José. This is a wonderful example of innovation with purpose. Spartan pride!
Or start a conversation about building experiences like this.