@orderlyshop/web-components 0.1.0-build.7061 → 0.1.0-build.7066

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  Use this package as a headless storefront component library. Prefer native custom elements, light-DOM templates, and normal CSS over framework-specific wrappers unless the user asks for a framework integration.
4
4
 
5
+ ## Agent Operating Contract
6
+
7
+ - These instructions are optimized for GPT-5.5-class coding agents and other modern LLMs. Work from the user's requested storefront outcome, choose the package-owned component or CLI that owns that outcome, and keep edits scoped to that path.
8
+ - Read stable package context before shop-specific files: `README.md`, `DESIGN.md`, component docs, then `custom-elements.json` or `html-custom-data.json` for exact API names. Inspect the consuming shop after that.
9
+ - Prefer package configuration, typed properties, declarative templates, semantic tokens, and package CLI tools over copying component internals into a shop.
10
+ - Do not infer attribute names, event names, template slots, or CSS hooks from memory. Use the docs and metadata in this package as the source of truth.
11
+ - Stop when the requested behavior is implemented and verified with the nearest relevant script. If validation needs data, account ids, credentials, or a running backend, report the exact missing prerequisite.
12
+
5
13
  ## Discovery
6
14
 
7
15
  - Read `README.md` for setup and package-wide concepts.
@@ -13,6 +21,14 @@ Use this package as a headless storefront component library. Prefer native custo
13
21
  - Inspect `examples/shop` for a complete vanilla TypeScript shop that customizes the defaults without replacing package logic.
14
22
  - When creating a new shop from scratch, run `npx orderly-init-shop` first. It scaffolds the vanilla HTML/TypeScript/Vite structure that the package expects, including `src/includes/head.html`, `src/navigation.ts`, `src/shop-query.ts`, page templates, and package scripts.
15
23
 
24
+ ## New Shop Intake
25
+
26
+ - Ask the user for the Orderly account id so `src/shop-query.ts` can tenant-scope the default `SearchQuery`.
27
+ - Ask the user for a reference website URL for the desired visual style. If they do not have one, ask for a short description of the target look.
28
+ - Use the reference website as design direction only: extract palette, density, radius, typography feel, spacing, and navigation patterns into semantic Orderly tokens and shop CSS. Do not copy proprietary assets, text, logos, or brand marks unless the user confirms they own or may use them.
29
+ - Put the resulting theme in `src/style.css` or the consuming shop stylesheet, starting with `DESIGN.md` tokens before adding component-specific selectors.
30
+ - After scaffolding, run the nearest local dev/build command and visually compare the shop against the requested reference at desktop and mobile widths when a browser is available.
31
+
16
32
  ## Query Rules
17
33
 
18
34
  - Use `configureShop({ defaultShop: { defaultQuery } })` for shop-wide query scope. `defaultQuery` is a full Core `SearchQuery`.
package/README.md CHANGED
@@ -4,6 +4,54 @@ Headless native web components for Orderly storefronts.
4
4
 
5
5
  The package depends on `@orderlyshop/core-client` and wraps Core contracts such as `SearchObject`, `SearchQuery`, and `DraftOrder` in reusable browser components. Components render practical light-DOM defaults and expose typed properties, events, controllers, stores, and template overrides so host shops keep full control over CSS, layout, routing, and copy.
6
6
 
7
+ ## Agent Prompt Template
8
+
9
+ Copy this prompt into a coding agent when you want it to install the package and build a finished Orderly shop. Fill in known values first; if a value is filled in and is not `ASK`, the agent should use it without asking again.
10
+
11
+ ```text
12
+ Build a production-ready Orderly storefront with @orderlyshop/web-components.
13
+
14
+ Inputs:
15
+ - Project directory: ASK
16
+ - Shop name: ASK
17
+ - Orderly account id: ASK
18
+ - Visual style reference: ASK
19
+ - Deployment target: ASK
20
+
21
+ Use any provided input above without asking again. Ask only for values that are still `ASK`.
22
+
23
+ Install and setup:
24
+ 1. Install @orderlyshop/core-client and @orderlyshop/web-components if they are not already installed.
25
+ 2. Read node_modules/@orderlyshop/web-components/AGENTS.md, DESIGN.md, README.md, and docs/components/README.md before changing shop files.
26
+ 3. Run npx orderly-init-shop for a new shop. Pass --account-id when the Orderly account id is provided. Preserve existing files unless I explicitly approve overwrite.
27
+
28
+ Navigation:
29
+ 4. Use the Orderly account id to tenant-scope src/shop-query.ts.
30
+ 5. Run npx orderly-init-navigation --suggest --account-id <account-id> when product sampling is possible.
31
+ 6. Build src/navigation.ts manually from navigation-products.json with at most two category levels, stable unique slugs, and plain SearchQueryInput objects.
32
+
33
+ Visual style:
34
+ 7. Use the visual style reference as design direction for palette, radius, spacing, density, typography feel, product tiles, navigation, checkout, and page rhythm.
35
+ 8. Start src/style.css from DESIGN.md semantic tokens. Add component-specific selectors only for details that tokens cannot express.
36
+ 9. Do not copy proprietary assets, text, logos, or brand marks from the reference unless I explicitly confirm they may be used.
37
+
38
+ Pages and behavior:
39
+ 10. Use package-owned components and configuration: orderly-home-page, orderly-category-page, orderly-product-detail-page, orderly-checkout-page, configureShop(...), templates, and the generated Vite setup.
40
+ 11. Keep product/category SSR and generated category URLs working unless the deployment target requires a different routing approach.
41
+
42
+ Deployment:
43
+ 12. Configure the build/publish flow for the deployment target.
44
+ - For static hosting, use npm run build and document the dist upload.
45
+ - For FTP, use npx orderly-publish-site --target ftp.
46
+ - For Apache/PHP or Nginx/PHP, keep the package-generated server renderers and document the required server helper files.
47
+ - For any other target, document the exact build output and any remaining deployment assumptions.
48
+
49
+ Validation:
50
+ 13. Run the nearest relevant build/test command.
51
+ 14. Start the dev server when useful and inspect desktop and mobile layouts.
52
+ 15. Report what changed, what was verified, and any missing backend, credential, or deployment prerequisite.
53
+ ```
54
+
7
55
  ## Install
8
56
 
9
57
  ```sh
@@ -26,6 +74,8 @@ Agents and developers should use `npx orderly-init-shop` before hand-writing sho
26
74
  npx orderly-init-shop --account-id 00000000-0000-0000-0000-000000000000
27
75
  ```
28
76
 
77
+ For agent-assisted shop creation, ask for both the Orderly account id and a reference website URL for visual style before customizing the scaffold. Use the account id for `src/shop-query.ts`; use the reference website to choose semantic design tokens, radius, spacing, navigation treatment, and component-level exceptions in `src/style.css`. Treat the reference as design direction, not as permission to copy proprietary assets, text, logos, or brand marks.
78
+
29
79
  Re-running `npx orderly-init-shop` in an existing shop is non-destructive by default. Existing scaffold files are left unchanged with warnings, while missing new scaffold files are added. Use `--force` only when you explicitly want scaffold files overwritten.
30
80
 
31
81
  The scaffold uses Vite for local development and static builds, but Vite is added to the generated shop's `devDependencies`. Dev mode SSR for product/category URLs is enabled by default, so View Source on local category/product URLs shows semantic server-rendered markup. Consumers should test locally from `http://localhost:61677` or `https://localhost:61677` because those are the expected local development origins for backend CORS. The generated Vite setup defaults to `http://localhost:61677`; if a local reverse proxy or TLS terminator is added, keep the same `localhost:61677` origin over HTTPS. `@orderlyshop/web-components` does not depend on Vite at runtime.
@@ -84,6 +134,8 @@ Developers and coding agents should start with these package-owned docs:
84
134
  - [`custom-elements.json`](./custom-elements.json) is the Custom Elements Manifest for tools that understand web component metadata.
85
135
  - [`html-custom-data.json`](./html-custom-data.json) is VS Code compatible custom data for HTML autocomplete and hover docs.
86
136
 
137
+ These docs are written for GPT-5.5-class coding agents as well as humans: start with the outcome the shop needs, use the package-owned API surface, and verify with the nearest package or shop script before changing broader app structure.
138
+
87
139
  Enable HTML editor hints in a consuming project by adding the package custom data file to `.vscode/settings.json`:
88
140
 
89
141
  ```json
@@ -308,16 +360,18 @@ npx orderly-init-navigation --path src/navigation.ts
308
360
  Agent workflow for a new shop:
309
361
 
310
362
  1. Ask the user for the new shop's Orderly account id.
311
- 2. Run the navigation helper to dump sampled product information:
363
+ 2. Ask the user for a reference website URL for the desired visual style, or a short style description when no reference site exists.
364
+ 3. Run the navigation helper to dump sampled product information:
312
365
 
313
366
  ```sh
314
367
  npx orderly-init-navigation --suggest --account-id <account-id>
315
368
  ```
316
369
 
317
- 3. Read the generated `navigation-products.json`. The helper does not infer categories. It writes sampled product records with `title`, `brand`, and `tags` only, plus sampling metadata.
318
- 4. Create `navigation.ts` manually from the dump. Export `navigationDefinitions: NavigationDefinition[]`. Each entry must have `label` and a stable, globally unique `slug`, and can also have optional `heroImage`, optional `description`, optional `query`, and optional recursive `children`. Use plain `SearchQueryInput` objects for `query`, such as `{ query: "sko sneakers", tags: ["sko"] }`.
319
- 5. Keep navigation to at most two category levels. Categories should be reasonably granular, but avoid empty categories or categories backed by only a few products.
320
- 6. Configure the shop scope with a Core `SearchQuery` and pass it to `configureShop({ defaultShop: { defaultQuery } })`.
370
+ 4. Read the generated `navigation-products.json`. The helper does not infer categories. It writes sampled product records with `title`, `brand`, and `tags` only, plus sampling metadata.
371
+ 5. Create `navigation.ts` manually from the dump. Export `navigationDefinitions: NavigationDefinition[]`. Each entry must have `label` and a stable, globally unique `slug`, and can also have optional `heroImage`, optional `description`, optional `query`, and optional recursive `children`. Use plain `SearchQueryInput` objects for `query`, such as `{ query: "sko sneakers", tags: ["sko"] }`.
372
+ 6. Keep navigation to at most two category levels. Categories should be reasonably granular, but avoid empty categories or categories backed by only a few products.
373
+ 7. Configure the shop scope with a Core `SearchQuery` and pass it to `configureShop({ defaultShop: { defaultQuery } })`.
374
+ 8. Translate the reference website into `src/style.css` by setting `DESIGN.md` semantic tokens first, then add scoped component selectors only for visual details the tokens cannot express.
321
375
 
322
376
  The helper is intentionally an explicit tool for developers and coding agents. It is not a postinstall action. Agents should keep user-owned navigation edits, ask before overwriting files, and treat the product dump as source material for human-reviewable navigation.
323
377
 
@@ -561,20 +615,20 @@ collection.query = searchQuery;
561
615
 
562
616
  - `orderly-page-layout` provides reusable page regions for header, header actions, responsive primary navigation placement, left/right sidebars, content, footer, and overlay content. It includes a default logo image using `https://orderly.shop/home/App_Icon.svg`; override it with `logo-src`, `logo-alt`, and `logo-href`. Use `primary-nav-mobile-placement="header"` for the common mobile header burger pattern without a duplicate mobile layout template.
563
617
  - `orderly-home-page` composes page layout, responsive primary navigation, one product rail per top-level category, basket icon, basket drawer, product detail dialog, and footer. Configure it with `configureShop({ defaultShop })` plus attributes such as `title`, `eyebrow`, `rail-cta-label`, and `product-href`. The product dialog expand link follows the configured product URL mode, and compact `https://orderly.shop/...` product URLs are preserved when it builds hash or path routes.
564
- - `orderly-category-page` composes page layout, navigation, search, product grid, product detail, basket icon, and basket around a navigation category. Without properties it uses the package default shop configuration. Override with `configureShop({ defaultShop })` once per shop, set `base-url` or `product-href` in markup, or assign `category`, `navigationItems`, `sortOptions`, `client`, `defaultQuery`, and `basketController` from JavaScript for advanced cases. The product dialog expand link uses the configured product URL mode and still supports explicit per-page `product-href` overrides when a shop wants a different physical product page URL.
565
- - `orderly-checkout-page` composes page layout, responsive primary navigation, checkout form, basket order summary, footer, shared basket state, delivery loading, and order-created cleanup. Delivery methods render as radio cards after address entry, service points render as radio-card pickup choices when required, and delivery changes verify the draft so totals update. Configure copy through `configureShop({ defaultShop: { checkoutPageTitle, checkoutPageDescription, checkoutOrderTitle, checkoutTermsHref, checkoutLabels, basketLabels } })`, or assign `client`, `basketController`, `navigationItems`, `checkoutLabels`, and `basketLabels` from JavaScript.
566
- - `orderly-product-detail-page` composes page layout, navigation, product detail, basket drawer, and footer for a product route. Set `share-url`, the `shareUrl` property, or pass `#url=<encoded-share-url>` in the page URL; compact Orderly slugs are restored to `https://orderly.shop/...` before it calls `SearchService.Search` with `SearchQuery.ShareUrl` and renders the resolved `SearchObject`. Shops can tune outer gutters with `--orderly-product-detail-page-padding`, `--orderly-product-detail-page-mobile-padding`, `--orderly-product-detail-page-inline-padding`, and `--orderly-product-detail-page-mobile-inline-padding`.
618
+ - `orderly-category-page` composes page layout, navigation, search, product grid, product detail, basket icon, and basket around a navigation category. Without properties it uses the package default shop configuration. Override with `configureShop({ defaultShop })` once per shop, set `base-url` or `product-href` in markup, or assign `category`, `navigationItems`, `sortOptions`, `client`, `defaultQuery`, and `basketController` from JavaScript for advanced cases. Configure `defaultShop.navigationLayout` or top-level `navigationLayout` to switch the package-owned category page from desktop side navigation to top horizontal category navigation while keeping the mobile burger in the header. The product dialog expand link uses the configured product URL mode and still supports explicit per-page `product-href` overrides when a shop wants a different physical product page URL.
619
+ - `orderly-checkout-page` composes page layout, responsive primary navigation, checkout form, basket order summary, footer, shared basket state, delivery loading, and order-created cleanup. Delivery methods render as radio cards after address entry, service points render as radio-card pickup choices when required, and delivery changes verify the draft so totals update. If a persisted draft already contains a complete address, delivery methods are restored on mount; if it also contains a delivery choice, the draft is verified so the basket summary can show backend shipping and total prices. Configure copy through `configureShop({ defaultShop: { checkoutPageTitle, checkoutPageDescription, checkoutOrderTitle, checkoutTermsHref, checkoutLabels, basketLabels } })`, or assign `client`, `basketController`, `navigationItems`, `checkoutLabels`, and `basketLabels` from JavaScript.
620
+ - `orderly-product-detail-page` composes page layout, navigation, product detail, basket drawer, and footer for a product route. Set `share-url`, the `shareUrl` property, or pass `#url=<encoded-share-url>` in the page URL; compact Orderly slugs are restored to `https://orderly.shop/...` before it calls `SearchService.Search` with `SearchQuery.ShareUrl` and renders the resolved `SearchObject`. It forwards `details-before`, `purchase-note`, `secondary-cta`, and `details-after` slots to the nested product page. Shops can tune outer gutters with `--orderly-product-detail-page-padding`, `--orderly-product-detail-page-mobile-padding`, `--orderly-product-detail-page-inline-padding`, and `--orderly-product-detail-page-mobile-inline-padding`.
567
621
  - `orderly-stored-image` accepts `image: StoredImage`, resolves image URLs from the configured prefix, and applies `RotationDeg`, crop, and full-size metadata in the browser.
568
622
  - `orderly-credit` accepts `credit: Credit` or declarative `amount` and `currency` attributes, then renders stylable money markup. DKK values are formatted as `kr. <pris>`, for example `kr. 100,00`.
569
623
  - `orderly-product-tile` accepts `product: SearchObject` and emits `orderly-product-selected`, `orderly-add-to-basket`, and `orderly-remove-from-basket`. Templates can bind the product share URL with `data-orderly-bind="share-url"`; anchors without an existing `href` keep the raw share URL, while anchors that already point at a product page are rewritten to the configured physical product route using hash or path mode. Default tiles and statically hydrated category tiles include `schema.org/Product` and `schema.org/Offer` microdata for name, image, URL, description, SKU, brand, price, currency, and in-stock availability when those fields are present. When a `BasketController` is assigned through `basketController`, the default action button toggles between add and remove, using an icon-only button next to the price. Keyboard focus is indicated on the product title instead of a frame around the whole tile; custom tile templates should keep a title element with `data-orderly-bind="title"` or `.orderly-product-tile__title`.
570
- - `orderly-product-page` accepts `product: SearchObject`, renders all product image thumbnails, switches the selected image on thumbnail click, and exposes product details plus add-to-basket behavior. Product-page templates bind `title`, `description`, `brand`, `size`, `color`, `condition`, `price`, `image`, `addLabel`, and `closeLabel`; they also support `basket-action-label`, `basket-action-icon`, and `basket-action-state` so product-page add-to-basket markup can share the same binding names as product tiles. The fullscreen image viewer is package-owned, so custom product templates only need inline image markup plus optional thumbnail markup; the overlay, click/wheel zoom behavior, labels, focus handling, square image viewport, and overlay thumbnails are injected by the component itself unless `image-viewer="false"` is set. When opened inside an existing product dialog, the viewer is portaled into that open `<dialog>` so it stays above the product overlay; otherwise it is portaled to `document.body`. Main image frame styling lives on the default wrapper, not the inner `orderly-stored-image`, and shops can tune spacing/image framing with `--orderly-product-page-gap`, `--orderly-product-page-mobile-gap`, `--orderly-product-page-media-gap`, `--orderly-product-page-padding`, `--orderly-product-page-mobile-padding`, `--orderly-product-page-details-padding`, `--orderly-product-page-mobile-details-padding`, `--orderly-product-page-image-border`, `--orderly-product-page-image-radius`, `--orderly-product-page-image-background`, and `--orderly-product-page-thumbnail-border`.
624
+ - `orderly-product-page` accepts `product: SearchObject`, renders all product image thumbnails, switches the selected image on thumbnail click, and exposes product details plus add-to-basket behavior. Product-page templates bind `title`, `description`, `brand`, `size`, `color`, `condition`, `price`, `image`, `addLabel`, and `closeLabel`; they also support `basket-action-label`, `basket-action-icon`, and `basket-action-state` so product-page add-to-basket markup can share the same binding names as product tiles. The default product template has extension slots `details-before`, `purchase-note`, `secondary-cta`, and `details-after`; use these for shop-specific notices or links without replacing the whole product template. For simple default content, configure `defaultShop.productDetail.trustNote` and `defaultShop.productDetail.secondaryCta`. The fullscreen image viewer is package-owned, so custom product templates only need inline image markup plus optional thumbnail markup; the overlay, click/wheel zoom behavior, labels, focus handling, square image viewport, and overlay thumbnails are injected by the component itself unless `image-viewer="false"` is set. When opened inside an existing product dialog, the viewer is portaled into that open `<dialog>` so it stays above the product overlay; otherwise it is portaled to `document.body`. Main image frame styling lives on the default wrapper, not the inner `orderly-stored-image`, and shops can tune spacing/image framing with `--orderly-product-page-gap`, `--orderly-product-page-mobile-gap`, `--orderly-product-page-media-gap`, `--orderly-product-page-padding`, `--orderly-product-page-mobile-padding`, `--orderly-product-page-details-padding`, `--orderly-product-page-mobile-details-padding`, `--orderly-product-page-image-border`, `--orderly-product-page-image-radius`, `--orderly-product-page-image-background`, and `--orderly-product-page-thumbnail-border`.
571
625
  - `orderly-search-box` binds to a target `orderly-product-grid`. Use `mode="textbox"` for an inline search input or `mode="icon"` for a header icon that opens a full-page search overlay. Icon mode searches automatically with a 500ms debounce and renders matching product tiles below the search field. Default home and category pages use icon mode next to the basket icon.
572
626
  - `orderly-product-grid` accepts `query: SearchQuery`, merges the configured shop query scope, calls `SearchService.Search`, renders its own sort control from `sortOptions`, supports opaque `ContinuationToken` paging, manual paging, dynamic/infinite scroll, and default loading placeholders while the first page is pending.
573
627
  - `orderly-product-rail` accepts `query: SearchQuery`, title, CTA label, and CTA href, then renders the search as a horizontal scroll list by composing `orderly-product-grid`. It is useful for homepages and editorial rows where several category searches should be stacked vertically.
574
628
  - `orderly-collection-page` accepts `query: SearchQuery`, title, description, and hero image, then delegates fetching to `orderly-product-grid`.
575
629
  - `orderly-shop-footer` renders configurable logo, about text, address, contact information, opening hours, and information links.
576
630
  - `orderly-basket-icon` and `orderly-basket` share a `BasketController` backed by `DraftOrder` persistence. Basket state events such as `orderly-basket-open`, `orderly-basket-change`, and `orderly-basket-verified` use the current `DraftOrder` directly as `event.detail`, so consumers can derive counts and totals from Core contracts instead of an internal basket data shape. `orderly-basket` renders an item overview, verifies non-empty persisted drafts on load plus later basket mutations through `OrderService.VerifyDraft` when a client or `base-url` is configured, includes a configurable checkout link through `checkout-href` and `checkout-label`, and only exposes quantity selection for lines where `MaxQuantity > 1`. Summary rows now render only backend-provided `DraftOrder` values, never local subtotal/total math, and the component renders both `DraftOrder.Errors` and `DraftOrderLine.Errors`. Custom basket templates can project order-level errors through `data-orderly-slot="errors"`.
577
- - `orderly-checkout` persists checkout contact and address fields directly on `DraftOrder.Transport`, defaults the phone country picker to `+45`, validates email and phone values with built-in component logic, looks up Danish city names from the entered postal code through Dataforsyningen's `https://api.dataforsyningen.dk/postnumre/{postnr}` endpoint, loads delivery methods and service points, verifies the draft, and calls `OrderService.Create`.
631
+ - `orderly-checkout` persists checkout contact and address fields directly on `DraftOrder.Transport`, defaults the phone country picker to `+45`, validates email and phone values with built-in component logic, looks up Danish city names from the entered postal code through Dataforsyningen's `https://api.dataforsyningen.dk/postnumre/{postnr}` endpoint, loads delivery methods and service points, verifies the draft, and calls `OrderService.Create`. On mount it restores delivery methods for a persisted complete address and verifies a persisted delivery/service-point choice once, so shared basket summaries receive backend shipping and total prices without waiting for another address edit.
578
632
  - `orderly-navigation` uses `NavigationController` and can be subclassed with site-specific `NavigationItem[]`. It is sticky by default, including when placed in `left`, `right`, or `primary-nav`; set `sticky="false"` to opt out. Use `layout="vertical"` for disclosure side navigation, `layout="horizontal"` for the tiered desktop bar, or `layout="burgermenu"` for an icon trigger that expands into the same nested disclosure menu inside a floating panel. Use `layout-desktop="horizontal" layout-mobile="burgermenu"` with `orderly-page-layout primary-nav-mobile-placement="header"` for desktop horizontal nav plus inline mobile burger.
579
633
  - `orderly-search-box`, `orderly-sort-select`, `orderly-filter-panel`, and `orderly-load-more` bind to `orderly-product-grid`.
580
634
 
@@ -586,6 +640,19 @@ There are two different mobile navigation patterns:
586
640
  - `layout-desktop="horizontal" layout-mobile="burgermenu"` plus `primary-nav-mobile-placement="header"` means desktop horizontal navigation and an inline mobile burger in the page header next to search, basket, or other icon buttons. This is the recommended setup for the common storefront header pattern.
587
641
  - Custom `data-orderly-viewport="mobile"` page-layout templates are only needed when a shop replaces the whole page layout and wants manual control over where `data-orderly-slot="primary-nav"` is rendered.
588
642
 
643
+ Package-owned home, category, product, checkout, and payment pages read the same pattern from configuration:
644
+
645
+ ```ts
646
+ configureShop({
647
+ navigationLayout: {
648
+ primaryNavDesktopPlacement: "primary-nav",
649
+ primaryNavMobilePlacement: "header",
650
+ layoutDesktop: "horizontal",
651
+ layoutMobile: "burgermenu"
652
+ }
653
+ });
654
+ ```
655
+
589
656
  ```html
590
657
  <orderly-page-layout primary-nav-mobile-placement="header">
591
658
  <a slot="header" href="/">Shop name</a>
@@ -678,6 +745,18 @@ For dynamic paging, `orderly-product-grid` keeps the returned `PageResult.Contin
678
745
 
679
746
  Every component has a default light-DOM implementation and matching template hooks. Use `data-orderly-bind` for values, `data-orderly-action` for behavior, and `data-orderly-slot` for repeated or projected content. Product tile templates can bind `basket-action-icon`, `basket-action-label`, and `basket-action-state` and use `data-orderly-action="add-to-basket"` for the add/remove toggle. Product page templates keep the existing `addLabel` binding and also support `basket-action-label`, `basket-action-icon`, and `basket-action-state` for the same add-to-basket concept; use `data-orderly-action="add-to-basket"` for the action. Product page galleries use `data-orderly-slot="thumbnails"` and `data-orderly-action="select-image"` for custom thumbnail markup, while the fullscreen viewer overlay stays package-owned; shops can optionally mark a custom trigger with `data-orderly-image-viewer-trigger`, otherwise the inline `data-orderly-bind="image"` element becomes the trigger automatically. The viewer overlay may be moved outside the product-page host while open, either to `document.body` or to the nearest open `<dialog>`, so custom CSS or tests should target `[data-orderly-image-overlay]` instead of assuming the overlay remains inside `orderly-product-page`. Basket templates can add `data-orderly-slot="errors"` to place order-level `DraftOrder.Errors` exactly where a shop wants them. Product rail templates can replace the outer `layout`, inner `grid`, product item, loading state, and empty state. The main template names are `layout`, `grid`, `footer`, `product`, `thumbnail`, `image`, `basket`, `basket-icon`, `line`, `checkout`, `navigation`, `item`, `search-box`, `sort`, `sort-select`, `filter-panel`, `load-more`, `address-line`, `contact-item`, `opening-hour`, and `information-link`.
680
747
 
748
+ Use product page detail slots for small shop-specific content without replacing the package product template:
749
+
750
+ ```html
751
+ <orderly-product-detail-page>
752
+ <section slot="purchase-note">
753
+ <strong>Kurateret secondhand</strong>
754
+ <p>Alle varer er udvalgt og pakket i butikken.</p>
755
+ </section>
756
+ <a slot="secondary-cta" href="/butik/">Besøg butikken på Nørrebrogade</a>
757
+ </orderly-product-detail-page>
758
+ ```
759
+
681
760
  Product sorting belongs to `orderly-product-grid`: assign `grid.sortOptions = [{ label, orderBy }]` or pass sort options through `orderly-collection-page.sortOptions`. The default grid layout renders the sort select above the products. Custom grid layouts should include `data-orderly-slot="sort"` where the control should appear, and custom sort templates can use `data-orderly-template="sort"` with a `<select data-orderly-action="sort">`.
682
761
 
683
762
  Simple product queries can be declared in markup on `orderly-product-grid`, `orderly-product-rail`, and `orderly-collection-page`:
@@ -136,8 +136,12 @@ function agentsSource() {
136
136
  return `# Agent Guide
137
137
 
138
138
  - This shop was scaffolded with \`npx orderly-init-shop\` from \`@orderlyshop/web-components\`.
139
+ - These instructions are optimized for GPT-5.5-class coding agents. Work from the requested storefront outcome, keep changes narrow, and verify with the nearest shop script.
140
+ - Read \`node_modules/@orderlyshop/web-components/AGENTS.md\`, \`DESIGN.md\`, and \`docs/components/README.md\` before changing package integration patterns.
141
+ - Ask the user for the Orderly account id and a reference website URL for the desired visual style before customizing the scaffold.
139
142
  - Keep storefront logic in Orderly web components. Customize navigation, content, templates, and CSS instead of replacing package components.
140
143
  - Start visual theming from the package \`DESIGN.md\` semantic tokens before using component-local selectors.
144
+ - Use the reference website as design direction for palette, radius, spacing, density, typography feel, and navigation treatment. Do not copy proprietary assets, text, logos, or brand marks unless the user confirms they own or may use them.
141
145
  - Configure shop-wide backend, default query, navigation, page layout, and component registration in \`src/includes/head.html\` through \`configureShop(...)\`.
142
146
  - Use \`src/navigation.ts\` for category/navigation structure. Every category needs a stable globally unique \`slug\`.
143
147
  - Use \`src/shop-query.ts\` for the shop-wide Core \`SearchQuery\`, such as tenant/account scoping.
@@ -183,6 +187,7 @@ Use \`npm run generate:categories\` when you want to inspect generated source pa
183
187
  ## Customize
184
188
 
185
189
  - For consistent theming across all components, start with the semantic token contract in \`node_modules/@orderlyshop/web-components/DESIGN.md\`.
190
+ - For agent-assisted visual setup, provide a reference website URL. Use it to choose semantic tokens, radius, spacing, and navigation treatment in \`src/style.css\` without copying protected assets or text.
186
191
  - \`src/navigation.ts\` defines storefront navigation and category queries.
187
192
  - \`src/shop-query.ts\` defines the shop-wide Core \`SearchQuery\`.
188
193
  - \`src/includes/head.html\` calls \`configureShop(...)\`.
@@ -813,8 +818,9 @@ Agent workflow:
813
818
  1. If no shop scaffold exists, run: npx orderly-init-shop
814
819
  2. Existing scaffold files are skipped with warnings. Use --force only when the user explicitly wants overwrite.
815
820
  3. Ask the user for the shop account id. Re-run with --account-id <id> or edit src/shop-query.ts.
816
- 4. Customize src/navigation.ts with categories and SearchQuery values.
817
- 5. Customize src/templates/*.html and src/style.css for the shop look and feel.
821
+ 4. Ask the user for a reference website URL for the desired visual style.
822
+ 5. Customize src/navigation.ts with categories and SearchQuery values.
823
+ 6. Translate the reference website into src/style.css with DESIGN.md semantic tokens first.
818
824
  `);
819
825
  }
820
826
 
@@ -107,7 +107,7 @@
107
107
  "name": "OrderlyCheckoutPageElement",
108
108
  "tagName": "orderly-checkout-page",
109
109
  "customElement": true,
110
- "description": "Default checkout page composed from page layout, navigation, checkout form, basket summary, footer, and shared basket state.",
110
+ "description": "Default checkout page composed from page layout, navigation, checkout form, basket summary, footer, shared basket state, and persisted delivery restore.",
111
111
  "attributes": [
112
112
  { "name": "base-url", "description": "Backend URL used when no client property is assigned." },
113
113
  { "name": "brand-label", "description": "Brand text." },
@@ -285,7 +285,7 @@
285
285
  "name": "OrderlyProductDetailPageElement",
286
286
  "tagName": "orderly-product-detail-page",
287
287
  "customElement": true,
288
- "description": "Default product detail page that resolves a SearchObject through SearchService.Search using SearchQuery.ShareUrl from share-url or #url.",
288
+ "description": "Default product detail page that resolves a SearchObject through SearchService.Search using SearchQuery.ShareUrl from share-url or #url and forwards product detail extension slots to the nested product page.",
289
289
  "attributes": [
290
290
  { "name": "base-url", "description": "Backend URL used when no client property is assigned." },
291
291
  { "name": "share-url", "description": "Product share URL mapped to SearchQuery.ShareUrl." },
@@ -306,6 +306,12 @@
306
306
  { "kind": "field", "name": "navigationItems", "type": { "text": "NavigationItem[]" } },
307
307
  { "kind": "field", "name": "basketLabels", "type": { "text": "BasketLabels" } }
308
308
  ],
309
+ "slots": [
310
+ { "name": "details-before", "description": "Forwarded to the nested product page before package-owned details." },
311
+ { "name": "purchase-note", "description": "Forwarded to the nested product page after the add-to-basket button." },
312
+ { "name": "secondary-cta", "description": "Forwarded to the nested product page after the purchase note." },
313
+ { "name": "details-after", "description": "Forwarded to the nested product page after package-owned details." }
314
+ ],
309
315
  "events": [
310
316
  { "name": "orderly-product-loaded", "type": { "text": "CustomEvent<{ product: SearchObject; shareUrl: string }>" } },
311
317
  { "name": "orderly-product-not-found", "type": { "text": "CustomEvent<{ shareUrl: string }>" } },
@@ -337,7 +343,7 @@
337
343
  "name": "OrderlyProductPageElement",
338
344
  "tagName": "orderly-product-page",
339
345
  "customElement": true,
340
- "description": "Product detail view with gallery thumbnails, package-owned fullscreen image viewer with a square viewport, add-to-basket behavior, and product-page template bindings including basket-action aliases.",
346
+ "description": "Product detail view with gallery thumbnails, package-owned fullscreen image viewer with a square viewport, add-to-basket behavior, product detail extension slots, and product-page template bindings including basket-action aliases.",
341
347
  "attributes": [
342
348
  { "name": "add-label", "description": "Add-to-basket button label." },
343
349
  { "name": "image-viewer", "description": "Controls the package-owned fullscreen image viewer. Set to false to disable it; when open, the viewer is portaled to document.body or the nearest open dialog." }
@@ -348,6 +354,12 @@
348
354
  { "kind": "field", "name": "basketController", "type": { "text": "BasketController | undefined" } },
349
355
  { "kind": "field", "name": "imageViewer", "type": { "text": "boolean" } }
350
356
  ],
357
+ "slots": [
358
+ { "name": "details-before", "description": "Content rendered before package-owned product details in the default template." },
359
+ { "name": "purchase-note", "description": "Content rendered after the add-to-basket button in the default template." },
360
+ { "name": "secondary-cta", "description": "Secondary call-to-action rendered after the purchase note in the default template." },
361
+ { "name": "details-after", "description": "Content rendered after package-owned product details in the default template." }
362
+ ],
351
363
  "events": [
352
364
  { "name": "orderly-add-to-basket", "type": { "text": "CustomEvent<ProductEventDetail>" } },
353
365
  { "name": "orderly-product-image-selected", "type": { "text": "CustomEvent<{ product?: SearchObject; image?: StoredImage; index: number }>" } }
@@ -439,7 +451,7 @@
439
451
  "name": "OrderlyCheckoutElement",
440
452
  "tagName": "orderly-checkout",
441
453
  "customElement": true,
442
- "description": "Checkout form that collects profile data, lists delivery methods and service points, verifies the draft, and creates an order.",
454
+ "description": "Checkout form that collects profile data, lists delivery methods and service points, restores persisted delivery choices, verifies the draft, and creates an order.",
443
455
  "attributes": [
444
456
  { "name": "base-url", "description": "Backend URL used when no client property is assigned." },
445
457
  { "name": "terms-href", "description": "Terms link URL." },