Starter templates

The Lifepeaks storefront starter is one production-shaped partner application with five Figma-composed, non-classic templates. The shared application owns API calls, server-only secrets, durable idempotency, webhook verification, and canonical order reconciliation. A template changes presentation without forking that security boundary. The classic compatibility template remains separate and untouched.

External standalone

The starter repository is currently private. Ask Lifepeaks for access, then clone it and run the generator from its repository root. Your API key, approved return origin, and webhook secret are issued separately during partner onboarding — the generator never creates them.

bash
git clone https://github.com/Lifepeaks/lifepeaks-storefront-starter.git
cd lifepeaks-storefront-starter
bun run create:storefront -- --template restaurant --out ../my-lifepeaks-storefront

cd ../my-lifepeaks-storefront
bun install
cp .env.example .env
chmod 0600 .env
# Fill .env with the credentials supplied by Lifepeaks.
bun run doctor
bun run check
bun run dev

Open the local URL printed by bun run dev. Replace restaurant with hotel, spa-wellness, retail, or experience to start with another vertical. The generated package also supports the non-watching local server bun run start.

Customization layers

The generator copies application code into the new repository. Customize it in layers:

  1. Edit storefront.manifest.json for brand, copy, locale, buyer guidance, and display choices. page.locations defines the visible location options and page.designs defines labels and images for visible designs. amountPresets are display suggestions only: positive whole numbers in the smallest unit of the currency, where 50000 is DKK 500.00.
  2. Replace project-local files in public/assets and update their /assets references in the manifest.
  3. Change the --lp-* custom properties in src/ui/tokens/tokens.css for global theme values.
  4. Edit the owned component copies under src/ui for structural or component-level changes. The starter already contains these copies, so users do not need access to the private component registry.

Generated projects contain owned copies and no component updater. Edit those files directly; they are yours. A separate Lifepeaks component registry exists for teams that want to pull refreshed components, and access to it is granted on request — note that installing over a component replaces your edits to it.

Server-authoritative commerce

Manifest values never become commerce authority. The Lifepeaks catalog supplies currency, amount limits, pricing type, quantity limits, and delivery methods. The current starter supports only DKK, requires variable pricing, sends every card by e-mail, and always submits quantity one even when the catalog maximum is higher. Those are limits of the starter, not of the API: the catalog publishes postal delivery and the order route accepts it. The server obtains the authoritative quote, refreshes it when inputs change or it expires, and refuses an expired quote. Checkout redirects to the Lifepeaks-hosted QuickPay page. Canonical order reads and signed, deduplicated webhooks remain authoritative after the browser returns.

Keep catalog, quote, checkout, order, and webhook calls in the reviewed server adapter. The manifest cannot change payable totals, fees, commission, merchant, callback, capture, idempotency, fulfillment, API-key, or webhook-secret policy.

Intentionally omitted UI

The five non-classic templates intentionally omit cart, quantity controls, add-ons, greeting fields, uploads, and alternate delivery methods. Every one of those has a public API contract already — see How the card is delivered and What a buyer can add to the card — so extending a starter is your own server validation, idempotency and tests against a contract that exists, not manifest-only controls and not a wait.

Production environment

The required runtime fields are LIFEPEAKS_API_BASE_URL (normally https://api.lifepeaks.dk), LIFEPEAKS_API_KEY, LIFEPEAKS_COMPANY_ID, and the HTTPS PARTNER_PUBLIC_URL.

Doctor readiness also requires LIFEPEAKS_APPROVED_RETURN_ORIGIN to equal the public URL, a current LIFEPEAKS_WEBHOOK_SECRET, and exactly these scopes:

text
catalog:read,quotes:create,orders:create,orders:read,checkout:create

LIFEPEAKS_WEBHOOK_SECRET is the current secret. LIFEPEAKS_WEBHOOK_PREVIOUS_SECRET is optional during rotation; keep both values only for the overlap window. Other optional fields are LIFEPEAKS_COMPANY_SLUG for an assigned agency tenant, PARTNER_DB_PATH (default ./var/storefront.sqlite), PARTNER_HOST (default 127.0.0.1), and PARTNER_PORT (default 4310). LIFEPEAKS_API_HOST_HEADER is local-only and must not be used with https://api.lifepeaks.dk. Production deployments need HTTPS, server-only secret storage, and durable storage for the database path.

Run bun run doctor after configuration changes. It checks required secrets and origins without printing their values. Run the starter's full check command before deployment:

bash
bun run check

Current templates

Every current template checks out the same product: gift_card_value, a variable-value gift card, and sends it by e-mail. The template does not create a new Lifepeaks product type. The API sells the company's experiences through the same quote and order routes, so adding experience lines to a starter is a change in your own code rather than a different integration — see Endpoints — Quote and order lines.

TemplateCustomer framingGuide
RestaurantDining gift valueRestaurant
HotelStay gift valueHotel
Spa & wellnessWellness gift valueSpa & wellness
RetailStore gift valueRetail
ExperienceExperience gift valueExperience

Capability boundaries

Event tickets and special offers are sold through the API, as the event_ticket and special_offer product families. No starter template presents them. Every template here sells gift value, so treat a ticket or an offer as work you build on top: read the families in Endpoints — The product catalog and price them with POST /v2/quotes like any other line. GET /v2/events remains a reporting route and is not a checkout contract.

Agency, marketplace, POS, and PMS models require Lifepeaks review because tenancy, liabilities, and payment responsibilities differ. Their availability is negotiated and entitlement-gated.

Non-Lifepeaks settlement is negotiated and entitlement-gated. POST /v2/orders/{order_id}/settle requires a dedicated scope plus an active commercial entitlement for the tenant, credential, and settlement mode; it is disabled by default. Do not design a public integration around it until Lifepeaks confirms the contract.

Physical delivery, inventory, booking, capacity, fixed packages, and ticket issuance are not implied by a template's copy or imagery. Integrate those concerns in your own system only when you have a separate source of truth and a documented Lifepeaks contract.

Production checklist

  • Use HTTPS for the storefront, return URL, and webhook endpoint.
  • Keep the Lifepeaks key and webhook secret in managed server-side secrets.
  • Persist operation keys, partner references, po_… IDs, and webhook event IDs in a transactional database.
  • Apply rate limits and request-size limits at the public partner edge.
  • Allow only your exact frontend origin to call partner checkout endpoints.
  • Log Lifepeaks resource IDs and idempotency keys, never credentials or recipient data.
  • Poll canonical order state on return and consume signed webhooks in the background.
  • Test successful, cancelled, failed, expired-session, lost-callback, and duplicate-delivery paths.

Continue with Headless checkout for the request sequence and Signed webhooks for the receiver contract.