> ## Documentation Index
> Fetch the complete documentation index at: https://opencals.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# NOIR Drive — luxury car rental template

> Free, open-source luxury car rental website template. Next.js 15, multi-day booking by the day, delivery or garage collection, per-day extras, chauffeur packages, Stripe checkout and passwordless accounts, built on the Opencals Storefront API.

A complete luxury car-rental website you can clone and deploy today. NOIR Drive
is the first template built around **multi-day bookings**: each car is booked
**by the day**, from a pick-up date to a return date, and blocked for the whole
span. Start here if you rent cars, boats, equipment or villas by the day. It runs
on the same [Storefront API](/docs/api-reference/introduction) and typed
[TypeScript SDK](/docs/guides/storefront-sdk) as [Haar](/docs/open-source/haar),
[Frisor](/docs/open-source/frisor), [Clear Care](/docs/open-source/clarity) and
[VOLT](/docs/open-source/volt).

It's set in Dubai (AED, `Asia/Dubai`) with an all-black fleet of twelve cars.
Two booking surfaces sit over one store: a **multi-day rental flow** for the
fleet, and a classic **chauffeur flow** with real drivers.

<CardGroup cols={3}>
  <Card title="Live demo" icon="external-link" href="https://template-noir.vercel.app">
    template-noir.vercel.app
  </Card>

  <Card title="Source code" icon="github" href="https://github.com/letsopencals/template-noir">
    letsopencals/template-noir (MIT)
  </Card>

  <Card title="Deploy to Vercel" icon="rocket" href="https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fletsopencals%2Ftemplate-noir&env=OPENCALS_API_KEY,AUTH_SECRET&envDescription=API%20key%20from%20your%20Opencals%20dashboard%20and%20a%20random%20secret%20for%20auth&project-name=noir-drive&repository-name=template-noir">
    One-click deploy
  </Card>
</CardGroup>

<Frame caption="NOIR Drive — the storefront on desktop, set in Dubai">
  <img src="https://raw.githubusercontent.com/letsopencals/template-noir/main/docs/cover.png" alt="NOIR Drive luxury car rental website template shown on a laptop in front of a black fleet in Dubai" />
</Frame>

<Frame caption="Homepage hero — cinematic, all-black, with Book a car up front">
  <img src="https://raw.githubusercontent.com/letsopencals/template-noir/main/docs/homepage-hero.png" alt="NOIR Drive template homepage hero reading Drive the night over a showroom of black cars" />
</Frame>

## Multi-day booking

Customers pick a car, choose pick-up and return dates on a range calendar that
reads the car's live availability, then choose *Deliver to my address* or
*Collect at the garage* and a handover window. Per-day extras (excess waiver,
additional driver) are priced × days, and fixed extras (child seat, prepaid
fuel) once. Driving licence and ID uploads and a deposit-and-terms checkbox are
regular checkout questions. The total is always **days × daily rate + extras**,
the same maths the engine charges.

<Frame caption="Book a car — range calendar on live availability, handover windows and a running total">
  <img src="https://raw.githubusercontent.com/letsopencals/template-noir/main/docs/book-a-car.png" alt="NOIR Drive template booking flow with a two-month range calendar, handover windows, delivery or garage choice and a rental summary" />
</Frame>

## The rental model

This is the part worth copying even if you never ship NOIR Drive itself. It
uses existing Opencals features only.

| Piece | How it's modelled |
| - | - |
| A car | One staffless product in its own product pool (so a booking blocks it at both locations), `duration: 86400`, `allowCustomDuration: true`, `maxDuration`, `maxAttendees: 1` |
| Availability across midnight | A continuous 24/7 schedule. Bookings longer than 24 hours are validated against continuous availability |
| Date picker | `getCurrentAvailabilitiesMerged` **without** `duration`; the client checks that pick-up → return fits inside one range |
| The slot | Pick-up date 00:00 → return date 00:00 in the store timezone, sent in UTC |
| Handover window, flight number, collection address | Appointment [custom attributes](/docs/changelog/custom-attributes) |
| Delivery or collection | A `PHYSICAL` garage location and a `DELIVERY` location; the customer's address is captured at checkout |
| Per-day extras | Add-ons with `durationMultiplied` |
| Security deposit | Shown per car and accepted with a required checkbox question; taken at handover, never charged online |

Dubai pick-up 10 Nov → return 13 Nov becomes
`{ fromDate: '2026-11-09', fromTime: '20:00:00', toDate: '2026-11-12', toTime: '20:00:00' }`:
three days, three units, three × the daily rate.

Give each car its own product rather than a variant: variants don't block each
other, so the same car could be booked twice.

## What's inside

<Frame caption="Car page — specs and the daily rate, with a jump to the availability calendar">
  <img src="https://raw.githubusercontent.com/letsopencals/template-noir/main/docs/car-page.png" alt="NOIR Drive template car page for a Rolls-Royce Cullinan priced per day" />
</Frame>

<Frame caption="Rates — one price per day, with deposit and km allowance for every car">
  <img src="https://raw.githubusercontent.com/letsopencals/template-noir/main/docs/rates.png" alt="NOIR Drive template rates table listing daily rate, deposit and kilometres per day for each car" />
</Frame>

<Frame caption="Chauffeur — packages booked through the classic staff flow">
  <img src="https://raw.githubusercontent.com/letsopencals/template-noir/main/docs/chauffeur.png" alt="NOIR Drive template chauffeur page offering airport transfers, hourly and full-day packages" />
</Frame>

| Feature | Notes |
| - | - |
| Fleet and car pages | Category filters from collections, "available for your dates", a two-month availability calendar with booked days struck through |
| Rates | A full rates table (daily rate, deposit, km per day) |
| Multi-day booking | Range calendar, delivery or garage, handover windows, per-day and fixed extras, checkout questions |
| Chauffeur | Packages booked through the classic staff flow, with a preferred-car request |
| Cart & Stripe checkout | Cart + Checkout + Payment endpoints |
| Rental-aware accounts | Pick-up → return dates in the store timezone, day count, handover details; customers can change dates (same length) or cancel within policy |
| Passwordless accounts | 6-digit email login (password fallback), one-time email links via `/link/[token]` |
| Motion | Lenis smooth scrolling, text and image reveals, parallax, count-up specs; every effect has a reduced-motion fallback |
| SEO | Per-page metadata, Open Graph, `AutoRental` and `Product` structured data, `robots.txt`, `sitemap.xml` |
| Stack | Next.js 15, TypeScript, Tailwind v4, Framer Motion, `@opencals/storefront-sdk` v0.3.14 |

## Get started

<Steps>
  <Step title="Clone and install">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark-default"}}
    git clone https://github.com/letsopencals/template-noir.git
    cd template-noir
    npm install
    ```
  </Step>

  <Step title="Add your API key">
    Create a store in the [Opencals dashboard](https://opencals.com) and choose
    the **NOIR Drive** dataset preset (category Car rental). It seeds the
    fleet on a 24/7 schedule, the garage and delivery locations, extras,
    checkout questions, chauffeurs and packages. Then grab a Storefront API key
    (see [Authentication](/docs/authentication)) and set `OPENCALS_API_KEY` and
    `AUTH_SECRET` in `.env`.
  </Step>

  <Step title="Run it">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark-default"}}
    npm run dev
    ```

    Your cars, rates and availability render immediately.
  </Step>

  <Step title="Deploy">
    Push to your own repo and
    [deploy to Vercel](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fletsopencals%2Ftemplate-noir\&env=OPENCALS_API_KEY,AUTH_SECRET\&envDescription=API%20key%20from%20your%20Opencals%20dashboard%20and%20a%20random%20secret%20for%20auth\&project-name=noir-drive\&repository-name=template-noir),
    or host anywhere Next.js runs.
  </Step>
</Steps>

<Note>
  Set **Storefront Base URL** in your dashboard (Settings → API) to your
  deployed domain. Every customer link (view, reschedule, cancel, leave
  feedback) is built as `{storefrontBaseUrl}/link/{token}`, so if it still
  points at localhost those emailed links go nowhere.
</Note>

## Make it yours

MIT-licensed: rebrand it, restructure it, or use it for client work. All
business copy lives in `lib/site-config.ts`: name, currency and timezone,
per-car specs and deposits, handover windows, delivery zones, FAQs and contact
details. Every colour and font is a Tailwind v4 `@theme` token in
`app/globals.css`:

```css theme={"theme":{"light":"github-light","dark":"github-dark-default"}}
@theme {
  --color-bg: #050505;          /* page black */
  --color-ink: #F4F1EA;         /* warm ivory text */
  --color-primary: #C8A96B;     /* champagne accent */
}
```

Building a different rental site with an AI agent? The
[build-booking-site skill](/docs/ai-agents/build-booking-site-skill) has a
`rentals-multi-day` reference with the full pattern.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.