---
name: build-lodera-booking-genesis
description: "Adapt, brand, validate, publish, and deploy the Lodera accommodation-booking Genesis reference for a connected Selldone shop. Use when building a Lodera-style lodging search, property detail, booking flow, or optional partner/vendor panel from the official static Genesis starter, then publishing it to the merchant's GitHub repository and deploying it through GitHub-connected Cloudflare Workers Builds on a custom domain."
---

# Build Lodera Booking Genesis

Build a truthful, production-ready Lodera storefront for one connected Selldone shop. Keep Selldone as the business backend, the browser app static, and every live feature traceable to a documented Selldone contract.

## Use these sources and boundaries

- Use `https://github.com/pajuhaan/selldone-custom-storefront-backoffice-1` as the official code starter and upstream remote.
- Use `https://booking.selldone.shop/` as the public Lodera experience reference and `https://booking.selldone.shop/vendor/` as the partner-panel reference. Treat them as design and interaction inspiration, not as an API specification or a source of merchant data/assets.
- Prefer the latest connected Selldone MCP resources and `https://github.com/selldone/storefront-sdk/tree/main/ai-guideline` when they conflict with this skill or the reference UI.
- Keep this skill self-contained. Do not assume companion files were included with the download.
- Never reuse sample shop handles, IDs, OAuth clients, domains, Worker names, listing IDs, copy, or images from the starter or live reference.

## Establish context and approvals

1. Confirm the intended shop, business model, brand, locales/currencies, required booking features, whether a partner panel is needed, destination GitHub owner/repository/visibility, production branch, Cloudflare account, and custom domain.
2. Verify the Selldone MCP connection with a read-only connection call. If disconnected, ask the user to connect `https://selldone.com/mcp/connector`, authorize in the browser, choose the shop and least-required scopes, and retry.
3. Never ask for an MCP bearer token, GitHub token, Cloudflare token, API key, refresh token, client secret, manual `shop_id`, or other credential in chat. Use the user's authenticated connector, app, or CLI session.
4. Read `selldone://guidelines/storefront-agent`, invoke `selldone_storefront_builder`, and call `selldone_storefront_plan` for an accommodation/listing business when available. Inspect the current public AI guideline before choosing endpoints or payloads.
5. Present the feature/API map and implementation stages before editing. Obtain approval for the proposed scope.
6. Proceed with read-only discovery and local implementation inside the approved scope. Obtain a fresh, explicit approval immediately before each external mutation group: creating a GitHub repository, pushing a branch, creating/connecting a Cloudflare project, deploying production, changing DNS/custom domains, or creating/updating a Selldone OAuth client or shop setting. State the exact account, repository, branch, project, and domain affected.

Do not interpret approval for local code changes as approval for external mutations. Never create charges, real reservations, refunds, messages, or production test data without separate authorization.

## Keep the product honest

Create a capability matrix with four states before implementing:

- **Live:** backed by an inspected, documented endpoint for this connected shop.
- **Derived:** calculated only from documented live fields; label assumptions and keep backend totals authoritative.
- **Demo:** suitable for an explicitly marked prototype only; never present as persisted or operational.
- **Blocked/omitted:** no verified contract, permission model, or required shop capability exists.

The public Lodera reference demonstrates generated rooms/rates, occupancy behavior, reservations, partner notifications, finance, analytics, and placeholder panel pages. Do not copy those assumptions into production. Replace each with a verified contract, visibly label it as demo, or remove it. If real availability, inventory, reservation, or payment contracts cannot be verified, ship a truthful listing/search or inquiry experience—not a fake booking checkout.

## Follow the Lodera blueprint

### Visual system

- Use Inter at weights 400, 500, and 700. Use a compact 14px body scale, clear 20–24px page headings, and tabular numerals for prices, scores, dates, and dashboard figures.
- Centralize tokens. Start with black `#111111` for primary bars and score badges, amber `#ffb700` for primary CTA backgrounds/search borders/stars, dark gold `#7a5600` for accessible links on white, text `#1a1a1a`, secondary text `#595959`, white surfaces, alternate surface `#f5f5f5`, and border `#e7e7e7`. Put near-black text—not white—on amber actions.
- Use a 4/8/12/16/20/24/32/40px spacing rhythm, 4px control radii, 8px card radii, restrained shadows, and a centered content width near 1110px. Keep the partner panel denser, with a cool-gray page field and white data cards.
- Build mobile-first at 375, 768, 1024, and 1440px. Preserve keyboard access, visible focus, semantic labels, useful alt text, reduced-motion behavior, and readable contrast.
- Keep one responsive design language. Do not clone Booking.com markup/assets or hotlink reference listing images.

### Guest storefront

- Provide a slim Selldone attribution strip, Lodera brand header, language/currency controls, customer account state, and a prominent search pill for destination, check-in/out dates, adults, children/ages, rooms, and pets. Only let fields influence results when the backend supports them; otherwise explain or omit them.
- Build search results with honest loading, empty, stale, error, and retry states; responsive 1/2/3/4-column property cards; image, location, official star class, guest score out of 10, review count, room/rate summary, and backend-derived price.
- Add documented filters such as budget, room/property type, amenities, review score, and star class; sorting; result count; and an accessible list/map switch. Use a map only when valid coordinates exist and provide a non-map alternative.
- Build property detail with gallery, title/location, classification and guest score, map action, overview, facilities, availability/rate choices, house rules/policies, reviews, FAQ, and a single reserve/inquiry CTA. Hide empty sections instead of inventing content.
- Build checkout only after verifying availability, price, reservation, basket/order type, payment, and confirmation contracts. Keep the server bill authoritative, show full totals and cancellation terms, prevent duplicate submission, and recover pending/error states.
- Implement customer login only when needed, using public-client OAuth Authorization Code with PKCE. Provide callback, signed-in account/order views, and logout from documented contracts.

### Partner/vendor panel

- Include `/vendor/` only when the shop's permission model and backoffice endpoints are verified. Otherwise omit it or mark a non-production prototype unambiguously.
- Use a black top bar with Lodera mark and “for partners,” property switcher, operational search, notifications, inbox, and account menu only where backed by real data.
- Organize verified modules under Home, Rates & Availability, Reservations, Property, Finance, Analytics, Guest reviews, Inbox, and Opportunities. Hide unsupported modules; do not populate them with deterministic demo metrics.
- Make Home operational: action notices, current reservation counts/statuses, availability/rate warnings, review tasks, and performance cards only from authorized data. Use compact tables, status pills, empty/error states, and no decorative motion.
- Enforce vendor/shop ownership on every call. Never rely on a hidden route or client-side check as authorization.

## Preserve the static Genesis architecture

Clone and inspect before editing:

```bash
git clone https://github.com/pajuhaan/selldone-custom-storefront-backoffice-1.git lodera-genesis
cd lodera-genesis
npm ci
```

Read `AGENT.md`, `README.md`, `package.json`, `wrangler.toml`, `.env.example`, relevant `docs/`, and the build scripts. Inspect `git status` and preserve user changes.

- Keep public source under `storefront/`, OAuth callback under `callback/`, shared browser modules under `shared/`, and the partner surface under `vendor/` when enabled. If retaining the starter's `dashboard/`, make its purpose and URL explicit; do not expose two accidental admin surfaces.
- Update `scripts/build-static.mjs` so every retained surface is copied to `dist/`. Keep `scripts/dev-static.mjs` development-only.
- Deploy only `dist/` as Cloudflare Workers Static Assets. Do not add a production Node server or commit `dist/`.
- Put only browser-safe runtime configuration in HTML meta tags or public config: shop handle/ID, public OAuth client ID, public host bases, locale/currency, and route paths.
- Remove all starter merchant identifiers and stale branding. Keep central modules for runtime config, URL construction, XAPI requests, OAuth PKCE, money, dates, images, errors, and token storage.
- Preserve clean production routes and deep-link fallback. Remove “demo” and “component inventory” language from production titles, URLs, metadata, and visible copy.

Implement in this order: configuration and API inventory; shared client/state; shell/routing/states; search/results; property detail; verified reservation/checkout; customer auth/account; verified partner panel; accessibility/responsive polish; deployment.

## Enforce Selldone security boundaries

- Use MCP for agent-time planning, shop inspection, and explicitly approved administrative mutations. Never call MCP from storefront JavaScript or ship MCP credentials.
- Use `https://xapi.selldone.com` for public/customer storefront runtime calls. Resolve every method, path, parameter, payload, auth mode, and response from current Selldone documentation; never infer an endpoint from the Lodera UI.
- Use `https://api.selldone.com` only for authenticated backoffice/dashboard/vendor contracts. Never call it from anonymous storefront flows.
- Use `https://selldone.com/oauth` for public-client PKCE with `S256`, `state`, an exact HTTPS `redirect_uri`, least-required scopes, and no client secret. Keep customer and vendor/dashboard token stores separate.
- Treat XAPI as public. Never select, request, serialize, log, or expose `private_attributes` or `ai_agent`; expose `public_attributes` only when returned by the documented public contract. Never add a client-side `makeVisible`/hide-after-fetch workaround.
- Do not invent listing availability, occupancy, room inventory, pricing, reservation, vendor ownership, or payment fields. Record documentation gaps and block dependent UI.
- Never store access/refresh tokens in source, HTML, build output, analytics, URLs, screenshots, or logs. Avoid logging authorization headers and personal booking data.
- Do not proxy privileged APIs through a static Worker. Add server-side behavior only through an approved architecture and threat review.

## Create and maintain the destination repository safely

Create an empty destination repository only after the user approves its exact owner, name, and visibility. Do not initialize it with a README, license, or `.gitignore`. Then preserve the reference as `upstream`:

```bash
git remote rename origin upstream
git remote add origin https://github.com/<owner>/<destination>.git
git fetch --all --prune
git remote -v
git status --short --branch
```

Run `git ls-remote origin` before the first push. If the destination is empty, show the tested diff/commit and obtain push approval, then run:

```bash
git push -u origin HEAD:main
```

If it is not empty, fetch and inspect its history. Never overwrite it, force-push, or join unrelated histories without a reviewed migration plan. Push work to a new branch and use a pull request.

For later reference updates, never run a blind `git pull`. Require a clean worktree, fetch `upstream`, create a sync branch, merge there, resolve deliberately, rebuild, and review before pushing:

```bash
git status --porcelain
git fetch upstream
git switch -c chore/sync-upstream-YYYYMMDD
git merge --no-ff --no-commit upstream/main
```

Abort the merge if it would erase merchant work or reintroduce sample configuration. Never force-push. Keep upstream changes separate from business customization when practical.

## Build and validate

Use the lockfile and supported scripts:

```bash
npm ci
npm run build:static
npm run preview:static
git diff --check
git status --short
```

Use `npm install` only when the lockfile is absent or intentionally updated. Verify `dist/index.html`, `dist/callback/index.html`, `dist/shared/`, and `dist/vendor/index.html` when the panel is enabled. Confirm `dist/` remains ignored.

Test root, search, filters, sort, map/list, property deep links, reservation/inquiry, callback, account/logout, and vendor authorization in a real browser at mobile/tablet/desktop widths. Check keyboard flow, focus, reduced motion, loading/empty/error states, console/network failures, CORS, duplicate submissions, and SPA fallback. Audit every request against the API map.

Search source and `dist/` for secrets and stale sample values without printing any discovered credential value. Check at minimum `.env`, auth headers, token-like strings, localhost URLs, starter domains/Worker names/client IDs, old shop handles/IDs, placeholder APIs, generated demo records, and reference-only copy/images. Stop and notify the user with file paths—not secret contents—if a real credential is found.

## Deploy through GitHub-connected Cloudflare Workers Builds

After push approval and a successful build, request approval to create or connect the exact Cloudflare project. Use a unique, DNS-safe Worker name and keep `wrangler.toml` configured for static assets:

```toml
[assets]
directory = "./dist/"
not_found_handling = "single-page-application"
html_handling = "auto-trailing-slash"
```

Connect the approved GitHub repository and production branch in Workers Builds. Configure:

- Root directory: `/`
- Build command: `npm run build:static`
- Deploy command: `npx wrangler deploy`
- Non-production branch command: `npx wrangler versions upload`
- Automatic production builds: enabled for the approved branch

Do not place Cloudflare API tokens in the repository or public build variables. Verify the selected Cloudflare account, repository access, build logs, deployed commit SHA, Worker URL, asset paths, and preview behavior.

Before adding the custom domain, confirm the exact hostname, Cloudflare zone, existing DNS records, TLS state, and whether the hostname may be repointed. Obtain explicit DNS/domain approval, attach the hostname to the Worker, wait for an active certificate, and verify HTTP-to-HTTPS behavior. Do not delete or replace a conflicting record without separate approval.

If OAuth is enabled, obtain explicit approval to register the exact `https://<domain>/callback/` URI on the shop's public client. Then smoke-test root, deep links, assets, XAPI CORS, customer PKCE, token separation, logout, vendor access control, and one non-charging reservation/inquiry path. Keep a rollback path through the previous known-good Worker version or a reviewed Git revert.

Finish only when the live commit and domain are identified, all enabled capabilities use real connected-shop contracts, unsupported reference features are omitted or labeled, no secrets/sample merchant data remain, automatic GitHub builds work, and the user receives the validation and rollback summary.
