Skip to main content

Den Evakuator

Local BusinessAutomotiveActive

A one-page bilingual landing for a tow-truck service covering Kyiv and the surrounding region around the clock, built to load instantly on a phone at the roadside and to cost almost nothing to run.

Client
Den Evakuator, a 24/7 tow-truck service in Kyiv
My role
Design and development, end to end
Period
2026
Den Evakuator

Project Overview

Everything about this site is shaped by where it gets read: at the side of a road, on a phone, by someone whose car has just stopped. That rules out a great deal. It has to arrive fast on a bad connection, the phone number has to be reachable without scrolling, and nothing may stand between the visitor and a call - no form to fill in, no account, no consent wall over the one button that matters. So it is a single page in two languages with no database behind it, and the design work went into removing things rather than adding them. The one place I spent effort instead of saving it was the coverage map, because that is the question a stranger actually has: do you come out to where I am.

The project in numbers

Coverage map

An embedded map, a key and a billing account

to3 KB of inline SVG

The section only ever needed to answer one question - do you come to me. An embedded map answers it with roads and labels nobody asked for, an API key, a billing account and an external request on every pageview. The Kyiv region and city outlines are drawn from OpenStreetMap data instead: simplified to 190 and 69 points, coloured by the theme's own tokens, and sharp on any screen.

Client-side JavaScript

Two islands

Conversion tracking, as a single delegated click listener for the whole page, and the photo lightbox - which earns its place because arrow keys and Escape cannot be expressed in markup. Everything the mockup held in React state is markup here: the language switch is two links, the FAQ is a native details element, and the responsive behaviour is media queries rather than a width measured in JavaScript.

Pages

One, in two languages

Ukrainian and Russian, a single route and a single sitemap entry. A tow-truck service is one decision - call or do not call - and splitting that across five pages only adds places to lose the visitor.

Runtime dependencies

Four

next, next-intl, react and react-dom. Tailwind is a build-time tool and ships no runtime of its own.

Data stored about visitors

None

No database, no accounts, no forms on the page at all: the calls to action are the phone and the messengers the owner already uses, so there is nothing to store, secure or lose.

Challenges

  • Loading fast on a phone with one bar of signal, for someone who is already having a bad day.
  • Showing a service area without an embedded map, its API key, its billing account and its external request on every pageview.
  • Serving Ukrainian and Russian equally without doubling the work of every edit.
  • Keeping a landing page from turning into a five-page site with the phone number three clicks deep.
  • Baking analytics identifiers into pages that are fully static, where there is no server left at runtime to inject them.

Solutions

  • Built the whole site as one static page in Next.js 16 with next-intl and Tailwind v4, Ukrainian by default and Russian under /ru, with a single route and a single sitemap entry.
  • Drew the coverage map as inline SVG from OpenStreetMap boundary data, simplified with Douglas-Peucker to 190 points for the region and 69 for the city, on an equirectangular projection corrected for latitude so no trigonometry runs at display time. Kyiv is a hole in the region polygon, so it is a second path drawn over the first.
  • Credited the map data in the footer under ODbL, in the form OpenStreetMap asks for, and documented in the source that the credit stays as long as the map does.
  • Held the client-side JavaScript to two islands and solved the rest with markup: two links for the locale switch, a native details element for the FAQ, media queries for the responsive behaviour.
  • Passed finished strings into the client components instead of the translation function, so the dictionary never reaches the browser bundle.
  • Rendered the gallery grid as server HTML and only the opened photo at full size, so a fourteen-image gallery costs nothing until someone actually opens one.
  • Moved the analytics identifier into a Docker build argument, since a fully static page has its counters baked in at build time and env files are deliberately not copied into the image.
  • Wired the Telegram lead pipeline and the conversion-tracking attributes ahead of the features that will use them, so adding a form or switching ads on is a configuration change rather than a rebuild of the page.

Key Features

  • One Page, Two Languages - Ukrainian and Russian, a single route, no navigation to get lost in.
  • Inline Coverage Map - The Kyiv region and city drawn from OpenStreetMap data as 3 KB of themeable SVG.
  • Call-First - Phone and messengers as the only calls to action, with no form standing in the way.
  • Photo Gallery - Server-rendered thumbnails with a keyboard-navigable lightbox.
  • Native FAQ - A details-element accordion that closes its siblings without a line of JavaScript.
  • Conversion Tracking - One delegated listener for the whole page, with the markup already in place for ads.
  • Static by Design - No database, no runtime server work, nothing stored about anyone.
  • Push to Deploy - Docker Compose on a self-hosted box, released through GitHub Actions.

Project Info

Launch Date:
September 16, 2026
Status:
Active

Technologies

Frontend

Next.js 16 (App Router)ReactTypeScriptnext-intlTailwind CSS v4Inline SVG

Translations

next-intl (UK/RU)

Messaging

Telegram Bot API

Security

No database, no forms, no stored visitor data

Hosting & Deployment

DockerDocker ComposeSelf-hosted

DevOps & CI/CD

GitHub ActionsBuild-time analytics injection

Monitoring & Analytics

Google AnalyticsConversion tracking hooks
Available for new projects

Need something like this?

Tell me what you are building and where it is stuck. I will tell you plainly whether it is work I should be doing.