Skip to content
51studio
Case Studies

Case Study: Building the 51 Studio Website with Next.js 16 and Sanity CMS

By 51 Studio10 min read
Case Study: Building the 51 Studio Website with Next.js 16 and Sanity CMS

When we built our own site, the brief was straightforward: show what we mean by 'quality web development' by actually shipping one. Not a marketing landing page. A full site: bilingual content, CMS, blog, contact forms, real performance numbers. Here's the technical decisions behind it and how it turned out.

Research and Technology Choices

Before writing any code, we worked through what the site actually needed. Key requirements:

  • Bilingual support with proper SEO for each language
  • Headless CMS so editors can manage content without developer involvement
  • Lighthouse scores: 90+ across all categories
  • Blog with syntax highlighting and Portable Text rendering
  • Contact form with validation, bot protection, and email notifications

We landed on: Next.js 16 (App Router, React 19), Sanity v5 as headless CMS, Tailwind CSS v4 for styling, Framer Motion for animations, Resend for transactional email.Next.js 16 (App Router, React 19), Sanity v5 as headless CMS, Tailwind CSS v4 for styling, Framer Motion for animations, and Resend for transactional emails.

Project Architecture

The site runs on Next.js 16 App Router with a clean split between server and client components. Pages, metadata, GROQ queries all run on the server. The interactive parts (forms, animations, modals) sit behind 'use client'.

Component Structure

We organized 24+ components by domain: blog/, contact/, layout/, services/, shared/, and ui/. UI primitives like Button and Sheet live separately from business components. Easier to find what you're looking for, easier to reuse.

Bilingual Implementation

For i18n, we use a dynamic [locale] segment in the route. Dictionaries (130+ keys) lazy-load via dynamic import. The t() function supports parameter interpolation, and TypeScript enforces key parity between locales at compile time.

Content in Sanity CMS uses dual fields: titleUk/titleEn, bodyUk/bodyEn, etc. GROQ queries use coalesce() to fall back to the default locale if the English translation is missing.

Performance and Lighthouse

Performance was in from day one. Here are the specific optimizations that got the scores up:

Image Optimization

A custom SanityImage component wraps Next.js Image and pulls dimensions from Sanity asset references automatically. You get native optimization (WebP/AVIF, responsive srcset) without typing width/height by hand. Above-the-fold images get the priority prop.

Animations Without Performance Cost

Framer Motion is loaded via LazyMotion with domAnimation, which loads only the animation code we actually use instead of the full bundle. Sections animate in on scroll via useInView() with once: true. We respect prefers-reduced-motion fully: when it's on, animations complete instantly.

Caching and Revalidation

Instead of Sanity's CDN cache, we use Next.js tag-based revalidation. Each GROQ query is tied to a tag ('blog', 'services', 'settings'), and a Sanity webhook calls revalidateTag() when content changes. Instant updates, no rebuild.

Lighthouse Results

The result, consistently across pages:

  • Performance: 95–100
  • Accessibility: 95–100
  • Best Practices: 95–100
  • SEO: 100

SEO and Structured Data

Every page generates metadata through a createPageMetadata() utility with canonical URLs and language alternates (hreflang). JSON-LD covers four schema types: Organization, Service (with price ranges), Article (for blog posts), and Breadcrumb. The sitemap is generated dynamically and includes every blog post with its update date.

Accessibility (a11y)

Accessibility isn't a checkbox you add at the end. It's how we build. Key decisions:

  • ARIA attributes on all interactive elements: aria-current for navigation, aria-live for error announcements, aria-required and aria-invalid for form fields
  • Keyboard navigation: arrow keys, Enter, and Space work on form selection cards
  • Minimum interactive target size of 44px for proper touch device support
  • Support for prefers-reduced-motion for users sensitive to animations
  • Semantic heading hierarchy (h1 → h2 → h3 → h4) and figcaption for blog images

Contact Form: Two Approaches

We built two contact form modes for different user types:

Guided (multi-step) — 4 steps: project type, goals, budget, contact details. Ideal for clients who want a more accurate estimate.

Quick — a single form with minimal fields. For those who just want to get in touch.

Both modes have bot protection (honeypot field), server-side validation, rate limiting (5 requests per hour per IP), and automatic emails: one to the admin about the new inquiry, one back to the client confirming. Data lives in Sanity as contactSubmission documents.

Blog with Syntax Highlighting

The blog runs on Sanity Portable Text with custom renderers for code blocks, images, lists, and headings. Syntax highlighting comes from Shiki: code is processed server-side and arrives on the client as pre-highlighted HTML. No Layout Shift on load.

Articles feature an auto-generated Table of Contents from h2/h3 headings, related posts, and category filtering.

Sanity CMS: Embedded Studio and Live Preview

Sanity Studio is embedded in the Next.js app at /studio, so editors don't need a separate deployment. Draft Mode is wired up through API routes with token-based auth, and live preview shows changes as they're typed.

The Studio desk structure is organized by content type: services, blog posts, process steps, form submissions, and site settings. Submissions are sorted by response status and date.

Conclusions and Results

What we ended up with isn't just a website. It's a working demo of how we build. The numbers:

  • Lighthouse Performance 95–100 consistently across all pages
  • Full bilingual support with SEO optimization for each language
  • Autonomous CMS — editors manage content without developer involvement
  • Accessibility at WCAG AA level
  • Structured data (JSON-LD) for improved search visibility

If you want this kind of build quality for your project, the contact form's right there.

Related articles