Skip to content

Latest commit

 

History

551 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Azur Menton

CI Next.js React TypeScript Tailwind CSS

Azur Menton is a multilingual direct-booking site for three central Menton apartments. The public surface combines apartment pages, a practical local guide, Riviera events, stay-planning pages, a useful-places map, and a manual booking funnel.

View the live site · Check availability · Explore the Menton guide

Azur Menton apartment terrace

Product at a glance

  • Direct booking: read-only availability guidance followed by a personally confirmed request.
  • Three distinct stays: two sea-view studios and one larger terrace apartment with parking.
  • Four languages: English, French, Italian, and Ukrainian routes with canonical and hreflang metadata.
  • Local utility: 90 maintained guides, 532 mapped places, Riviera events, weather, marine conditions, transport, and travel tools.
  • Privacy-first operations: server-only calendar feeds, non-PII analytics, Turnstile, rate limiting, and nonce-based CSP.

Read first for a fresh coding session:

  1. README.md
  2. AGENTS.md
  3. docs/product-context.md
  4. docs/content-operations.md
  5. task-specific docs only

What matters

  • Booking is manual. The site never promises instant confirmation.
  • Availability previews are read-only planning guidance from external iCal feeds.
  • Guide, stay and event content exist to support direct booking intent, not compete with it.
  • Content is typed in-repo; there is no CMS.

Product and claim boundaries live in:

Current operating phase

Azur Menton is currently in normal guide-first publishing and observation mode:

  • guide corpus remains the primary product surface for booking intent;
  • event freshness observatory exists and remains review-first;
  • guide freshness / provenance / verification loops exist as editorial maintenance signals;
  • booking attribution baseline is recorded as an observation layer, not a fully automated growth engine;
  • routine publication and image attachment now have bounded operational playbooks;
  • City Engine and broader automation remain intentionally out of scope.

Stack

  • Next.js 16 App Router
  • React 19
  • strict TypeScript
  • Tailwind CSS 4
  • Vitest + optional Playwright
  • Resend for booking-request email delivery
  • Cloudflare Turnstile, honeypot, rate limiting, CSP
  • Plausible + Vercel Analytics
  • Sharp-based image derivative pipeline

Local development

Requirements: Node.js 20.9+ (Node.js 22 is used in CI).

npm ci
npm run dev

Open http://localhost:3000. Root redirects to /en.

Core commands

Daily engineering checks:

npm run lint
npm run typecheck
npm test
npm run build

Content and SEO checks:

npm run preflight
npm run content:report
npm run events:ingest
npm run events:prepare -- --latest
npm run events:publish -- --batch <batch-id> --all --dry-run
npm run events:assets -- --published-events --assets-dir /absolute/path/to/assets --missing-only --apply
npm run events:review
npm run seo:priorities

Event publication keeps owner-approved images local and can attach related guides/places through relatedGuideSlugs and relatedPlaceIds; missing event images should stay visible until an owner asset pack is applied.

Additional checks when relevant:

npm run content:audit
npm run images:check
npm run seo:validate
npm run test:e2e
npm run preflight:postbuild

Environment

Use .env.local from .env.example when needed.

Key variables:

NEXT_PUBLIC_SITE_URL=https://azurmenton.com

NEXT_PUBLIC_PLAUSIBLE_DOMAIN=
NEXT_PUBLIC_PLAUSIBLE_API_HOST=
NEXT_PUBLIC_PLAUSIBLE_SCRIPT_SRC=

NEXT_PUBLIC_TURNSTILE_SITE_KEY=
TURNSTILE_SECRET_KEY=

RESEND_API_KEY=
BOOKING_REQUEST_TO_EMAIL=
BOOKING_REQUEST_FROM_EMAIL=
BOOKING_REQUEST_BCC_EMAIL=

WEATHER_PROVIDER=open-meteo
WEATHER_LATITUDE=43.7745
WEATHER_LONGITUDE=7.4975

EVENT_INGEST_SECRET=
CRON_SECRET=

AZUR_ICAL_SEA_VIEW_BALCONY_STUDIO=
AZUR_ICAL_TERRACE_PARKING_APARTMENT=
AZUR_ICAL_PANORAMIC_SEA_VIEW_STUDIO=

Important:

  • never commit real iCal URLs;
  • never expose iCal URLs client-side;
  • keep Plausible Stats API keys local-only;
  • never hotlink third-party event posters; use event image queues and owner-approved asset packs;
  • do not commit .env.local.

Main route families

Supported locales: en, fr, it, uk.

  • /[locale]
  • /[locale]/apartments
  • /[locale]/apartments/[slug]
  • /[locale]/check-availability
  • /[locale]/guide
  • /[locale]/guide/[slug]
  • /[locale]/stay
  • /[locale]/stay/[slug]
  • /[locale]/events
  • /[locale]/events/[slug]
  • /[locale]/events/this-week
  • /[locale]/map
  • /[locale]/partners
  • /[locale]/faq
  • /[locale]/contact
  • /llms.txt

Key subsystems

Booking and availability

  • Manual request flow: src/components/booking/, src/app/actions/booking-request.ts, src/app/api/booking-request/route.ts
  • Read-only availability layer: src/lib/availability/, src/components/availability/, src/app/api/availability/

Current booking UX includes:

  • availability hub on /[locale]/check-availability;
  • nearest available stay windows;
  • selected-stay prefill into the request form;
  • repeated server-side date validation before submit;
  • compact availability previews on apartment detail pages;
  • compact next-availability hints on the apartment listing page.

Do not expose provider URLs, booking titles, guest names, summaries, or booking notes.

Apartments

Source of truth: src/content/apartments.ts

Current slugs:

  • sea-view-balcony-studio
  • beachside-family-apartment
  • panoramic-sea-view-studio

Guide, places and map

Main content files:

  • src/content/guide.ts
  • src/content/guide-intents.ts
  • src/content/places.ts
  • src/content/stay-pages.ts

Main UI:

  • src/app/[locale]/guide/page.tsx
  • src/components/guide/
  • src/components/places/UsefulPlacesMap.tsx
  • src/components/tools/TravelTools.tsx
  • src/components/tools/RadioConsole.tsx
  • src/components/guide/utility/AirportLiveBoard.tsx

The guide portal is not a plain article list. It includes editorial selections, planning clusters, finder/search entry points, compact catalogues, map previews and apartment-aware recommendations.

Travel Tools

The Travel Tools hub at /[locale]/tools is a compact planning surface, not a second editorial section. Its current order is:

  1. live weather and marine context;
  2. world clocks and euro reference rates;
  3. transport routes, airport-board links/embeds and the local radio console;
  4. emergency numbers and official safety links.

The detailed /[locale]/tools/weather and /[locale]/tools/sea pages carry the expanded forecast and marine views. The radio console is hub-only and uses stations with direct audioStreamUrl values. Radio guide cards remain the detailed station reference; stations that only expose a web player remain website links rather than being presented as native streams.

Airport boards are either embedded or presented through official external links according to the provider. Embedded providers can show their own cookie or consent UI inside a cross-origin iframe; Azur Menton cannot style or dismiss that provider-owned surface.

Events

Main files:

  • src/content/riviera-events.ts
  • src/content/event-sources.ts
  • src/content/event-occurrences.ts
  • src/components/events/EventsCalendar.tsx
  • src/lib/event-discovery.ts

Events use a pragmatic annual-series model with confirmed, pending and estimated states. The /[locale]/events page is a curated discovery surface with shareable filters for quick periods, custom stay dates, locations and interests. Keep stale annual events archived for future refresh; do not invent dates.

Automated event ingestion is intentionally only a foundation for now: source registry, adapter contracts, deterministic dedupe and review-first candidates. Do not add fragile broad scraping or publish unverified events as live listings.

The publication workflow is repository-based and explicit:

npm run events:ingest
npm run events:prepare -- --latest
npm run events:publish -- --batch <batch-id> --all --dry-run
npm run events:publish -- --batch <batch-id> --all

Preparation never publishes. Publication requires --all, --city <city> or --ids <id,id>; otherwise it prints a safe no-write summary. Menton uses a broad local usefulness threshold, while Monaco, Nice, Ventimiglia and Sanremo require destination-worthy value from a Menton base.

Post-publish event images use the owner-approved asset path:

npm run events:assets -- --published-events --assets-dir /absolute/path/to/assets --missing-only --apply --fail-on-unmatched

This writes local WebP event covers, updates published media records and locks owner decisions in src/content/events/overrides/image-overrides.json. The event asset pipeline normalizes covers to a consistent 1200x720 crop so event cards keep equal image height.

Guide automation

The guide workflow is now partially automated and remains review-first:

npm run guide:new
npm run guide:check
npm run guide:assets
npm run guide:apply
npm run guide:publish
npm run guide:patch
npm run guide:review

Detailed usage:

This pipeline prepares and validates guide/place/link/image work. It does not blindly auto-publish.

For image work after a guide is already live, use the post-publish path:

npm run guide:assets -- --published-guide <guide-slug> --assets-dir /absolute/path/to/assets --missing-only --report-only

Add --fail-on-unmatched when the asset package must be fully reconciled before sign-off.

In post-publish mode the script now writes two reports:

  • transient full report in build/guide-assets-postpublish/
  • small git-tracked summary in reports/guide-assets-postpublish/

SEO, analytics and structured data

Main files:

  • src/lib/seo.ts
  • src/lib/structured-data.ts
  • src/lib/analytics.ts

The site emits:

  • localized metadata;
  • canonical + hreflang links;
  • sitemap and robots;
  • JSON-LD for lodging, vacation rental, article, FAQ, breadcrumb and related page types.

Keep analytics non-PII. Funnel events are for attribution and drop-off analysis, not guest profiling.

Useful docs:

Security and performance

Main files:

  • next.config.ts
  • src/proxy.ts
  • src/lib/security-headers.ts

Notes:

  • CSP is nonce-based and intentionally keeps App Router responses dynamic.
  • npm run preflight:postbuild runs the current CSP/cache audit.
  • next/image plus generated derivatives are the default media path.

See:

Repo layout

src/app/            App Router pages and API routes
src/components/     UI and feature components
src/content/        Typed site content
src/i18n/           Locale definitions
src/lib/            Booking, SEO, analytics, availability, security helpers
public/images/      Local media assets
scripts/            Validation, reporting and automation scripts
tests/              Unit and E2E tests
docs/               Operational docs

Operational rules

  • English is the editorial source language.
  • Keep FR/IT/UK natural; do not leave placeholder translations.
  • Do not invent dates, prices, ratings, opening hours or official rules.
  • Keep partner/perk content separate from core booking paths.
  • Prefer structured content updates over hardcoded page copy.
  • Use the docs before making content, SEO or booking-flow changes.

Contributing and license

Focused fixes and source-backed content corrections are welcome. Read CONTRIBUTING.md and report vulnerabilities through SECURITY.md.

Release notes are maintained in CHANGELOG.md.

Application code, tests, scripts, and technical documentation are available under the MIT license. Apartment content, editorial material, media, guest data, and Azur Menton branding are excluded unless stated otherwise; see NOTICE.md.

Primary docs

ABVX ecosystem

  • AGENTS.md_generator — Keeps repository guidance and machine-readable context current. Current release: v0.5.1.
  • abvx-shortener — Uses stable short links for public campaigns and QR destinations. Current release: v0.4.0.
  • abvx-agent-skills — Uses shared, reviewable agent capabilities during maintenance. Current release: v0.15.0.

This block is generated from the reviewed ABVX ecosystem registry.

About

Multilingual direct-booking platform for three Menton beachfront/beachside apartments, with localized stay guides, Riviera events, weather, map-based trip planning, and a secure booking request flow (EN/FR/IT/UK)

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages