Skip to content

Latest commit

 

History

167 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sea Saba — Professional Scuba Diving Website

A fast, SEO-first, destination-led marketing website for Sea Saba, a professional scuba diving operation on the island of Saba in the Dutch Caribbean.

Automated tests

See the testing guide for the audit, coverage, fixtures, CI and required merge check. With Node 24, run npm ci, npx playwright install chromium webkit, then npm run test:ci. For fast feedback, use npm test or npm run test:watch.

This project is a migration from Wix to a custom Next.js stack.

The website is intentionally designed as a premium, destination-first marketing site, not a generic dive shop catalog.
The homepage is a positioning + routing page, while inner pages carry the SEO-rich informational depth.


Core Strategy

The site should communicate:

  • Why dive Saba
  • Why choose Sea Saba
  • What experiences are available
  • How to take the next step

Strategic Principles

  • Destination-first — sell Saba as a unique diving destination
  • Experience-led — emphasize boat diving, signature sites, and trip planning
  • Trust-first — calm, professional, safety-forward
  • SEO-first — semantic, indexable, stable content architecture
  • Conversion-ready — clear routing and strong Checkfront booking paths

This is not intended to be a retail-heavy or generic dive shop template.


Tech Stack

  • Framework: Next.js 16 (App Router)
  • Language: TypeScript
  • Styling: Tailwind CSS 4 + shadcn/ui
  • Content: TSX pages for marketing / informational / dive site content
  • Dynamic Data: Firestore (dives, boats, sites, species, guides)
  • Booking: Checkfront (deep links, embedded widgets)
  • Analytics: Vercel Analytics, Google Analytics 4 (optional), Google Tag Manager (optional)
  • PDF Export: jsPDF (premium card-style dive log export)
  • Deployment: Vercel

Getting Started

npm install
cp .env.example .env.local
# fill in .env.local with your Firebase values
npm run dev

Open http://localhost:3000 to view the site.


Layout Rules (Critical)

There are exactly two layouts in this project:

1. Homepage Layout

  • Static hero image at top
  • One homepage video background section (3rd major section)
  • Minimal copy
  • Destination positioning + routing
  • Strong but restrained CTA hierarchy

2. Standard Content Layout

  • Used for all non-home pages
  • No video backgrounds
  • Text-first, SEO-focused
  • Breadcrumbs encouraged
  • Semantic, content-rich, stable

Do not introduce additional layouts unless explicitly requested.


Homepage Rules (Critical)

The homepage must follow this high-level structure:

  1. Hero (Static Image)
  2. Supporting Static Section
  3. Single Video Section + CTA
  4. Static Routing Sections
  5. Final CTA

Homepage Intent

The homepage should answer:

  1. Why dive Saba?
  2. Why Sea Saba?
  3. What can I choose?
  4. Where do I go next?

Important Notes

  • The homepage is not a content dump
  • The homepage is not the primary SEO text page for every topic
  • Detailed content belongs on inner pages
  • Motion is minimal and only used on the homepage
  • Mobile video must degrade to a poster image

Project Structure

app/
├── layout.tsx                     # Root layout (header, footer, fonts, SEO, JSON-LD)
├── page.tsx                       # Homepage (destination-first layout)
├── not-found.tsx                  # Custom 404 page
├── robots.ts                      # robots.txt
├── sitemap.ts                     # sitemap.xml
├── book/page.tsx                  # Booking page (Checkfront widget + fallback)
├── (content)/                     # Standard content layout group
│   ├── layout.tsx                 # Content layout (breadcrumbs, prose, SEO-first)
│   ├── about/
│   ├── contact/
│   ├── courses/
│   ├── dive-log/
│   ├── dive-sites/
│   ├── diving/
│   ├── partners/
│   ├── plan-your-trip/
│   ├── privacy/
│   └── terms/
components:
├── ui/                            # shadcn/ui components
├── header.tsx                     # Sticky header
├── footer.tsx                     # Site footer
├── footer-wrapper.tsx             # Footer wrapper
├── hero.tsx                       # Homepage hero
├── breadcrumbs.tsx                # Breadcrumb navigation
├── booking-cta.tsx                # Reusable booking call-to-action
├── booking-widget.tsx             # Checkfront embedded widget
├── dive-log-client.tsx            # Interactive dive log UI
├── find-sea-saba.tsx              # Map / location component
└── structured-data.tsx            # JSON-LD LocalBusiness structured data
lib/
├── metadata.ts                    # SEO metadata helpers
├── constants.ts                   # Site-wide constants (URLs, nav items)
├── firebase.ts                    # Firebase client SDK setup
├── firestore/
│   ├── dive-log.ts                # Firestore dive log fetching and normalization
├── dive-log-export.ts             # Premium PDF export for selected dives
└── ...
public/
├── images/                        # Site images (hero, OG, posters, content, logo)
└── video/                         # Homepage video assets

Roadmap

Phase 1 — Foundation (Complete)

  • Project scaffolding (Next.js, Tailwind, TypeScript)
  • shadcn/ui setup and design system
  • Root layout with Header and Footer
  • Homepage layout with hero section (hero image may extend under navbar; no full-image color filter overlay by default)
  • Standard content layout with breadcrumbs
  • Global SEO setup (metadata helper, sitemap, robots.txt)

Phase 2 — Core Pages (Complete)

  • About page
  • Diving overview page
  • Courses / certifications page
  • Contact page
  • Partners page
  • Privacy & Terms pages
  • Homepage refined to answer the four key questions
  • /dive-sites section
  • /plan-your-trip content cluster
  • Homepage routing destinations aligned to destination-first strategy

Phase 3 — Booking Integration (Complete)

  • Reusable BookingCTA component
  • Embedded booking widget with graceful fallback
  • Dedicated /book page
  • Checkfront deep link CTAs on relevant pages

Phase 4 — Dynamic Content (Complete)

  • Firestore integration (client-side)
  • Live dive log (/dive-log) with filtering, selection, and PDF export

Phase 5 — Polish & Launch (Complete)

  • Custom 404 page
  • Skip-to-content accessibility link
  • 301 redirect scaffold in next.config.ts
  • Structured data (JSON-LD LocalBusiness)
  • Open Graph / Twitter Card metadata
  • Real OG image configured
  • Vercel Analytics installed
  • Performance and accessibility baseline

Production Deployment

The site is deployed on Vercel from the master branch.

Required Environment Variables

Copy .env.example to .env.local and fill in the values from your Firebase Console.

Critical: the browser-side Firebase SDK requires the public variables to use the NEXT_PUBLIC_ prefix:

NEXT_PUBLIC_FIREBASE_API_KEY
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
NEXT_PUBLIC_FIREBASE_PROJECT_ID
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
NEXT_PUBLIC_FIREBASE_APP_ID
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID
NEXT_PUBLIC_SITE_URL=https://www.seasaba.com

Firestore Security Rules

Public read access is required for the collections used by the live site:

match /dives/{docId} { allow read: if true; }
match /boats/{docId} { allow read: if true; }
match /sites/{docId} { allow read: if true; }
match /species/{docId} { allow read: if true; }
match /guides/{docId} { allow read: if true; }

Deployment Steps

  1. Ensure environment variables are set in Vercel (Production + Preview)
  2. Merge changes to master
  3. Vercel builds and deploys automatically
  4. Verify /dive-log loads dives and /sitemap.xml is valid

Post-Launch Monitoring

  • Check Vercel Analytics for Core Web Vitals
  • Monitor Search Console for crawl errors and 301 redirect coverage
  • Keep 301 redirects in data/redirects.ts populated from the old Wix site
  • Verify GA4 / GTM events fire in Google Tag Assistant or browser DevTools Network tab

Analytics & Conversion Tracking

The site loads Google Tag Manager in app/layout.tsx via the AnalyticsLoader component.

  • Vercel Analytics: enabled independently through @vercel/analytics/next.
  • Google Tag Manager: loaded only when NEXT_PUBLIC_GTM_ID is set.
  • Google Analytics 4 and marketing tags: configured and loaded inside GTM. The application does not load GA4 or call window.gtag() directly.

Tracked events are sent through the shared trackEvent, trackLinkClick, and trackBookingClick helpers in lib/analytics.ts. Each business event is pushed once to the GTM data layer and is also sent independently to Vercel Analytics.

Tracked events include:

  • book_now_click — Sea Saba booking CTAs
  • checkfront_click — Checkfront fallback and direct booking links
  • contact_click — internal contact CTAs
  • contact_form_submit — contact form handoff to email or WhatsApp
  • email_click, phone_click, whatsapp_click — contact link clicks
  • directions_click — Google and Apple Maps directions links
  • ferry_link_click — Makana Ferry and other ferry partner links
  • social_click — social media, partner, and outbound resource links
  • pdf_download — dive log PDF export

All events include page_location, page_path, page_title, and page_referrer. Link events also include link_url, link_text, link_domain, and outbound. Booking events include button_name, button_location, and booking_item. Legacy parameters such as link_destination, button_text, and referrer remain available for historical compatibility. Sensitive URL query strings are removed before link data is sent.


Design Principles

  • Clarity over flash — text-first, SEO-focused content pages
  • Trust over hype — calm, professional, conservation-minded tone
  • Speed over spectacle — static generation, minimal JS, optimized assets
  • Motion is minimal — only on homepage, degrades gracefully on mobile
  • Destination over catalog — sell Saba and the Sea Saba experience first
  • Understated sophistication — premium without being flashy

Booking Rules

  • Checkfront is the system of record
  • Use:
    • Deep links
    • Embedded widgets
    • Optional availability previews
  • Do not move checkout logic into the website
  • The website must still convert even if widgets fail

Content Rules

TSX pages are used for:

  • Core marketing pages
  • Diving overview pages
  • Dive site pages
  • Trip planning content
  • FAQs and informational content

Firestore is preferred for:

  • Testimonials
  • Reviews
  • Staff profiles
  • Dynamic operational / timely data

Visual Rules

  • Homepage hero uses a static full-bleed image
  • No full-image color filter overlay by default
  • Text readability should come from:
    • image selection
    • typography
    • subtle local gradient behind text only
    • light text-shadow
  • Homepage may have one video background section only
  • Inner pages should remain calm, stable, and text-first

Design North Star

The site should feel like:

Premium expedition diving on a special island.

And the brand message should feel like:

Experienced. Deliberate. Professional.

About

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages