2025–2026 · Live
Moments like cinema.
Brand positioning is a code problem. Lift one photographer from €1,500 per wedding into the €3,500 conversation, without changing his work.
Evgenij Doppler (legal name Evgenij Patschinski, trading as `jev doppler`) photographs weddings with the compositional discipline he brings from film direction: every frame composed, not captured; couples guided into moments rather than posed for them. That is the differentiation. The problem was that nothing in his digital presence communicated it.
The positioning gap this project closed.
The maths was simple.
At €1,500 per wedding he needs three times as many bookings as he would at €4,500 to land the same revenue. His target market — international DACH/UK/NL couples, 20–60 guests, destination weddings in Spain with venue budgets of €5,000–€10,000+ — does not ask whether someone charges €3,500. The question is whether the website tells the truth about him persuasively enough that the right couples self-qualify.
The technical gap was real. The audit (28 April 2026)
documented a P0 bug: the hamburger-menu overlay was a
pointer-events-none
sibling of the navigation. Every iPhone visitor coming in
from Instagram landed in a dead end. With ~70% of traffic
coming from Instagram, that was a continuous conversion
disaster. The lightbox had no mobile navigation: a
22-image gallery was being served as 22 separate
close-and-tap-again interactions.
The positioning gap ran deeper. The site had no native German, no native Spanish, no native Russian. The English copy contained the word "luxury" and submissive phrasings ("I would love to"). The brand asked too little, delivered too little, and didn't speak the languages the bookings were coming from.
Design system first.
DESIGN.md before the first component. The
warm-black / cream / gold palette
(#0d0c0b,
#f5f0e8,
#b8a07a)
was distilled from six reference brands: Runway, Cursor,
SpaceX, Apple, Linear, Vercel. Every border comes from
brand-black or brand-cream at low alpha. No grey
(no #ccc)
anywhere in the code.
Typography: Cormorant Garamond (display) + Jost (body / UI). Cormorant turns cinematic at large sizes. Jost stays clean at body size, getting out of the photography's way.
Copy written natively per language. English: editorial, first-person, no "luxury", no "we would love to". German: matter-of-fact and warm with "du", DACH photographic register ("authentisch", "echte Momente"). Spanish: Iberian register with "vosotros", "cinematográfico", "reportaje" — not Latin American, not corporate. Russian: literary register with "ты", intimate. Each language file was written as if a native speaker had drafted it inside a premium-photography conversation. Not translation.
Gallery architecture: six real galleries
with named couples and venues. Dehesa de Don Pedro
(Extremadura, 46 images), Ana & Matt at Tambor del
Llano, Bride d'Life editorial, Elisabeth & Thomas in
Innsbruck, Marie & Allen at Tissington Hall, Dani &
Santi at Bodegas Hidalgo–La Gitana in Sanlúcar de Barrameda.
Lightbox with keyboard navigation, focus trap, swipe gesture
(Framer Motion drag="x"),
mobile close button (overlay click is desktop-only).
Performance: the hero scale animation is
tied to useInView
(it had previously been running off-screen continuously).
GlassBackground (Three.js WebGL) is lazy-loaded and disabled
on mobile. Skip-to-content is wired. The contact-form
honeypot was renamed from website
to confirmation_token;
browser autofill had been triggering false positives.
SEO infrastructure: JSON-LD
(LocalBusiness,
Person,
WebSite,
ImageGallery
on gallery slugs), hreflang alternates for 4 languages × 9
routes = 36 indexable URLs.
What made the build possible.
-
Next.js 16.1.6 (App Router, Turbopack)
Statically generated 28 pages across 4 languages. generateMetadata per page for full SEO control.
-
Tailwind CSS 4
Token-based, warm palette, no grey system colours anywhere in the code.
-
Framer Motion 12.35.2
Entrance animations, lightbox drag/swipe, hero scale loop. useReducedMotion on every motion component.
-
Three.js 0.183 / R3F 9.5
Ambient GlassBackground in the hero. Lazy-loaded, disabled on mobile to protect LCP.
-
Nodemailer 8.0.4 + Server Actions
Contact form runs server-side, no client credentials.
-
Custom 4-locale i18n
No next-intl. [lang] segment. Dictionaries in src/lib. hreflang generated on every page.
Production-ready, modulo two items.
All 28 static pages build clean. Every P0 and P1 audit
item from 28 April 2026 has been resolved. The mobile
hamburger menu works. The lightbox swipes between images.
sizes
attributes are set: an estimated 50–70% mobile bandwidth
saving on gallery loads. JSON-LD covers
LocalBusiness,
Person,
WebSite
and per-gallery
ImageGallery.
hreflang maps 36 language-route combinations.
Live: jevdoppler.com. Final Vercel deployment pending image compression and the Spanish tax ID on the imprint.
Live pricing at audit time: Essential €2,000 / Cinematic €2,500 / Full Day €3,500. Strategic target (positioning analysis): €2,800 / €3,500 / €4,800. The difference, €600–€900 per booking, is a decision, not a code bug. The infrastructure carries the target price. The decision is Evgenij's.
Brand positioning is a code problem. The brief was not "a website for a wedding photographer". The brief was: infrastructure that lets "Moments like cinema" read at €2,900 without triggering a haggling reflex.
The mirror image holds for antomata: every Mittelstand AI audit deliverable isn't the PDF. It's the client who no longer asks "do we really need this?" The infrastructure that retires that objection — the evidence skeleton, the price clarity, the GDPR zoning that says "green / grey / red" instead of "it depends" — gets built first.
"He saw things we didn't even notice ourselves. The images feel like scenes from a film we never knew we were starring in."
— Ana & Matt · Tambor del Llano, 2025 · clients of Evgenij's photography