Full-stack web development

Africa Safari Escapes — A Case Study

A production travel website built from scratch: public-facing pages, a flight search engine, an admin dashboard, a safari shop, and a custom design system — all shipped as a single full-stack application.

Project Overview

Africa Safari Escapes is a full-stack travel website serving a real business. The brief called for a premium, conversion-focused public site alongside a protected admin dashboard — all built on a modern React + TypeScript + Express stack with server-side rendering for SEO.

Every feature was designed and implemented end-to-end: information architecture, component design, backend API routes, database schema, third-party integrations, and a bespoke colour and typography system that runs consistently across every page and form.

Live production site

africasafariescapes.com

This case study is the site you are currently viewing. Every feature described below is live and in production.

View live site

Tech Stack

React 19 + TypeScript

Strict typing throughout; zero any-casts in application code

Vite + SSR

Server-side rendering via Express for SEO and social previews

Tailwind CSS + shadcn/ui

Semantic CSS variable colour system; 40+ pre-built components extended

Express API routes

Provider-agnostic booking adapter, inbox, auth, and file upload endpoints

Drizzle ORM + MySQL

Typed schema migrations; users, documents, and company structure tables

BetterAuth

Session-based authentication with protected admin routes

Motion (Framer)

Scroll-triggered entrance animations and hover states site-wide

React Router v8

Data router with SSR loaders; 20+ routes including dynamic blog slugs

What Was Built

01

Flight Search Widget

A Skyscanner-style search widget with return/one-way toggle, airport autocomplete (IATA code-first scoring, portal-rendered dropdowns), passenger and cabin class selectors, and a provider-agnostic backend adapter ready for live API credentials.

ReactTypeScriptPortal renderingREST API
02

Custom Design System

A site-wide colour system using CSS variables — each form field type (name, email, phone, date, budget, etc.) has a unique semantic colour applied consistently across every page. Labels, placeholders, and focus states all follow a single source of truth in globals.css.

Tailwind CSSCSS variablesDesign tokensAccessibility
03

Admin Dashboard

A protected dashboard with tab navigation via URL search params, stats overview, document management, user management, and a company structure directory. Auth-aware header with session management and sign-out.

BetterAuthProtected routesDrizzle ORMMySQL
04

Safari Shop

A full e-commerce storefront integrated with GoDaddy Commerce — product catalogue, category filtering, product detail pages, cart, and checkout. Product images sourced and placed via a managed media slot system.

GoDaddy CommerceE-commerceProduct catalogueCart & checkout
05

Multi-page Public Site

20+ pages including destinations, packages, city stays, car hire, transfers, hotels, vetted accommodation, blog (with dynamic slug routing), and a marketing landing page system — each with full SEO metadata, Open Graph tags, and JSON-LD structured data.

SSRSEOJSON-LDReact Helmet
06

Enquiry & Booking Forms

Multiple context-specific forms (general enquiry, flight booking, car hire, transfers, city tour) all wired to a shared Inbox backend with email notifications. Each form uses the bespoke colour system and accessible label/placeholder standards.

Form designInbox APIAccessibilityUX

Key Technical Decisions

Portal rendering for dropdowns

Date pickers and autocomplete dropdowns render via createPortal into document.body with getBoundingClientRect positioning — preventing z-index conflicts with sibling sections and overflow:hidden clipping.

Provider-agnostic flight adapter

The flight search backend is built as a clean adapter layer in booking-api.ts — the frontend and API route are fully wired; swapping in live Falcon Flights credentials requires only filling in one adapter file.

Content layer for inline editing

All user-visible copy lives in src/content/ as typed JSON, scaffolded with Zod schemas. This keeps every text element inline-editable from the canvas without touching source code.

SSR-first for SEO

Every public page uses React Router v8 data loaders and @dr.pogodin/react-helmet for server-side head collection — titles, descriptions, canonical URLs, Open Graph, and JSON-LD are all in the first HTML byte that crawlers receive.

Interested in working together?

This project demonstrates end-to-end full-stack capability — from database schema and API design through to pixel-level UI and SEO. If you are looking for a developer who can own a product from brief to production, get in touch.