@wix/agent-skills 1.13.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 -244
- 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/Footer.astro +0 -27
- package/skills/wix-headless/references/astro/templates/Layout.astro +0 -132
- package/skills/wix-headless/references/astro/templates/Navigation.astro +0 -38
- 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/index.astro +0 -56
- 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 -141
- 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 -525
- 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 -148
- 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,354 +0,0 @@
|
|
|
1
|
-
# Recipe: Resource Library / Downloads
|
|
2
|
-
|
|
3
|
-
Build a downloadable resource library using `@wix/data` — file listings with category filtering, file type badges, and detail pages with download buttons. Use for documents, guides, templates, whitepapers, or any downloadable assets.
|
|
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
|
-
| `title` | Text | Resource name |
|
|
14
|
-
| `slug` | Text | URL-friendly identifier |
|
|
15
|
-
| `description` | Rich Text | Resource description (HTML) |
|
|
16
|
-
| `category` | Text | Resource category (e.g., "Guides", "Templates") |
|
|
17
|
-
| `fileType` | Text | File extension — `PDF`, `DOC`, `ZIP`, `XLS`, etc. |
|
|
18
|
-
| `fileUrl` | URL | Download URL (external link or Wix media URL) |
|
|
19
|
-
| `fileSize` | Text | Human-readable file size (e.g., "2.4 MB") |
|
|
20
|
-
| `coverImage` | Image | Thumbnail (`wix:image://` — resolve with `media.getScaledToFillImageUrl()`) |
|
|
21
|
-
| `published` | Boolean | Publish status |
|
|
22
|
-
| `_createdDate` | Date | Auto-populated creation date |
|
|
23
|
-
|
|
24
|
-
## Files to Create
|
|
25
|
-
|
|
26
|
-
| File | Purpose |
|
|
27
|
-
|------|---------|
|
|
28
|
-
| `src/lib/resources.ts` | Service module — queries, category filtering, related resources |
|
|
29
|
-
| `src/pages/resources/index.astro` | Listing with category filter + file type badges |
|
|
30
|
-
| `src/pages/resources/[slug].astro` | Detail page with download button + related resources |
|
|
31
|
-
| `src/components/ResourceCard.astro` | Card with file type icon, title, size |
|
|
32
|
-
| `src/components/FileTypeIcon.astro` | SVG switch for PDF/DOC/ZIP/generic |
|
|
33
|
-
|
|
34
|
-
## Implementation
|
|
35
|
-
|
|
36
|
-
### 1. Resources Service Module (`src/lib/resources.ts`)
|
|
37
|
-
|
|
38
|
-
```typescript
|
|
39
|
-
import { items } from "@wix/data";
|
|
40
|
-
import { auth } from "@wix/essentials";
|
|
41
|
-
import { media } from "@wix/sdk";
|
|
42
|
-
|
|
43
|
-
const COLLECTION_ID = "Resources";
|
|
44
|
-
|
|
45
|
-
export interface Resource {
|
|
46
|
-
_id: string;
|
|
47
|
-
title: string;
|
|
48
|
-
slug: string;
|
|
49
|
-
description?: string;
|
|
50
|
-
category: string;
|
|
51
|
-
fileType: string;
|
|
52
|
-
fileUrl: string;
|
|
53
|
-
fileSize?: string;
|
|
54
|
-
coverImage?: string;
|
|
55
|
-
published: boolean;
|
|
56
|
-
_createdDate?: string;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function resolveImage(url: string | undefined): string | undefined {
|
|
60
|
-
if (!url) return undefined;
|
|
61
|
-
return media.getScaledToFillImageUrl(url, 600, 400, {});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function mapResource(item: Record<string, any>): Resource {
|
|
65
|
-
return {
|
|
66
|
-
_id: item._id,
|
|
67
|
-
title: item.title ?? "",
|
|
68
|
-
slug: item.slug ?? "",
|
|
69
|
-
description: item.description,
|
|
70
|
-
category: item.category ?? "",
|
|
71
|
-
fileType: (item.fileType ?? "FILE").toUpperCase(),
|
|
72
|
-
fileUrl: item.fileUrl ?? "",
|
|
73
|
-
fileSize: item.fileSize,
|
|
74
|
-
coverImage: resolveImage(item.coverImage),
|
|
75
|
-
published: item.published ?? false,
|
|
76
|
-
_createdDate: item._createdDate,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export async function queryResources(): Promise<Resource[]> {
|
|
81
|
-
const elevatedQuery = auth.elevate(items.query);
|
|
82
|
-
const { items: results } = await elevatedQuery(COLLECTION_ID)
|
|
83
|
-
.eq("published", true)
|
|
84
|
-
.descending("_createdDate")
|
|
85
|
-
.limit(50)
|
|
86
|
-
.find();
|
|
87
|
-
|
|
88
|
-
return results.map(mapResource);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export async function getResourceBySlug(slug: string): Promise<Resource | null> {
|
|
92
|
-
const elevatedQuery = auth.elevate(items.query);
|
|
93
|
-
const { items: results } = await elevatedQuery(COLLECTION_ID)
|
|
94
|
-
.eq("slug", slug)
|
|
95
|
-
.eq("published", true)
|
|
96
|
-
.limit(1)
|
|
97
|
-
.find();
|
|
98
|
-
|
|
99
|
-
const item = results[0];
|
|
100
|
-
if (!item) return null;
|
|
101
|
-
return mapResource(item);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export async function queryRelatedResources(category: string, excludeId: string, limit = 3): Promise<Resource[]> {
|
|
105
|
-
const elevatedQuery = auth.elevate(items.query);
|
|
106
|
-
const { items: results } = await elevatedQuery(COLLECTION_ID)
|
|
107
|
-
.eq("published", true)
|
|
108
|
-
.eq("category", category)
|
|
109
|
-
.ne("_id", excludeId)
|
|
110
|
-
.descending("_createdDate")
|
|
111
|
-
.limit(limit)
|
|
112
|
-
.find();
|
|
113
|
-
|
|
114
|
-
return results.map(mapResource);
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
Key details:
|
|
119
|
-
- `queryRelatedResources()` finds same-category items excluding the current one
|
|
120
|
-
- `fileType` normalized to uppercase for consistent badge display
|
|
121
|
-
- Sorted by `_createdDate` descending (newest first)
|
|
122
|
-
- Update `COLLECTION_ID` to match the exact collection name from the Wix dashboard (no namespace prefix for native collections)
|
|
123
|
-
|
|
124
|
-
### 2. File Type Icon (`src/components/FileTypeIcon.astro`)
|
|
125
|
-
|
|
126
|
-
```astro
|
|
127
|
-
---
|
|
128
|
-
interface Props {
|
|
129
|
-
type: string;
|
|
130
|
-
class?: string;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const { type, class: className = "w-8 h-8" } = Astro.props;
|
|
134
|
-
const fileType = type.toUpperCase();
|
|
135
|
-
|
|
136
|
-
// File type colors are applied by the design skill's component styles
|
|
137
|
-
---
|
|
138
|
-
|
|
139
|
-
<div class={className}>
|
|
140
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="w-full h-full">
|
|
141
|
-
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" />
|
|
142
|
-
<polyline points="14 2 14 8 20 8" />
|
|
143
|
-
<text x="12" y="17" text-anchor="middle" font-size="5" fill="currentColor" stroke="none" font-weight="bold">{fileType.slice(0, 4)}</text>
|
|
144
|
-
</svg>
|
|
145
|
-
</div>
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
Key details:
|
|
149
|
-
- The SVG uses `stroke="currentColor"` — any per-file-type coloring is purely CSS-driven (e.g. a `.file-type-pdf` class on the wrapper), not set here
|
|
150
|
-
- File type label rendered inside the document icon SVG
|
|
151
|
-
|
|
152
|
-
### 3. Resource Card (`src/components/ResourceCard.astro`)
|
|
153
|
-
|
|
154
|
-
```astro
|
|
155
|
-
---
|
|
156
|
-
import FileTypeIcon from "./FileTypeIcon.astro";
|
|
157
|
-
|
|
158
|
-
interface Props {
|
|
159
|
-
resource: {
|
|
160
|
-
title: string;
|
|
161
|
-
slug: string;
|
|
162
|
-
category: string;
|
|
163
|
-
fileType: string;
|
|
164
|
-
fileSize?: string;
|
|
165
|
-
coverImage?: string;
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const { resource } = Astro.props;
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
<a href={`/resources/${resource.slug}`}>
|
|
173
|
-
{resource.coverImage ? (
|
|
174
|
-
<div><img src={resource.coverImage} alt={resource.title} /></div>
|
|
175
|
-
) : (
|
|
176
|
-
<div><FileTypeIcon type={resource.fileType} /></div>
|
|
177
|
-
)}
|
|
178
|
-
<div>
|
|
179
|
-
<div>
|
|
180
|
-
<span>{resource.fileType}</span>
|
|
181
|
-
{resource.fileSize && <span>{resource.fileSize}</span>}
|
|
182
|
-
</div>
|
|
183
|
-
<h3>{resource.title}</h3>
|
|
184
|
-
<p>{resource.category}</p>
|
|
185
|
-
</div>
|
|
186
|
-
</a>
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
> **Styling note:** ResourceCard styling is created by the design skill. See `references/shared/STYLING.md` (Resource Card).
|
|
190
|
-
|
|
191
|
-
### 4. Resource Listing Page (`src/pages/resources/index.astro`)
|
|
192
|
-
|
|
193
|
-
```astro
|
|
194
|
-
---
|
|
195
|
-
import Layout from "../../layouts/Layout.astro";
|
|
196
|
-
import ResourceCard from "../../components/ResourceCard.astro";
|
|
197
|
-
import CategoryFilter from "../../components/CategoryFilter.astro";
|
|
198
|
-
import { queryResources } from "../../lib/resources";
|
|
199
|
-
|
|
200
|
-
const activeCategory = Astro.url.searchParams.get("category");
|
|
201
|
-
const allResources = await queryResources();
|
|
202
|
-
const filtered = activeCategory
|
|
203
|
-
? allResources.filter((r) => r.category === activeCategory)
|
|
204
|
-
: allResources;
|
|
205
|
-
const categories = [...new Set(allResources.map((r) => r.category).filter(Boolean))];
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
<Layout title="Resources">
|
|
209
|
-
<main>
|
|
210
|
-
<div>
|
|
211
|
-
<h1>Resources</h1>
|
|
212
|
-
<p>Download guides, templates, and documents.</p>
|
|
213
|
-
|
|
214
|
-
<CategoryFilter categories={categories} activeCategory={activeCategory} basePath="/resources" />
|
|
215
|
-
|
|
216
|
-
<div>
|
|
217
|
-
{filtered.map((resource) => (
|
|
218
|
-
<ResourceCard resource={resource} />
|
|
219
|
-
))}
|
|
220
|
-
</div>
|
|
221
|
-
|
|
222
|
-
{filtered.length === 0 && (
|
|
223
|
-
<p>No resources found.</p>
|
|
224
|
-
)}
|
|
225
|
-
</div>
|
|
226
|
-
</main>
|
|
227
|
-
</Layout>
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
> Reuses the same `CategoryFilter.astro` component from the portfolio use case. If building both, no need to create it twice.
|
|
231
|
-
|
|
232
|
-
### 5. Resource Detail Page (`src/pages/resources/[slug].astro`)
|
|
233
|
-
|
|
234
|
-
```astro
|
|
235
|
-
---
|
|
236
|
-
import Layout from "../../layouts/Layout.astro";
|
|
237
|
-
import ResourceCard from "../../components/ResourceCard.astro";
|
|
238
|
-
import FileTypeIcon from "../../components/FileTypeIcon.astro";
|
|
239
|
-
import { getResourceBySlug, queryRelatedResources } from "../../lib/resources";
|
|
240
|
-
|
|
241
|
-
const { slug } = Astro.params;
|
|
242
|
-
const resource = await getResourceBySlug(slug!);
|
|
243
|
-
if (!resource) return Astro.redirect("/404");
|
|
244
|
-
|
|
245
|
-
const related = await queryRelatedResources(resource.category, resource._id);
|
|
246
|
-
|
|
247
|
-
const date = resource._createdDate
|
|
248
|
-
? new Date(resource._createdDate).toLocaleDateString("en-US", {
|
|
249
|
-
year: "numeric",
|
|
250
|
-
month: "long",
|
|
251
|
-
day: "numeric",
|
|
252
|
-
})
|
|
253
|
-
: "";
|
|
254
|
-
---
|
|
255
|
-
|
|
256
|
-
<Layout title={resource.title}>
|
|
257
|
-
<main>
|
|
258
|
-
<div>
|
|
259
|
-
<a href="/resources">
|
|
260
|
-
← Back to resources
|
|
261
|
-
</a>
|
|
262
|
-
|
|
263
|
-
<div>
|
|
264
|
-
<FileTypeIcon type={resource.fileType} />
|
|
265
|
-
<div>
|
|
266
|
-
<div>
|
|
267
|
-
<span>{resource.fileType}</span>
|
|
268
|
-
{resource.fileSize && (
|
|
269
|
-
<span>{resource.fileSize}</span>
|
|
270
|
-
)}
|
|
271
|
-
</div>
|
|
272
|
-
{date && <p>Added {date}</p>}
|
|
273
|
-
</div>
|
|
274
|
-
</div>
|
|
275
|
-
|
|
276
|
-
<h1>{resource.title}</h1>
|
|
277
|
-
|
|
278
|
-
{resource.coverImage && (
|
|
279
|
-
<div>
|
|
280
|
-
<img
|
|
281
|
-
src={resource.coverImage}
|
|
282
|
-
alt={resource.title}
|
|
283
|
-
/>
|
|
284
|
-
</div>
|
|
285
|
-
)}
|
|
286
|
-
|
|
287
|
-
{resource.description && (
|
|
288
|
-
<article set:html={resource.description} />
|
|
289
|
-
)}
|
|
290
|
-
|
|
291
|
-
{resource.fileUrl && (
|
|
292
|
-
<a
|
|
293
|
-
href={resource.fileUrl}
|
|
294
|
-
download
|
|
295
|
-
>
|
|
296
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
|
297
|
-
Download {resource.fileType}
|
|
298
|
-
</a>
|
|
299
|
-
)}
|
|
300
|
-
|
|
301
|
-
{related.length > 0 && (
|
|
302
|
-
<section>
|
|
303
|
-
<h2>Related Resources</h2>
|
|
304
|
-
<div>
|
|
305
|
-
{related.map((r) => (
|
|
306
|
-
<ResourceCard resource={r} />
|
|
307
|
-
))}
|
|
308
|
-
</div>
|
|
309
|
-
</section>
|
|
310
|
-
)}
|
|
311
|
-
</div>
|
|
312
|
-
</main>
|
|
313
|
-
</Layout>
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
Key details:
|
|
317
|
-
- `<a download>` triggers browser download for the file
|
|
318
|
-
- Related resources query pulls same-category items, excluding the current one
|
|
319
|
-
- File type icon and badge prominently displayed
|
|
320
|
-
|
|
321
|
-
## Seed with Images
|
|
322
|
-
|
|
323
|
-
After seeding resources via REST, generate cover images following `../../shared/IMAGE_GENERATION.md` and `../../cms/CMS_FOUNDATIONS.md` → "Seeding with Images".
|
|
324
|
-
|
|
325
|
-
**Prompt template:**
|
|
326
|
-
|
|
327
|
-
```
|
|
328
|
-
Cover image for [TITLE], a [FILE TYPE]. Abstract [BRAND AESTHETIC]. Color tones: [BRAND COLORS]. No text, no watermarks
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
**Patch field:** `coverImage`
|
|
332
|
-
|
|
333
|
-
Example patch:
|
|
334
|
-
|
|
335
|
-
```
|
|
336
|
-
REST: PATCH https://www.wixapis.com/wix-data/v2/items/{resourceId}
|
|
337
|
-
body: {
|
|
338
|
-
"dataCollectionId": "Resources",
|
|
339
|
-
"dataItem": {
|
|
340
|
-
"data": {
|
|
341
|
-
"coverImage": "<wixstatic-url>"
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
## Testing
|
|
348
|
-
|
|
349
|
-
Assumes the `seed` scope has already created the "Resources" collection and inserted items via REST (see `../../cms/CMS_FOUNDATIONS.md`) — 4+ resources across 2+ categories with different file types (PDF, DOC, ZIP) and `fileUrl` links (any downloadable URL for testing).
|
|
350
|
-
|
|
351
|
-
1. Run `npx @wix/cli@latest dev`
|
|
352
|
-
2. `/resources` — shows all resources with category filters and file type badges
|
|
353
|
-
3. Click a category — filters resources
|
|
354
|
-
4. Click a resource — detail page with download button and related resources
|
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
# Recipe: Team / Staff Directory
|
|
2
|
-
|
|
3
|
-
Build a team directory using `@wix/data` — staff cards grouped by department with individual profile pages. Use for about us, our team, meet the staff, or any people directory.
|
|
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
|
-
| `name` | Text | Full name |
|
|
14
|
-
| `slug` | Text | URL-friendly identifier |
|
|
15
|
-
| `role` | Text | Job title or role |
|
|
16
|
-
| `department` | Text | Department or team (e.g., "Engineering", "Design") |
|
|
17
|
-
| `bio` | Rich Text | Bio or description (HTML) |
|
|
18
|
-
| `photo` | Image | Headshot (`wix:image://` — resolve with `media.getScaledToFillImageUrl()`) |
|
|
19
|
-
| `email` | Text | Contact email |
|
|
20
|
-
| `linkedIn` | URL | LinkedIn profile URL |
|
|
21
|
-
| `twitter` | URL | Twitter/X profile URL |
|
|
22
|
-
| `orderIndex` | Number | Manual sort order within department |
|
|
23
|
-
|
|
24
|
-
## Files to Create
|
|
25
|
-
|
|
26
|
-
| File | Purpose |
|
|
27
|
-
|------|---------|
|
|
28
|
-
| `src/lib/team.ts` | Service module — queries, department grouping |
|
|
29
|
-
| `src/pages/team/index.astro` | Department-sectioned directory |
|
|
30
|
-
| `src/pages/team/[slug].astro` | Individual member profile |
|
|
31
|
-
| `src/components/TeamMemberCard.astro` | Photo, name, role, social icons |
|
|
32
|
-
|
|
33
|
-
## Implementation
|
|
34
|
-
|
|
35
|
-
### 1. Team Service Module (`src/lib/team.ts`)
|
|
36
|
-
|
|
37
|
-
```typescript
|
|
38
|
-
import { items } from "@wix/data";
|
|
39
|
-
import { auth } from "@wix/essentials";
|
|
40
|
-
import { media } from "@wix/sdk";
|
|
41
|
-
|
|
42
|
-
const COLLECTION_ID = "Team";
|
|
43
|
-
|
|
44
|
-
export interface TeamMember {
|
|
45
|
-
_id: string;
|
|
46
|
-
name: string;
|
|
47
|
-
slug: string;
|
|
48
|
-
role: string;
|
|
49
|
-
department: string;
|
|
50
|
-
bio?: string;
|
|
51
|
-
photo?: string;
|
|
52
|
-
email?: string;
|
|
53
|
-
linkedIn?: string;
|
|
54
|
-
twitter?: string;
|
|
55
|
-
orderIndex: number;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function resolvePhoto(url: string | undefined): string | undefined {
|
|
59
|
-
if (!url) return undefined;
|
|
60
|
-
return media.getScaledToFillImageUrl(url, 400, 400, {});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function mapMember(item: Record<string, any>): TeamMember {
|
|
64
|
-
return {
|
|
65
|
-
_id: item._id,
|
|
66
|
-
name: item.name ?? "",
|
|
67
|
-
slug: item.slug ?? "",
|
|
68
|
-
role: item.role ?? "",
|
|
69
|
-
department: item.department ?? "",
|
|
70
|
-
bio: item.bio,
|
|
71
|
-
photo: resolvePhoto(item.photo),
|
|
72
|
-
email: item.email,
|
|
73
|
-
linkedIn: item.linkedIn,
|
|
74
|
-
twitter: item.twitter,
|
|
75
|
-
orderIndex: item.orderIndex ?? 0,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export async function queryTeamMembers(): Promise<TeamMember[]> {
|
|
80
|
-
const elevatedQuery = auth.elevate(items.query);
|
|
81
|
-
const { items: results } = await elevatedQuery(COLLECTION_ID)
|
|
82
|
-
.ascending("orderIndex")
|
|
83
|
-
.limit(100)
|
|
84
|
-
.find();
|
|
85
|
-
|
|
86
|
-
return results.map(mapMember);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export async function getMemberBySlug(slug: string): Promise<TeamMember | null> {
|
|
90
|
-
const elevatedQuery = auth.elevate(items.query);
|
|
91
|
-
const { items: results } = await elevatedQuery(COLLECTION_ID)
|
|
92
|
-
.eq("slug", slug)
|
|
93
|
-
.limit(1)
|
|
94
|
-
.find();
|
|
95
|
-
|
|
96
|
-
const item = results[0];
|
|
97
|
-
if (!item) return null;
|
|
98
|
-
return mapMember(item);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export function groupByDepartment(members: TeamMember[]): Map<string, TeamMember[]> {
|
|
102
|
-
return members.reduce((map, member) => {
|
|
103
|
-
const dept = member.department || "Team";
|
|
104
|
-
if (!map.has(dept)) map.set(dept, []);
|
|
105
|
-
map.get(dept)!.push(member);
|
|
106
|
-
return map;
|
|
107
|
-
}, new Map<string, TeamMember[]>());
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
Key details:
|
|
112
|
-
- `resolvePhoto()` uses 400x400 for square headshot crops
|
|
113
|
-
- `groupByDepartment()` returns a `Map` preserving insertion order — departments appear in the order of their first member
|
|
114
|
-
- Update `COLLECTION_ID` to match the exact collection name from the Wix dashboard (no namespace prefix for native collections)
|
|
115
|
-
|
|
116
|
-
### 2. Team Member Card (`src/components/TeamMemberCard.astro`)
|
|
117
|
-
|
|
118
|
-
```astro
|
|
119
|
-
---
|
|
120
|
-
interface Props {
|
|
121
|
-
member: {
|
|
122
|
-
name: string;
|
|
123
|
-
slug: string;
|
|
124
|
-
role: string;
|
|
125
|
-
photo?: string;
|
|
126
|
-
email?: string;
|
|
127
|
-
linkedIn?: string;
|
|
128
|
-
twitter?: string;
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const { member } = Astro.props;
|
|
133
|
-
---
|
|
134
|
-
|
|
135
|
-
<a href={`/team/${member.slug}`}>
|
|
136
|
-
<div>
|
|
137
|
-
{member.photo ? (
|
|
138
|
-
<img src={member.photo} alt={member.name} />
|
|
139
|
-
) : (
|
|
140
|
-
<div>{member.name.charAt(0)}</div>
|
|
141
|
-
)}
|
|
142
|
-
</div>
|
|
143
|
-
<h3>{member.name}</h3>
|
|
144
|
-
<p>{member.role}</p>
|
|
145
|
-
<div>
|
|
146
|
-
{member.email && (
|
|
147
|
-
<a href={`mailto:${member.email}`} onclick="event.stopPropagation()">Email</a>
|
|
148
|
-
)}
|
|
149
|
-
{member.linkedIn && (
|
|
150
|
-
<a href={member.linkedIn} target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()">LinkedIn</a>
|
|
151
|
-
)}
|
|
152
|
-
{member.twitter && (
|
|
153
|
-
<a href={member.twitter} target="_blank" rel="noopener noreferrer" onclick="event.stopPropagation()">Twitter</a>
|
|
154
|
-
)}
|
|
155
|
-
</div>
|
|
156
|
-
</a>
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
> **Styling note:** TeamMemberCard styling is created by the design skill. See `references/shared/STYLING.md` (Team Member Card).
|
|
160
|
-
|
|
161
|
-
Key details:
|
|
162
|
-
- Inline SVG icons — no icon library dependency
|
|
163
|
-
- Fallback initial letter when no photo
|
|
164
|
-
- Social links use `onclick="event.stopPropagation()"` to prevent navigation to profile when clicking social icons
|
|
165
|
-
|
|
166
|
-
### 3. Team Directory Page (`src/pages/team/index.astro`)
|
|
167
|
-
|
|
168
|
-
```astro
|
|
169
|
-
---
|
|
170
|
-
import Layout from "../../layouts/Layout.astro";
|
|
171
|
-
import TeamMemberCard from "../../components/TeamMemberCard.astro";
|
|
172
|
-
import { queryTeamMembers, groupByDepartment } from "../../lib/team";
|
|
173
|
-
|
|
174
|
-
const members = await queryTeamMembers();
|
|
175
|
-
const departments = groupByDepartment(members);
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
<Layout title="Our Team">
|
|
179
|
-
<main>
|
|
180
|
-
<div>
|
|
181
|
-
<h1>Our Team</h1>
|
|
182
|
-
|
|
183
|
-
{[...departments.entries()].map(([dept, deptMembers]) => (
|
|
184
|
-
<section>
|
|
185
|
-
<h2>{dept}</h2>
|
|
186
|
-
<div>
|
|
187
|
-
{deptMembers.map((member) => (
|
|
188
|
-
<TeamMemberCard member={member} />
|
|
189
|
-
))}
|
|
190
|
-
</div>
|
|
191
|
-
</section>
|
|
192
|
-
))}
|
|
193
|
-
|
|
194
|
-
{members.length === 0 && (
|
|
195
|
-
<p>No team members found.</p>
|
|
196
|
-
)}
|
|
197
|
-
</div>
|
|
198
|
-
</main>
|
|
199
|
-
</Layout>
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
### 4. Member Profile Page (`src/pages/team/[slug].astro`)
|
|
203
|
-
|
|
204
|
-
```astro
|
|
205
|
-
---
|
|
206
|
-
import Layout from "../../layouts/Layout.astro";
|
|
207
|
-
import { getMemberBySlug } from "../../lib/team";
|
|
208
|
-
|
|
209
|
-
const { slug } = Astro.params;
|
|
210
|
-
const member = await getMemberBySlug(slug!);
|
|
211
|
-
if (!member) return Astro.redirect("/404");
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
<Layout title={member.name}>
|
|
215
|
-
<main>
|
|
216
|
-
<div>
|
|
217
|
-
<a href="/team">
|
|
218
|
-
← Back to team
|
|
219
|
-
</a>
|
|
220
|
-
|
|
221
|
-
<div>
|
|
222
|
-
{member.photo && (
|
|
223
|
-
<div>
|
|
224
|
-
<img
|
|
225
|
-
src={member.photo}
|
|
226
|
-
alt={member.name}
|
|
227
|
-
/>
|
|
228
|
-
</div>
|
|
229
|
-
)}
|
|
230
|
-
<div>
|
|
231
|
-
<h1>{member.name}</h1>
|
|
232
|
-
<p>{member.role}</p>
|
|
233
|
-
{member.department && (
|
|
234
|
-
<p>{member.department}</p>
|
|
235
|
-
)}
|
|
236
|
-
<div>
|
|
237
|
-
{member.email && (
|
|
238
|
-
<a href={`mailto:${member.email}`}>
|
|
239
|
-
{member.email}
|
|
240
|
-
</a>
|
|
241
|
-
)}
|
|
242
|
-
{member.linkedIn && (
|
|
243
|
-
<a href={member.linkedIn} target="_blank" rel="noopener noreferrer">
|
|
244
|
-
LinkedIn
|
|
245
|
-
</a>
|
|
246
|
-
)}
|
|
247
|
-
{member.twitter && (
|
|
248
|
-
<a href={member.twitter} target="_blank" rel="noopener noreferrer">
|
|
249
|
-
Twitter
|
|
250
|
-
</a>
|
|
251
|
-
)}
|
|
252
|
-
</div>
|
|
253
|
-
</div>
|
|
254
|
-
</div>
|
|
255
|
-
|
|
256
|
-
{member.bio && (
|
|
257
|
-
<article set:html={member.bio} />
|
|
258
|
-
)}
|
|
259
|
-
</div>
|
|
260
|
-
</main>
|
|
261
|
-
</Layout>
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
## Seed with Images
|
|
265
|
-
|
|
266
|
-
> **Do not skip:** Team members without photos appear as initial-letter placeholders.
|
|
267
|
-
> Always ask the user if they want to generate headshot images before moving on.
|
|
268
|
-
|
|
269
|
-
After seeding team members via REST, generate headshot images following `../../shared/IMAGE_GENERATION.md` and `../../cms/CMS_FOUNDATIONS.md` → "Seeding with Images".
|
|
270
|
-
|
|
271
|
-
**Prompt template:**
|
|
272
|
-
|
|
273
|
-
```
|
|
274
|
-
Professional headshot portrait of [NAME], [ROLE] at [BUSINESS NAME]. [BRAND AESTHETIC]. Warm studio lighting, neutral background with [BRAND COLORS]. No text, no watermarks
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
**Patch field:** `photo`
|
|
278
|
-
|
|
279
|
-
Example: after generating and importing the image, patch the team member item:
|
|
280
|
-
|
|
281
|
-
```
|
|
282
|
-
REST: PATCH https://www.wixapis.com/wix-data/v2/items/{memberId}
|
|
283
|
-
body: {
|
|
284
|
-
"dataCollectionId": "Team",
|
|
285
|
-
"dataItem": {
|
|
286
|
-
"data": {
|
|
287
|
-
"photo": "<wixstatic-url>"
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
## Testing
|
|
294
|
-
|
|
295
|
-
Assumes the `seed` scope has already created the "Team" collection and inserted items via REST (see `../../cms/CMS_FOUNDATIONS.md`) — 4+ members across 2+ departments, with social links (and headshots after the image pass).
|
|
296
|
-
|
|
297
|
-
1. Run `npx @wix/cli@latest dev`
|
|
298
|
-
2. `/team` — shows members grouped by department
|
|
299
|
-
3. Click a member — profile page with photo, bio, and social links
|