RUEN
Start a project

Client project

Baya & Grand Kennel

Website for a Cavalier King Charles Spaniel kennel in Minsk: two locales, an editor that lives on the live site, and enquiries in Telegram.

external dependencies
0
locales
2
sections
9

Open the site — bayagrand.by ↗

Baya & Grand Kennel home page

A Cavalier King Charles Spaniel kennel in Minsk. The client is the kennel owner, not a developer: she has dogs, litters, titles and shows, and every one of those changes month to month.

The problem worth solving

A brochure site is easy. The hard part is different: the owner has to fill the site herself, without touching a repository, a server, or an admin panel on some other domain. Otherwise the site shows last year’s litters six months in, and changing a comma goes through a developer.

The second condition was two full versions, Russian and English. Puppy buyers write from abroad, and the kennel shows dogs across Europe.

The editor lives on the site itself

The owner opens her own site with ?edit=1, enters a password, and edits the page in the place where visitors see it. There is no second interface to learn.

Almost everything is editable: text, photographs, section backgrounds, card galleries, decorative rules, and five lists — breed articles, dogs, current litters, titles and past litters. Adding a new puppy means pressing “add” inside the Puppies section.

Edits do not live in the site’s files. They go to the server into separate storage and are layered over the original content when the page loads. A new deploy therefore cannot wipe what the owner wrote — that is the one requirement that makes this kind of editor safe rather than a trap.

Two locales, no reload

Translatable places are marked in the markup itself — 159 nodes across nine sections. The dictionary for both locales sits in a single file, so switching is instant and never hits the server.

Meta tags switch with the language: title, description, Open Graph. On a first visit the language is decided by a chain — URL parameter, then last visit’s choice, then the browser’s language.

One detail that matters to the owner: she writes an edit in one language only. The backend translates the other one and saves both at once. The translation can be corrected by hand later — but a blank English page never appears.

A backend on the standard library

761 lines of Python with no external dependency at all. It does three things:

  • takes enquiries from the form and sends them to Telegram;
  • serves the owner’s edits over a public endpoint the page fetches on load;
  • runs the editor: login, saving text, image upload, translation, list operations.

The editor password is never stored in the clear — only as an scrypt hash, compared in constant time. A session token lives 12 hours. Eight failed attempts block the address.

The form is protected by a honeypot, field length limits, a request body cap, and five submissions per address per ten minutes. Image upload has an allow-list of types, a size cap and a random suffix in the filename. Edits are written atomically, so an interrupted save cannot leave a corrupted file behind.

The server

nginx with a strict CSP, restricted methods, static caching and two separate rate-limit zones — one for the site, one for the API. The backend runs under systemd in a sandbox: no privilege escalation, write access only to its own directory. fail2ban with standard jails plus a custom filter for scanners probing for .env, .git and PHP admin panels.

No build step, no dependencies

There is no package.json and no requirements.txt, on either side. No bundler, no node_modules, nothing to install. The site is HTML, three script files and one stylesheet.

This is not minimalism for its own sake. The project’s horizon is years, and the owner will never update a dependency. In three years this site will open and deploy exactly as it does today — because there is nothing to build and nothing to update.

HTML · CSS · JavaScript (ES6) · Python (standard library) · Telegram Bot API · nginx · systemd · fail2ban