Skip to content

Frontend Overview

The Volare frontend is built with Astro 5 and Tailwind CSS v4, providing optimal performance and SEO-friendly travel product pages.

ComponentTechnologyVersion
FrameworkAstro5.x
StylingTailwind CSS4.x
RuntimeNode.js18+
Package Managerpnpm8+
DeploymentCloudflare Pages-
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)
  • 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
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.json
src/pages/index.astro -> /
src/pages/about.astro -> /about
src/pages/contact.astro -> /contact
src/pages/[market]/index.astro -> /{market}
src/pages/[market]/products/[slug].astro -> /{market}/products/{slug}
src/pages/products/[slug].astro -> /products/{slug}
src/pages/health.ts -> /health (JSON response)
---
// 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>
---
import MainLayout from '../layouts/MainLayout.astro';
---
<MainLayout title="Page Title">
<main>
<h1>Content here</h1>
</main>
</MainLayout>

Tailwind v4 uses CSS-first configuration:

src/styles/global.css
@import "tailwindcss";
@theme {
--color-primary: #3b82f6;
--color-secondary: #64748b;
}
<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>
Terminal window
# Start development server
pnpm dev
# Build for production
pnpm build
# Preview production build
pnpm preview

The frontend runs at http://localhost:4321 by default.

---
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>

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}
/>
---
// In layout or page
const { 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>
<script type="application/ld+json">
{JSON.stringify({
"@context": "https://schema.org",
"@type": "Product",
"name": product.title,
"description": product.description
})}
</script>

The frontend deploys to Cloudflare Pages:

Terminal window
# Deploy to staging
pnpm deploy-staging

Build output is in dist/ directory.