Frontend Overview
The Volare frontend is built with Astro 5 and Tailwind CSS v4, providing optimal performance and SEO-friendly travel product pages.
Technology Stack
Section titled “Technology Stack”| Component | Technology | Version |
|---|---|---|
| Framework | Astro | 5.x |
| Styling | Tailwind CSS | 4.x |
| Runtime | Node.js | 18+ |
| Package Manager | pnpm | 8+ |
| Deployment | Cloudflare Pages | - |
Architecture
Section titled “Architecture”Frontend├── Pages (File-based routing)│ ├── Static pages (Astro components)│ ├── Dynamic routes ([market], [slug])│ └── API endpoints (.ts files)├── Layouts (Shared structure)│ └── MainLayout.astro├── Components (Reusable UI)│ └── Feature-specific components└── Shared (Utilities & config)Key Features
Section titled “Key Features”- Zero JavaScript by default - Astro components ship no JS unless needed
- File-based routing - Pages map directly to URLs
- Dynamic routes - Market and product slug parameters
- SSR/SSG flexibility - Server or static rendering per page
- Tailwind CSS v4 - Utility-first styling with CSS variables
Project Structure
Section titled “Project Structure”frontend/├── src/│ ├── components/ # Reusable Astro components│ ├── features/ # Feature-specific components│ ├── layouts/ # Page layouts│ │ └── MainLayout.astro│ ├── pages/ # File-based routing│ │ ├── index.astro│ │ ├── health.ts│ │ ├── [market]/ # Dynamic market routes│ │ └── products/│ ├── shared/ # Shared utilities│ └── styles/ # Global styles├── public/ # Static assets├── astro.config.mjs # Astro configuration└── package.jsonRouting
Section titled “Routing”Static Pages
Section titled “Static Pages”src/pages/index.astro -> /src/pages/about.astro -> /aboutsrc/pages/contact.astro -> /contactDynamic Routes
Section titled “Dynamic Routes”src/pages/[market]/index.astro -> /{market}src/pages/[market]/products/[slug].astro -> /{market}/products/{slug}src/pages/products/[slug].astro -> /products/{slug}API Endpoints
Section titled “API Endpoints”src/pages/health.ts -> /health (JSON response)Astro Components
Section titled “Astro Components”Basic Component
Section titled “Basic Component”---// Component script (runs at build time)interface Props { title: string; description?: string;}
const { title, description } = Astro.props;---
<article class="product-card"> <h2>{title}</h2> {description && <p>{description}</p>}</article>
<style> .product-card { @apply p-4 rounded-lg shadow-md; }</style>Layout Usage
Section titled “Layout Usage”---import MainLayout from '../layouts/MainLayout.astro';---
<MainLayout title="Page Title"> <main> <h1>Content here</h1> </main></MainLayout>Styling with Tailwind CSS v4
Section titled “Styling with Tailwind CSS v4”Configuration
Section titled “Configuration”Tailwind v4 uses CSS-first configuration:
@import "tailwindcss";
@theme { --color-primary: #3b82f6; --color-secondary: #64748b;}Usage in Components
Section titled “Usage in Components”<div class="bg-primary text-white p-4 rounded-lg"> <h1 class="text-2xl font-bold">Title</h1> <p class="text-secondary">Description</p></div>Development
Section titled “Development”Commands
Section titled “Commands”# Start development serverpnpm dev
# Build for productionpnpm build
# Preview production buildpnpm previewDevelopment Server
Section titled “Development Server”The frontend runs at http://localhost:4321 by default.
API Integration
Section titled “API Integration”Fetching from Backend
Section titled “Fetching from Backend”---const market = Astro.params.market;const lang = 'en';
const response = await fetch( `${import.meta.env.API_URL}/api/${market}/${lang}/products`);const { data: products } = await response.json();---
<ul> {products.map((product) => ( <li> <a href={`/${market}/products/${product.url_slug}`}> {product.title} </a> </li> ))}</ul>Image Optimization
Section titled “Image Optimization”Use Astro’s <Image /> component for optimized images:
---import { Image } from 'astro:assets';import heroImage from '../assets/hero.jpg';---
<Image src={heroImage} alt="Hero image" width={1200} height={600}/>Meta Tags
Section titled “Meta Tags”---// In layout or pageconst { title, description } = Astro.props;---
<head> <title>{title} | Volare Travel</title> <meta name="description" content={description} /> <meta property="og:title" content={title} /> <meta property="og:description" content={description} /></head>Structured Data
Section titled “Structured Data”<script type="application/ld+json"> {JSON.stringify({ "@context": "https://schema.org", "@type": "Product", "name": product.title, "description": product.description })}</script>Deployment
Section titled “Deployment”The frontend deploys to Cloudflare Pages:
# Deploy to stagingpnpm deploy-stagingBuild output is in dist/ directory.