Back to Blog

Building Mr. Watson: A Botanical Restaurant Website

4 minsWeb Development

Mr. Watson is a vegan wood-fired restaurant in Amsterdam with a unique philosophy: "Where perspective changes perception." Named after Sherlock Holmes' legendary sidekick who always saw things from a different angle, the restaurant needed a website that captured this spirit while showcasing their botanical cuisine.

The Design System

The brand revolves around three core colors that evoke a warm, earthy, botanical feeling:

Forest Green
Gold
Cream

These colors work together to create a feeling of nature, warmth, and sophistication — perfect for a plant-based restaurant that takes its craft seriously.

Tech Stack

  • Next.js 14 with App Router for the framework
  • Tailwind CSS for styling with a custom color palette
  • Framer Motion for scroll-driven animations
  • Static export for fast, traditional hosting

The decision to use static export was deliberate — a restaurant website doesn't need server-side rendering for every request. Static files are faster, cheaper to host, and more reliable.

The Parallax Ribbons

The most eye-catching feature is the parallax ribbon section. Three angled ribbons scroll at different speeds as you move down the page, each displaying rotating text with the restaurant's key messages.

const { scrollYProgress } = useScroll({
  target: ref,
  offset: ['start end', 'end start'],
});

const x = useTransform(
  scrollYProgress,
  [0, 1],
  direction === 'left'
    ? ['5%', '-20%']
    : ['-20%', '5%']
);

The trick is using useScroll from Framer Motion to track the element's position in the viewport, then useTransform to map that progress to horizontal movement. Each ribbon gets a different speed multiplier and direction for visual depth.

The ribbons are rotated with CSS transforms and extended beyond the viewport width to prevent any gaps showing at the edges:

style={{
  transform: `rotate(${angle}deg)`,
  marginLeft: '-60%',
  marginRight: '-60%',
  width: '220%',
}}

Performance Considerations

Parallax effects can be performance killers if not done carefully. A few optimizations made a big difference:

  • transform-gpu class forces GPU acceleration
  • willChange: 'transform' hints to the browser about upcoming animations
  • backfaceVisibility: 'hidden' prevents rendering artifacts
  • Using transform instead of position properties for movement

Reservation Integration

The site integrates with Tebi, a restaurant reservation system. Rather than building a custom booking system, embedding their widget provides a battle-tested solution that the restaurant staff already knows how to manage.

Deployment

A simple deployment script builds the static export locally and rsyncs it to the server:

npm run build  # Generates static files in /out
rsync -avz --delete out/ server:/var/www/mrwatson/

No Node.js process needed on the server — just nginx serving static files. Fast, reliable, and easy to maintain.

Lessons Learned

  1. Static export is underrated: Not every site needs SSR. Static sites are fast and cheap.
  2. Framer Motion makes scroll animations easy: The useScroll/useTransform combo is powerful.
  3. Extend beyond viewport for rotated elements: Always account for the diagonal when rotating.
  4. GPU acceleration matters: A few CSS properties can make animations buttery smooth.
  5. Use existing services: Don't rebuild reservation systems from scratch.

Project Links

  • Live site: mrwatson.nl
  • Tech: Next.js 14, Tailwind CSS, Framer Motion
  • Hosting: Static export on nginx

If you're ever in Amsterdam and want to experience plant-based cuisine done right, check out Mr. Watson. The website might be my work, but the food is all them.