Laughlin River Logo

Laughlin River Jet Ski Rentals

Laughlin River - Thumbnail
Laughlin River - Hero Section - After Image
Laughlin River - Hero Section - Spanish Locale
Laughlin River - About Section
Laughlin River -  Fleet Section
Laughlin River - Info Section
Laughlin River - Widgets Section - After Image
Laughlin River - Footer Section - After Image
Laughlin River - Video Player Section
Laughlin River - Reserve Section - After Image

About

Laughlin River Jet Ski Rentals

Client

Laughlin River Jet Ski Rentals

Year

2025

Scope of Work

Website Redesign, Platform Migration, UI/UX Design, Custom Booking System

From Shopify to premium: a full website rebuild for Laughlin's top-rated watercraft rental. Custom booking, bilingual EN/ES, and zero-downtime SEO migration.
laughlinriverjetskirental.com

Live Website

View the live Laughlin River Jet Ski Rentals website

Technologies Used

Frontend

Next.js 16 icon
Next.js 16

Cutting-edge App Router framework powering server-side rendering, locale-based routing, and ISR-cached data fetching. Running v16 with React 19 Server Components to minimize client-side JavaScript on a site built for phones in the desert.

React 19 icon
React 19

Server Components handle the weather widget, product cards, and reservation banner. Client-side React ships only where interactivity is required: the hero, navigation, testimonials carousel, and booking form.

TypeScript icon
TypeScript

End-to-end type safety across the entire stack. Product definitions, form schemas, API route handlers, and i18n message keys are all statically typed, eliminating an entire class of runtime errors.

Tailwind CSS v4 icon
Tailwind CSS v4

Utility-first styling with Tailwind v4's new @theme directive and oklch perceptual color space for the entire design token system. Custom 3xl breakpoint at 1920px for ultrawide displays.

shadcn/ui icon
shadcn/ui

Base component library providing accessible, unstyled primitives for the calendar, popover, dialog, drawer, tabs, and form inputs. Customized with the brand's electric yellow primary color.

Motion React icon
Motion React

Powers the sticky header show/hide transitions, mobile menu height animations, testimonials carousel, and section entrance animations. All animations are GPU-accelerated and respect prefers-reduced-motion.

TanStack Form icon
TanStack Form

Client-side form state management for the reservation system with field-level validation, auto-formatted phone inputs, calendar date picking, and passenger count controls.

next-intl icon
next-intl

Production-grade internationalization powering full EN/ES bilingual support. Locale-based routing with prefix-as-needed strategy, structured JSON translation files, and SEO parity via hreflang alternates.

Lenis icon
Lenis

Global smooth scroll engine providing buttery page scrolling, with intelligent iOS Safari detection that falls back to native scroll to avoid known WebKit rendering issues.

Backend

Brevo icon
Brevo

Transactional email delivery for the reservation pipeline and newsletter signups. Dual emails on every booking (admin + customer), plus contact list management for the footer newsletter.

Upstash Redis icon
Upstash Redis

Distributed rate limiting for the reservation API endpoint. A sliding window of 3 requests per 60 seconds per IP, enforced consistently across all serverless instances via Upstash's Redis-backed rate limiter.

Design

Figma icon
Figma

All UI design, component specifications, and responsive breakpoint planning were produced in Figma before development, ensuring design intent translated cleanly into code.

From Shopify to Premium: Rebuilding Laughlin’s Top Watercraft Rental for the Modern Web


I. The Problem


Laughlin River Jet Ski Rentals had the fundamentals locked down. 4.9 stars across 929 Google reviews. Brand-new Yamaha WaveRunners. A Car Jet Boat, a Sea-Doo Speedster, and a Pontoon Boat out of the New Pioneer Casino dock. Private beach access. No security deposit. The on-water experience was already excellent.


The website was not. It was a Shopify store with a neon yellow background, decorative fonts that looked like they were set in 2005, and a third-party weather widget with a "POWR — Create your own for free!" watermark at the bottom. The reservation "system" was a basic contact form that sent an email and hoped for the best. No confirmation emails. No vessel selection. No mobile optimization for tourists browsing on their phones at the casino.


For a business pulling in five-star reviews, the website was actively working against them:

  1. No after-hours booking. Every tourist searching "jet ski rental Laughlin" after 8pm was a missed sale. That's the majority of the booking intent window.
  2. An untapped Spanish-speaking market. Laughlin draws heavily from Southern California and the broader Southwest. A monolingual English Shopify store was leaving a significant customer segment behind.
  3. The website killed the brand. A neon yellow Shopify template told visitors this was a budget operation. The 4.9-star reputation on Google was doing all the heavy lifting, and the website was undermining it the moment someone clicked through.
Homepage
Laughlin River - Hero Section - After Image
Laughlin River - Hero Section - Before Image
Shopify Store
Custom Build

II. What We Built


A complete rebuild from the ground up. Designed to convert, not just to look good.

We scrapped the Shopify store entirely and rebuilt on a modern stack: Next.js 16, React 19, and Tailwind CSS v4. The first scroll does the selling. Bold design, electric yellow brand accents against dark backgrounds, and a curated fleet showcase immediately signal that this is a premium operation. Every element on the page is engineered to break down purchase objections: lowest price guarantee removes price anxiety, no deposit eliminates commitment risk, flexible scheduling and online booking capture intent around the clock, and a dedicated safety section with video reassures first-timers. Every section ends with a "Reserve Now" CTA. No dead ends.


The fleet is presented as a guided selling flow, not a product catalog. Each watercraft gets its own spotlight: the Yamaha WaveRunner leads as the premium flagship, the Car Jet Boat targets speed seekers, the Sea-Doo Speedster appeals to groups, and the Pontoon Boat serves families. Compare the old Shopify product listing to the new fleet showcase:

Fleet & Products
Laughlin River - About & Fleet Section - After Image
Laughlin River - About & Fleet Section - Before Image
Shopify Store
Custom Build

The reservation system is fully custom. No Shopify, no third-party plugin taking a percentage of each sale. Tourists can browse the fleet, pick a vessel, choose a date, and confirm their booking at midnight from their phone. Both the business and the customer receive instant email confirmations. The old Shopify form didn't even let you select which vessel you wanted.

Reservation System
Laughlin River - Reserve Section - After Image
Laughlin River - Reservation Section - Before Image
Shopify Store
Custom Build

Every piece of content exists in both English and Spanish, professionally localized rather than machine-translated. A live weather widget shows real-time Laughlin conditions with a 5-day forecast, replacing the old POWR embed and its free-tier watermark. An embedded Google Maps widget puts the dock location front and center with a contact card overlay. And the footer now includes a newsletter signup powered by Brevo, turning one-time visitors into a re-marketable audience for seasonal promotions.


The entire site was designed mobile-first with dedicated optimizations for both iOS Safari and Android Chrome. Smooth scrolling adapts to the device. The sticky navigation knows which direction you're scrolling and which section you're reading. Every interaction was built for a phone held in the Nevada sun, not a desktop in an office.

Weather, Map & Integrations
Laughlin River - Widgets Section - After Image
Laughlin River - Widgets Section - Before Image
Shopify Store
Custom Build
Footer & Newsletter
Laughlin River - Footer Section - After Image
Laughlin River - Footer Section - Before Image
Shopify Store
Custom Build

III. Zero-Downtime SEO Migration


The old site lived on a myshopify.com subdomain. Swapping it for a custom domain meant risking the search rankings the business had built over years. We handled the transition in two phases: first, we migrated the domain and pointed it to the existing Shopify store, monitoring Google Search Console to confirm Google re-indexed under the new URL and preserved existing rankings. Only once rankings were stable did we swap the Shopify store for the new custom-built site. The result: zero ranking loss, and a new site architecture that's built to climb. Structured data, hreflang alternates, and proper Googlebot directives give Google far richer signals than the Shopify store ever could.

IV. The Results


This wasn't a redesign for the sake of redesign. Every decision, from the 24/7 booking system to the bilingual SEO to the objection-breaking UX, was made to convert visitors into confirmed reservations.

  • After-hours booking captured. Late-night hotel browsing, early morning planning, mid-afternoon impulse decisions. The 24/7 booking system catches every one.
  • Two markets, one site. English and Spanish audiences both get a native-quality experience with full SEO parity.
  • Every booking dollar stays in the business. Custom reservation system at zero marginal cost. No per-transaction fees, no platform percentages, no vendor lock-in.
  • Premium positioning in a commodity market. The design and UX justify premium pricing where competitors compete on price alone.
  • Zero-downtime SEO migration. Shopify subdomain to custom domain with full ranking preservation, plus a new site architecture built to climb.


The math is straightforward: one extra booking per week pays for the entire website within the first season. Everything after that is pure return on investment.

Key Metrics

01

24/7
After-Hours Booking
Tourists can book from their hotel room at midnight. No phone calls, no waiting for business hours. The highest-intent window is now fully captured.

02

$0
Third-Party Booking Fees
Custom-built reservation system with zero per-transaction fees, no platform percentages, and no vendor lock-in. Every booking dollar stays in the business.

03

2 Locales
Market Reach
Full English and Spanish coverage serving the tri-state tourist corridor (Nevada, Arizona, California) with idiomatic localization and SEO parity.

04

4.9/5
Google Rating
929 verified reviews embedded in structured data, surfacing directly in search results and reinforcing trust before a visitor even clicks.
Technical Breakdown

A closer look at the engineering decisions behind this project, from the reservation pipeline to the zero-downtime SEO migration.

Architecture & Stack

Built on Next.js 16 with React 19 Server Components. The weather widget, product sections, reservation banner, and about section are all async server components. Client-side React ships only where interactivity is required: navigation, testimonials carousel, and booking form. Styling via Tailwind CSS v4 with the oklch perceptual color space for the design token system, shadcn/ui (base-vega variant) for accessible primitives, and a custom 3xl breakpoint at 1920px for ultrawide displays.


Custom Reservation Pipeline

The booking form runs on TanStack Form with field-level validation: name, email, 10-digit phone (auto-formatted), date (calendar picker, past dates disabled), passenger count (1 to 20), hotel name, optional message, and vessel selection. Server-side validation runs independently. Product names resolve from a typed registry, not user input. Brevo handles dual transactional emails (admin + customer). Upstash Redis provides distributed rate limiting (3 req/60s/IP) across serverless instances.


Internationalization Architecture

Full EN/ES support via next-intl with localePrefix: 'as-needed' routing. English has no URL prefix; Spanish routes through /es/. Locale-specific og:locale and hreflang alternates. Zero hardcoded text in components.


Mobile-First Engineering

Specific optimizations per browser engine:

  • iOS Safari: Lenis disabled (native fallback), backdrop-blur replaced with solid rgba, will-change stripped, video play debounced.
  • Android Chrome: Lenis smooth scroll enabled, content-visibility optimizations, GPU-accelerated animations.
  • Scroll system: Three custom hooks: use-lenis-scroll, use-scroll-direction, use-scroll-spy.


Live Weather Integration

Server-rendered widget fetching from OpenWeather API with 10-minute ISR cache. Processes 3-hour forecast intervals into daily min/max values. Six weather condition categories each map to unique gradient backgrounds. Wind direction calculated to 16-point compass resolution, fully translated for Spanish. Replaces the old POWR third-party embed.


Map Widget

Locale-aware Google Maps iframe with lazy loading. The hl parameter switches between en and es based on active locale. Contact information overlay card with phone, email, and address. React Suspense with skeleton fallback for zero-layout-shift loading.


Newsletter Pipeline

Brevo-powered email capture in the footer. In-memory sliding-window rate limiting (3 req/min/IP), disposable email domain blocking, and canvas-confetti brand-colored burst on success.


Domain & SEO Migration

Two-phase migration from *.myshopify.com to custom domain:

  1. Domain transfer: Custom domain pointed to existing Shopify store. Google Search Console monitored for re-indexing confirmation and ranking retention.
  2. Platform swap: Once rankings stabilized, Shopify replaced with the Next.js site. New structured data, sitemap, and hreflang alternates provided Google richer signals than Shopify ever could.


Local SEO Architecture

Two JSON-LD schemas injected in the layout:

  • LocalBusiness + SportsActivityLocation: Full postal address, geo coordinates, opening hours, aggregate rating (4.9/929), area served, and Offer objects for flagship vessels.
  • WebSite: Publisher and creator attribution with Vean Digital URL.

Googlebot directives: max-video-preview: -1, max-image-preview: "large", max-snippet: -1. Full hreflang alternates for EN/ES with locale-specific og:locale values.