Bella Vista
Fine-dining restaurant template with 3 switchable color themes and a gallery lightbox

About This Template
Bella Vista is a fine-dining restaurant template for trattorias, bistros, and chef-led kitchens. Eight routes cover the homepage, a full menu with four courses and sixteen dishes, a filterable photo gallery with lightbox, the story page, contact with a tabbed reservation form, a 404, and two live theme-preview routes. Three complete color themes — Classic burgundy, Coastal navy and terracotta, Urban charcoal and olive — swap through a single `theme` prop on the layout, with a dark mode on top. The hero runs a twenty-second Ken Burns loop under a three-stop gradient with staggered entrance animations. Built on Astro 5 and React 19 with CSS Modules and a full design-token system, no animation library required, and fifty-four real photos optimized to WebP via sharp.
Signature
The hero pairs a slow Ken Burns loop with a choreographed entrance. A 20-second infinite-alternate CSS keyframe scales the background photo from 1 to 1.1 while translating it -1% on both axes, so the image never sits still, all under a three-stop dark gradient (0.4 → 0.6 → 0.7 black) that keeps the type readable. On top, one fadeInUp keyframe cascades through the block: the content wrapper at 0.3s, the tagline at 0.5s, the Playfair headline with its Great Vibes accent line at 0.7s, the subtitle at 0.9s and the CTA pair at 1.1s — pure CSS, no animation library shipped to the browser.
Features
- 8 routes — Home, Menu, Gallery, About, Contact, 404, plus /demo/coastal and /demo/urban live theme previews
- 3 complete color themes switched by one `theme` prop — Classic burgundy #8B2635, Coastal terracotta #D4755E, Urban olive #6B8E4E
- Dark mode layered on top via data-mode="dark" — overrides backgrounds to #1A1A1A / #242424 without touching the theme
- Ken Burns hero — 20s infinite-alternate CSS keyframe scaling the background 1 → 1.1 under a three-stop dark gradient
- Full menu section — 4 courses (Antipasti, Pasta, Secondi, Dolci), 16 dishes with prices, photos and V/GF dietary badges
- Filterable gallery — 12 captioned images with All / Interior / Food / Team filters and a lightbox with wrap-around prev/next navigation
- Tabbed reservation + contact form with submitting and success states, auto-opening the reservation tab on the #reserve hash
- Sticky navigation that compacts after 50px, with a full-screen mobile overlay and body scroll lock while open
- Testimonials block with 5-star ratings and source attribution (Google, OpenTable, press)
- Location section with address, phone, email and an optional Google Maps embed that falls back to a static map image
- Opening-hours schedule rendered in both the footer and the contact page from plain day/time arrays you edit in place
- IntersectionObserver scroll reveals (.reveal / .reveal-left / .reveal-right) — no animation library, no extra JS weight
- CSS Modules per component with camelCase locals — 11 components, zero global class collisions
- Design-token system in custom properties — colors, 11-step type scale (xs → 7xl), spacing, radii, shadows, transitions and z-index
- 54 real photos in src/assets pre-optimized to WebP with getImage() and the sharp service at explicit dimensions
- Astro View Transitions, skip-to-content link, aria-expanded mobile toggle and TypeScript strict — zero any
Need a CMS?
Every template can be delivered as a WordPress, Sanity, or Emdash build — your content team edits copy and images without touching code. Tell us which one you need and we will quote the conversion.
Deployment
Tech Stack
Typography
Playfair Display (display headings) + Inter (body) + Great Vibes (script accent) — the high-contrast serif carries the fine-dining tone, Inter keeps menus and prices scannable, and the script sets the hero accent line and section flourishes
Color Palette
Three restaurant identities — Classic: cream #F5F1E8 over near-black #1A1A1A with burgundy #8B2635; Coastal: same cream over navy #1E3A5F with terracotta #D4755E; Urban: white #FFFFFF over charcoal #3A3A3A with olive #6B8E4E. Dark mode drops to #1A1A1A with #242424 cards