Catalog website Krasnodar, Russia

Yuzhnye Portaly — a catalog website for an installation company

An 82-page static website for a company in Krasnodar that sells and installs gates, roller shutters, automation, seals, and dock levelers. Hand-built, no site builder, with its own backend for handling inquiries.

Role: markup, backend, anti-spam, lead intake Stack: HTML5 · CSS3 · Node.js · TypeScript Status: delivered to the client

A demo copy of the site, blocked from search indexing.

Homepage of the Yuzhnye Portaly catalog website
Task

Task

A company that sells and installs gates, roller shutters, automation, seals, and dock levelers needed a catalog website with a clear structure and a working inquiry form.

One condition was non-negotiable: no site builder, no CMS — built by hand, with full control over every detail of the markup, styling, and form behavior.

Solution

Solution

A static multi-page site built in plain HTML/CSS/JS, with no third-party framework or bundler, plus a custom Node.js backend for handling inquiries. The catalog is organized into three levels — category → subcategory → product — so customers can find the right model quickly instead of scrolling through a flat list of a hundred items.

The header and footer are byte-identical across all 82 pages except for the active menu item — the rules are written down in dedicated template documents, not kept in someone's head.

Catalog, markup, and SEO

82 HTML pages built to a single template, with complete search markup on every one.

82 HTML pages, hand-built to a single template — header and footer match on every page
A three-level catalog: 5 root categories → 15 subcategory hubs → 57 product/model pages
A custom CSS system built on custom properties, CSS Grid with auto-fit/minmax, and 19 media queries, including prefers-reduced-motion
SEO markup (title, description, Open Graph) on 100% of pages — every title is unique

Accessibility

Built to a noticeably higher standard than is typical for a site of this size.

A fully custom-built accessible lightbox for product photos: role="dialog", a circular focus trap, full keyboard control
Escape closes it, arrow keys page through, and focus returns to the trigger element after closing
Hundreds of ARIA attributes site-wide, and 100% of images (576 of 576) carry alt text

Lead intake and anti-spam

A dedicated Express/TypeScript backend built specifically for the inquiry form.

Zod validation, per-IP rate limiting (6 requests per 10 minutes), a honeypot field, and an HMAC-signed cookie enforcing a minimum form-fill time
A durable SQLite outbox queue: atomic record claiming, exponential retries, and recovery after a server restart
Inquiries delivered to Telegram, with email as a fallback via Nodemailer
Result

Result

The site is technically complete: inquiries flow through form → anti-spam check → queue → Telegram/email without loss even if the server fails partway through. Before delivery, we ran our own pre-launch audit across 6 areas — blockers, SEO, accessibility and markup, CSS and responsiveness, JS and backend, and speed and media.

82
HTML pages, hand-built to a single template
100%
of pages with a unique title, description, and Open Graph tags
576/576
images carry alt text
62
findings from our own pre-launch audit, each individually re-verified against the files

To be candid: sitemap.xml, JSON-LD/schema.org, rel="canonical", and twitter:card aren't implemented yet — that's openly tracked in our own launch checklist as a scoped task, not an oversight.

Another case

1 more project
Web platform 64 automated tests

A website with payments and a member account

Before The client needed a site that does more than describe a product — one that sells: takes payment, opens access immediately, and gives the buyer an account. After An idempotent payment-to-access flow, a member dashboard, OAuth sign-in, and 64 automated tests behind it.
5 + 2 pricing tiers — 5 paid plans and 2 free levels
Similar task?
Need a catalog site or a multi-page website with an inquiry form — tell us the details, we'll suggest an approach.
Start a project