@wix/agent-skills 1.14.0 → 1.15.0
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/README.md +4 -1
- package/package.json +1 -1
- package/skills/README.md +23 -0
- package/skills/wix-app/SKILL.md +10 -2
- package/skills/wix-app/references/AUTO_PATTERNS_DASHBOARD.md +326 -0
- package/skills/wix-app/references/CODE_QUALITY.md +1 -0
- package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +124 -115
- package/skills/wix-app/references/DASHBOARD_PAGE.md +3 -0
- package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +23 -9
- package/skills/wix-app/references/SITE_PLUGIN.md +1 -1
- package/skills/wix-app/references/auto-patterns-dashboard/action-cell.md +115 -0
- package/skills/wix-app/references/auto-patterns-dashboard/app-config-structure.md +264 -0
- package/skills/wix-app/references/auto-patterns-dashboard/app-context.md +37 -0
- package/skills/wix-app/references/auto-patterns-dashboard/bulk-actions.md +86 -0
- package/skills/wix-app/references/auto-patterns-dashboard/collection-page-actions.md +119 -0
- package/skills/wix-app/references/auto-patterns-dashboard/collection-page.md +103 -0
- package/skills/wix-app/references/auto-patterns-dashboard/custom-actions-override.md +76 -0
- package/skills/wix-app/references/auto-patterns-dashboard/custom-columns-override.md +82 -0
- package/skills/wix-app/references/auto-patterns-dashboard/custom-components-override.md +89 -0
- package/skills/wix-app/references/auto-patterns-dashboard/custom-header-override.md +124 -0
- package/skills/wix-app/references/auto-patterns-dashboard/custom-sections-override.md +91 -0
- package/skills/wix-app/references/auto-patterns-dashboard/custom-slots-override.md +71 -0
- package/skills/wix-app/references/auto-patterns-dashboard/entity-page-actions.md +70 -0
- package/skills/wix-app/references/auto-patterns-dashboard/entity-page-view-actions.md +73 -0
- package/skills/wix-app/references/auto-patterns-dashboard/entity-page.md +98 -0
- package/skills/wix-app/references/auto-patterns-dashboard/example-patterns.json +278 -0
- package/skills/wix-app/references/auto-patterns-dashboard/pages-configuration.md +94 -0
- package/skills/wix-app/references/auto-patterns-dashboard/resolved-action.md +43 -0
- package/skills/wix-app/references/auto-patterns-dashboard/sdk-utilities.md +66 -0
- package/skills/wix-app/references/auto-patterns-dashboard/views.md +76 -0
- package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +1 -14
- package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +54 -29
- package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +2 -2
- package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +17 -105
- package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +127 -0
- package/skills/wix-app/references/editor-react-component/PARTS.md +2 -1
- package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +15 -15
- package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +25 -53
- package/skills/wix-app/scripts/generate-auto-patterns.js +510 -0
- package/skills/wix-auth/SKILL.md +12 -0
- package/skills/wix-auth/references/device-flow.md +140 -0
- package/skills/wix-docs/SKILL.md +188 -0
- package/skills/wix-docs/references/API_SPEC_SEARCH.md +213 -0
- package/skills/wix-docs/references/EXTRACTING.md +120 -0
- package/skills/wix-headless/SKILL.md +84 -130
- package/skills/wix-headless/entry/bootstrap.mjs +93 -0
- package/skills/wix-headless/entry/skill.md +78 -0
- package/skills/wix-headless/references/AI_FEATURES.md +178 -0
- package/skills/wix-headless/references/CAPABILITIES.md +84 -0
- package/skills/wix-headless/references/DISCOVERY.md +34 -56
- package/skills/wix-headless/references/DOC_DISCOVERY.md +37 -0
- package/skills/wix-headless/references/FEEDBACK.md +118 -0
- package/skills/wix-headless/references/IMAGE_GENERATION.md +69 -0
- package/skills/wix-headless/references/SDK_HANDOFF.md +97 -0
- package/skills/wix-headless/references/SEED.md +44 -188
- package/skills/wix-headless/references/SETUP.md +32 -103
- package/skills/wix-headless/references/astro.md +98 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +196 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +236 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-bookings.md +279 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-cms.md +163 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-events.md +203 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +222 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +124 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +160 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +118 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-portfolio.md +132 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +124 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +188 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +173 -0
- package/skills/wix-headless/references/inline-recipes/how-to-code-restaurants.md +161 -0
- package/skills/wix-headless/references/inline-recipes/setup-blog.md +175 -0
- package/skills/wix-headless/references/inline-recipes/setup-bookings.md +228 -0
- package/skills/wix-headless/references/inline-recipes/setup-cms.md +200 -0
- package/skills/wix-headless/references/inline-recipes/setup-events.md +196 -0
- package/skills/wix-headless/references/inline-recipes/setup-forms.md +174 -0
- package/skills/wix-headless/references/inline-recipes/setup-online-store.md +176 -0
- package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +153 -0
- package/skills/wix-headless/references/inline-recipes/setup-pricing-plans.md +229 -0
- package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +161 -0
- package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +117 -0
- package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +152 -0
- package/skills/wix-headless/references/managed/AUTHENTICATION.md +57 -0
- package/skills/wix-headless/references/managed/CONNECT.md +74 -0
- package/skills/wix-headless/references/managed/CREATE.md +130 -0
- package/skills/wix-headless/references/managed/DEPLOYMENT.md +57 -0
- package/skills/wix-headless/references/non-astro.md +59 -0
- package/skills/wix-headless/references/self-managed/AUTHENTICATION.md +22 -0
- package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +7 -0
- package/skills/wix-headless/references/stripe/AUTHENTICATION.md +55 -0
- package/skills/wix-headless/references/stripe/DEPLOYMENT.md +63 -0
- package/skills/wix-manage/SKILL.md +24 -1
- package/skills/wix-manage/references/analytics/query-site-analytics.md +241 -0
- package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +1 -1
- package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +265 -0
- package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +436 -0
- package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +209 -0
- package/skills/wix-manage/references/rich-content/author-ricos-rich-content.md +249 -0
- package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +51 -0
- package/skills/wix-vibe-headless/SKILL.md +136 -0
- package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +128 -0
- package/skills/wix-vibe-headless/references/blog/wix-blog.js +217 -0
- package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +153 -0
- package/skills/wix-vibe-headless/references/bookings/wix-bookings-checkout.js +147 -0
- package/skills/wix-vibe-headless/references/bookings/wix-bookings-services.js +215 -0
- package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +154 -0
- package/skills/wix-vibe-headless/references/cms/wix-cms.js +186 -0
- package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +142 -0
- package/skills/wix-vibe-headless/references/events/wix-events-browse.js +135 -0
- package/skills/wix-vibe-headless/references/events/wix-events-registration.js +187 -0
- package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +211 -0
- package/skills/wix-vibe-headless/references/members/wix-members-auth.js +387 -0
- package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +111 -0
- package/skills/wix-vibe-headless/references/portfolio/wix-portfolio.js +194 -0
- package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +127 -0
- package/skills/wix-vibe-headless/references/pricing-plans/wix-pricing-plans.js +157 -0
- package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +138 -0
- package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-menu.js +224 -0
- package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-ordering.js +156 -0
- package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-reservations.js +107 -0
- package/skills/wix-vibe-headless/references/shared/wix-client.js +186 -0
- package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +155 -0
- package/skills/wix-vibe-headless/references/storefront/wix-store-cart.js +147 -0
- package/skills/wix-vibe-headless/references/storefront/wix-store-catalog.js +142 -0
- package/skills/wix-headless/references/BUILD-astro.md +0 -253
- package/skills/wix-headless/references/BUILD-own-build.md +0 -167
- package/skills/wix-headless/references/BUILD.md +0 -105
- package/skills/wix-headless/references/DESIGN_SYSTEM.md +0 -165
- package/skills/wix-headless/references/DISCOVERY-connect.md +0 -55
- package/skills/wix-headless/references/DISCOVERY-create.md +0 -238
- package/skills/wix-headless/references/PLAN-connect.md +0 -19
- package/skills/wix-headless/references/PLAN-create.md +0 -17
- package/skills/wix-headless/references/PLAN.md +0 -92
- package/skills/wix-headless/references/astro/blog/BLOG_PAGES.md +0 -300
- package/skills/wix-headless/references/astro/blog/BLOG_SETUP.md +0 -218
- package/skills/wix-headless/references/astro/bookings/COMPONENTS.md +0 -45
- package/skills/wix-headless/references/astro/bookings/SERVICES_PAGES.md +0 -77
- package/skills/wix-headless/references/astro/cms/CMS_FOUNDATIONS.md +0 -214
- package/skills/wix-headless/references/astro/cms/FAQ_KNOWLEDGE_BASE.md +0 -231
- package/skills/wix-headless/references/astro/cms/PORTFOLIO.md +0 -453
- package/skills/wix-headless/references/astro/cms/RESOURCE_LIBRARY.md +0 -354
- package/skills/wix-headless/references/astro/cms/TEAM_DIRECTORY.md +0 -299
- package/skills/wix-headless/references/astro/designer/INSTRUCTIONS.md +0 -351
- package/skills/wix-headless/references/astro/ecom/CART_PAGES.md +0 -119
- package/skills/wix-headless/references/astro/ecom/CART_WIRING.md +0 -103
- package/skills/wix-headless/references/astro/ecom/COMPONENTS_CSS.md +0 -132
- package/skills/wix-headless/references/astro/forms/CONTACT_FORM.md +0 -463
- package/skills/wix-headless/references/astro/gift-cards/COMPONENTS.md +0 -119
- package/skills/wix-headless/references/astro/gift-cards/PAGES.md +0 -129
- package/skills/wix-headless/references/astro/stores/BACK_IN_STOCK.md +0 -178
- package/skills/wix-headless/references/astro/stores/CATEGORY_PAGES.md +0 -85
- package/skills/wix-headless/references/astro/stores/COMPONENTS_CSS.md +0 -129
- package/skills/wix-headless/references/astro/stores/HOME_AND_NAV.md +0 -229
- package/skills/wix-headless/references/astro/stores/PRODUCT_PAGES.md +0 -215
- package/skills/wix-headless/references/astro/stores/SHARED_WIRING.md +0 -165
- package/skills/wix-headless/references/astro/templates/Layout.astro +0 -132
- package/skills/wix-headless/references/astro/templates/astro.config.mjs +0 -41
- package/skills/wix-headless/references/astro/templates/bookings/AvailabilityCalendar.tsx +0 -374
- package/skills/wix-headless/references/astro/templates/bookings/BookingForm.tsx +0 -136
- package/skills/wix-headless/references/astro/templates/bookings/SeoTags.astro +0 -25
- package/skills/wix-headless/references/astro/templates/bookings/ServiceBookingFlow.tsx +0 -71
- package/skills/wix-headless/references/astro/templates/bookings/ServiceCard.astro +0 -54
- package/skills/wix-headless/references/astro/templates/bookings/booking-confirmation.astro +0 -49
- package/skills/wix-headless/references/astro/templates/bookings/bookingDriver.ts +0 -245
- package/skills/wix-headless/references/astro/templates/bookings/components-bookings.css +0 -424
- package/skills/wix-headless/references/astro/templates/bookings/services/[slug].astro +0 -176
- package/skills/wix-headless/references/astro/templates/bookings/services/index.astro +0 -181
- package/skills/wix-headless/references/astro/templates/ecom/CartBadge.tsx +0 -84
- package/skills/wix-headless/references/astro/templates/ecom/CartView.tsx +0 -543
- package/skills/wix-headless/references/astro/templates/ecom/cart.astro +0 -13
- package/skills/wix-headless/references/astro/templates/ecom/components-ecom.css +0 -302
- package/skills/wix-headless/references/astro/templates/ecom/discounts.ts +0 -71
- package/skills/wix-headless/references/astro/templates/ecom/thank-you.astro +0 -24
- package/skills/wix-headless/references/astro/templates/gift-cards/GiftCardPurchase.tsx +0 -172
- package/skills/wix-headless/references/astro/templates/gift-cards/_home-teaser-snippet.astro +0 -42
- package/skills/wix-headless/references/astro/templates/gift-cards/_nav-snippet.astro +0 -11
- package/skills/wix-headless/references/astro/templates/gift-cards/components-gift-cards.css +0 -220
- package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.astro +0 -51
- package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.ts +0 -75
- package/skills/wix-headless/references/astro/templates/global.css +0 -288
- package/skills/wix-headless/references/astro/templates/stores/AddToCartButton.tsx +0 -77
- package/skills/wix-headless/references/astro/templates/stores/BackInStockForm.tsx +0 -176
- package/skills/wix-headless/references/astro/templates/stores/CategoryRail.astro +0 -69
- package/skills/wix-headless/references/astro/templates/stores/ProductCard.astro +0 -79
- package/skills/wix-headless/references/astro/templates/stores/ProductPurchase.tsx +0 -397
- package/skills/wix-headless/references/astro/templates/stores/SeoTags.astro +0 -21
- package/skills/wix-headless/references/astro/templates/stores/back-in-stock.ts +0 -67
- package/skills/wix-headless/references/astro/templates/stores/categories.ts +0 -155
- package/skills/wix-headless/references/astro/templates/stores/category/[slug].astro +0 -130
- package/skills/wix-headless/references/astro/templates/stores/components-stores.css +0 -400
- package/skills/wix-headless/references/astro/templates/stores/products/[slug].astro +0 -128
- package/skills/wix-headless/references/astro/templates/stores/products/index.astro +0 -101
- package/skills/wix-headless/references/blog/BLOG_CONTENT.md +0 -161
- package/skills/wix-headless/references/blog/INSTRUCTIONS.md +0 -32
- package/skills/wix-headless/references/bookings/FLOW.md +0 -246
- package/skills/wix-headless/references/bookings/INSTRUCTIONS.md +0 -95
- package/skills/wix-headless/references/bookings/SERVICES_DATA.md +0 -355
- package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +0 -176
- package/skills/wix-headless/references/cms/INSTRUCTIONS.md +0 -71
- package/skills/wix-headless/references/commands/known-apps.json +0 -6
- package/skills/wix-headless/references/custom/CONNECTION_PLAN.md +0 -142
- package/skills/wix-headless/references/custom/INSTRUCTIONS.md +0 -88
- package/skills/wix-headless/references/custom/blog/WIRING.md +0 -52
- package/skills/wix-headless/references/custom/bookings/WIRING.md +0 -197
- package/skills/wix-headless/references/custom/cms/WIRING.md +0 -97
- package/skills/wix-headless/references/custom/ecom/WIRING.md +0 -67
- package/skills/wix-headless/references/custom/forms/WIRING.md +0 -101
- package/skills/wix-headless/references/custom/stores/WIRING.md +0 -80
- package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +0 -59
- package/skills/wix-headless/references/forms/INSTRUCTIONS.md +0 -43
- package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +0 -51
- package/skills/wix-headless/references/images/INSTRUCTIONS.md +0 -357
- package/skills/wix-headless/references/seed-recipes.md +0 -49
- package/skills/wix-headless/references/shared/AGENTS_MD.md +0 -47
- package/skills/wix-headless/references/shared/AUTHENTICATION.md +0 -108
- package/skills/wix-headless/references/shared/BUILD_NOISE.md +0 -8
- package/skills/wix-headless/references/shared/DESIGN_MD.md +0 -84
- package/skills/wix-headless/references/shared/DOCS_SEARCH.md +0 -41
- package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +0 -186
- package/skills/wix-headless/references/shared/IMPLEMENTER.md +0 -206
- package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +0 -97
- package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +0 -143
- package/skills/wix-headless/references/shared/STYLING.md +0 -140
- package/skills/wix-headless/references/stores/INSTRUCTIONS.md +0 -126
- package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +0 -252
- package/skills/wix-headless/references/verticals/_schema.json +0 -74
- package/skills/wix-headless/references/verticals/_schema.md +0 -95
- package/skills/wix-headless/references/verticals/blog.md +0 -31
- package/skills/wix-headless/references/verticals/bookings.md +0 -41
- package/skills/wix-headless/references/verticals/cms.md +0 -30
- package/skills/wix-headless/references/verticals/ecom.md +0 -25
- package/skills/wix-headless/references/verticals/forms.md +0 -26
- package/skills/wix-headless/references/verticals/gift-cards.md +0 -24
- package/skills/wix-headless/references/verticals/stores.md +0 -33
- package/skills/wix-headless/scripts/check-manifest.mjs +0 -335
- package/skills/wix-headless/scripts/compose.mjs +0 -520
- package/skills/wix-headless/scripts/emit-design-tokens.mjs +0 -157
- package/skills/wix-headless/scripts/flatten.sh +0 -61
- package/skills/wix-headless/scripts/generate-images.mjs +0 -242
- package/skills/wix-headless/scripts/patch-decorative-slots.mjs +0 -154
- package/skills/wix-headless/scripts/plan-entity-image-waves.mjs +0 -190
- package/skills/wix-headless/scripts/scaffold.sh +0 -139
- package/skills/wix-headless/scripts/seed-utilities.sh +0 -93
- package/skills/wix-headless/scripts/write-decorative-json.mjs +0 -62
- package/skills/wix-headless/shared-utilities/analytics.ts +0 -40
- package/skills/wix-headless/shared-utilities/ricos.ts +0 -179
- package/skills/wix-headless/shared-utilities/wix-image.ts +0 -72
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# Bookings Pages — the SSR routes (astro)
|
|
2
|
-
|
|
3
|
-
The `pages` scope of the bookings vertical. You write the route files. The
|
|
4
|
-
**logic** is in `../../bookings/FLOW.md` (read it first); this doc is the astro
|
|
5
|
-
wiring + the gotchas. Read `references/shared/IMPLEMENTER.md` +
|
|
6
|
-
`references/shared/STYLING.md` first.
|
|
7
|
-
|
|
8
|
-
> **Start from the templates — don't re-author the SSR data access.** Examples at
|
|
9
|
-
> `<SKILL_ROOT>/references/astro/templates/bookings/`: `ServiceCard.astro`,
|
|
10
|
-
> `services/index.astro`, `services/[slug].astro`, `booking-confirmation.astro`.
|
|
11
|
-
> Read and adapt (copy, headings, styling); keep the SDK query shapes.
|
|
12
|
-
|
|
13
|
-
## Pages you write
|
|
14
|
-
|
|
15
|
-
| File | From template | Role |
|
|
16
|
-
|------|---------------|------|
|
|
17
|
-
| `src/pages/services/index.astro` | `…/services/index.astro` | SSR catalog grid (SEO). `queryServices` via ambient `@wix/essentials`. |
|
|
18
|
-
| `src/components/ServiceCard.astro` | `…/ServiceCard.astro` | static service card for the grid. |
|
|
19
|
-
| `src/pages/services/[slug].astro` | `…/services/[slug].astro` | SSR detail (SEO) + mounts `<ServiceBookingFlow client:only="react">`. Also fetches the **booking-form schema** and passes `fields` to the island. |
|
|
20
|
-
| `src/pages/booking-confirmation.astro` | `…/booking-confirmation.astro` | confirmation — renders from the `service`/`startDate` query params (no re-fetch). |
|
|
21
|
-
|
|
22
|
-
Plus the nav/home links (shell chain — see below).
|
|
23
|
-
|
|
24
|
-
## astro-specific rules
|
|
25
|
-
|
|
26
|
-
1. **SSR reads use the ambient `@wix/essentials` client — never `OAuthStrategy`.**
|
|
27
|
-
`const result = await auth.elevate(services.queryServices)({ query: { filter: { appId: BOOKING_APP_ID }, paging: { limit: 100 } }, conditionalFields: ["STAFF_MEMBER_DETAILS"] }).find();`
|
|
28
|
-
Building `createClient({ auth: OAuthStrategy({ clientId: import.meta.env.* }) })`
|
|
29
|
-
in frontmatter 500s in the deployed runtime (the env var is client-only).
|
|
30
|
-
Always include **`appId`** in the filter. Single service by slug: the
|
|
31
|
-
`.eq("mainSlug.name", slug).eq("appId", BOOKING_APP_ID).limit(1).find()` chain.
|
|
32
|
-
The same elevation works for `services.queryLocations` and
|
|
33
|
-
`categoriesV2.queryCategories` (used by the optional catalog filters, below).
|
|
34
|
-
1b. **Optional catalog filters (location + category) — auto-skip; see `../../bookings/FLOW.md` §7.**
|
|
35
|
-
The catalog page reads `?locationId`/`?category` from the request URL and merges
|
|
36
|
-
them into the **same** `queryServices` filter (location → `locations.business.id`
|
|
37
|
-
$hasSome, or the synthetic `locations.type` mapping; category → `category.id` $eq).
|
|
38
|
-
It SSRs `queryLocations()` (show the selector only when business+custom+customer
|
|
39
|
-
count > 1) and `queryCategories().find()` (non-fatal — render without the bar on
|
|
40
|
-
failure; show only when > 1 category). The chosen location is carried into the
|
|
41
|
-
detail link (`ServiceCard` `locationId`/`locationType` props) so availability is
|
|
42
|
-
scoped to it. Reference: `…/templates/bookings/services/index.astro`.
|
|
43
|
-
2. **The detail page fetches the booking-form schema server-side.** Read
|
|
44
|
-
`service.form._id`'s form via `@wix/forms` (`auth.elevate(forms.getForm)(formId)`),
|
|
45
|
-
map `formFields` to `{ label, target, required, componentType, identifier, options }`,
|
|
46
|
-
and pass the array as `fields` into `<ServiceBookingFlow>`. **Filter to fields with a
|
|
47
|
-
recognized string `componentType`** (`TEXT_INPUT`/`PHONE_INPUT`/`DROPDOWN`) — skip
|
|
48
|
-
complex object-valued fields (e.g. the default form's multi-line `ADDRESS`), or
|
|
49
|
-
`createBooking` fails with "must be object". Pass the full `service` too — the
|
|
50
|
-
booking step reads its payment/policy. Same field-mapping as `../forms/CONTACT_FORM.md`.
|
|
51
|
-
Also pass, through to `<ServiceBookingFlow>`: `service.staffMemberDetails?.staffMembers`
|
|
52
|
-
(the staff picker — the service was queried with `STAFF_MEMBER_DETAILS`); the
|
|
53
|
-
service's **business `locations`** — sourced from `auth.elevate(services.queryLocations)()`
|
|
54
|
-
(the site's real business locations) intersected with the service's own location ids,
|
|
55
|
-
NOT from `service.locations` alone (its ids can be ones the availability engine doesn't
|
|
56
|
-
recognize → 0 slots) — so the calendar scopes availability to one location and avoids
|
|
57
|
-
duplicate per-location slots (FLOW.md §7); and the `?locationId` read from the request
|
|
58
|
-
URL (the picker's default).
|
|
59
|
-
3. **Only the read pages are SSR.** The detail page SSRs the service info for SEO,
|
|
60
|
-
then the booking UI runs in the `client:only` island. Do not SSR availability.
|
|
61
|
-
4. **Confirmation renders from query params.** The booking step redirects with
|
|
62
|
-
`?service=…&startDate=…`; render those. Do not re-fetch a stranger's booking
|
|
63
|
-
from this public page.
|
|
64
|
-
5. **Two dirs deep** (`services/[slug].astro`) → import with `../../`, not `../../../`.
|
|
65
|
-
|
|
66
|
-
## Shell chain — nav + home (this scope patches shared files)
|
|
67
|
-
|
|
68
|
-
- **Navigation** — at `<!-- nav:links -->` in `src/components/Navigation.astro`,
|
|
69
|
-
append a link to **`/services`** (label fitting the brand: "Book", "Services", "Appointments").
|
|
70
|
-
- **Home** — at `<!-- home:bookings -->` in `src/pages/index.astro`, add a short,
|
|
71
|
-
brand-voiced CTA linking to **`/services`** (heading + a line + a button-styled
|
|
72
|
-
link). Use the site's primary-action token (`--color-accent`). Do not list
|
|
73
|
-
specific services or hardcode slugs — the catalog renders them live.
|
|
74
|
-
- Append at the markers; keep the markers; never replace other packs' insertions.
|
|
75
|
-
|
|
76
|
-
## Return
|
|
77
|
-
`{ status, phase, scope: "pages", summary, data, files, errors }`. Run the pre-return file-existence assertion (`../../bookings/INSTRUCTIONS.md`). If `index.astro`/`Navigation.astro` lacks its marker, return `status: "partial"` with the coded error.
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
# CMS Foundations — Code Patterns for `@wix/data` (astro)
|
|
2
|
-
|
|
3
|
-
The **rendering / code-patterns** half of CMS foundations: service module template, `@wix/data` SDK queries, image resolution, elevated access, and rich-text (Ricos) rendering — everything a CMS **page** scope needs to read collections and render them in Astro.
|
|
4
|
-
|
|
5
|
-
> **Seeding lives in the business track.** Creating collections and inserting/verifying items via REST is **not** here — it is in `<SKILL_ROOT>/references/cms/CMS_FOUNDATIONS.md` (the `seed` scope's doc). This file is consumed by the `pages` scope; that file by the `seed` scope. The `cms/INSTRUCTIONS.md` router points each scope at the right half.
|
|
6
|
-
|
|
7
|
-
> **Import note (read first).** The Wix Data items API is the **`items`** named export of **`@wix/data`**: `import { items } from "@wix/data"`, then `items.query` / `items.insert` / `items.update` / `items.remove` (plus `items.bulkInsert` / `bulkSave` / `bulkPatch` / …). This is the documented form and what every CMS page here uses. Do **not** import from the internal `@wix/wix-data-items-sdk`. SETUP.md's per-pack install table (Step 4c) installs `@wix/data` + `@wix/essentials` for the cms pack.
|
|
8
|
-
|
|
9
|
-
## Rendering Ricos rich-text fields
|
|
10
|
-
|
|
11
|
-
Wix CMS stores `RICH_TEXT` / `RICH_CONTENT` fields as **Ricos JSON** — a structured node tree (PARAGRAPH, HEADING, BULLETED_LIST, etc.), not HTML. The dashboard's rich-text editor reads and writes this format.
|
|
12
|
-
|
|
13
|
-
For SSR Astro pages (about, faq, portfolio, team, resource), import the seeded `renderRicos` util from `src/utils/ricos.ts`. The util is shipped by `seed-utilities.sh` (copied from `<SKILL_ROOT>/shared-utilities/ricos.ts` during Setup), so it's already on disk — do NOT inline a Ricos walker in your page.
|
|
14
|
-
|
|
15
|
-
```astro
|
|
16
|
-
---
|
|
17
|
-
import { items } from "@wix/data";
|
|
18
|
-
import { auth } from "@wix/essentials";
|
|
19
|
-
import { renderRicos } from "../utils/ricos";
|
|
20
|
-
|
|
21
|
-
const elevatedQuery = auth.elevate(items.query);
|
|
22
|
-
const { items: results } = await elevatedQuery("about-content")
|
|
23
|
-
.limit(1)
|
|
24
|
-
.find();
|
|
25
|
-
const about = results[0];
|
|
26
|
-
const bodyHtml = renderRicos(about?.body);
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
<article class="prose">
|
|
30
|
-
<h1>{about?.heading}</h1>
|
|
31
|
-
<div set:html={bodyHtml} />
|
|
32
|
-
</article>
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
The util covers the common subset (PARAGRAPH, HEADING 1-6, BULLETED_LIST / ORDERED_LIST / LIST_ITEM, BLOCKQUOTE, DIVIDER + BOLD / ITALIC / UNDERLINE / LINK decorations). Anything outside that set renders defensively as a `<p>` with the raw text — never throws.
|
|
36
|
-
|
|
37
|
-
> **Why not @wix/ricos?** The blog vertical uses `@wix/ricos`'s React `RicosViewer` as a client island because blog posts can carry the full Ricos feature set (galleries, polls, embedded media). For static CMS pages, that's ~80kb of React for paragraphs and lists — overkill. Use the seeded SSR walker instead.
|
|
38
|
-
|
|
39
|
-
> **Do NOT `set:html={item.body}` directly.** That ships JSON-encoded text into the page (e.g. `[object Object]` or `{"nodes":...}`). Always go through `renderRicos`.
|
|
40
|
-
|
|
41
|
-
> **Critical Rules — Read Before Starting**
|
|
42
|
-
> 1. **Collection IDs have NO namespace** — user collections use just the name (e.g., `"Projects"`). Only Wix App collections use `<namespace>/<name>`. Verify via `curl`: `GET /wix-data/v2/collections?fields=id`.
|
|
43
|
-
> 2. **SDK query pattern** — `items.query("CollectionId").find()`. There is no `items.queryDataItems()` in the SDK.
|
|
44
|
-
> 3. **`auth.elevate` on every query** — without it, restricted collections silently return no items.
|
|
45
|
-
> 4. **CMS only for user collections** — use `@wix/blog` for blog posts, `@wix/stores` for products, `@wix/forms` for form submissions.
|
|
46
|
-
|
|
47
|
-
## Prerequisites (page-side)
|
|
48
|
-
|
|
49
|
-
- `@wix/data` + `@wix/essentials` installed (collected by SETUP.md Step 4c — do NOT install independently).
|
|
50
|
-
- The collections + items already created and seeded by the `seed` scope (see `../../cms/CMS_FOUNDATIONS.md`). Pages only **read**.
|
|
51
|
-
|
|
52
|
-
## Collection ID Format
|
|
53
|
-
|
|
54
|
-
Native (user-created) CMS collections use **just the collection name** — no namespace prefix.
|
|
55
|
-
|
|
56
|
-
Example: if the collection is called `Projects`, the collection ID is simply `"Projects"`.
|
|
57
|
-
|
|
58
|
-
Only Wix App collections (e.g., `Members/PublicData`, `Locations/Locations`) use a `<namespace>/<name>` format. User-created collections never use a namespace.
|
|
59
|
-
|
|
60
|
-
> **How to verify**: Call `GET /wix-data/v2/collections?fields=id` via `curl` (with the standard REST headers from `../../shared/AUTHENTICATION.md`) and use the exact `id` value from the response. Never guess — the dashboard name may differ from the ID.
|
|
61
|
-
|
|
62
|
-
## Quick Reference — Inline Query (Simple Pages)
|
|
63
|
-
|
|
64
|
-
For pages that just need to list items from a collection:
|
|
65
|
-
|
|
66
|
-
```astro
|
|
67
|
-
---
|
|
68
|
-
import { items } from "@wix/data";
|
|
69
|
-
import { auth } from "@wix/essentials";
|
|
70
|
-
|
|
71
|
-
// Always elevate queries for permission safety
|
|
72
|
-
const elevatedQuery = auth.elevate(items.query);
|
|
73
|
-
const { items: results } = await elevatedQuery("MyCollection")
|
|
74
|
-
.ascending("sortField")
|
|
75
|
-
.limit(50)
|
|
76
|
-
.find();
|
|
77
|
-
|
|
78
|
-
// Fields are directly on each item (NOT item.data.field)
|
|
79
|
-
const myItems = results.map((item) => ({
|
|
80
|
-
name: item.name, // correct
|
|
81
|
-
// name: item.data.name // wrong — REST pattern, not SDK
|
|
82
|
-
}));
|
|
83
|
-
---
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
> **Common mistake:** `items.queryDataItems(...)` does NOT exist in the
|
|
87
|
-
> `@wix/data` SDK. The REST API uses `/items/query` with a `dataCollectionId`
|
|
88
|
-
> body field, but the SDK uses `items.query("collectionId")` — a chainable
|
|
89
|
-
> QueryBuilder. Do not confuse REST and SDK patterns.
|
|
90
|
-
|
|
91
|
-
## Service Module Template
|
|
92
|
-
|
|
93
|
-
Every CMS use case follows the same `src/lib/{usecase}.ts` pattern — a typed interface and query functions that pages import.
|
|
94
|
-
|
|
95
|
-
```typescript
|
|
96
|
-
import { items } from "@wix/data";
|
|
97
|
-
import { auth } from "@wix/essentials";
|
|
98
|
-
import { media } from "@wix/sdk";
|
|
99
|
-
|
|
100
|
-
// -- Collection ID (use exact name from Wix dashboard — no namespace for native collections) --
|
|
101
|
-
const COLLECTION_ID = "collection-name";
|
|
102
|
-
|
|
103
|
-
// -- Typed interface matching collection fields --
|
|
104
|
-
export interface CollectionItem {
|
|
105
|
-
_id: string;
|
|
106
|
-
title: string;
|
|
107
|
-
slug: string;
|
|
108
|
-
// ...add fields matching your collection schema
|
|
109
|
-
coverImage?: string;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// -- Image resolution helper --
|
|
113
|
-
function resolveImage(wixImageUrl: string | undefined, width = 800, height = 600): string | undefined {
|
|
114
|
-
if (!wixImageUrl) return undefined;
|
|
115
|
-
return media.getScaledToFillImageUrl(wixImageUrl, width, height, {});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// -- Query all items --
|
|
119
|
-
// Wrap every Wix SDK await in try/catch. If the query throws at SSR, an empty
|
|
120
|
-
// array keeps the page renderable instead of crashing it. (Unguarded SSR
|
|
121
|
-
// awaits truncate Astro's response stream mid-body — nav renders, then blank.)
|
|
122
|
-
export async function queryItems(): Promise<CollectionItem[]> {
|
|
123
|
-
try {
|
|
124
|
-
const elevatedQuery = auth.elevate(items.query);
|
|
125
|
-
const { items: results } = await elevatedQuery(COLLECTION_ID)
|
|
126
|
-
.ascending("orderIndex")
|
|
127
|
-
.limit(50)
|
|
128
|
-
.find();
|
|
129
|
-
|
|
130
|
-
return results.map((item) => ({
|
|
131
|
-
...item,
|
|
132
|
-
coverImage: resolveImage(item.coverImage),
|
|
133
|
-
})) as CollectionItem[];
|
|
134
|
-
} catch (err) {
|
|
135
|
-
console.error(`[cms:${COLLECTION_ID}] query failed:`, err);
|
|
136
|
-
return [];
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// -- Get single item by slug --
|
|
141
|
-
export async function getItemBySlug(slug: string): Promise<CollectionItem | null> {
|
|
142
|
-
try {
|
|
143
|
-
const elevatedQuery = auth.elevate(items.query);
|
|
144
|
-
const { items: results } = await elevatedQuery(COLLECTION_ID)
|
|
145
|
-
.eq("slug", slug)
|
|
146
|
-
.limit(1)
|
|
147
|
-
.find();
|
|
148
|
-
|
|
149
|
-
const item = results[0];
|
|
150
|
-
if (!item) return null;
|
|
151
|
-
|
|
152
|
-
return {
|
|
153
|
-
...item,
|
|
154
|
-
coverImage: resolveImage(item.coverImage),
|
|
155
|
-
} as CollectionItem;
|
|
156
|
-
} catch (err) {
|
|
157
|
-
console.error(`[cms:${COLLECTION_ID}] getItemBySlug failed:`, err);
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
Key details:
|
|
164
|
-
- `auth.elevate(items.query)` wraps the query for restricted collections — always use this by default since collection permissions vary
|
|
165
|
-
- `media.getScaledToFillImageUrl(url, w, h, {})` resolves `wix:image://` URLs to sized CDN URLs
|
|
166
|
-
- Sort by `orderIndex` (ascending) for manually ordered content, or `_createdDate` (descending) for chronological
|
|
167
|
-
- The interface must match the collection fields — check the dashboard, don't guess
|
|
168
|
-
|
|
169
|
-
## Multi-Image Resolution
|
|
170
|
-
|
|
171
|
-
For collections with image arrays (e.g., gallery images):
|
|
172
|
-
|
|
173
|
-
```typescript
|
|
174
|
-
function resolveImages(imageUrls: string[] | undefined, width = 800, height = 600): string[] {
|
|
175
|
-
if (!imageUrls || imageUrls.length === 0) return [];
|
|
176
|
-
return imageUrls
|
|
177
|
-
.map((url) => media.getScaledToFillImageUrl(url, width, height, {}))
|
|
178
|
-
.filter(Boolean);
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
## Category Filtering Pattern
|
|
183
|
-
|
|
184
|
-
Many use cases filter by category via URL search params (server-rendered, no client JS):
|
|
185
|
-
|
|
186
|
-
```astro
|
|
187
|
-
---
|
|
188
|
-
const activeCategory = Astro.url.searchParams.get("category");
|
|
189
|
-
const allItems = await queryItems();
|
|
190
|
-
const filtered = activeCategory
|
|
191
|
-
? allItems.filter((item) => item.category === activeCategory)
|
|
192
|
-
: allItems;
|
|
193
|
-
const categories = [...new Set(allItems.map((item) => item.category).filter(Boolean))];
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
<nav>
|
|
197
|
-
<a href="?" class:list={[!activeCategory && "active"]}>All</a>
|
|
198
|
-
{categories.map((cat) => (
|
|
199
|
-
<a
|
|
200
|
-
href={`?category=${encodeURIComponent(cat)}`}
|
|
201
|
-
class:list={[activeCategory === cat && "active"]}
|
|
202
|
-
>{cat}</a>
|
|
203
|
-
))}
|
|
204
|
-
</nav>
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
> **Styling note:** Category filter pill styling composes `@theme` tokens as Tailwind utilities at the call site — see `../../shared/STYLING.md`.
|
|
208
|
-
|
|
209
|
-
## Testing
|
|
210
|
-
|
|
211
|
-
1. Confirm the collection exists in the Wix dashboard → CMS (the `seed` scope created it — see `../../cms/CMS_FOUNDATIONS.md`).
|
|
212
|
-
2. Run `npx @wix/cli@latest dev`.
|
|
213
|
-
3. Navigate to the listing page — should show items.
|
|
214
|
-
4. Click an item — should navigate to the detail page.
|
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
# Recipe: FAQ / Knowledge Base
|
|
2
|
-
|
|
3
|
-
Build a FAQ page using `@wix/data` — Q&A pairs organized by category with accordion UI and client-side search. Use for frequently asked questions, help centers, or knowledge bases.
|
|
4
|
-
|
|
5
|
-
> Read `CMS_FOUNDATIONS.md` (this folder — service module, query patterns, image resolution, elevation) for page-rendering patterns, and `../../cms/CMS_FOUNDATIONS.md` for REST-based seeding.
|
|
6
|
-
|
|
7
|
-
## Collection Schema
|
|
8
|
-
|
|
9
|
-
The schema the `seed` scope creates via REST (see `../../cms/CMS_FOUNDATIONS.md`) — fields:
|
|
10
|
-
|
|
11
|
-
| Field | Type | Purpose |
|
|
12
|
-
|-------|------|---------|
|
|
13
|
-
| `question` | Text | The question |
|
|
14
|
-
| `slug` | Text | URL-friendly identifier (for anchor links) |
|
|
15
|
-
| `answer` | Rich Text | The answer (HTML) |
|
|
16
|
-
| `category` | Text | FAQ category (e.g., "Shipping", "Returns") |
|
|
17
|
-
| `orderIndex` | Number | Manual sort order within category |
|
|
18
|
-
| `published` | Boolean | Publish status |
|
|
19
|
-
|
|
20
|
-
## Files to Create
|
|
21
|
-
|
|
22
|
-
| File | Purpose |
|
|
23
|
-
|------|---------|
|
|
24
|
-
| `src/lib/faq.ts` | Service module — queries, category grouping |
|
|
25
|
-
| `src/pages/faq/index.astro` | Single FAQ page with category sections |
|
|
26
|
-
| `src/components/FaqSection.tsx` | React island — accordion + search combined |
|
|
27
|
-
|
|
28
|
-
> FAQ is a single-page pattern — no detail pages needed.
|
|
29
|
-
|
|
30
|
-
## Implementation
|
|
31
|
-
|
|
32
|
-
### 1. FAQ Service Module (`src/lib/faq.ts`)
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
import { items } from "@wix/data";
|
|
36
|
-
import { auth } from "@wix/essentials";
|
|
37
|
-
|
|
38
|
-
const COLLECTION_ID = "FAQ";
|
|
39
|
-
|
|
40
|
-
export interface FaqItem {
|
|
41
|
-
_id: string;
|
|
42
|
-
question: string;
|
|
43
|
-
slug: string;
|
|
44
|
-
answer: string;
|
|
45
|
-
category: string;
|
|
46
|
-
orderIndex: number;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function mapFaqItem(item: Record<string, any>): FaqItem {
|
|
50
|
-
return {
|
|
51
|
-
_id: item._id,
|
|
52
|
-
question: item.question ?? "",
|
|
53
|
-
slug: item.slug ?? "",
|
|
54
|
-
answer: item.answer ?? "",
|
|
55
|
-
category: item.category ?? "General",
|
|
56
|
-
orderIndex: item.orderIndex ?? 0,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export async function queryFaqItems(): Promise<FaqItem[]> {
|
|
61
|
-
const elevatedQuery = auth.elevate(items.query);
|
|
62
|
-
const { items: results } = await elevatedQuery(COLLECTION_ID)
|
|
63
|
-
.eq("published", true)
|
|
64
|
-
.ascending("orderIndex")
|
|
65
|
-
.limit(200)
|
|
66
|
-
.find();
|
|
67
|
-
|
|
68
|
-
return results.map(mapFaqItem);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function groupByCategory(faqItems: FaqItem[]): Map<string, FaqItem[]> {
|
|
72
|
-
return faqItems.reduce((map, item) => {
|
|
73
|
-
const cat = item.category || "General";
|
|
74
|
-
if (!map.has(cat)) map.set(cat, []);
|
|
75
|
-
map.get(cat)!.push(item);
|
|
76
|
-
return map;
|
|
77
|
-
}, new Map<string, FaqItem[]>());
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
Key details:
|
|
82
|
-
- No image resolution needed — FAQ items are text-only
|
|
83
|
-
- `published` filter ensures draft items don't appear
|
|
84
|
-
- Higher limit (200) since FAQ items are lightweight
|
|
85
|
-
- Update `COLLECTION_ID` to match the exact collection name from the Wix dashboard (no namespace prefix for native collections)
|
|
86
|
-
|
|
87
|
-
### 2. FAQ Section React Island (`src/components/FaqSection.tsx`)
|
|
88
|
-
|
|
89
|
-
```tsx
|
|
90
|
-
import { useState } from "react";
|
|
91
|
-
|
|
92
|
-
interface FaqItem {
|
|
93
|
-
_id: string;
|
|
94
|
-
question: string;
|
|
95
|
-
slug: string;
|
|
96
|
-
answer: string;
|
|
97
|
-
category: string;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
interface Props {
|
|
101
|
-
categories: Array<{ name: string; items: FaqItem[] }>;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export default function FaqSection({ categories }: Props) {
|
|
105
|
-
const [search, setSearch] = useState("");
|
|
106
|
-
const query = search.toLowerCase().trim();
|
|
107
|
-
|
|
108
|
-
const filtered = query
|
|
109
|
-
? categories
|
|
110
|
-
.map((cat) => ({
|
|
111
|
-
...cat,
|
|
112
|
-
items: cat.items.filter(
|
|
113
|
-
(item) =>
|
|
114
|
-
item.question.toLowerCase().includes(query) ||
|
|
115
|
-
item.answer.toLowerCase().includes(query)
|
|
116
|
-
),
|
|
117
|
-
}))
|
|
118
|
-
.filter((cat) => cat.items.length > 0)
|
|
119
|
-
: categories;
|
|
120
|
-
|
|
121
|
-
return (
|
|
122
|
-
<div>
|
|
123
|
-
<div>
|
|
124
|
-
<input
|
|
125
|
-
type="text"
|
|
126
|
-
placeholder="Search questions..."
|
|
127
|
-
value={search}
|
|
128
|
-
onChange={(e) => setSearch(e.target.value)}
|
|
129
|
-
className="faq-search"
|
|
130
|
-
/>
|
|
131
|
-
</div>
|
|
132
|
-
|
|
133
|
-
{filtered.length === 0 && (
|
|
134
|
-
<p>No matching questions found.</p>
|
|
135
|
-
)}
|
|
136
|
-
|
|
137
|
-
{filtered.map((cat) => (
|
|
138
|
-
<section key={cat.name} className="faq-section" id={cat.name.toLowerCase().replace(/\s+/g, "-")}>
|
|
139
|
-
<h2 className="faq-category">{cat.name}</h2>
|
|
140
|
-
<div>
|
|
141
|
-
{cat.items.map((item) => (
|
|
142
|
-
<details key={item._id} className="faq-item" id={item.slug}>
|
|
143
|
-
<summary className="faq-question">
|
|
144
|
-
<span>{item.question}</span>
|
|
145
|
-
<svg
|
|
146
|
-
className="faq-toggle"
|
|
147
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
148
|
-
viewBox="0 0 24 24"
|
|
149
|
-
fill="none"
|
|
150
|
-
stroke="currentColor"
|
|
151
|
-
strokeWidth="2"
|
|
152
|
-
strokeLinecap="round"
|
|
153
|
-
strokeLinejoin="round"
|
|
154
|
-
>
|
|
155
|
-
<polyline points="6 9 12 15 18 9" />
|
|
156
|
-
</svg>
|
|
157
|
-
</summary>
|
|
158
|
-
<div
|
|
159
|
-
className="faq-answer"
|
|
160
|
-
dangerouslySetInnerHTML={{ __html: item.answer }}
|
|
161
|
-
/>
|
|
162
|
-
</details>
|
|
163
|
-
))}
|
|
164
|
-
</div>
|
|
165
|
-
</section>
|
|
166
|
-
))}
|
|
167
|
-
</div>
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
> **Styling note:** Uses `.faq-search`, `.faq-section`, `.faq-category`, `.faq-item`, `.faq-question`, `.faq-toggle`, `.faq-answer` from the designed component's `<style is:global>` block. See `references/shared/STYLING.md` (FAQ Accordion).
|
|
173
|
-
|
|
174
|
-
Key details:
|
|
175
|
-
- `<details>/<summary>` for native accordion behavior — no JavaScript needed for open/close
|
|
176
|
-
- CSS transition on the chevron via the `.faq-toggle` class
|
|
177
|
-
- Client-side search filters across both question and answer text
|
|
178
|
-
- `dangerouslySetInnerHTML` for rich text answers (content is from the CMS, not user input)
|
|
179
|
-
- Anchor `id` on each category section and question for direct linking
|
|
180
|
-
|
|
181
|
-
### 3. FAQ Page (`src/pages/faq/index.astro`)
|
|
182
|
-
|
|
183
|
-
**Layout width:** Center the page column with `container-reading` (from designer `global.css`) or `max-w-6xl mx-auto px-6` when `--container-6xl` exists in `@theme`. **Do not** use `max-w-3xl` unless `--container-3xl` is declared in `@theme` — with only a spacing scale, Tailwind maps `max-w-3xl` to ~5rem and the FAQ collapses to one word per line. See `references/shared/STYLING.md` § "Prose / reading width".
|
|
184
|
-
|
|
185
|
-
```astro
|
|
186
|
-
---
|
|
187
|
-
import Layout from "../../layouts/Layout.astro";
|
|
188
|
-
import FaqSection from "../../components/FaqSection";
|
|
189
|
-
import { queryFaqItems, groupByCategory } from "../../lib/faq";
|
|
190
|
-
|
|
191
|
-
const faqItems = await queryFaqItems();
|
|
192
|
-
const grouped = groupByCategory(faqItems);
|
|
193
|
-
const categories = [...grouped.entries()].map(([name, items]) => ({ name, items }));
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
<Layout title="FAQ">
|
|
197
|
-
<main>
|
|
198
|
-
<div class="container-reading px-6">
|
|
199
|
-
<h1>Frequently Asked Questions</h1>
|
|
200
|
-
<p>Find answers to common questions below, or use the search to find what you need.</p>
|
|
201
|
-
|
|
202
|
-
{categories.length > 1 && (
|
|
203
|
-
<nav>
|
|
204
|
-
{categories.map((cat) => (
|
|
205
|
-
<a
|
|
206
|
-
href={`#${cat.name.toLowerCase().replace(/\s+/g, "-")}`}
|
|
207
|
-
>{cat.name}</a>
|
|
208
|
-
))}
|
|
209
|
-
</nav>
|
|
210
|
-
)}
|
|
211
|
-
|
|
212
|
-
<FaqSection client:only="react" categories={categories} />
|
|
213
|
-
</div>
|
|
214
|
-
</main>
|
|
215
|
-
</Layout>
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
Key details:
|
|
219
|
-
- Category jump links in the nav work because `FaqSection` renders matching `id` attributes
|
|
220
|
-
- `client:only="react"` — required for search state
|
|
221
|
-
- Data is fetched server-side and passed as props to the React island
|
|
222
|
-
|
|
223
|
-
## Testing
|
|
224
|
-
|
|
225
|
-
Assumes the `seed` scope has already created the "FAQ" collection and inserted items via REST (see `../../cms/CMS_FOUNDATIONS.md`) — with 6+ FAQ items across 2+ categories, all `published: true`.
|
|
226
|
-
|
|
227
|
-
1. Run `npx @wix/cli@latest dev`
|
|
228
|
-
2. `/faq` — shows all questions grouped by category
|
|
229
|
-
3. Click a question — accordion opens with the answer
|
|
230
|
-
4. Type in search — filters questions in real-time
|
|
231
|
-
5. Click a category jump link — scrolls to that section
|