Anton Bohachuk
← ALL WORK

Rowdy

Site and admin panel for a newly opened barbershop, in three languages.

Type
Client work
Year
2024
Duration
~1 month
Team
Solo
Rowdy
Context

A barbershop that had just opened, where my girlfriend had started working. Same shape of problem as the first one I'd built a year earlier — a new business with no web presence, needing somewhere to send people and a way to keep it current without calling me. This one served a mixed-language clientele, so the site had to work in Ukrainian, Russian and English.

Building the second one meant I already knew which parts of the first had been wrong. Some of that I fixed; some of it I traded away again, for different reasons.

Problem

The site had to be handed over, not maintained. Prices, barbers and gallery photos all change on their own schedule, and a shop that has to ask a developer to update a price will simply stop updating it. Everything the customer sees needed to be editable from an admin panel by someone who has never seen a deployment — and it needed to be editable in three languages without tripling the work of using it.

Stack

Next.js for the public site and the admin, with next-intl for locale routing, NextUI, Tailwind and Redux, deployed on Vercel. A NestJS API on Cloud Run, MongoDB through Mongoose, and Google Cloud Storage for gallery images uploaded through the admin. Bookings open the shop's existing Altegio widget.

SHAPE
Public site
Next.js · Vercel
Admin panel
prices · barbers · gallery
/UK · /RU · /EN
next-intl routing
locale in the path
NestJS API
Cloud Run · Mongoose
Data base
MongoDB Atlas
Cloud Storage
gallery images
Altegio
booking widget
TypeScriptNext.jsReactnext-intlReduxNextUITailwind CSSNestJSMongooseMongoDBCloud RunCloud StorageVercel
Decisions

Locale in the URL

Three languages, each on its own path. On the barbershop site I'd built the year before, the equivalent choice — which location you were viewing — lived in client state, which meant nothing was linkable and search engines only ever saw one version. Putting the locale in the path instead means every language is a real address that can be shared and indexed.

Object storage this time

On the previous build, gallery images uploaded to the API server's own filesystem, which meant they didn't survive a redeploy onto fresh storage. Here they go to Google Cloud Storage, so the images outlive any particular instance and the API stays stateless. Same feature, one lesson later.

Ship the admin as part of the deliverable

The shop needed to own its own content from day one. Services, barbers and the gallery are all editable through the admin, which is more work at build time and none afterwards — the alternative is being the person who edits a price list forever.

Hand off booking rather than build it

Appointments go through Altegio, which the shop already ran its calendar in. A second booking system would have been a second source of truth the staff had no reason to trust.

Outcome
client stateURL
every locale linkable and indexable
filesystemobject storage
the fix carried over from the previous build
no sitelive in 3 languages
handed over with content the shop maintains

The second barbershop site I built, a year after the first. Most of what changed between them came from what the first one got wrong.

Trade-offs

MongoDB was chosen for its free tier, not for its shape. The data here is thoroughly relational — barbers, services and prices with obvious foreign keys — and a document store was the wrong model for it. Managed Postgres on GCP was expensive, I didn't know Supabase existed yet, and Atlas had a free tier, so that decided it. It works, but the reason it works has nothing to do with the reason I picked it.

Translations are managed as files, so adding a language or fixing a phrase is a developer's job even though everything else about the site isn't. The admin covers content and stops at copy, which is a seam the owners can feel.

Redux again, and again for a site with almost no client state. That was the tool I reached for by default at the time rather than a judgement about this project.

Contact

Let's talk

Open to full stack roles, remote or on-site in Varna. The fastest way to reach me is email or Telegram.

ANTON BOHACHUK · VARNA, BULGARIA (EET)© 2026