What someone standing in an unfamiliar city needs
Google Maps will tell you two things reliably: there's a hall nearby, and yes, it's open right now. Ask it anything more useful, what a day pass costs, whether there's a café worth sitting in afterward, whether the place is even bouldering and not a rope hall that happens to show up in the same search, and it shrugs. Someone standing in a city they don't live in, phone in hand, wants five answers: is there a hall here, is it open, what's a ticket, is there somewhere to sit afterward, can I rent shoes. Every decision that follows in this directory, from what gets filtered to how long a description is allowed to run, traces back to that list. The gap between what Maps answers and what people are looking for is the whole reason for the directory to exist.
Where the data comes from
Every gym starts as a scrape: name, address, opening hours, and however many reviews are public, pulled in from the web rather than typed in by hand. Reviewer names and any other identifying details get stripped out before anything is stored, only the review text and star rating survive. That raw pull isn't usable on its own. It becomes an actual listing through an enrichment pipeline, built together with Claude over the months that followed, that reads through the scraped reviews and the hall's own website and decides what to fill in: which amenities are genuinely present, what the real opening hours are, whether the tone of the reviews suggests a hall worth trusting.
Every amenity tag a gym shows now, café, kids' area, training area, and the rest, comes out the other end of that pipeline. None of it is typed in by hand, and none of it existed at all in the first version. Whenever the pipeline got something wrong, the fix was never just that one hall, it was a rule specific enough that the next hall with the same problem wouldn't need a human to catch it again. What that pipeline gets right and wrong, and how those rules built up over six months, is most of what the rest of this is about.
Airtable, Astro, and Leaflet: three early choices
Airtable was the obvious pick in February. I already knew it, it keeps data clean, and it's
fast to wire up when you want to be building by the weekend, not reading documentation. I
knew going in about the 1,000 API calls a month on the free tier. What I didn't know was
how often Claude Code would hit it during builds, since I'd never paired the two before and
had no feel yet for the call volume that generates. The site blew straight through the
limit in April. Once that happened, I found the fix: stop calling Airtable at build time at
all. A local cache, and a build that reads from a checked-in src/data/gyms.json
instead of hitting the API live. Airtable wasn't a bad call, it just needed a build pattern
I hadn't worked out yet. One smaller lesson lived in the same table: after some
experimenting with field types, leaving cities as free text instead of a locked dropdown, so
new ones could get added straight from the crawl, turned out to be the better call.
Leaflet over Google Maps was Claude's suggestion, picked because it was easier to wire up. Google Maps wouldn't have been impossible to make GDPR-compliant, just a lot more engineering to defer properly. Leaflet paired with OpenStreetMap tiles made it easy, almost by accident: OSM tiles are just static image requests, trivial to hold back until someone consents. That's its own section further down.
Astro's static generation means every page gets built ahead of time, and that build step is also when a handful of scripts run to check that everything's still in order: one confirms the hall counts in the visible copy match the actual data, another pings roughly 200 gym websites looking for dead links, a third flags any closure banner that's overdue for a recheck. Catch a problem there and the build fails before anything ships. None of that works if pages were rendering on the fly, there'd be no fixed moment to run the checks in.
Five prompts, one weekend, and then finding out if it was worth continuing
Years of WordPress and Elementor had taught me a way to build websites, but it wasn't suitable for what I wanted to do here without dragging in a lot of bloat. Boulder gyms weren't the first idea either. I tried out a handful of directory categories before settling on this one, weighing search volume, how much decent competition was already out there, and how manageable a first AI-built directory needed to be. Boulder gyms in Germany hit the right size on all three.
I didn't just open Claude Code and start typing at it. Requirements came first, worked out in a plain chat conversation: what the directory needed, how the data should be shaped, what mattered for search. Then five prompts, each one a slice of that document, fed to Claude Code one at a time. By the end of the weekend I had a functioning MVP: filters, a map, sorting, a first attempt at enriching the data.
Of course the traffic didn't show up in the first week, that would have been a lot to ask. I kept working on it anyway for a while, mostly because I wanted to refine what was there, not because anything was telling me to yet. The real signal took about two months: Google started surfacing pages on its own, traffic began climbing, and that lined up with a handful of blog articles I'd been writing alongside the directory that were pulling in search traffic of their own. That combination, not any single moment, was enough to say this was worth continuing rather than becoming another abandoned side project. It helped that continuing cost basically nothing: hosting was already in place from years of building other sites, so there was no infrastructure bill making the decision for me either way.
Part of that first stretch was just watching. Which cities started ranking on their own, without any push from me, was the clearest signal for where real demand sat. The blog posts helped in a second way too: a handful of them picked up backlinks from other sites, which did more for the domain's authority than anything on the directory pages themselves could.
What happened in between: the weekend produced an MVP, lo-fi and “a little rough,” and once I saw I could build on it, I built out more cities first. At some point the lo-fi look stopped being charming and started getting in the way, so it went from barely-styled to at least good enough not to distract from the content.
Is a climbing hall with a boulder corner a boulder gym?
Germany has hundreds of climbing venues, and a fair number of them will argue with you about whether they count as a boulder gym. Rope halls, DAV club centres, high ropes courses, outdoor crags, fitness studios with one lonely wall, university halls, kids' formats, and one memorable venue that projects video games onto the holds, so you can technically boulder a level of Mario. Working out which of those belong in a boulder directory is the actual product decision of the whole project, and it took four tries to land on a rule that held.
Judge by review language
Count how often reviewers mention bouldering versus rope climbing. Worked fine until the ratio came out dead even, which it kept doing, stubbornly, across half of Bavaria.
Try a ratio on floor area
Compare published bouldering square metres to total climbing square metres instead. Rejected: it punished large halls for the crime of having more of everything, bouldering included.
Settle on an absolute floor
200 square metres of boulder wall, on its own, no matter what else is in the building. The sparkassendome DAV Kletterwelt in Neu-Ulm publishes 2,900 square metres of climbing wall, 300 of it bouldering. Just over the line, so it's in.
Rule the cases a formula can't reach
A club hall a non-member can't walk into stays in, with a banner explaining the access. A university hall counts only if the public can pay at the door. The video-game wall is out, and the ruling covers the format, not just the one hall, in case anyone else builds one.
A directory's inclusion criteria are the product. They can't be derived from data, only argued into existence and written down somewhere. A handful of halls still just need manual checking, there's no way around that, but every one of them also teaches the rule something, and it gets a little sharper each time.
The same amenity, shown two different ways
The amenity data used to render exactly the same wherever it showed up, a card and a full profile got identical treatment, which in hindsight was a bit lazy. It now comes from one shared component and looks different in each place on purpose: compact pill chips on a card, a two-column labelled list on a profile. On a card you're comparing halls and scanning for one thing, so density wins. On a profile you've already picked the hall and you're reading, so legibility wins. Same data, dressed for two different occasions.
Why "the café is expensive" proves there's a café
The original insight still holds up: when a review complains the café is expensive, that's not bad news for the café amenity, it's confirmation the café exists. Nobody complains about the price of a thing that isn't there. Negative sentiment is still evidence.
What six months added is the harder half, and it's basically the opposite claim: silence doesn't mean absence, and treating it like it does will quietly wreck your data. A sweep that proposed removing amenities no review had mentioned was wrong 8 times out of 10. One hall's outdoor area got flagged for deletion across 23 silent reviews, until digging in showed a single reviewer had described it in loving detail using the word „Außenfläche“ instead of the „Außenbereich“ the pattern was searching for. A café flagged the same way was disproved by one look at the hall's own website, which, in fairness, is where most people would have checked first. And a kids' area that looked solidly confirmed by four separate reviews was actually four phrases inside a single review, written by the one person arguing the hall didn't have one.
Reviews were never the only input either. Website crawls filled in plenty that reviews left silent, and when even that was unclear, the only way through was checking the hall's site myself and turning whatever I found into a rule for the next hall like it.
An AI can tell you what a review says. It genuinely cannot tell you what a review's silence means, and treating the two as equivalent is how a directory gets quietly less accurate while looking more thorough the whole time.
Writing 222 descriptions that don't all sound the same
222 of 226 gyms have an individual description now, and every single one has to survive the same test: swap the hall's name for any other hall's, and if the paragraph still reads fine, it says nothing and gets rewritten. Getting there took more than a one-line prompt. Claude Code writes from a set of guidelines I've built up over the months since: rules for tone, for what's worth mentioning versus left out, and specifically for how to handle a negative review, fold it in plainly rather than smoothing it into something vague. Those guidelines get revised the same way everything else here does: whenever one produces a description that reads flat or misleading, the fix becomes the next rule. Nothing gets quoted from a review verbatim either, partly for copyright, mostly because it's someone else's sentence, not mine to sell.
The detail I genuinely didn't expect to lose an afternoon to was German grammatical gender in front of a business name. It's das Stuntwerk Essen, but die CAMPUS Boulderhalle and der Boulderwürfel, and there's no shortcut, no rule of thumb, nothing. A dedicated module resolves the article per hall, and where it can't tell, it rewrites the sentence to avoid needing one rather than guessing and hoping. Getting this wrong across 244 pages is a tiny error that reads as a huge one: it's exactly the kind of slip that makes a site feel like nobody wrote it.
Descriptions weren't the only content decision. Every city page opens with its own intro paragraph, built from the specific halls in that town rather than one template with the city name swapped in, and a hall's district gets mentioned naturally wherever it's genuinely part of the story, not stuffed in for the keyword. Both city pages and individual gym profiles carry an FAQ section at the bottom: real questions someone would ask before a first visit, opening hours, kids, renting shoes, answered plainly. They're there for the visitor first, but they also happen to be exactly the kind of clearly labelled, quotable content that search engines and AI answer engines are built to pull from. Blog posts get headlines that say what they're about rather than something clever, and every gym profile's H2s carry both the relevant keyword and the hall's own name, so a page has a shot at ranking for someone searching the hall by name and not just the category.
GDPR as a design constraint, not a checkbox
The map on the site won't load until a visitor says yes to it, and that's not a blank grey rectangle with a cookie banner stapled on awkwardly. It's a designed state with its own layout, explaining what loading the map means before it happens rather than after. Fonts are self-hosted instead of pulled from a CDN, because loading them from Google would hand every visitor's IP address over before anyone had agreed to anything at all. Analytics fires after consent or not at all, and the banner offers accept and reject with equal visual weight, not a big green button next to a small grey link that's clearly hoping you won't notice it.
The consent gate is a page state, the same as an empty state or an error state, and most sites design it like they forgot it was there. This one didn't get to forget.
Redesigning a site that already had 350 live pages
Each version had a specific job, not just a fresher coat of paint. V1 in February existed to prove the product worked at all, functional and technically sound, nothing more. Once that was settled, usability became the driver behind the next two versions. An earlier redesign focused on making the site easier to use while the technical foundation stayed untouched, and started laying groundwork for monetization to see what would stick. This latest redesign continues that thread: another usability pass, and also where the richer profile type gyms will eventually pay to upgrade to, shown below, got built out for the first time.
The redesign shipped in August, six months in, onto a site that already had real, indexed pages doing real work in Google. That changes what a redesign is allowed to do: it can't move a URL, full stop. The sitemap was checked before and after against the same 385 addresses, and nothing needed a redirect. A directory's only real asset is the pages Google already trusts, and a redesign that reshuffles URLs for a fresher coat of paint is setting fire to that trust to make things look nicer.
The comps themselves came from a separate design tool, handed over as flat HTML. A few got built differently than drawn, on purpose, and the reasoning for each is written down in the repo rather than quietly lost. That's the normal, slightly untidy gap between what gets designed and what ships, and it's usually the part a portfolio leaves out because it's less flattering than a clean before-and-after.
Where this goes next
This started as a practice project. Six months in, it looks more like something that could genuinely work as a business, and the plan has shifted accordingly: keep expanding coverage, keep earning rankings with real content, and start turning that traffic into revenue rather than just watching the numbers climb. Roughly 75 German cities above 50,000 people still haven't been checked for a hall, and that's still the most straightforward way to grow.
The monetization side is still early, but it's not vague. Premium profiles are the first piece: gym owners can already claim their listing, and a paid tier on top of that adds photos, a fuller description, and better placement. After that, the plan is affiliate links where they make sense, paid placement in the guide articles and city pages themselves, and direct brand cooperations with gyms or gear companies who want in front of this specific audience. None of that works without the content and the rankings coming first, which is exactly why that part came first.
Not every gym will pay for a premium profile, so there's a second track running alongside it: a badge gyms can embed on their own site, just released, that links back to their directory profile. It costs a gym nothing to add, and it hands the directory the one thing rankings depend on, backlinks, without needing a single sales conversation.
The build is the cheap part. Budget for the judgment, not the code.
Any rule that runs on its own needs a measured error rate before you trust it blindly. The silence rule was wrong 8 times in 10 and felt completely right the entire time it was running, which is the scary part.
As of early August, before the individual gym profiles rolled out in full, July sat at roughly 50,000 impressions and a few hundred visitors. Enough to keep going. What a much larger profile-page expansion does to those numbers is the next real test.
The original point still holds, and it's aged well: AI removes the roadblocks that stop you from acting on your thinking, but it doesn't do the thinking for you.
Appendix The first version, February 2026
Published February 2026, the week the MVP went live. Kept exactly as it was written, including the numbers and claims that no longer hold, because the before-state is the point of keeping it.
The shift
I'm not a developer. I've spent years building sites with WordPress and Elementor, which works, but the lack of control was sometimes frustrating. I wanted to become more independent from Elementor specifically and have less bloat. I wanted to see if pages really are much faster without all of that overlay. Now, with AI and what people call "vibe coding," I can think in systems, orchestrate problems, and let Claude Code handle the technical details.
This boulder gym directory is my practice project. It's a real business idea with a legitimate monetization model, but more importantly, it's my way of learning how to work with AI as a building partner. Within 24 hours of my first prompt, I had a functioning MVP with filters, maps, sorting, and data enrichment. And honestly? It really plays on the parts that I like doing in the creation process. It lets me be creative and enjoy building.
Finding a process
I didn't just jump into Claude Code and start prompting. I took a structured approach that turned out to be surprisingly clever:
Requirements discovery (Claude chat)
Started in Claude's chat interface to talk through requirements: what the directory needs, how data should be structured, what features matter, SEO considerations. This became my foundation document.
Learning from others (YouTube + Claude)
Found YouTube tutorials on building directories. Extracted the scripts, pasted them into Claude chat, and had discussions after each video. This helped me refine the requirements and catch things I'd missed: features, structure, markup, SEO tags.
Breaking it down (Claude chat)
Had Claude break everything into manageable chunks. It created five sequential prompts that I could feed to Claude Code one by one. This turned an overwhelming project into a clear, step-by-step process.
Building the foundation (Claude Code)
Worked through the five prompts systematically. Within a few hours, I had a bare-bones but functional directory website. Not pretty yet, but it worked.
Iterating and refining
From there it was all iteration. Walk through the site, see what needs changing, prompt Claude Code to fix it. Design tweaks, structural changes, adding features, removing complexity. The kind of back-and-forth that actually feels productive.
What I learned
Vibe coding actually works
I can build functional sites without being bogged down by little technical problems that aren't in my field of expertise. I can find ways to work through these technical problems that I come up with. The roadblocks that used to stop me now just... don't.
My strengths are systems thinking
I'm good at understanding problems, thinking in systems, and orchestrating solutions. I don't need to be the one writing the code. I just need to understand what's happening.
Manual first, automate second
My first impulse is to want to automate everything immediately. But doing things manually first taught me where the real problems are. Now I can automate intelligently.
Start small and niche
Choosing boulder gyms in Germany meant a few hundred data points, not thousands. Small enough to manually review, big enough to feel real. Geographic + topic niching was perfect for learning.
Human input still essential
Claude couldn't see certain problems, like why gyms weren't being added to Airtable (the city dropdown was hardcoded). I needed to understand the logic to fix it.
Reducing complexity over adding features
A lot of my iteration work was removing things. Icons that added nothing. Overcomplicated filters. The best version was simpler, not fancier.
Building is fun again
I feel in the zone when doing this. I'm genuinely excited to see ideas come to life. Even my wife has to hear about it (she doesn't understand much but shares the joy, what a gal).
The clever bits
Airtable as the data foundation
I knew from the start I wanted Airtable as the backend. It's easy to integrate, keeps data clean, and I already understood how it works. This wasn't just convenient. It gave me a clear mental model for how data flows through the site.
Structuring amenities with boulder grips
The amenities needed to be filterable: cafe, training area, kids' area, courses, etc. Instead of boring icons, I had them styled to look like boulder climbing grips. A small touch, but it makes the site feel considered.
Maps with Leaflet, not Google
Claude suggested Leaflet over Google Maps for easier integration. I trusted the suggestion. It worked perfectly. Sometimes you don't need to be the expert. You just need to know when to trust good advice.
Scraping + AI enrichment
I manually scraped data for the first five or six gyms to understand what information mattered. Then I used a scraping tool to pull 25 reviews per gym and had Claude Code extract amenity information and write short AI-generated descriptions. Manual to understand, then automate.
"I have a tendency to want to automate everything from the beginning. But this was a good experiment for me to see what I should do manually first. I need to go through it manually to understand where the problems lie. Then I can develop better automations from that foundation."
Premium listings from day one
Monetization isn't the priority yet, but I built the structure for premium listings from the start: detailed pages, images, better placement. Planning ahead without overbuilding now.
SEO baked in
Directories are perfect for SEO. I'm targeting city-specific keywords: "best boulder gyms in [city]," "boulder gyms for kids in [city]." Claude helped structure markup and tags correctly from the beginning.
Where it got messy
Scripts that almost worked
Claude had a tendency to write scripts to solve problems. I played along because I wanted to understand what was happening. But there were always little things that needed fixing. Sometimes my fault (an extra space), sometimes Claude's (missing context). It still required a human to understand what was actually happening.
The Airtable city dropdown problem
I'd set cities to a dropdown menu in Airtable to prevent typos from creating phantom city pages. But the scraped data included surrounding cities like Potsdam near Berlin, and since Potsdam wasn't in the dropdown, those gyms weren't added. Claude couldn't see this problem. I changed the field type to free text, which let new cities be added automatically. I figured the risk is small because I can clean up the data manually if need be. It's not something that takes a genius, just a little logical problem to solve.
Empty columns breaking scripts
I had a "short description" column that Claude's script was supposed to populate. All the fields were empty, so the script didn't recognize the column existed. I had to manually confirm it. Small things like this still need human input (or somebody with experience who can predict these problems, but I'll get there).
Data quality challenges
Getting clean, accurate data turned out to be one of the more interesting challenges. I needed AI to help filter and enrich the scraped data, which created its own set of problems.
Boulder gyms vs. climbing gyms
I only wanted boulder gyms, not climbing gyms with rope climbing. Getting AI to reliably distinguish between the two took some work. Even trickier were businesses that had "climbing" in their description but weren't gyms at all: tree maintenance companies, building maintenance services, that kind of thing. I had to iterate on the filtering logic to catch these edge cases.
Review crawling issues
At first, the AI was only looking at gym titles and descriptions to determine amenities. It took me a while to figure out that it wasn't actually reading all the reviews I'd scraped. Once I realized what was happening, I adjusted the prompt to make sure it processed the full review data.
The negative indicator problem
Another issue: if reviews mentioned an amenity negatively ("no cafe," "wish they had a kids area"), the AI would sometimes disregard that amenity entirely instead of marking it as absent. I had to prompt around that behavior to get it to handle negative mentions correctly.
Claude's self-correction
Surprisingly, Claude actually did a pretty good job at self-managing once I started questioning what was happening. Pushing back with "are you sure?" or "can you check that again?" often led to better results. Still, getting from messy scraped data to clean, structured information in less than 24 hours is pretty wild.
What actually worked
After all the iterations and problem-solving, I ended up with a 3-layer detection system that dramatically improved data quality: keyword detection searching actual review text, AI analysis with proper context, and a website scraper as fallback. The key was using OR logic across all three: if any layer found an amenity, it got included.
The breakthrough insight
Negative signals are positive data. When reviews said "cafe is expensive" or "kids area is small," that actually confirmed the amenity existed. A complaint about something is still evidence that it's there. Once I understood that, detection rates jumped.
The numbers, that first week
Amenity detection went from around 10% to 87% average across all categories, in the first week of tuning the three-layer system. Timeline: less than 24 hours from first prompt to a production-ready system that could process a new city in about 5 minutes, versus 8 hours of manual work. Not perfect, but functional and scalable.
Why this feels different
Working with AI like this makes me think about problems differently. I'm orchestrating solutions, not getting stuck in implementation details. I can really play on my strengths: systems thinking, understanding logical problems. The technical roadblocks that used to frustrate me into quitting can just be prompted away.
It's exciting. I feel in the zone. I'm genuinely thrilled to see these things come to life. This is what building should feel like.
What's next
Finish the MVP
Complete the core features: submission form that funnels into Airtable, AI verification of new gyms, "claim this listing" button for premium upgrades. Keep it simple and functional.
Launch and learn
Get it live. See if it gets traffic. Test the SEO strategy. Learn what works and what doesn't. This is a real business experiment, not just a portfolio piece.
Build the next one
This is just the foundation. I chose boulder gyms specifically to learn the process with a manageable dataset. Now that I understand how to build directories, I can apply this to other niches. The workflow is repeatable.
Keep vibe coding
I've started projects before, but I often abandoned them for other shiny ideas. Now, because the building part is such a flow situation, I'm enjoying building these things a lot more than manually hacking together no-code tools.
I'm super excited to see what else is going to happen in the future. There are still some problems, of course, but I'm excited about the future with this.
The real lesson
I don't need to be a developer to build real things (but it couldn't hurt to partner with one to get things right). I just need to think clearly, structure problems well, and use the right tools.
AI isn't replacing the thinking. It's removing the roadblocks that prevented me from acting on my thinking. Getting things done now is much easier, and that's pretty cool. The creative work of entrepreneurship feels like it's more prevalent now, which I'm really enjoying.