@dani-builder/strapi-client 0.2.0 → 0.3.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/AGENTS.md +9 -5
- package/LICENSE +21 -0
- package/README.md +50 -0
- package/dist/api/articles.d.ts +3 -0
- package/dist/api/articles.d.ts.map +1 -1
- package/dist/api/articles.js +8 -5
- package/dist/api/articles.js.map +1 -1
- package/dist/api/authors.d.ts +2 -0
- package/dist/api/authors.d.ts.map +1 -1
- package/dist/api/authors.js +5 -2
- package/dist/api/authors.js.map +1 -1
- package/dist/api/categories.d.ts +2 -0
- package/dist/api/categories.d.ts.map +1 -1
- package/dist/api/categories.js +4 -1
- package/dist/api/categories.js.map +1 -1
- package/dist/api/faqs.d.ts +2 -0
- package/dist/api/faqs.d.ts.map +1 -1
- package/dist/api/faqs.js +4 -1
- package/dist/api/faqs.js.map +1 -1
- package/dist/api/global.js +1 -1
- package/dist/api/global.js.map +1 -1
- package/dist/api/inquiry.js +1 -1
- package/dist/api/inquiry.js.map +1 -1
- package/dist/api/navigation.js +1 -1
- package/dist/api/navigation.js.map +1 -1
- package/dist/api/pages.d.ts +9 -1
- package/dist/api/pages.d.ts.map +1 -1
- package/dist/api/pages.js +26 -9
- package/dist/api/pages.js.map +1 -1
- package/dist/api/series.d.ts +2 -0
- package/dist/api/series.d.ts.map +1 -1
- package/dist/api/series.js +5 -2
- package/dist/api/series.js.map +1 -1
- package/dist/api/site-settings.js +1 -1
- package/dist/api/site-settings.js.map +1 -1
- package/dist/api/tags.d.ts +2 -0
- package/dist/api/tags.d.ts.map +1 -1
- package/dist/api/tags.js +4 -1
- package/dist/api/tags.js.map +1 -1
- package/dist/client/create-client.d.ts +7 -3
- package/dist/client/create-client.d.ts.map +1 -1
- package/dist/client/create-client.js +13 -5
- package/dist/client/create-client.js.map +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/populate/builders.d.ts +12 -0
- package/dist/populate/builders.d.ts.map +1 -1
- package/dist/populate/builders.js +10 -0
- package/dist/populate/builders.js.map +1 -1
- package/dist/populate/core-blocks.d.ts.map +1 -1
- package/dist/populate/core-blocks.js +15 -9
- package/dist/populate/core-blocks.js.map +1 -1
- package/dist/types/components/blocks.d.ts +12 -11
- package/dist/types/components/blocks.d.ts.map +1 -1
- package/dist/types/components/index.d.ts +1 -1
- package/dist/types/components/index.d.ts.map +1 -1
- package/dist/types/components/shared.d.ts +14 -3
- package/dist/types/components/shared.d.ts.map +1 -1
- package/dist/types/components/shared.js +1 -1
- package/dist/types/content-types/article.d.ts +3 -1
- package/dist/types/content-types/article.d.ts.map +1 -1
- package/dist/types/content-types/article.js +1 -1
- package/dist/types/content-types/article.js.map +1 -1
- package/dist/types/content-types/author.js +1 -1
- package/dist/types/content-types/author.js.map +1 -1
- package/dist/types/content-types/category.js +1 -1
- package/dist/types/content-types/category.js.map +1 -1
- package/dist/types/content-types/faq.js +1 -1
- package/dist/types/content-types/faq.js.map +1 -1
- package/dist/types/content-types/global.js +1 -1
- package/dist/types/content-types/global.js.map +1 -1
- package/dist/types/content-types/inquiry.js +1 -1
- package/dist/types/content-types/inquiry.js.map +1 -1
- package/dist/types/content-types/navigation.js +1 -1
- package/dist/types/content-types/navigation.js.map +1 -1
- package/dist/types/content-types/page.d.ts +12 -3
- package/dist/types/content-types/page.d.ts.map +1 -1
- package/dist/types/content-types/page.js +1 -1
- package/dist/types/content-types/page.js.map +1 -1
- package/dist/types/content-types/series.js +1 -1
- package/dist/types/content-types/series.js.map +1 -1
- package/dist/types/content-types/site-settings.js +1 -1
- package/dist/types/content-types/site-settings.js.map +1 -1
- package/dist/types/content-types/tag.js +1 -1
- package/dist/types/content-types/tag.js.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/strapi.d.ts +10 -0
- package/dist/types/strapi.d.ts.map +1 -1
- package/docs/api-guide.md +22 -22
- package/docs/block-reference.md +147 -554
- package/docs/components.md +234 -0
- package/docs/content-types.md +173 -382
- package/docs/elements.md +50 -0
- package/package.json +25 -8
package/docs/block-reference.md
CHANGED
|
@@ -1,601 +1,194 @@
|
|
|
1
|
-
# Block Reference
|
|
2
|
-
|
|
3
|
-
## Quick Reference Table
|
|
4
|
-
|
|
5
|
-
| Block | `__component` | Variants | Media Policy | Items Type |
|
|
6
|
-
|-------|--------------|----------|-------------|-----------|
|
|
7
|
-
| Hero | `blocks.hero` | `side-by-side`, `media-extending`, `fullscreen-media`, `stacked-media` | heroMedia: images+videos | — |
|
|
8
|
-
| Features | `blocks.features` | `simple-grid`, `dual-column`, `media-aside`, `media-aside-compact` | media: images only | `FeatureItem[]` |
|
|
9
|
-
| CTA | `blocks.cta` | `inline-spread`, `inline-centered`, `inline-stacked`, `card-stacked`, `card-centered`, `card-horizontal` | ctaMedia: images+videos | — |
|
|
10
|
-
| Slider | `blocks.slider` | `cover-flow`, `card-slider` | — | `SliderItem[]` |
|
|
11
|
-
| InquiryForm | `blocks.inquiry-form` | — | — | — |
|
|
12
|
-
| FAQ | `blocks.faq` | — | — | `FaqDocument[]` (relation) |
|
|
13
|
-
| Highlights | `blocks.highlights` | `dual-column`, `triple-column`, `alternating` | media: images+videos | `HighlightItem[]` |
|
|
14
|
-
| BentoGrid | `blocks.bento-grid` | — (layout via `columns` + item spans) | — | `BentoItem[]` |
|
|
15
|
-
| Testimonials | `blocks.testimonials` | `centered`, `side-by-side`, `card-grid`, `subtle-grid` | media: images+videos | `TestimonialItem[]` |
|
|
16
|
-
| LogoCloud | `blocks.logo-cloud` | `inline`, `grid`, `split` | — | `LogoItem[]` |
|
|
17
|
-
| Stats | `blocks.stats` | `simple`, `card-grid`, `split` | media: images+videos | `StatItem[]` |
|
|
18
|
-
| Pricing | `blocks.pricing` | `two-column`, `three-column`, `single`, `with-comparison` | — | `PricingTier[]` |
|
|
19
|
-
| Content | `blocks.content` | `prose`, `wide`, `full-width` | — | — |
|
|
20
|
-
| Team | `blocks.team` | `grid`, `large-image`, `compact` | — | `TeamMember[]` |
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## Media Policy Summary
|
|
25
|
-
|
|
26
|
-
### Images + Videos
|
|
27
|
-
|
|
28
|
-
These fields accept both image and video uploads. Render `<video>` or `<img>` based on `asset.mime`.
|
|
29
|
-
|
|
30
|
-
| Field | Component |
|
|
31
|
-
|-------|-----------|
|
|
32
|
-
| `heroMedia` | `blocks.hero` |
|
|
33
|
-
| `ctaMedia` | `blocks.cta` |
|
|
34
|
-
| `media` | `blocks.highlights` |
|
|
35
|
-
| `media` | `blocks.testimonials` |
|
|
36
|
-
| `media` | `blocks.stats` |
|
|
37
|
-
| `media` | `shared.highlight-item` |
|
|
38
|
-
| `media` | `shared.slider-item` |
|
|
39
|
-
|
|
40
|
-
### Images Only
|
|
41
|
-
|
|
42
|
-
These fields reject video uploads. Always render as `<img>`.
|
|
43
|
-
|
|
44
|
-
| Field | Component |
|
|
45
|
-
|-------|-----------|
|
|
46
|
-
| `media` | `blocks.features` |
|
|
47
|
-
| `backgroundImage` | `elements.section` |
|
|
48
|
-
| `logo` | `elements.footer` |
|
|
49
|
-
| `logo` | `shared.logo-item` |
|
|
50
|
-
| `avatar` | `shared.testimonial-item` |
|
|
51
|
-
| `logo` | `shared.testimonial-item` |
|
|
52
|
-
| `media` | `shared.bento-item` |
|
|
53
|
-
| `photo` | `shared.team-member` |
|
|
54
|
-
| `ogImage` | `shared.seo` |
|
|
55
|
-
| `mainLogo` | Navigation CT |
|
|
56
|
-
| `darkLogo` | Navigation CT |
|
|
57
|
-
| `favicon` | Global CT |
|
|
58
|
-
| `cover` | Article CT |
|
|
59
|
-
| `gallery` | Article CT |
|
|
60
|
-
| `avatar` | Author CT |
|
|
61
|
-
| `cover` | Series CT |
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## Section (`elements.section`)
|
|
66
|
-
|
|
67
|
-
Every block has an optional `section: Section | null` field. Section provides the heading, theme, and background for the block. It can also appear standalone in `Page.blocks` as a separator.
|
|
68
|
-
|
|
69
|
-
| Field | Type | Description |
|
|
70
|
-
|-------|------|-------------|
|
|
71
|
-
| `heading` | `string \| null` | Section heading |
|
|
72
|
-
| `subheading` | `string \| null` | Subheading |
|
|
73
|
-
| `kickerText` | `string \| null` | Small text above heading |
|
|
74
|
-
| `anchorId` | `string \| null` | Anchor ID for in-page navigation |
|
|
75
|
-
| `headerAlign` | `'auto' \| 'left' \| 'center' \| 'right' \| null` | Heading alignment |
|
|
76
|
-
| `theme` | `'default' \| 'light' \| 'dark' \| 'accent' \| 'muted' \| 'contrast'` | Tailwind preset key |
|
|
77
|
-
| `backgroundImage` | `StrapiMedia \| null` | Background image (images only) |
|
|
78
|
-
| `backgroundImageOpacity` | `number \| null` | Opacity 0–1 for background image overlay |
|
|
79
|
-
|
|
80
|
-
**Constraints:**
|
|
81
|
-
- `theme` maps to a Tailwind preset in the frontend theme config. DO NOT use arbitrary CSS colors.
|
|
82
|
-
- `backgroundImage` is images-only. DO NOT attempt to use video backgrounds here.
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## Hero (`blocks.hero`)
|
|
87
|
-
|
|
88
|
-
**`__component`: `'blocks.hero'`**
|
|
89
|
-
**Used in:** Page.blocks, Global.siteWideBlocks
|
|
90
|
-
|
|
91
|
-
### Variants
|
|
92
|
-
|
|
93
|
-
| Value | Layout |
|
|
94
|
-
|-------|--------|
|
|
95
|
-
| `side-by-side` | Text on one side, media on the other — split layout |
|
|
96
|
-
| `media-extending` | Media extends beyond container bounds |
|
|
97
|
-
| `fullscreen-media` | Full-viewport background media with text overlay |
|
|
98
|
-
| `stacked-media` | Media below the text content |
|
|
99
|
-
|
|
100
|
-
### Fields
|
|
101
|
-
|
|
102
|
-
| Field | Type | Description |
|
|
103
|
-
|-------|------|-------------|
|
|
104
|
-
| `variant` | enum | Layout variant (see above) |
|
|
105
|
-
| `section` | `Section \| null` | Section wrapper |
|
|
106
|
-
| `heroMedia` | `StrapiMedia \| null` | Hero media — **images+videos** |
|
|
107
|
-
| `ctaText` | `string \| null` | Supplementary CTA text |
|
|
108
|
-
| `ctaLink` | `Link \| null` | Primary CTA link |
|
|
109
|
-
| `secondaryLink` | `Link \| null` | Secondary link |
|
|
110
|
-
| `headerMode` | `'none' \| 'transparent-black' \| 'transparent-white'` | Header overlay mode for navigation |
|
|
111
|
-
|
|
112
|
-
**Constraints:**
|
|
113
|
-
- `heroMedia` accepts images+videos. Check `mime` to decide between `<img>` and `<video>`.
|
|
114
|
-
- `headerMode` controls how the page header (navigation) renders over this hero. `none` = default header, `transparent-*` = transparent with light/dark text.
|
|
115
|
-
- DO NOT confuse `headerMode` here with `Page.headerMode` (`'overlay' | 'offset'`).
|
|
116
|
-
|
|
117
|
-
---
|
|
118
|
-
|
|
119
|
-
## Features (`blocks.features`)
|
|
120
|
-
|
|
121
|
-
**`__component`: `'blocks.features'`**
|
|
122
|
-
**Used in:** Page.blocks, Global.siteWideBlocks
|
|
123
|
-
|
|
124
|
-
### Variants
|
|
125
|
-
|
|
126
|
-
| Value | Layout |
|
|
127
|
-
|-------|--------|
|
|
128
|
-
| `simple-grid` | Icon+text items in a uniform grid |
|
|
129
|
-
| `dual-column` | Two-column grid layout |
|
|
130
|
-
| `media-aside` | Items on one side, media image on the other |
|
|
131
|
-
| `media-aside-compact` | Compact version of media-aside |
|
|
132
|
-
|
|
133
|
-
### Fields
|
|
134
|
-
|
|
135
|
-
| Field | Type | Description |
|
|
136
|
-
|-------|------|-------------|
|
|
137
|
-
| `name` | `string \| null` | Admin label — DO NOT display |
|
|
138
|
-
| `variant` | enum | Layout variant |
|
|
139
|
-
| `section` | `Section \| null` | Section wrapper |
|
|
140
|
-
| `media` | `StrapiMedia \| null` | Supporting image — **images only** |
|
|
141
|
-
| `items` | `FeatureItem[]` | Feature items list |
|
|
142
|
-
|
|
143
|
-
**Constraints:**
|
|
144
|
-
- `media` is images-only and only relevant for `media-aside` / `media-aside-compact` variants.
|
|
145
|
-
- DO NOT render the `media` field for `simple-grid` or `dual-column` variants.
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
|
-
## CTA (`blocks.cta`)
|
|
150
|
-
|
|
151
|
-
**`__component`: `'blocks.cta'`**
|
|
152
|
-
**Used in:** Page.blocks
|
|
153
|
-
|
|
154
|
-
### Variants
|
|
155
|
-
|
|
156
|
-
| Value | Layout |
|
|
157
|
-
|-------|--------|
|
|
158
|
-
| `inline-spread` | Text and buttons spread horizontally |
|
|
159
|
-
| `inline-centered` | Centered text with buttons below |
|
|
160
|
-
| `inline-stacked` | Text and buttons stacked vertically |
|
|
161
|
-
| `card-stacked` | Card container with stacked content |
|
|
162
|
-
| `card-centered` | Card container with centered content |
|
|
163
|
-
| `card-horizontal` | Card container with horizontal layout |
|
|
164
|
-
|
|
165
|
-
### Fields
|
|
166
|
-
|
|
167
|
-
| Field | Type | Description |
|
|
168
|
-
|-------|------|-------------|
|
|
169
|
-
| `section` | `Section \| null` | Section wrapper |
|
|
170
|
-
| `variant` | enum | Layout variant |
|
|
171
|
-
| `ctaMedia` | `StrapiMedia \| null` | CTA media — **images+videos** |
|
|
172
|
-
| `ctaText` | `string \| null` | Supplementary text |
|
|
173
|
-
| `ctaLink` | `Link \| null` | Primary CTA link |
|
|
174
|
-
| `secondaryLink` | `Link \| null` | Secondary link |
|
|
175
|
-
|
|
176
|
-
**Constraints:**
|
|
177
|
-
- `ctaMedia` accepts images+videos. Most relevant for `card-*` variants.
|
|
178
|
-
- `inline-*` variants are borderless/background-less; `card-*` variants have a card container.
|
|
179
|
-
|
|
180
|
-
---
|
|
181
|
-
|
|
182
|
-
## Slider (`blocks.slider`)
|
|
183
|
-
|
|
184
|
-
**`__component`: `'blocks.slider'`**
|
|
185
|
-
**Used in:** Page.blocks, Global.siteWideBlocks
|
|
186
|
-
|
|
187
|
-
### Variants
|
|
188
|
-
|
|
189
|
-
| Value | Layout |
|
|
190
|
-
|-------|--------|
|
|
191
|
-
| `cover-flow` | Cover-flow style with center-focused active slide |
|
|
192
|
-
| `card-slider` | Card-based slider/carousel |
|
|
193
|
-
|
|
194
|
-
### Fields
|
|
195
|
-
|
|
196
|
-
| Field | Type | Description |
|
|
197
|
-
|-------|------|-------------|
|
|
198
|
-
| `name` | `string \| null` | Admin label — DO NOT display |
|
|
199
|
-
| `variant` | enum | Slider style |
|
|
200
|
-
| `section` | `Section \| null` | Section wrapper |
|
|
201
|
-
| `items` | `SliderItem[]` | Slider items (media required per item) |
|
|
202
|
-
|
|
203
|
-
**Constraints:**
|
|
204
|
-
- Each `SliderItem.media` is required (images+videos). Always render media for each slide.
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
## InquiryForm (`blocks.inquiry-form`)
|
|
209
|
-
|
|
210
|
-
**`__component`: `'blocks.inquiry-form'`**
|
|
211
|
-
**Used in:** Page.blocks, Global.siteWideBlocks
|
|
212
|
-
|
|
213
|
-
### Fields
|
|
214
|
-
|
|
215
|
-
| Field | Type | Description |
|
|
216
|
-
|-------|------|-------------|
|
|
217
|
-
| `section` | `Section \| null` | Section wrapper |
|
|
218
|
-
| `successMessage` | `string \| null` | Message displayed after successful submission |
|
|
219
|
-
|
|
220
|
-
**Constraints:**
|
|
221
|
-
- The form UI is rendered by the frontend (not from CMS data). Submit to `postInquiry(client, data)`.
|
|
222
|
-
- Form fields: `name` (required), `email`, `phone`, `subject`, `message` — see `InquiryFormData` type.
|
|
223
|
-
|
|
224
|
-
---
|
|
225
|
-
|
|
226
|
-
## FAQ (`blocks.faq`)
|
|
227
|
-
|
|
228
|
-
**`__component`: `'blocks.faq'`**
|
|
229
|
-
**Used in:** Page.blocks
|
|
230
|
-
|
|
231
|
-
### Fields
|
|
232
|
-
|
|
233
|
-
| Field | Type | Description |
|
|
234
|
-
|-------|------|-------------|
|
|
235
|
-
| `section` | `Section \| null` | Section wrapper |
|
|
236
|
-
| `items` | `FaqDocument[]` | FAQ entries (relation: oneToMany → `api::faq.faq`) |
|
|
237
|
-
|
|
238
|
-
**Constraints:**
|
|
239
|
-
- `items` are full FAQ documents (with `question`, `answer`, `category`, `sortOrder`).
|
|
240
|
-
- `answer` is `BlocksContent | null` — use a Blocks renderer, not markdown.
|
|
241
|
-
- No variant — use a single accordion/expandable pattern.
|
|
242
|
-
|
|
243
|
-
---
|
|
244
|
-
|
|
245
|
-
## Highlights (`blocks.highlights`)
|
|
246
|
-
|
|
247
|
-
**`__component`: `'blocks.highlights'`**
|
|
248
|
-
**Used in:** Page.blocks
|
|
249
|
-
|
|
250
|
-
### Variants
|
|
251
|
-
|
|
252
|
-
| Value | Layout |
|
|
253
|
-
|-------|--------|
|
|
254
|
-
| `dual-column` | Two-column image+text grid |
|
|
255
|
-
| `triple-column` | Three-column grid |
|
|
256
|
-
| `alternating` | Zigzag layout — alternating image/text sides |
|
|
257
|
-
|
|
258
|
-
### Fields
|
|
259
|
-
|
|
260
|
-
| Field | Type | Description |
|
|
261
|
-
|-------|------|-------------|
|
|
262
|
-
| `name` | `string \| null` | Admin label — DO NOT display |
|
|
263
|
-
| `variant` | enum | Layout variant |
|
|
264
|
-
| `media` | `StrapiMedia \| null` | Block-level supporting media — **images+videos** |
|
|
265
|
-
| `section` | `Section \| null` | Section wrapper |
|
|
266
|
-
| `items` | `HighlightItem[]` | Highlight items (each has required media) |
|
|
267
|
-
|
|
268
|
-
**Constraints:**
|
|
269
|
-
- Block-level `media` is a supporting visual, not per-item media.
|
|
270
|
-
- Each `HighlightItem.media` is required (images+videos).
|
|
271
|
-
- For `alternating` variant, items alternate between text-left/media-right and media-left/text-right.
|
|
272
|
-
|
|
273
1
|
---
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
### Fields
|
|
281
|
-
|
|
282
|
-
| Field | Type | Description |
|
|
283
|
-
|-------|------|-------------|
|
|
284
|
-
| `name` | `string \| null` | Admin label — DO NOT display |
|
|
285
|
-
| `section` | `Section \| null` | Section wrapper |
|
|
286
|
-
| `columns` | `number` | Grid columns (2–4, default 3) |
|
|
287
|
-
| `items` | `BentoItem[]` | Grid items with colSpan/rowSpan |
|
|
288
|
-
|
|
289
|
-
**Constraints:**
|
|
290
|
-
- No variant — layout is controlled by `columns` + each item's `colSpan`/`rowSpan`.
|
|
291
|
-
- Use CSS Grid: `grid-template-columns: repeat(columns, 1fr)`.
|
|
292
|
-
- `BentoItem.media` is images-only.
|
|
293
|
-
- Each item's `colSpan` (1–4) and `rowSpan` (1–3) define its grid area.
|
|
294
|
-
|
|
2
|
+
type: reference
|
|
3
|
+
status: current
|
|
4
|
+
generated: true
|
|
5
|
+
generator: .claude/skills/docs-steward/scripts/gen-reference.mjs
|
|
6
|
+
sources:
|
|
7
|
+
- packages/strapi-plugin-builder/server/src/components/blocks/*.json
|
|
295
8
|
---
|
|
296
9
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
**`__component`: `'blocks.testimonials'`**
|
|
300
|
-
**Used in:** Page.blocks
|
|
301
|
-
|
|
302
|
-
### Variants
|
|
10
|
+
<!-- DO NOT EDIT. Run `pnpm docs:gen` after changing the schemas. -->
|
|
303
11
|
|
|
304
|
-
|
|
305
|
-
|-------|--------|
|
|
306
|
-
| `centered` | Single/few quotes centered, large format |
|
|
307
|
-
| `side-by-side` | Quote + supporting media in split layout |
|
|
308
|
-
| `card-grid` | Multiple testimonials as cards in a grid |
|
|
309
|
-
| `subtle-grid` | Multiple testimonials in a minimal grid |
|
|
12
|
+
# Blocks
|
|
310
13
|
|
|
311
|
-
|
|
14
|
+
Top-level components usable in the `Page.blocks` dynamic zone.
|
|
15
|
+
Every block object must carry `__component`. Heading and subheading text
|
|
16
|
+
lives inside the nested `section` component, not at the block root.
|
|
312
17
|
|
|
313
|
-
|
|
314
|
-
|-------|------|-------------|
|
|
315
|
-
| `name` | `string \| null` | Admin label — DO NOT display |
|
|
316
|
-
| `variant` | enum | Layout variant |
|
|
317
|
-
| `section` | `Section \| null` | Section wrapper |
|
|
318
|
-
| `media` | `StrapiMedia \| null` | Block-level supporting media — **images+videos** |
|
|
319
|
-
| `items` | `TestimonialItem[]` | Testimonial items |
|
|
18
|
+
## Quick reference
|
|
320
19
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
20
|
+
| Component | `__component` | Variants |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| Bento Grid | `blocks.bento-grid` | — |
|
|
23
|
+
| Content | `blocks.content` | `prose`, `wide`, `full-width` |
|
|
24
|
+
| CTA | `blocks.cta` | `inline-spread`, `inline-centered`, `inline-stacked`, `card-stacked`, `card-centered`, `card-horizontal` |
|
|
25
|
+
| FAQ | `blocks.faq` | — |
|
|
26
|
+
| Features | `blocks.features` | `simple-grid`, `dual-column`, `media-aside`, `media-aside-compact` |
|
|
27
|
+
| Hero | `blocks.hero` | `side-by-side`, `media-extending`, `fullscreen-media`, `stacked-media` |
|
|
28
|
+
| Highlights | `blocks.highlights` | `dual-column`, `triple-column`, `alternating` |
|
|
29
|
+
| Inquiry Form | `blocks.inquiry-form` | — |
|
|
30
|
+
| Logo Cloud | `blocks.logo-cloud` | `inline`, `grid`, `split`, `marquee` |
|
|
31
|
+
| Pricing | `blocks.pricing` | `two-column`, `three-column`, `single`, `with-comparison` |
|
|
32
|
+
| Slider | `blocks.slider` | `cover-flow`, `card-slider` |
|
|
33
|
+
| Stats | `blocks.stats` | `simple`, `card-grid`, `split` |
|
|
34
|
+
| Team | `blocks.team` | `grid`, `large-image`, `compact` |
|
|
35
|
+
| Testimonials | `blocks.testimonials` | `centered`, `side-by-side`, `card-grid`, `subtle-grid` |
|
|
325
36
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
## LogoCloud (`blocks.logo-cloud`)
|
|
37
|
+
## Bento Grid
|
|
329
38
|
|
|
330
|
-
|
|
331
|
-
**Used in:** Page.blocks
|
|
39
|
+
`blocks.bento-grid` — Asymmetric grid layout with per-item span control
|
|
332
40
|
|
|
333
|
-
|
|
41
|
+
| Attribute | Type | Required | Default | Notes |
|
|
42
|
+
|---|---|---|---|---|
|
|
43
|
+
| `name` | string | — | — | — |
|
|
44
|
+
| `section` | component `elements.section` | — | — | — |
|
|
45
|
+
| `columns` | integer | — | `3` | — |
|
|
46
|
+
| `items` | component `shared.bento-item` (repeatable) | — | — | — |
|
|
334
47
|
|
|
335
|
-
|
|
336
|
-
|-------|--------|
|
|
337
|
-
| `inline` | Logos in a single horizontal row (4–8 logos) |
|
|
338
|
-
| `grid` | Logos in a grid layout (8+ logos) |
|
|
339
|
-
| `split` | Text on left (section heading/subheading) + logo grid on right |
|
|
48
|
+
## Content
|
|
340
49
|
|
|
341
|
-
|
|
50
|
+
`blocks.content` — Rich text content block using Strapi Blocks editor
|
|
342
51
|
|
|
343
|
-
|
|
|
344
|
-
|
|
345
|
-
| `
|
|
346
|
-
| `variant` |
|
|
347
|
-
| `
|
|
348
|
-
| `items` | `LogoItem[]` | Logo items |
|
|
52
|
+
| Attribute | Type | Required | Default | Notes |
|
|
53
|
+
|---|---|---|---|---|
|
|
54
|
+
| `section` | component `elements.section` | — | — | — |
|
|
55
|
+
| `variant` | enumeration | — | — | `prose`, `wide`, `full-width` |
|
|
56
|
+
| `body` | blocks | yes | — | — |
|
|
349
57
|
|
|
350
|
-
|
|
351
|
-
- No block-level media. `split` variant uses `section.heading`/`subheading` for text.
|
|
352
|
-
- `LogoItem.logo` is required (images only).
|
|
58
|
+
## CTA
|
|
353
59
|
|
|
354
|
-
|
|
60
|
+
`blocks.cta` — Call-to-Action block with media and action links
|
|
355
61
|
|
|
356
|
-
|
|
62
|
+
| Attribute | Type | Required | Default | Notes |
|
|
63
|
+
|---|---|---|---|---|
|
|
64
|
+
| `section` | component `elements.section` | — | — | — |
|
|
65
|
+
| `variant` | enumeration | — | `inline-spread` | `inline-spread`, `inline-centered`, `inline-stacked`, `card-stacked`, `card-centered`, `card-horizontal` |
|
|
66
|
+
| `image` | component `shared.image` | — | — | — |
|
|
67
|
+
| `ctaText` | text | — | — | — |
|
|
68
|
+
| `ctaLink` | component `shared.link` | — | — | — |
|
|
69
|
+
| `secondaryLink` | component `shared.link` | — | — | — |
|
|
357
70
|
|
|
358
|
-
|
|
359
|
-
**Used in:** Page.blocks
|
|
71
|
+
## FAQ
|
|
360
72
|
|
|
361
|
-
|
|
73
|
+
`blocks.faq` — FAQ list block linked to FAQ content type via relation
|
|
362
74
|
|
|
363
|
-
|
|
|
364
|
-
|
|
365
|
-
| `
|
|
366
|
-
| `
|
|
367
|
-
| `split` | Stats on one side + media on the other |
|
|
75
|
+
| Attribute | Type | Required | Default | Notes |
|
|
76
|
+
|---|---|---|---|---|
|
|
77
|
+
| `section` | component `elements.section` | — | — | — |
|
|
78
|
+
| `items` | relation `oneToMany` → `plugin::builder.faq` | — | — | — |
|
|
368
79
|
|
|
369
|
-
|
|
80
|
+
## Features
|
|
370
81
|
|
|
371
|
-
|
|
372
|
-
|-------|------|-------------|
|
|
373
|
-
| `name` | `string \| null` | Admin label — DO NOT display |
|
|
374
|
-
| `variant` | enum | Layout variant |
|
|
375
|
-
| `section` | `Section \| null` | Section wrapper |
|
|
376
|
-
| `media` | `StrapiMedia \| null` | Supporting media — **images+videos** |
|
|
377
|
-
| `items` | `StatItem[]` | Stat items |
|
|
82
|
+
`blocks.features` — Feature/service showcase with icon+text items
|
|
378
83
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
84
|
+
| Attribute | Type | Required | Default | Notes |
|
|
85
|
+
|---|---|---|---|---|
|
|
86
|
+
| `name` | string | — | — | — |
|
|
87
|
+
| `variant` | enumeration | — | — | `simple-grid`, `dual-column`, `media-aside`, `media-aside-compact` |
|
|
88
|
+
| `section` | component `elements.section` | — | — | — |
|
|
89
|
+
| `image` | component `shared.image` | — | — | — |
|
|
90
|
+
| `items` | component `shared.feature-item` (repeatable) | — | — | — |
|
|
382
91
|
|
|
383
|
-
|
|
92
|
+
## Hero
|
|
384
93
|
|
|
385
|
-
|
|
94
|
+
`blocks.hero` — Hero banner with media, CTA links, and layout variants
|
|
386
95
|
|
|
387
|
-
|
|
388
|
-
|
|
96
|
+
| Attribute | Type | Required | Default | Notes |
|
|
97
|
+
|---|---|---|---|---|
|
|
98
|
+
| `variant` | enumeration | — | — | `side-by-side`, `media-extending`, `fullscreen-media`, `stacked-media` |
|
|
99
|
+
| `section` | component `elements.section` | — | — | — |
|
|
100
|
+
| `image` | component `shared.image` | — | — | — |
|
|
101
|
+
| `ctaText` | text | — | — | — |
|
|
102
|
+
| `ctaLink` | component `shared.link` | — | — | — |
|
|
103
|
+
| `secondaryLink` | component `shared.link` | — | — | — |
|
|
104
|
+
| `headerMode` | enumeration | — | `none` | `none`, `transparent-black`, `transparent-white` |
|
|
389
105
|
|
|
390
|
-
|
|
106
|
+
## Highlights
|
|
391
107
|
|
|
392
|
-
|
|
393
|
-
|-------|--------|
|
|
394
|
-
| `two-column` | Side-by-side comparison of 2 plans |
|
|
395
|
-
| `three-column` | Three plans (Good/Better/Best) |
|
|
396
|
-
| `single` | Single plan detail view |
|
|
397
|
-
| `with-comparison` | Plans + feature comparison table below |
|
|
108
|
+
`blocks.highlights` — Highlight/feature showcase with media+text items
|
|
398
109
|
|
|
399
|
-
|
|
110
|
+
| Attribute | Type | Required | Default | Notes |
|
|
111
|
+
|---|---|---|---|---|
|
|
112
|
+
| `name` | string | — | — | — |
|
|
113
|
+
| `variant` | enumeration | — | — | `dual-column`, `triple-column`, `alternating` |
|
|
114
|
+
| `image` | component `shared.image` | — | — | — |
|
|
115
|
+
| `section` | component `elements.section` | — | — | — |
|
|
116
|
+
| `items` | component `shared.highlight-item` (repeatable) | — | — | — |
|
|
400
117
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
|
406
|
-
|
|
118
|
+
## Inquiry Form
|
|
119
|
+
|
|
120
|
+
`blocks.inquiry-form` — Contact form block that submits to Inquiry content type
|
|
121
|
+
|
|
122
|
+
| Attribute | Type | Required | Default | Notes |
|
|
123
|
+
|---|---|---|---|---|
|
|
124
|
+
| `section` | component `elements.section` | — | — | — |
|
|
125
|
+
| `successMessage` | text | — | — | — |
|
|
126
|
+
| `errorMessage` | text | — | — | — |
|
|
407
127
|
|
|
408
|
-
|
|
409
|
-
- `PricingTier.price` is a string (e.g. `"$29"`, `"Free"`, `"Contact us"`). DO NOT parse as number.
|
|
410
|
-
- `PricingTier.featureList` is richtext (Markdown). Render as a bullet list.
|
|
411
|
-
- `PricingTier.highlighted` marks the recommended plan — apply visual emphasis (ribbon, border, etc.).
|
|
128
|
+
## Logo Cloud
|
|
412
129
|
|
|
413
|
-
|
|
130
|
+
`blocks.logo-cloud` — Client/partner logo showcase block
|
|
414
131
|
|
|
415
|
-
|
|
132
|
+
| Attribute | Type | Required | Default | Notes |
|
|
133
|
+
|---|---|---|---|---|
|
|
134
|
+
| `name` | string | — | — | — |
|
|
135
|
+
| `variant` | enumeration | — | — | `inline`, `grid`, `split`, `marquee` |
|
|
136
|
+
| `section` | component `elements.section` | — | — | — |
|
|
137
|
+
| `items` | component `shared.logo-item` (repeatable) | — | — | — |
|
|
416
138
|
|
|
417
|
-
|
|
418
|
-
**Used in:** Page.blocks
|
|
139
|
+
## Pricing
|
|
419
140
|
|
|
420
|
-
|
|
141
|
+
`blocks.pricing` — Pricing plans/tiers comparison block
|
|
421
142
|
|
|
422
|
-
|
|
|
423
|
-
|
|
424
|
-
| `
|
|
425
|
-
| `
|
|
426
|
-
| `
|
|
143
|
+
| Attribute | Type | Required | Default | Notes |
|
|
144
|
+
|---|---|---|---|---|
|
|
145
|
+
| `name` | string | — | — | — |
|
|
146
|
+
| `variant` | enumeration | — | — | `two-column`, `three-column`, `single`, `with-comparison` |
|
|
147
|
+
| `section` | component `elements.section` | — | — | — |
|
|
148
|
+
| `items` | component `shared.pricing-tier` (repeatable) | — | — | — |
|
|
427
149
|
|
|
428
|
-
|
|
150
|
+
## Slider
|
|
429
151
|
|
|
430
|
-
|
|
431
|
-
|-------|------|-------------|
|
|
432
|
-
| `section` | `Section \| null` | Section wrapper |
|
|
433
|
-
| `variant` | enum | Content width variant |
|
|
434
|
-
| `body` | `BlocksContent` | Rich text body — **required** |
|
|
152
|
+
`blocks.slider` — Slider/carousel block with media+text items
|
|
435
153
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
154
|
+
| Attribute | Type | Required | Default | Notes |
|
|
155
|
+
|---|---|---|---|---|
|
|
156
|
+
| `name` | string | — | — | — |
|
|
157
|
+
| `variant` | enumeration | — | — | `cover-flow`, `card-slider` |
|
|
158
|
+
| `section` | component `elements.section` | — | — | — |
|
|
159
|
+
| `items` | component `shared.slider-item` (repeatable) | — | — | — |
|
|
439
160
|
|
|
440
|
-
|
|
161
|
+
## Stats
|
|
441
162
|
|
|
442
|
-
|
|
163
|
+
`blocks.stats` — Key metrics/numbers showcase block
|
|
443
164
|
|
|
444
|
-
|
|
445
|
-
|
|
165
|
+
| Attribute | Type | Required | Default | Notes |
|
|
166
|
+
|---|---|---|---|---|
|
|
167
|
+
| `name` | string | — | — | — |
|
|
168
|
+
| `variant` | enumeration | — | — | `simple`, `card-grid`, `split` |
|
|
169
|
+
| `section` | component `elements.section` | — | — | — |
|
|
170
|
+
| `image` | component `shared.image` | — | — | — |
|
|
171
|
+
| `items` | component `shared.stat-item` (repeatable) | — | — | — |
|
|
446
172
|
|
|
447
|
-
|
|
173
|
+
## Team
|
|
448
174
|
|
|
449
|
-
|
|
450
|
-
|-------|--------|
|
|
451
|
-
| `grid` | Standard grid — circular/square photos + name/role/bio. For 4–12 members. |
|
|
452
|
-
| `large-image` | Large photo emphasis. For leadership/key members. |
|
|
453
|
-
| `compact` | Small photos + minimal info. For large teams (12+). |
|
|
175
|
+
`blocks.team` — Team member showcase block
|
|
454
176
|
|
|
455
|
-
|
|
177
|
+
| Attribute | Type | Required | Default | Notes |
|
|
178
|
+
|---|---|---|---|---|
|
|
179
|
+
| `name` | string | — | — | — |
|
|
180
|
+
| `variant` | enumeration | — | — | `grid`, `large-image`, `compact` |
|
|
181
|
+
| `section` | component `elements.section` | — | — | — |
|
|
182
|
+
| `items` | component `shared.team-member` (repeatable) | — | — | — |
|
|
456
183
|
|
|
457
|
-
|
|
458
|
-
|-------|------|-------------|
|
|
459
|
-
| `name` | `string \| null` | Admin label — DO NOT display |
|
|
460
|
-
| `variant` | enum | Layout variant |
|
|
461
|
-
| `section` | `Section \| null` | Section wrapper |
|
|
462
|
-
| `items` | `TeamMember[]` | Team members |
|
|
184
|
+
## Testimonials
|
|
463
185
|
|
|
464
|
-
|
|
465
|
-
- `TeamMember.photo` is images-only.
|
|
466
|
-
- `TeamMember.socialLinks` is `Link[]` — render as icon links.
|
|
467
|
-
|
|
468
|
-
---
|
|
469
|
-
|
|
470
|
-
## Shared Sub-Components
|
|
471
|
-
|
|
472
|
-
### FeatureItem (`shared.feature-item`)
|
|
473
|
-
|
|
474
|
-
| Field | Type | Description |
|
|
475
|
-
|-------|------|-------------|
|
|
476
|
-
| `label` | `string \| null` | Item label |
|
|
477
|
-
| `description` | `string \| null` | Markdown richtext |
|
|
478
|
-
| `icon` | `string \| null` | Icon picker value |
|
|
479
|
-
| `infoText` | `string \| null` | Supplementary info text |
|
|
480
|
-
| `link` | `Link \| null` | Optional link |
|
|
481
|
-
|
|
482
|
-
### HighlightItem (`shared.highlight-item`)
|
|
483
|
-
|
|
484
|
-
| Field | Type | Description |
|
|
485
|
-
|-------|------|-------------|
|
|
486
|
-
| `label` | `string \| null` | Item label |
|
|
487
|
-
| `description` | `string \| null` | Markdown richtext |
|
|
488
|
-
| `media` | `StrapiMedia` | **Required** — images+videos |
|
|
489
|
-
| `link` | `Link \| null` | Optional link |
|
|
490
|
-
|
|
491
|
-
### SliderItem (`shared.slider-item`)
|
|
492
|
-
|
|
493
|
-
| Field | Type | Description |
|
|
494
|
-
|-------|------|-------------|
|
|
495
|
-
| `label` | `string \| null` | Item label |
|
|
496
|
-
| `description` | `string \| null` | Description text |
|
|
497
|
-
| `link` | `Link \| null` | Optional link |
|
|
498
|
-
| `media` | `StrapiMedia` | **Required** — images+videos |
|
|
499
|
-
|
|
500
|
-
### BentoItem (`shared.bento-item`)
|
|
501
|
-
|
|
502
|
-
| Field | Type | Description |
|
|
503
|
-
|-------|------|-------------|
|
|
504
|
-
| `title` | `string \| null` | Item title |
|
|
505
|
-
| `description` | `string \| null` | Description text |
|
|
506
|
-
| `media` | `StrapiMedia \| null` | Screenshot/illustration — images only |
|
|
507
|
-
| `icon` | `string \| null` | Decorative icon |
|
|
508
|
-
| `colSpan` | `number` | Column span (1–4, default 1) |
|
|
509
|
-
| `rowSpan` | `number` | Row span (1–3, default 1) |
|
|
510
|
-
| `link` | `Link \| null` | Optional link |
|
|
511
|
-
|
|
512
|
-
### TestimonialItem (`shared.testimonial-item`)
|
|
513
|
-
|
|
514
|
-
| Field | Type | Description |
|
|
515
|
-
|-------|------|-------------|
|
|
516
|
-
| `quote` | `string` | **Required** — testimonial text |
|
|
517
|
-
| `authorName` | `string \| null` | Author name |
|
|
518
|
-
| `authorRole` | `string \| null` | Author title/role |
|
|
519
|
-
| `avatar` | `StrapiMedia \| null` | Profile image — images only |
|
|
520
|
-
| `logo` | `StrapiMedia \| null` | Company logo — images only |
|
|
521
|
-
| `rating` | `number \| null` | Star rating 1–5 |
|
|
522
|
-
|
|
523
|
-
### LogoItem (`shared.logo-item`)
|
|
524
|
-
|
|
525
|
-
| Field | Type | Description |
|
|
526
|
-
|-------|------|-------------|
|
|
527
|
-
| `logo` | `StrapiMedia` | **Required** — images only |
|
|
528
|
-
| `companyName` | `string \| null` | Company name (for alt text/accessibility) |
|
|
529
|
-
| `link` | `Link \| null` | Optional link |
|
|
530
|
-
|
|
531
|
-
### StatItem (`shared.stat-item`)
|
|
532
|
-
|
|
533
|
-
| Field | Type | Description |
|
|
534
|
-
|-------|------|-------------|
|
|
535
|
-
| `value` | `string` | **Required** — formatted value string |
|
|
536
|
-
| `label` | `string \| null` | Short label |
|
|
537
|
-
| `description` | `string \| null` | Supplementary description |
|
|
538
|
-
|
|
539
|
-
### PricingTier (`shared.pricing-tier`)
|
|
540
|
-
|
|
541
|
-
| Field | Type | Description |
|
|
542
|
-
|-------|------|-------------|
|
|
543
|
-
| `planName` | `string` | **Required** — plan name |
|
|
544
|
-
| `price` | `string` | **Required** — formatted price string |
|
|
545
|
-
| `billingPeriod` | `string \| null` | e.g. "/mo", "/year" |
|
|
546
|
-
| `description` | `string \| null` | Plan description |
|
|
547
|
-
| `featureList` | `string \| null` | Markdown bullet list |
|
|
548
|
-
| `ctaLink` | `Link \| null` | CTA link |
|
|
549
|
-
| `highlighted` | `boolean` | Recommended plan flag |
|
|
550
|
-
|
|
551
|
-
### TeamMember (`shared.team-member`)
|
|
552
|
-
|
|
553
|
-
| Field | Type | Description |
|
|
554
|
-
|-------|------|-------------|
|
|
555
|
-
| `memberName` | `string` | **Required** — member name |
|
|
556
|
-
| `role` | `string \| null` | Title/role |
|
|
557
|
-
| `bio` | `string \| null` | Short bio |
|
|
558
|
-
| `photo` | `StrapiMedia \| null` | Profile photo — images only |
|
|
559
|
-
| `socialLinks` | `Link[]` | Social media links |
|
|
560
|
-
|
|
561
|
-
### Link (`shared.link`)
|
|
562
|
-
|
|
563
|
-
| Field | Type | Description |
|
|
564
|
-
|-------|------|-------------|
|
|
565
|
-
| `label` | `string` | **Required** — link label |
|
|
566
|
-
| `href` | `string` | **Required** — URL |
|
|
567
|
-
| `newWindow` | `boolean` | Open in new window (default false) |
|
|
568
|
-
| `icon` | `string \| null` | Icon picker value |
|
|
569
|
-
|
|
570
|
-
---
|
|
186
|
+
`blocks.testimonials` — Customer testimonials/reviews block
|
|
571
187
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
case 'blocks.hero': return <HeroSection block={block} />;
|
|
580
|
-
case 'blocks.features': return <FeaturesSection block={block} />;
|
|
581
|
-
case 'blocks.cta': return <CtaSection block={block} />;
|
|
582
|
-
case 'blocks.slider': return <SliderSection block={block} />;
|
|
583
|
-
case 'blocks.inquiry-form': return <InquiryFormSection block={block} />;
|
|
584
|
-
case 'blocks.faq': return <FaqSection block={block} />;
|
|
585
|
-
case 'blocks.highlights': return <HighlightsSection block={block} />;
|
|
586
|
-
case 'blocks.bento-grid': return <BentoGridSection block={block} />;
|
|
587
|
-
case 'blocks.testimonials': return <TestimonialsSection block={block} />;
|
|
588
|
-
case 'blocks.logo-cloud': return <LogoCloudSection block={block} />;
|
|
589
|
-
case 'blocks.stats': return <StatsSection block={block} />;
|
|
590
|
-
case 'blocks.pricing': return <PricingSection block={block} />;
|
|
591
|
-
case 'blocks.content': return <ContentSection block={block} />;
|
|
592
|
-
case 'blocks.team': return <TeamSection block={block} />;
|
|
593
|
-
case 'elements.section': return <SectionDivider section={block} />;
|
|
594
|
-
default: return null;
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
```
|
|
598
|
-
|
|
599
|
-
**PageBlocks union** (15 members): `Section | HeroBlock | FeaturesBlock | CtaBlock | SliderBlock | InquiryFormBlock | FaqBlock | HighlightsBlock | BentoGridBlock | TestimonialsBlock | LogoCloudBlock | StatsBlock | PricingBlock | ContentBlock | TeamBlock`
|
|
600
|
-
|
|
601
|
-
**SiteWideBlocks union** (4 members): `SliderBlock | InquiryFormBlock | HeroBlock | FeaturesBlock`
|
|
188
|
+
| Attribute | Type | Required | Default | Notes |
|
|
189
|
+
|---|---|---|---|---|
|
|
190
|
+
| `name` | string | — | — | — |
|
|
191
|
+
| `variant` | enumeration | — | — | `centered`, `side-by-side`, `card-grid`, `subtle-grid` |
|
|
192
|
+
| `section` | component `elements.section` | — | — | — |
|
|
193
|
+
| `image` | component `shared.image` | — | — | — |
|
|
194
|
+
| `items` | component `shared.testimonial-item` (repeatable) | — | — | — |
|