← All work
Web · studioConcept build · live demo

Safar Travel

A rebuild of a travel agency's website with a calm-cinematic motion system and a CMS staff can run without a developer. Designed and built as a speculative proposal.

Role
Design and full-stack build
Status
Concept build · live demo
Stack
Next.js App Router · TypeScript · Tailwind · shadcn/ui · Motion · GSAP · Lenis · Payload CMS · Postgres · Vitest · Playwright
Links
AdamMostofi/safar-travel-and-tourism ↗
Live demo ↗

Context

Safar is a concept build, designed and built as an unsolicited proposal for a travel and tourism agency and never commissioned. The live link is a demo, not a client site.

Design: “Ocean Breeze”

Light-first, breezy and structured. Airy blues (#F0F8FF, #E0F2FE), an ocean-teal primary, a pine-green call to action, Fraunces for display type and Inter for UI. The palette moved from the warm “Sea & Sand” set to “Ocean Breeze” in V1.1, and the token names stayed so the swap was low-risk.

Motion: graceful, not static

A set of reusable, reduced-motion-aware primitives: RevealOnScroll, HoverLift, KenBurns, Parallax, AnimatedCounter and an app-level SmoothScroll. Motion (motion/react) handles component interactions, while GSAP, ScrollTrigger and Lenis handle scroll and hero choreography. The reduced-motion policy is a unit-tested function.

Engineering

  • Payload CMS embedded in Next.js on Postgres, so staff manage packages at /admin.
  • A server data layer as the test seam. Pages only consume UI-ready view models (listPackages, getPackageBySlug) and never call Payload directly.
  • Self-contained tests. Vitest integration tests boot a throwaway embedded Postgres, apply migrations and seed fixed content. Playwright runs the smoke tests.
  • Migrations are the source of truth. Live schema push is disabled.