Emergency car locksmith, Bucharest and Ilfov. Next.js, PWA, 2,332 static pages.
Eleven seconds of the build. The home screen, then one of the 2,332 generated pages for one service in one sector of Bucharest, then the keyword monitor with its service by location matrix open. The two public pages are the live site. Every figure on the dashboard was generated for the photograph: invented queries, invented impressions, invented dates, laid over the real service and location names.
An emergency car locksmith covering Bucharest, Ilfov and five counties around them. The public product is one screen answering one question for somebody standing next to a car they cannot open: will somebody come, and how do I reach them now. There is no form, no account and no cart. Around that screen sits a layer of 2,332 landing pages, one for every service in every place, in two languages, generated at build time out of one typed data layer. Behind a sign-in there is a dashboard counting what the site is actually for, and a second one, built and not yet deployed, that reads the search results back.
The problem
Somebody is standing next to a car they cannot open. The keys are inside it, or the fob is dead, or the car is new enough that the electronics have simply decided not to. They search, they tap the first result, and they have one question: will somebody come, and how do I reach them now. The phone in their hand is usually nearly flat.
Nobody in that state fills in a form or makes an account. So there is no form, no account and no cart. Every public action leaves the site: a phone call, a WhatsApp message with the first line already written, a map pin, a mailbox in the footer. The primary one is pinned to the bottom edge of the screen, where a thumb already is.
What we built
01
A site that installs like an app
Add to home screen and it opens standalone and dark, with a bottom tab bar and a shortcut straight to the emergency sheet. No store, no download, no update to miss. The same code renders a conventional website on a laptop. Both chromes are written into the static HTML and one of them is hidden by CSS, so the right one paints before any JavaScript runs, then the DOM is pruned to the shell that matched rather than left doubled.
The same page on a phone and on a laptop. Deciding to ship both chromes in one document is what costs the homepage 303 KB of HTML, and it is why neither layout ever flashes into the other.
02
There is no form anywhere in it
Every service card carries the two things a person in this situation will actually do, and so does every one of the generated pages, and so does the sheet behind the SOS disc. A WhatsApp tap asks the phone where it is and writes the answer into the message as a map link, so the locksmith gets a map pin rather than somebody’s description of where they are. Nothing about a caller is stored: the location goes into the message and nowhere else.
This is one of the app’s own preview routes, where the shell draws the full-width tab bar. The homepage renders the same shell with a floating capsule at the right edge instead, which is the version in the film above.
03
A page for every service in every place
Twenty two services across fifty three places, in Romanian and English: 1,166 combinations and 2,332 pages, all generated at build time from 927 lines of typed data. The headings, the breadcrumbs, the structured data, the matrix of internal links, the 2,494 sitemap entries and a social card for every page come out of those same three modules, so adding a location adds its pages and everything that points at them.
One of the 2,332, for one service in one sector of Bucharest. The body text on it is the fallback the data layer synthesizes rather than copy written for this page, because the per-page copy has never been generated.
04
One map, and it is a real one
The 44 service hubs carry Leaflet over OpenStreetMap tiles, no API key, all 53 places pinned at their true coordinates with the view fitted to them. The search box strips diacritics before it compares, so typing stefanesti finds Ștefăneștii de Jos. Select a pin and the map flies to it and opens a card with a call and a WhatsApp message already addressed to that service in that place. Its 158 KB is loaded on demand and reaches no other page.
The map at rest on a phone, and on the laptop capture, one word into the search box: stefanesti typed without diacritics has narrowed the list to two, the map has flown to the first, and its card is open with both actions filled in.
05
Its own traffic, counted without a cookie
The dashboard counts what the site is for: calls, WhatsApp taps, map taps, mail taps, SOS opens. It sets no cookie. The session id lives in the tab and is not written at all until consent is given, and no address, no browser string and no location is ever stored. A signed in admin is not counted. Every write goes through one server route; the browser rules deny writes on every collection, so a forged request cannot reach the database at all.
Every visit count, tap count and date on this screen was invented for the photograph. The dashboard was run against generated fixtures in a throwaway copy of the app with the database taken out, so none of it is the business’s real traffic.
06
Which of the 1,166 pages are doing anything
This screen and the next one are built and not deployed: the two commits that carry them, and the daily job that would fill them from Search Console, have never been merged into what ships. The coverage tab only exists because the site is programmatic. Locations down the side, services across the top, one cell per generated page, coloured by average position and labelled with impressions, genuine gaps left grey. Above it, how many of the 1,166 have been seen at all.
Invented impressions and invented positions throughout. Only the service and location names are real, because the matrix resolves them against the same data layer the 2,332 pages are generated from, and it would render empty otherwise.
07
The queries one place off the first page
Opportunities takes every query sitting between position four and twenty and scores it: impressions multiplied by the click rate a third position typically earns, less the clicks it gets now, sorted by the difference. The same arithmetic runs over pages. A fourth tab flags two of the site’s own pages competing for one query, which is the failure a 1,166-page site invites. None of it is precomputed. It is all worked out in the browser from the stored rows.
Every query and every figure in this table was invented for the photograph. The one column that is an estimate says so in the app’s own footnote rather than in ours.
A panicking person does not need flashing red. The SOS disc pulses once a second, which is a resting heart rate rather than an alarm.
The emergency path, which is the whole product: tap the SOS disc, the sheet rises, press the call row. The press is held rather than released, so nothing was ever dialled and WhatsApp was never opened.
The parts worth telling
The arrival estimate was built, and then deleted
Each page used to carry a drive time: straight line distance from the dispatch point, multiplied because roads wind, divided by an average city speed, plus five minutes to get somebody moving, rounded into a five minute range. On 3 June 2026 all of it came off the screen, fifteen files and 230 lines, on the stated grounds that an arrival time is a liability when it cannot be met. The arithmetic is still there. Its answer is now only ever read as true or false: this place gets a fast response, that one gets call for availability.
A refused location is a fact, not an absence
WhatsApp messages were arriving with no address, from phones only. iOS Safari fails silently after a dismissed permission prompt and never asks again, and the missing coordinates were collapsing quietly to nothing. Now a refusal comes back as a reason. High accuracy is switched off on purpose, because a coarse fix in a second or two is precise enough to send a van and GPS regularly overruns the timeout. The message keeps its location line either way: if the phone will not say where it is, the sentence asks the caller to drop a pin.
There is no test suite, and one check that matters
No test runner, no test files, no continuous integration. What stands in for all of it is a single script: service and location ids and slugs unique, every coordinate finite and in range, nearer places estimating lower than farther ones, and every place either inside the fast tier or outside it, never both. It throws rather than warns, and it finishes in 0.16 seconds. Linting does not pass either, at four errors, all of them the same new React rule.
294 KB, on a page written for five percent battery
The homepage pulls thirteen scripts and 294 KB of gzipped JavaScript. The splits work: the 460 KB Firebase chunk, Recharts and Leaflet are none of them on it, and the homepage HTML does not reference Firebase once. What is left is the shell, and it is still more than the brief asked for. Lighthouse on mobile, measured on 25 August 2026, reads 87 for performance, 100 for accessibility and 100 for best practices. The 91 the repository recorded was measured on 31 May, at the second commit, when the app was a shell and nothing else.
How it works
22 services
53 locations with real coordinates
One dispatch point
Typed data, checked before the build
2,332 landing pages
2,494 sitemap URLs, ro and en
Fast response, or call for availability
Numbers
2,332
landing pages in two languages, from 22 services and 53 locations
4,845
prerendered route entries in one build, 310 MB of HTML on disk
192 / 192
message keys in Romanian and English, none of them diverging
87 / 100 / 100
Lighthouse on mobile, 25 August 2026: performance, accessibility, best practices
Built with
Next.js 16
React 19
TypeScript
Tailwind 4
next-intl
Static at build time
Progressive web app
Leaflet and OpenStreetMap
Firestore
Firebase Admin
Recharts
Google Search Console
Vercel
Launched, and it is a client’s business. Two things on it are honestly unfinished. The 2,332 pages render the fallback text the data layer synthesizes rather than copy written for each of them, because that copy was designed to be generated once, offline, and committed, and it has not been run. And the keyword monitor is finished but not deployed: it sits on a branch 1,574 lines ahead of the one that ships, with its daily job and its database rules alongside it.