Skip to content
Kamran Code

RJ Hair & Nail Studio — a static salon site ported one-to-one to Next.js

A hair and nail salon's site, first built as a static HTML system and then ported page-for-page to Next.js 16 for per-page metadata, sitemap, manifest and a HairSalon JSON-LD service catalogue — same markup, same stylesheet, same motion.

Live siteClient site · Hair & nail salon, Rewa (MP)

What needed solving?

The salon books through WhatsApp and Instagram and needed a site that feels like its work — dramatic photography, a full service menu, signature looks — while being findable for local searches. The first version was a static HTML build; the question was how to gain proper SEO (canonical URLs, Open Graph, structured data) without redesigning or re-animating anything the owner had already approved.

Who was it for?

Client site · Hair & nail salon, Rewa (MP)

  • Port, don't rebuild: each HTML page's main content becomes JSX with the same classes, the stylesheet is carried over verbatim, and the original behaviour script loads after hydration — so the preloader, inertial scroll, masked reveals, slanted wipes, sliders and modals behave exactly as before.
  • Write a converter that regenerates the Next.js pages and the shared shell from the built HTML site, so either source can be edited and the other regenerated.
  • Add what Next.js makes cheap: per-page metadata, canonical URLs, Open Graph and Twitter cards, sitemap, robots, a web manifest and JSON-LD.
  • Keep booking where customers already are — a WhatsApp call to action and the Instagram profile — and remember 'saved looks' in the visitor's browser.

How the system was designed.

Statically prerendered Next.js 16 pages that render the original HTML as JSX inside a shared shell (icon sprite, preloader, header, footer, modals, cookie bar). The original CSS and behaviour script are served unchanged; a Python converter can regenerate the pages from the HTML source. Site facts and the service menu are data files that also feed the JSON-LD.

RJ Hair & Nail Studio — a static salon site ported one-to-one to Next.js — architecturebookVisitor17 prerendered pagesShared shellOriginal main.jsSite facts + service menuMetadata · sitemap · JSON…WhatsApp / Instagram
AIDataApplicationExternal

What was built.

  • 01Seventeen routes statically prerendered — home, services, looks, studio, why RJ, how to book, find us, team, offers, latest work, gallery, reels, FAQ, menu, about, contact, privacy — each page a `page-…` class on `<main>` so the original page-scoped styles still apply.
  • 02The stylesheet is the original file with only font URLs and two selector families changed, because the page class moved from `<body>` to `<main>`; the behaviour script is loaded with next/script after hydration.
  • 03A catalogue of sixteen services in three families, filterable by `?type=`, also emitted as a HairSalon JSON-LD offer catalogue.
  • 04Self-hosted licensed typefaces (SangBleu Empire, Euclid Square, Wonder Garden Script) as woff2; photography from the studio's own Instagram posts plus credited stock.
  • 05A converter script (`scripts/convert-html.py`) rebuilds the pages and the shell from the HTML site, keeping both versions in step.
RJ Studio homepage on desktop: a dark portrait of a model with wind-blown hair behind large serif capitals reading RJ Studio and a script line Hair & Nails
Homepage, desktop — production build
RJ Studio homepage on a phone: monochrome close-up portrait, the RJ Studio headline and a Book your transformation on Instagram card
Homepage, phone

Where AI was used and why.

This project did not use AI — a deliberate choice. Not every system needs a model.

Relevant stack.

  • Next.js 16
  • React 19
  • TypeScript
  • Static HTML → JSX converter (Python)
  • JSON-LD
  • Railway

Only factual results.

Outcome to be added. Results are only published here when they can be stated factually — no estimated metrics.

Important engineering insights.

  • A one-to-one port is a legitimate engineering choice: the owner keeps the approved design and gains the framework's SEO plumbing.
  • Moving a page class from body to main is the kind of small change that breaks a whole stylesheet — the `:has()` selector rescued it without rewriting rules.
  • Structured data for a service menu is worth building from the same data file the page renders, so the two can never disagree.

Have a project in mind?

Tell me what you're trying to build. I'll come back with an honest view on scope, architecture and the right approach.