VISIT VISA SERVICE

Spread the love
# SV VisasTechnical Specification

## Dependencies

### Production

| Package | Version | Purpose |
|---------|---------|---------|
| `react` | `^19.1.0` | UI framework |
| `react-dom` | `^19.1.0` | DOM renderer |
| `three` | `^0.172.0` | 3D engineflight path visualization |
| `@react-three/fiber` | `^9.1.0` | React renderer for Three.js |
| `@react-three/drei` | `^10.0.6` | R3F helpersuseGLTF, Line, Environment |
| `gsap` | `^3.12.7` | Core animation engine + ScrollTrigger plugin |
| `lenis` | `^1.3.1` | Smooth scroll with velocity tracking |
| `splitting` | `^1.1.0` | Text splitting for character-level animations |
| `tailwindcss` | `^4.1.7` | Utility-first CSS |
| `@tailwindcss/vite` | `^4.1.7` | Tailwind Vite integration |

### Development

| Package | Version | Purpose |
|---------|---------|---------|
| `typescript` | `^5.8.3` | Type safety |
| `vite` | `^6.3.5` | Build tool |
| `@vitejs/plugin-react` | `^4.4.1` | React Fast Refresh for Vite |
| `@types/react` | `^19.1.3` | React type definitions |
| `@types/react-dom` | `^19.1.3` | ReactDOM type definitions |
| `@types/three` | `^0.172.0` | Three.js type definitions |

### Fonts

Playfair Display (700) and Inter (300–700) loaded via Google Fonts `<link>` in `index.html`.

---

## Component Inventory

### Layout

| Component | Source | Reuse |
|-----------|--------|-------|
| `Navigation` | Custom | Global — fixed nav with scroll-aware shadow |
| `Footer` | Custom | Global |
| `WhatsAppFloat` | Custom | Global — fixed FAB with pulse animation |

### Sections

| Component | Source | Notes |
|-----------|--------|-------|
| `HeroSection` | Custom | Contains Canvas, content overlay, parallax images |
| `PanicMarqueeSection` | Custom | Dual-row infinite scroll with CSS animations |
| `DestinationsSection` | Custom | 3D tilt cards in horizontal scroll container |
| `PricingSection` | Custom | Tabbed panels with country-specific pricing data |
| `WhyUsSection` | Custom | 6-card feature grid |
| `ProcessSection` | Custom | 5-step timeline with connecting line |
| `GallerySection` | Custom | Dual-row infinite scroll with parallax speed offset |
| `TestimonialsSection` | Custom | 3 testimonial cards |
| `FormSection` | Custom | Two-column with application form + disclaimer |
| `FinalCTASection` | Custom | Dark gradient CTA band |

### 3D System

| Component | Source | Notes |
|-----------|--------|-------|
| `FlightStage` | Custom (R3F) | Canvas wrapper — camera, lighting, scene composition |
| `Airplane` | Custom (R3F) | GLTF model loader + flight path follower |
| `FlightTrails` | Custom (R3F) | Three trail meshes with custom shader material |
| `EnvironmentParticles` | Custom (R3F) | 20 Points clouds with drift animation |
| `Preloader` | Custom | Loading overlay fades after 3D init |

### Reusable Components

| Component | Source | Used By |
|-----------|--------|---------|
| `SectionEye` | Custom | All sections — decorative label with gold lines |
| `Badge` | Custom | Hero — gold badge pill |
| `PrimaryButton` | Custom | Hero, Pricing, CTA, Form |
| `WhatsAppButton` | Custom | Hero, Nav, CTA, Float |
| `GoldButton` | Custom | Pricing cards |
| `StatCounter` | Custom | Hero stats — animated count-up |
| `SplitHeading` | Custom | Hero, all section headings — char-level animation |
| `DestinationCard` | Custom | DestinationsSection — 3D tilt effect |
| `PricingCard` | Custom | PricingSection — standard + dark variants |
| `FeatureCard` | Custom | WhyUsSection — icon + title + description |
| `ProcessStep` | Custom | ProcessSection — number circle + content |
| `TestimonialCard` | Custom | TestimonialsSection — stars + quote + author |
| `GalleryCard` | Custom | GallerySection — emoji + label overlay |
| `FlagCard` | Custom | PanicMarqueeSection — country pill with badge |

---

## Animation Implementation

| Animation | Library | Approach | Complexity |
|-----------|---------|----------|------------|
| 3D Flight Path System | Three.js + R3F | CatmullRomCurve3 path generation, per-frame position/rotation lerp, trail mesh vertex shifting, dashOffset decrement | **High** 🔒 |
| Trail Mesh Shaders | Three.js (custom ShaderMaterial) | Custom vertex/fragment shaders for thick line rendering with dash animation and texture support | **High** 🔒 |
| 3D Tilt Cards | CSS + JS | onMouseMove calculates rotation from card center → perspective(800px) rotateX/Y(±8deg), smooth reset on leave | **Medium** |
| Scroll → Plane Speed | Lenis + R3F useFrame | Read `lenis.velocity` each frame, multiply path progression delta by `(1 + Math.abs(velocity) * 0.002)` | **Medium** |
| Parallax Images (Hero) | GSAP ScrollTrigger | `scrub: true`, left image `y: 0→-60`, right image `y: 0→-100` | **Low** |
| Split Character Reveal | Splitting.js + GSAP | Split text into `.char` spans, stagger `0.03s`, `opacity:0→1`, `y:40→0`, `rotateX:-20→0`, `back.out(1.7)` | **Medium** |
| Panic Marquee | CSS animations | `@keyframes translateX(0→-50%)` infinite linear, reverse row; `@keyframes` for card bounce (staggered delays), plane shake, badge blink | **Low** |
| Gallery Parallax Speed | Lenis + CSS | Row scroll speed modulated by `lenis.velocity` via JS style updates | **Low** |
| Process Step Bounce | CSS animations | `@keyframes translateY(0→-8px)` 3s infinite, staggered `animation-delay` per step | **Low** |
| WhatsApp Pulse | CSS animations | `@keyframes box-shadow` expansion 2.5s infinite | **Low** |
| Nav Scroll Shadow | CSS + JS | Scroll listener toggles box-shadow value | **Low** |
| Stat Counter | JS | IntersectionObserver triggers count-up interval, `t/55` step increments | **Low** |
| Scroll Reveal (default) | GSAP ScrollTrigger | Batch reveal: `opacity:0→1`, `y:32→0`, `0.7s`, `power2.out` | **Low** |
| Card Hover Transitions | CSS | `cubic-bezier(0.34, 1.56, 0.64, 1)` for bouncy feel on translateY + scale | **Low** |
| Tab Panel Crossfade | GSAP | Outgoing `opacity:1→0` (0.2s), incoming `opacity:0→1` + `y:10→0` (0.3s) | **Low** |
| Gallery Hover Scale | CSS | `transform: scale(1.04)`, 0.3s transition | **Low** |
| Floating Badge/Images | CSS | `@keyframes float`gentle translateY oscillation, different durations per element | **Low** |
| Preloader Fade | GSAP | `opacity:1→0` over 0.6s on 3D init complete | **Low** |

---

## State & Logic

### 3D Flight PathPath Generation & Animation Loop

Three `useRef` values manage the animation state: `pathProgress` (number 01), `planePosition` (THREE.Vector3), `planeTarget` (THREE.Vector3), plus `currentPath` (CatmullRomCurve3). The `useFrame` hook runs every frame: increments progress by `delta * 0.05 * (1 + |scrollVelocity| * 0.002)`, regenerates the curve with new random control points when progress exceeds 1, samples position and lookahead target from the curve, then applies `lerp` and `lookAt` to the plane mesh. Trail meshes update by shifting vertex arrays backward and inserting the plane's current position at index 0.

### Trail Mesh ShadersUniforms & Attributes

The custom ShaderMaterial requires per-vertex attributes (`previous`, `next`, `side`, `width`, `counters`) and uniforms (`resolution`, `lineWidth`, `color`, `opacity`, `dashOffset`, `dashRatio`, `visibility`, `near`, `far`, `sizeAttenuation`, `alphaTest`, `repeat`, `hasTexture`, `uTex`). The dashOffset uniform decrements each frame to create the flowing trail animation. On mobile (≤700px), particle count reduces from 20 to 10 and bloom post-processing is disabled.

### LenisGSAP ScrollTrigger Bridge

Lenis instance created at app root. The `scroll` event calls `ScrollTrigger.update()`. GSAP ticker callback drives `lenis.raf(time)`. Scroll velocity is read from `lenis.velocity` in both the 3D flight system (plane speed) and the gallery section (parallax speed offset).

### Pricing Tab State

React `useState` tracks `activeCountry` (string: "canada" | "usa" | "uk" | "australia" | "europe"). Tab click updates state, triggers GSAP crossfade animation on the panel container. Pricing data is a static object keyed by country code.

---

## Other Key Decisions

### Asset Loading Strategy

The GLTF airplane model is loaded via `useGLTF` from drei with a Suspense boundary. A fallback composite geometry (CapsuleGeometry + BoxGeometry) renders as a stylized silhouette if the model fails to load or while loading. Images use standard `<img>` with `loading="lazy"` for gallery cards.

### Mobile 3D Degradation

On mobile viewports (≤700px), the 3D flight stage continues to render but with reduced fidelity: fewer particles, no post-processing bloom, and potentially reduced trail segment count. This is handled via a `useMediaQuery` hook or R3F conditional rendering.

### No shadcn/ui Components

This is a fully custom design with no standard UI patterns (dialogs, tables, dropdowns) that would benefit from shadcn/ui. All components are custom-built with Tailwind CSS. The shadcn/ui components installed by the init script remain available but are not actively used.
wpChatIcon
wpChatIcon