← Fabio Hase

LQΛL

A bikepark discovery platform for the DACH region. Twelve months of work, three of them public in both app stores, shut down on its own numbers.

Role
Product, engineering, strategy and project management
Duration
Aug 2025 – Aug 2026
Team
2 founders
Stack
Flutter · Riverpod · Supabase · Next.js · PostHog
Status
Delisted 3 August 2026 · 142 installs · €0 revenue

I owned product, engineering, strategy and project management; my co-founder owned marketing, sales, B2B partnerships and the commercial side.

01

The bet

Anyone planning a bikepark trip needs four things: is it open, what does it cost, which trails are there, what is the weather at the summit. Those four sit scattered across hundreds of separate bikepark websites — hours as a PDF, prices as an image, trail lists years out of date, weather measured in the valley rather than at the peak. Comparing two parks is effectively impossible.

So the bet, stated plainly: put the four in one place, complete and comparable, and riders use it — and bikeparks pay to appear there correctly. The reference model was Bergfex, which does exactly this for ski resorts and earns from the resorts rather than the visitors. Established for skiing, and as far as we could find, unbuilt for bikeparks.

We tested neither half. The first stayed open because we never reached enough riders to confirm or refute it. The second failed on a precondition we had not seen — section 06. And the gap itself was ambiguous in a way we never checked: an empty niche can mean nobody looked, or it can mean others looked and gave up. We only ever read it the first way.

The LQΛL map screen on a phone — a dark map of Germany, Austria and Switzerland with bikepark logo pins at Hahnenklee, Erbeskopf, Osternohe, Todtnau, Adelboden-Lenk, Saalbach and others.
What the app opened on. Twelve bikeparks, as logo pins.
The Saalbach trail list on a phone — a blue dot beside the heading 'Leicht' over rows for Buchegg-Line, Panorama-Line, Monti-Line, 12er Sky-Line and Learn to Ride Park, then a red dot beside 'Mittel' over Scheeleitn-Line, Z-Line, Sheepy Hollow-Line, Wetterkreuz-Trail and seven more, each row carrying a small numeric badge and a chevron.
And what sat behind one pin. 125 trails across the twelve parks, grouped by difficulty, every one entered by hand.
02

The rebuild, and what it cost

We started in FlutterFlow because neither of us knew Flutter and it put something on screen in days — the right call for “can this be built at all”. It broke in three places: generated widgets that could not be maintained without losing the generator, state in one global object, database calls sitting in the UI.

In February 2026 I relaid the structure by hand in one concentrated phase: a repository layer so widgets no longer knew the database, separate Riverpod providers instead of one global object, a theme of my own, GoRouter for navigation. What worked was kept rather than rewritten. It cost weeks of feature time, spent before the app was public and had users to lose. Left later it would have cost more; left undone it would have capped the product at what a generator could maintain.

The same rebuild took the backend off Firebase. The data was relational from the first sketch — parks have trails, trails have difficulty grades, parks have price tables by age band and season — and in Firestore that meant denormalising and keeping consistency by hand. In Postgres the bikepark list collapsed into a single server-side call that returns it already sorted by distance with the user’s favourites joined in. The price: migration time is lost feature time, and vendor lock-in moved rather than disappeared. It is Postgres, so it is migratable — but it is still someone else’s Postgres.

The weather is the one integration that had to be designed rather than called: OpenWeather’s forecast returns only future three-hour blocks, so an afternoon request would have shown half a day, and a cron job writes every park into a cache table where the morning’s blocks are merged back in from the previous run.

One legacy import on flutter_flow_model.dart still lives in utils.dart: broad changes to working code for a cosmetic gain, so it stays — documented, and not extended.

03

What I owned, and what I did not

Two founders, a GbR, split by department and 50/50 on paper. Product, engineering, strategy and project management on my side; marketing, sales, B2B partnerships, data maintenance, finance and administration on his. Agreed that way and lived that way: each of us decided inside his own area.

From the February rebuild the entire technical side was mine: the Flutter app, the Next.js admin, the backend with its data model and edge functions, the landing page, and the store releases on both platforms. Getting twelve bikeparks to sign written permission for their data, logos and trail maps — for an unknown two-person project with no users and no references — is real sales work, and it is his. Without those twelve there was no product; the entire dataset rests on them.

What had no owner is what decided the outcome. There was no dependable plan for how riders would hear about the app, and no acquisition after the launch. Both sat under “jointly owned” on purpose: a go-to-market plan is a founder decision, not a departmental task.

04

The AI assistant, and what I never measured

Free text in, a shortlist of parks out. The call runs in a Supabase edge function rather than on the device: the API key never ships to a phone, the cost stays controllable, and the prompt can change without a store release. The function gets the user’s position and question plus the riding level and trail preferences collected during onboarding, and answers against the park data — including what is open today. At 61 deployments it was the most-revised part of the backend.

The LQΛL assistant's start screen on a phone: the Λ mark over the line 'Dein KI-Assistent für Bikeparks. Frage mich nach Empfehlungen, Wetter oder Öffnungszeiten', above a single suggested question — 'Empfiehl mir einen Bikepark für heute…'.
What it offered, in the app’s own words: recommendations, weather, opening hours — and one suggested question to start from.
The LQΛL assistant answering a request for a bikepark recommendation: it reports that every listed park is closed today, then names three for tomorrow matched to the rider's advanced level and flow, enduro and downhill preferences, each with its distance.
And what it did with that question. Three parks for tomorrow, matched to the rider’s level, with today’s opening hours already checked.

37 of 142 installs tried it and 60 conversations were saved. I never built an evaluation, so I cannot tell you whether the answers were any good. Shipping an LLM feature without one is the mistake I would not repeat.

05

Where it landed

Over 90 people joined a waitlist in autumn 2025. Half a year later that became 142 installs, 43 completed onboardings and 26 registered accounts, live in both stores, on about €1,186 of our own money and €0 of revenue. The relevant number was never the 90 — it was the distance between it and the 26. Joining a waitlist costs nothing, so it measures interest in an idea, not willingness to use a thing.

Usage peaked before the app was public: 71 monthly active users in March, in the closed test phase; 38 in May, the first full public month; 8 in June, 7 in July. The launch did not lift usage, it coincided with the fall. And 81% of users were active on exactly one day — 114 of roughly 140. A bikepark app is used before a trip, not daily, but 81% is too high to explain that way.

From installation · PostHog · 20 Mar – 26 Jul 2026 · mobile only

App installed 142 100%
Bikepark opened 57 40%
Onboarding completed 43 30%
Trail list opened 41 29%
AI chat used 37 26%
Account registered 26 18%

More people opened a bikepark than finished onboarding: the entry stood between the user and the product instead of leading into it. Eight steps — an account, six questions, a privacy dialog — before anyone could see whether a park near them was in there.

The LQΛL listing on the Google Play Store in a desktop browser: the title LQΛL over a 10+ downloads counter and a green Installieren button, the app icon to the right, four dark preview screenshots below, and a USK ab 0 Jahren panel. No review score is shown anywhere.
The public Play Store counter reads 10+ against 89 Android installs in the analytics — most came through the closed test channel, which the public counter never sees. Organic reach was near zero, and there is no rating to show either.
06

Why I shut it down

The decision came in two steps, and both were mine. In May 2026 I stopped development. My degree had priority, and without working user acquisition every further hour would have gone into a product nobody finds. Improving the app was never the bottleneck.

The first summer was the test, and it answered clearly. Bikepark season, the app available on both stores, and eight active users in June, seven in July. In the best months of the year, with the product live, nothing happened. At the end of July I decided to end it formally.

The part I got wrong is not in those numbers. I prioritised the work I was good at and where progress was visible — a commit feels like a result, an unanswered email to a bikepark feels like nothing. I could see that the sales side was not moving, and for months I compensated by building more rather than saying so while the problem was still small enough for two people to fix together.

The 50/50 was a number rather than an agreement. It was fixed before anyone had defined what each side would deliver by when, so there were no milestones, no vesting, no shared numbers and no agreed way to adjust the split as the load moved. By the time it mattered there was no tool left except the question of whether to continue at all. That is where my decision came from — the structure, not a reproach.

And the reason for switching off rather than letting it sit was not the missing revenue. Opening hours, prices and trail conditions move with the season, and without the time to maintain them the app would have kept shipping, only increasingly wrong. Someone would have driven to a closed park because we said it was open. An ignored app in a store harms nobody. Wrong information harms the people who believed it.

The LQΛL admin dashboard editing the Saalbach park: a sidebar listing information, opening hours, prices, trails, media and a change log, beside a form of name, region, country, lift count, an open-today switch and coordinates, above an explicit save bar.
The self-service admin, built so parks could maintain their own hours, prices and trails. Two accounts ever existed, both ours.

All 291 logged changes came from us. Not one bikepark login was ever created, though the system was finished, documented and deployed.

The bikeparks would not maintain their own data because they had no capacity. We shut down for exactly the same reason.

Twelve months of spending · three groups of nine lines

Tools — AI assistants, Adobe, FlutterFlow
~€728
Infrastructure — Supabase, Apple, domains
~€217
Marketing — posters and flyers, the entire spend
€49.71
Twelve months, against €0 revenue
~€1,186

The other €191 is trade registration and the landing-page tool. Not one euro went to paid reach: the entire marketing budget was €49.71 of printed posters and flyers. The expenditure is an exact picture of the mistake.

07

What I’d do differently

  • 01Split contributions with a mechanism, and put one number on each side of the split that both of us see weekly. Vesting, milestones, defined deliverables — not out of distrust, but so there is a tool at all when the load shifts.
  • 02Sell before building. Ten serious conversations with bikeparks before the first feature would have surfaced the capacity problem while the model was still cheap to change.
  • 03Show value before asking for anything. Eight steps stood between installing the app and the first bikepark, and every one of them came before anything useful was on screen.