← cd ../projects

CLIENT SITE · FRONTEND & SEO

Mebo Photobooth: Bilingual Local-Business Site

role: Solo Developer

links:live site ↗

## problem

The business sells through Instagram and WhatsApp, so nothing it publishes is reachable from a search for "sewa photobooth Bali". It also sells into two markets at once: local Indonesian customers, and the destination-wedding traffic that searches in English. One page in one language would miss half the demand, and two languages behind a toggle would leave one of them unindexable.

## what I built

Built the site solo on Next.js 16, every route prerendered at build time. Indonesian sits at / and English at /en as independent URLs rather than a toggle, targeting different keywords rather than translating each other, with hreflang linking only genuinely corresponding pages. All copy is typed content in one module per locale, so a missing field fails the build instead of rendering an empty section, and LocalBusiness, Offer and FAQPage JSON-LD are generated from that same content. Every section is a Server Component: the two client components render null and attach behaviour from the outside by data attribute, so adding motion or a lightbox never converts a section to a client component. Deployed on Vercel under the business's own domain, with a host-matched header keeping the *.vercel.app copies out of the index so only the canonical host is crawled.

## highlights

  • Two locales as two indexable URL trees, each aimed at its own market instead of translating the other
  • One conversion path: every call to action opens a prefilled WhatsApp chat, tagged with a single data attribute
  • Server Components throughout: the two client components render null and attach behaviour by data attribute
  • Animation that cannot break the page: hidden start states come from JavaScript rather than CSS, and the LCP hero is never animated
  • GSAP ships in a lazy chunk, so it stays off the initial payload and reduced-motion visitors never download it
  • LocalBusiness, Offer and FAQPage structured data generated from the same typed content the page renders
  • Image size ladder and allowed qualities trimmed to the widths the layout actually requests

## tech stack

TypeScriptNext.js 16React 19Tailwind CSS v4GSAP / ScrollTriggernext/imageJSON-LDVercel

Interested in the details? Get in touch →