← BACKMonolizovna / CASE STUDY
Sole engineer · 2026 · Freelance

Monolizovna

A photographer's site and its own fast little CMS.

Monolizovna.ru is the portfolio of a Saint Petersburg photographer, and the custom CMS behind it. The public side is an editorial, image-heavy showcase — a works archive, client reviews kept exactly as they arrived, pricing formats and a hand-curated 'where to shoot in the city' guide — and it loads fast: server-rendered Astro with lazy Preact islands, inlined critical CSS and a tuned image pipeline. The private side is a full admin I built from scratch, where she edits works, reviews, pricing, locations and even the site's own copy, with drag-to-reorder and instant publishing. I built all of it solo, end to end, and ship it on Docker with GitLab CI.

monolizovna.ru
Monolizovna photographer site home page
Solo
site + CMS
Astro 5
SSR + islands
~28KB
HTML, gzipped
8
CMS sections
Astro 5SSR (node)Preact islandsTailwind v4PrismaSQLitejose (JWT auth)bcryptsharpZodExpressgrammy (Telegram)vk-ioDockerGitLab CI/CD
/ my contribution

What I built.

Full ownership & architecture

Built the site and its CMS solo, end to end

Sole engineer: the public site, the admin, the data model, the deploy — all of it. Astro 5 in SSR mode with islands of Preact (compat) hydrated only where the page is actually interactive.

A tiny self-hosted CMS on Prisma + SQLite

Nine Prisma models (works and photos, reviews, formats, FAQ, locations, editable site texts, leads, the admin user) back a CMS small enough to run from a single SQLite file, with no SaaS in the loop.

Custom auth from scratch

A signed-JWT session in an httpOnly cookie via jose, bcrypt-hashed credentials, a rate-limited login, and a middleware guard over every /admin and /api/admin route. No auth library, no third party.

Performance, tuned by hand

~28KB of gzipped HTML with the CSS inlined

Critical CSS is inlined to kill the render-blocking request, so the whole document arrives in roughly 28KB gzipped and paints without waiting on a stylesheet round-trip.

Cut the request chains Lighthouse hated

Disabled the modulepreload hints that chained Base → preload-helper → Lenis, and load the smooth-scroll library on first interaction instead, so nothing non-essential blocks the critical path.

A real image pipeline

sharp generates responsive AVIF/WebP variants with blur-up placeholders, and the LCP hero image is preloaded over HTTP headers so it starts downloading before the HTML is even parsed.

SSR straight to SQLite

The public site reads SQLite on every request, so an edit in the admin is live instantly with no ISR cache to bust, while lazy-hydrated islands keep the JS that ships tiny.

The admin

Eight sections, all hers to edit

Works, reviews, FAQ, pricing formats, locations, the site's own texts, leads and the account — a full dashboard, not a developer's escape hatch.

Drag-to-reorder and photo upload

Reorder works and reviews by dragging (sortablejs), toggle what shows on the home page, and upload photos that are processed server-side through sharp on the way in.

Even the copy is content

The marketing text on the public site is stored as editable site-text keys, so she can rewrite her own headlines without a deploy.

Delivery & growth

Dockerized with a real CI pipeline

GitLab CI runs lint → typecheck → build → image → smoke → deploy, and the prod server is Express with gzip and year-long cache headers for assets, behind Caddy.

Lead-gen automation

A Telegram bot (grammy) drives the PDF-freebie funnel and notifies on new leads, with a VK integration (vk-io) on top for outreach.

/ the product

What the site does.

Built for Photography, Personal brand & portfolio.

Editorial photo portfolio

A works archive with filtering and a full-screen lightbox, tuned to stay fast even though it is all photographs.

Reviews kept as-is

Real messenger screenshots, unedited, in a carousel and a full archive — proof over polish.

Pricing formats

Three shooting packages, each one editable from the admin without touching code.

'Where to shoot' city guide

A curated, categorized guide to Saint Petersburg shooting locations, each with its own page.

Her own CMS

She edits every section herself: works, reviews, FAQ, pricing, locations and the site's own marketing copy.

Lead funnel with bots

A PDF freebie funnel wired to a Telegram bot, plus a VK integration for reaching clients.

/ screens
Curated 'where to shoot in Saint Petersburg' location guide
The 'where to shoot' city guide
Pricing section with three shooting packages
Three pricing formats
Works archive page
The works archive
Client reviews shown as raw messenger screenshots
Reviews, kept exactly as they arrived
Admin dashboard with section counts
The admin dashboard
Admin works manager with drag-to-reorder
Drag-to-reorder works manager

Live client site. The admin screenshots run on seeded demo content — no real leads or personal data are shown.

Visit the site ↗← ALL WORK