Heurig.at
A search engine for Heurigen taverns across Lower Austria, Vienna, and Styria
Heurig.at is a hobby project built by three of us — a directory and search engine for traditional Austrian Heurigen taverns across Lower Austria, Vienna, and Styria. Andreas Babic, Malek Morad, and I have been working on it since 2023, through several phases and a few stack rewrites.
The problem
Heurigen are seasonal, regionally scattered, and their data lives in disparate sources — association lists, local tourism boards, individual websites, sometimes only a notice on a wall. Anyone looking for a Heuriger nearby scrolls through PDFs from three different chambers of agriculture, or asks their grandparents. We wanted a single surface where you can filter by region, name, or listing — and where the opening hours actually match reality.
Constraints
Three developers, no budget, no pressure to scale. That shaped the architecture: simple stack, cheap hosting, data largely curated by hand or semi-automated. No investor also means we could make stack changes that would be hard to justify in a commercial context.
Architecture
The app is a classic frontend/backend split. The backend is a NestJS service in TypeScript persisting to MySQL via TypeORM. After the last rewrite the frontend is Standalone Angular with server-side rendering — which matters for search indexing and for time-to-first-paint on mobile in rural areas with weak connections.
The search engine is custom. Instead of an off-the-shelf tool we run a tree-based autocomplete in PHP that operates on pre-built indices over Heurigen names, locations, and tags. Leaflet handles maps; Heurigen are rendered as clusters so dense regions stay legible. Deployment runs through GitHub Actions and Docker/Portainer on our own infrastructure.
Decisions — and what we rejected
Frontend: Ionic + Angular → Standalone Angular with SSR. We started with Ionic because a mobile app was originally part of the vision. When the web became the primary platform, Ionic became dead weight — bigger bundle, restrictive component philosophy, no real SSR path. Moving to Standalone Angular with SSR gave us faster first-paint and better SEO, without locking the mobile variant out — it will come back later as a PWA on the same stack.
Search: off-the-shelf engine → custom tree autocomplete in PHP. We considered ElasticSearch and rejected it. Reasoning: our dataset is small, our queries are narrow (name, place, region), and hosting Elastic costs money every month. A PHP-resident trie-based index runs on the same server as the site, is deterministic, and explains itself in fifty lines of code. If we ever need full-text search across long descriptions we’ll revisit.
Data layer: NoSQL → MySQL/TypeORM. A document model would have been more comfortable for the irregular shape of Heurigen profiles (some have opening hours, some menus, some only an address). We picked MySQL anyway because that’s the language we debug fastest in — and in a volunteer project every wasted weekend counts.
Hosting: cloud → Plesk. We host on a Plesk server Andreas runs rather than at a hyperscaler. Saves money and makes deployments predictable, at the cost of auto-scaling. Accepted: we’re not big enough for that to matter.
What we learned
The biggest takeaway was the velocity a tiny team gets with a deliberate stack — we shipped more productive hours on boring tech than in any project that celebrated its tooling first. Also: deployment automation pays off even at low traffic. Not because of scale, but because release friction stretches release pauses, and long pauses erode the codebase.
What I would do differently
Pin the data model down sooner. We restructured the schemas several times because new sources brought new fields (ratings, menus, opening hours in odd shapes). One iteration over the data model with an explicit extensibility path would have saved two migrations.
Opening hours as their own sub-model. Heurigen hours violate every software assumption: open for two weeks, closed for three, sometimes only weekends, sometimes by appointment only. We initially shoved this into free-text fields — too painful in hindsight. A structured time-window model from day one would have been the right investment.
SSR earlier. We added SSR late because we overestimated the effort. In reality the rewrite was a single weekend, and the SEO impact was measurable in the next indexing wave. Doing it in Q1 would have got us organic traffic months earlier.