@bytesbrains/weblocks 0.2.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.
Files changed (109) hide show
  1. package/AGENT.md +214 -0
  2. package/CATALOG.md +387 -0
  3. package/CHANGELOG.md +63 -0
  4. package/LICENSE +21 -0
  5. package/README.md +294 -0
  6. package/catalog.json +1850 -0
  7. package/lib/blocks/about.d.ts +2 -0
  8. package/lib/blocks/about.js +50 -0
  9. package/lib/blocks/accordion.d.ts +2 -0
  10. package/lib/blocks/accordion.js +51 -0
  11. package/lib/blocks/announcementBar.d.ts +2 -0
  12. package/lib/blocks/announcementBar.js +56 -0
  13. package/lib/blocks/appShell.d.ts +2 -0
  14. package/lib/blocks/appShell.js +54 -0
  15. package/lib/blocks/auth.d.ts +2 -0
  16. package/lib/blocks/auth.js +82 -0
  17. package/lib/blocks/blogList.d.ts +2 -0
  18. package/lib/blocks/blogList.js +81 -0
  19. package/lib/blocks/blogPost.d.ts +2 -0
  20. package/lib/blocks/blogPost.js +60 -0
  21. package/lib/blocks/carousel.d.ts +2 -0
  22. package/lib/blocks/carousel.js +56 -0
  23. package/lib/blocks/contactDetails.d.ts +2 -0
  24. package/lib/blocks/contactDetails.js +50 -0
  25. package/lib/blocks/contactForm.d.ts +2 -0
  26. package/lib/blocks/contactForm.js +100 -0
  27. package/lib/blocks/cta.d.ts +2 -0
  28. package/lib/blocks/cta.js +40 -0
  29. package/lib/blocks/divider.d.ts +2 -0
  30. package/lib/blocks/divider.js +28 -0
  31. package/lib/blocks/faq.d.ts +2 -0
  32. package/lib/blocks/faq.js +52 -0
  33. package/lib/blocks/features.d.ts +2 -0
  34. package/lib/blocks/features.js +58 -0
  35. package/lib/blocks/feed.d.ts +2 -0
  36. package/lib/blocks/feed.js +81 -0
  37. package/lib/blocks/footer.d.ts +2 -0
  38. package/lib/blocks/footer.js +40 -0
  39. package/lib/blocks/gallery.d.ts +2 -0
  40. package/lib/blocks/gallery.js +64 -0
  41. package/lib/blocks/hero.d.ts +2 -0
  42. package/lib/blocks/hero.js +48 -0
  43. package/lib/blocks/heroApp.d.ts +2 -0
  44. package/lib/blocks/heroApp.js +65 -0
  45. package/lib/blocks/logos.d.ts +2 -0
  46. package/lib/blocks/logos.js +59 -0
  47. package/lib/blocks/map.d.ts +2 -0
  48. package/lib/blocks/map.js +43 -0
  49. package/lib/blocks/nav.d.ts +2 -0
  50. package/lib/blocks/nav.js +39 -0
  51. package/lib/blocks/newsletter.d.ts +2 -0
  52. package/lib/blocks/newsletter.js +56 -0
  53. package/lib/blocks/pricing.d.ts +2 -0
  54. package/lib/blocks/pricing.js +89 -0
  55. package/lib/blocks/prose.d.ts +5 -0
  56. package/lib/blocks/prose.js +46 -0
  57. package/lib/blocks/richText.d.ts +2 -0
  58. package/lib/blocks/richText.js +46 -0
  59. package/lib/blocks/services.d.ts +2 -0
  60. package/lib/blocks/services.js +65 -0
  61. package/lib/blocks/sidebar.d.ts +2 -0
  62. package/lib/blocks/sidebar.js +58 -0
  63. package/lib/blocks/socialLinks.d.ts +2 -0
  64. package/lib/blocks/socialLinks.js +53 -0
  65. package/lib/blocks/spacer.d.ts +2 -0
  66. package/lib/blocks/spacer.js +25 -0
  67. package/lib/blocks/split.d.ts +2 -0
  68. package/lib/blocks/split.js +67 -0
  69. package/lib/blocks/stats.d.ts +2 -0
  70. package/lib/blocks/stats.js +64 -0
  71. package/lib/blocks/steps.d.ts +2 -0
  72. package/lib/blocks/steps.js +63 -0
  73. package/lib/blocks/tabs.d.ts +2 -0
  74. package/lib/blocks/tabs.js +57 -0
  75. package/lib/blocks/team.d.ts +2 -0
  76. package/lib/blocks/team.js +94 -0
  77. package/lib/blocks/testimonials.d.ts +2 -0
  78. package/lib/blocks/testimonials.js +54 -0
  79. package/lib/blocks/timeline.d.ts +2 -0
  80. package/lib/blocks/timeline.js +53 -0
  81. package/lib/blocks/video.d.ts +2 -0
  82. package/lib/blocks/video.js +61 -0
  83. package/lib/catalog.d.ts +26 -0
  84. package/lib/catalog.js +62 -0
  85. package/lib/generate.d.ts +35 -0
  86. package/lib/generate.js +160 -0
  87. package/lib/index.d.ts +19 -0
  88. package/lib/index.js +11 -0
  89. package/lib/ops.d.ts +85 -0
  90. package/lib/ops.js +248 -0
  91. package/lib/presets.d.ts +16 -0
  92. package/lib/presets.js +50 -0
  93. package/lib/pwa.d.ts +30 -0
  94. package/lib/pwa.js +79 -0
  95. package/lib/registry.d.ts +53 -0
  96. package/lib/registry.js +81 -0
  97. package/lib/render.d.ts +8 -0
  98. package/lib/render.js +105 -0
  99. package/lib/runtime.d.ts +68 -0
  100. package/lib/runtime.js +46 -0
  101. package/lib/schema.d.ts +67 -0
  102. package/lib/schema.js +150 -0
  103. package/lib/tokens.d.ts +37 -0
  104. package/lib/tokens.js +136 -0
  105. package/lib/types.d.ts +108 -0
  106. package/lib/types.js +10 -0
  107. package/lib/validate.d.ts +10 -0
  108. package/lib/validate.js +48 -0
  109. package/package.json +65 -0
package/catalog.json ADDED
@@ -0,0 +1,1850 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "package": "@bytesbrains/weblocks",
4
+ "version": "0.2.0",
5
+ "description": "Block catalog for @bytesbrains/weblocks. Send this to the model as its API reference; it composes a SiteManifest ({ meta, design, blocks[] }) using ONLY these block types. The engine then validates and renders it.",
6
+ "blockTypes": [
7
+ "app-shell",
8
+ "nav",
9
+ "announcement-bar",
10
+ "sidebar",
11
+ "hero",
12
+ "hero-app",
13
+ "features",
14
+ "about",
15
+ "rich-text",
16
+ "split",
17
+ "steps",
18
+ "stats",
19
+ "services-catalogue",
20
+ "pricing",
21
+ "logos",
22
+ "team",
23
+ "gallery",
24
+ "carousel",
25
+ "video",
26
+ "map",
27
+ "timeline",
28
+ "tabs",
29
+ "accordion",
30
+ "testimonials",
31
+ "faq",
32
+ "blog-list",
33
+ "blog-post",
34
+ "feed",
35
+ "contact-form",
36
+ "newsletter",
37
+ "auth",
38
+ "cta",
39
+ "social-links",
40
+ "contact-details",
41
+ "divider",
42
+ "spacer",
43
+ "footer"
44
+ ],
45
+ "blocks": [
46
+ {
47
+ "type": "app-shell",
48
+ "description": "A persistent bottom tab bar for app-like navigation, each tab an optional icon plus a label linking to a view.",
49
+ "schema": {
50
+ "type": "object",
51
+ "properties": {
52
+ "brand": {
53
+ "type": "string",
54
+ "maxLength": 60,
55
+ "default": ""
56
+ },
57
+ "tabs": {
58
+ "type": "array",
59
+ "items": {
60
+ "type": "object",
61
+ "properties": {
62
+ "label": {
63
+ "type": "string",
64
+ "maxLength": 40,
65
+ "default": ""
66
+ },
67
+ "href": {
68
+ "type": "string",
69
+ "maxLength": 500,
70
+ "default": ""
71
+ },
72
+ "icon": {
73
+ "type": "string",
74
+ "maxLength": 8,
75
+ "default": ""
76
+ }
77
+ },
78
+ "required": [
79
+ "label"
80
+ ],
81
+ "additionalProperties": false
82
+ },
83
+ "maxItems": 6
84
+ }
85
+ },
86
+ "additionalProperties": false
87
+ }
88
+ },
89
+ {
90
+ "type": "nav",
91
+ "description": "Top navigation bar: brand/logo text, a row of links, and an optional call-to-action button. Place first.",
92
+ "schema": {
93
+ "type": "object",
94
+ "properties": {
95
+ "brand": {
96
+ "type": "string",
97
+ "maxLength": 60,
98
+ "default": "Brand"
99
+ },
100
+ "sticky": {
101
+ "type": "boolean",
102
+ "default": false
103
+ },
104
+ "links": {
105
+ "type": "array",
106
+ "items": {
107
+ "type": "object",
108
+ "properties": {
109
+ "label": {
110
+ "type": "string",
111
+ "maxLength": 40,
112
+ "default": "Link"
113
+ },
114
+ "href": {
115
+ "type": "string",
116
+ "maxLength": 300,
117
+ "default": "#"
118
+ }
119
+ },
120
+ "required": [
121
+ "label"
122
+ ],
123
+ "additionalProperties": false
124
+ },
125
+ "maxItems": 8
126
+ },
127
+ "cta": {
128
+ "type": "object",
129
+ "properties": {
130
+ "label": {
131
+ "type": "string",
132
+ "maxLength": 40,
133
+ "default": ""
134
+ },
135
+ "href": {
136
+ "type": "string",
137
+ "maxLength": 300,
138
+ "default": "#"
139
+ }
140
+ },
141
+ "additionalProperties": false
142
+ }
143
+ },
144
+ "required": [
145
+ "brand"
146
+ ],
147
+ "additionalProperties": false
148
+ }
149
+ },
150
+ {
151
+ "type": "announcement-bar",
152
+ "description": "A dismissible full-width strip for a short promo or notice, with an optional inline link and info/promo/warning tone.",
153
+ "schema": {
154
+ "type": "object",
155
+ "properties": {
156
+ "text": {
157
+ "type": "string",
158
+ "maxLength": 200,
159
+ "default": ""
160
+ },
161
+ "linkLabel": {
162
+ "type": "string",
163
+ "maxLength": 40,
164
+ "default": ""
165
+ },
166
+ "href": {
167
+ "type": "string",
168
+ "maxLength": 500,
169
+ "default": ""
170
+ },
171
+ "tone": {
172
+ "enum": [
173
+ "info",
174
+ "promo",
175
+ "warning"
176
+ ],
177
+ "default": "info"
178
+ },
179
+ "dismissible": {
180
+ "type": "boolean",
181
+ "default": true
182
+ }
183
+ },
184
+ "required": [
185
+ "text"
186
+ ],
187
+ "additionalProperties": false
188
+ }
189
+ },
190
+ {
191
+ "type": "sidebar",
192
+ "description": "A vertical section/drawer navigation for multi-view apps: an optional title over a list of icon-and-label links.",
193
+ "schema": {
194
+ "type": "object",
195
+ "properties": {
196
+ "title": {
197
+ "type": "string",
198
+ "maxLength": 60,
199
+ "default": ""
200
+ },
201
+ "links": {
202
+ "type": "array",
203
+ "items": {
204
+ "type": "object",
205
+ "properties": {
206
+ "label": {
207
+ "type": "string",
208
+ "maxLength": 60,
209
+ "default": ""
210
+ },
211
+ "href": {
212
+ "type": "string",
213
+ "maxLength": 500,
214
+ "default": ""
215
+ },
216
+ "icon": {
217
+ "type": "string",
218
+ "maxLength": 8,
219
+ "default": ""
220
+ }
221
+ },
222
+ "required": [
223
+ "label"
224
+ ],
225
+ "additionalProperties": false
226
+ },
227
+ "maxItems": 20
228
+ }
229
+ },
230
+ "additionalProperties": false
231
+ }
232
+ },
233
+ {
234
+ "type": "hero",
235
+ "description": "Top-of-page banner: a big headline with an optional eyebrow, subheading, and one call-to-action button.",
236
+ "schema": {
237
+ "type": "object",
238
+ "properties": {
239
+ "eyebrow": {
240
+ "type": "string",
241
+ "maxLength": 80,
242
+ "default": ""
243
+ },
244
+ "headline": {
245
+ "type": "string",
246
+ "maxLength": 160,
247
+ "default": "Your headline here"
248
+ },
249
+ "subhead": {
250
+ "type": "string",
251
+ "maxLength": 320,
252
+ "default": ""
253
+ },
254
+ "align": {
255
+ "enum": [
256
+ "center",
257
+ "left"
258
+ ],
259
+ "default": "center"
260
+ },
261
+ "cta": {
262
+ "type": "object",
263
+ "properties": {
264
+ "label": {
265
+ "type": "string",
266
+ "maxLength": 40,
267
+ "default": ""
268
+ },
269
+ "href": {
270
+ "type": "string",
271
+ "maxLength": 500,
272
+ "default": "#"
273
+ }
274
+ },
275
+ "additionalProperties": false
276
+ }
277
+ },
278
+ "required": [
279
+ "headline"
280
+ ],
281
+ "additionalProperties": false
282
+ }
283
+ },
284
+ {
285
+ "type": "hero-app",
286
+ "description": "An app landing hero: a headline and subhead over a primary install button, with a horizontal scroll row of app screenshots.",
287
+ "schema": {
288
+ "type": "object",
289
+ "properties": {
290
+ "headline": {
291
+ "type": "string",
292
+ "maxLength": 120,
293
+ "default": ""
294
+ },
295
+ "subhead": {
296
+ "type": "string",
297
+ "maxLength": 240,
298
+ "default": ""
299
+ },
300
+ "installLabel": {
301
+ "type": "string",
302
+ "maxLength": 40,
303
+ "default": "Install app"
304
+ },
305
+ "installHref": {
306
+ "type": "string",
307
+ "maxLength": 500,
308
+ "default": ""
309
+ },
310
+ "screenshots": {
311
+ "type": "array",
312
+ "items": {
313
+ "type": "object",
314
+ "properties": {
315
+ "src": {
316
+ "type": "string",
317
+ "maxLength": 500,
318
+ "default": ""
319
+ },
320
+ "alt": {
321
+ "type": "string",
322
+ "maxLength": 200,
323
+ "default": ""
324
+ }
325
+ },
326
+ "required": [
327
+ "src"
328
+ ],
329
+ "additionalProperties": false
330
+ },
331
+ "maxItems": 6
332
+ }
333
+ },
334
+ "required": [
335
+ "headline"
336
+ ],
337
+ "additionalProperties": false
338
+ }
339
+ },
340
+ {
341
+ "type": "features",
342
+ "description": "A grid of value propositions, each with an optional icon/emoji, a title, and a short line of text.",
343
+ "schema": {
344
+ "type": "object",
345
+ "properties": {
346
+ "title": {
347
+ "type": "string",
348
+ "maxLength": 120,
349
+ "default": ""
350
+ },
351
+ "subtitle": {
352
+ "type": "string",
353
+ "maxLength": 240,
354
+ "default": ""
355
+ },
356
+ "columns": {
357
+ "type": "integer",
358
+ "enum": [
359
+ 2,
360
+ 3,
361
+ 4
362
+ ],
363
+ "default": 3
364
+ },
365
+ "items": {
366
+ "type": "array",
367
+ "items": {
368
+ "type": "object",
369
+ "properties": {
370
+ "icon": {
371
+ "type": "string",
372
+ "maxLength": 8,
373
+ "default": ""
374
+ },
375
+ "title": {
376
+ "type": "string",
377
+ "maxLength": 80,
378
+ "default": "Feature"
379
+ },
380
+ "text": {
381
+ "type": "string",
382
+ "maxLength": 240,
383
+ "default": ""
384
+ }
385
+ },
386
+ "required": [
387
+ "title"
388
+ ],
389
+ "additionalProperties": false
390
+ },
391
+ "maxItems": 12
392
+ }
393
+ },
394
+ "additionalProperties": false
395
+ }
396
+ },
397
+ {
398
+ "type": "about",
399
+ "description": "A story/mission section: eyebrow, title, prose body, and an optional side image (choose which side).",
400
+ "schema": {
401
+ "type": "object",
402
+ "properties": {
403
+ "eyebrow": {
404
+ "type": "string",
405
+ "maxLength": 60,
406
+ "default": ""
407
+ },
408
+ "title": {
409
+ "type": "string",
410
+ "maxLength": 120,
411
+ "default": "About us"
412
+ },
413
+ "body": {
414
+ "type": "string",
415
+ "maxLength": 1200,
416
+ "default": ""
417
+ },
418
+ "image": {
419
+ "type": "string",
420
+ "maxLength": 500,
421
+ "default": ""
422
+ },
423
+ "imageAlt": {
424
+ "type": "string",
425
+ "maxLength": 200,
426
+ "default": ""
427
+ },
428
+ "imageSide": {
429
+ "enum": [
430
+ "left",
431
+ "right"
432
+ ],
433
+ "default": "right"
434
+ }
435
+ },
436
+ "additionalProperties": false
437
+ }
438
+ },
439
+ {
440
+ "type": "rich-text",
441
+ "description": "A typed prose section with ordered headings, paragraphs, quotes, and bullet/numbered lists — a safe freeform-content block, never raw HTML.",
442
+ "schema": {
443
+ "type": "object",
444
+ "properties": {
445
+ "blocks": {
446
+ "type": "array",
447
+ "items": {
448
+ "type": "object",
449
+ "properties": {
450
+ "kind": {
451
+ "enum": [
452
+ "heading",
453
+ "subheading",
454
+ "paragraph",
455
+ "quote",
456
+ "bullet",
457
+ "numbered"
458
+ ],
459
+ "default": "paragraph"
460
+ },
461
+ "text": {
462
+ "type": "string",
463
+ "maxLength": 2000,
464
+ "default": ""
465
+ }
466
+ },
467
+ "required": [
468
+ "text"
469
+ ],
470
+ "additionalProperties": false
471
+ },
472
+ "maxItems": 60
473
+ }
474
+ },
475
+ "additionalProperties": false
476
+ }
477
+ },
478
+ {
479
+ "type": "split",
480
+ "description": "Alternating image-and-text rows; the image side flips each row, and rows without an image collapse to centered text.",
481
+ "schema": {
482
+ "type": "object",
483
+ "properties": {
484
+ "rows": {
485
+ "type": "array",
486
+ "items": {
487
+ "type": "object",
488
+ "properties": {
489
+ "title": {
490
+ "type": "string",
491
+ "maxLength": 120,
492
+ "default": ""
493
+ },
494
+ "text": {
495
+ "type": "string",
496
+ "maxLength": 600,
497
+ "default": ""
498
+ },
499
+ "image": {
500
+ "type": "string",
501
+ "maxLength": 500,
502
+ "default": ""
503
+ },
504
+ "imageAlt": {
505
+ "type": "string",
506
+ "maxLength": 200,
507
+ "default": ""
508
+ }
509
+ },
510
+ "additionalProperties": false
511
+ },
512
+ "maxItems": 8
513
+ }
514
+ },
515
+ "additionalProperties": false
516
+ }
517
+ },
518
+ {
519
+ "type": "steps",
520
+ "description": "A numbered how-it-works / process list: an optional title and subtitle over auto-numbered step cards, each with a title and short text.",
521
+ "schema": {
522
+ "type": "object",
523
+ "properties": {
524
+ "title": {
525
+ "type": "string",
526
+ "maxLength": 120,
527
+ "default": ""
528
+ },
529
+ "subtitle": {
530
+ "type": "string",
531
+ "maxLength": 240,
532
+ "default": ""
533
+ },
534
+ "items": {
535
+ "type": "array",
536
+ "items": {
537
+ "type": "object",
538
+ "properties": {
539
+ "title": {
540
+ "type": "string",
541
+ "maxLength": 100,
542
+ "default": "Step"
543
+ },
544
+ "text": {
545
+ "type": "string",
546
+ "maxLength": 300,
547
+ "default": ""
548
+ }
549
+ },
550
+ "required": [
551
+ "title"
552
+ ],
553
+ "additionalProperties": false
554
+ },
555
+ "maxItems": 12
556
+ }
557
+ },
558
+ "additionalProperties": false
559
+ }
560
+ },
561
+ {
562
+ "type": "stats",
563
+ "description": "A grid of metric counters: each stat shows an optional prefix/suffix around a big value with a muted label, with an optional count-up animation.",
564
+ "schema": {
565
+ "type": "object",
566
+ "properties": {
567
+ "title": {
568
+ "type": "string",
569
+ "maxLength": 120,
570
+ "default": ""
571
+ },
572
+ "columns": {
573
+ "type": "integer",
574
+ "enum": [
575
+ 2,
576
+ 3,
577
+ 4
578
+ ],
579
+ "default": 4
580
+ },
581
+ "items": {
582
+ "type": "array",
583
+ "items": {
584
+ "type": "object",
585
+ "properties": {
586
+ "value": {
587
+ "type": "string",
588
+ "maxLength": 24,
589
+ "default": ""
590
+ },
591
+ "label": {
592
+ "type": "string",
593
+ "maxLength": 60,
594
+ "default": ""
595
+ },
596
+ "prefix": {
597
+ "type": "string",
598
+ "maxLength": 8,
599
+ "default": ""
600
+ },
601
+ "suffix": {
602
+ "type": "string",
603
+ "maxLength": 8,
604
+ "default": ""
605
+ }
606
+ },
607
+ "required": [
608
+ "value",
609
+ "label"
610
+ ],
611
+ "additionalProperties": false
612
+ },
613
+ "maxItems": 8
614
+ }
615
+ },
616
+ "additionalProperties": false
617
+ }
618
+ },
619
+ {
620
+ "type": "services-catalogue",
621
+ "description": "A grid of services or products, each with a name, optional price, description, and link. Use for \"what we offer\".",
622
+ "schema": {
623
+ "type": "object",
624
+ "properties": {
625
+ "title": {
626
+ "type": "string",
627
+ "maxLength": 120,
628
+ "default": ""
629
+ },
630
+ "subtitle": {
631
+ "type": "string",
632
+ "maxLength": 240,
633
+ "default": ""
634
+ },
635
+ "items": {
636
+ "type": "array",
637
+ "items": {
638
+ "type": "object",
639
+ "properties": {
640
+ "name": {
641
+ "type": "string",
642
+ "maxLength": 80,
643
+ "default": "Service"
644
+ },
645
+ "description": {
646
+ "type": "string",
647
+ "maxLength": 300,
648
+ "default": ""
649
+ },
650
+ "price": {
651
+ "type": "string",
652
+ "maxLength": 40,
653
+ "default": ""
654
+ },
655
+ "ctaLabel": {
656
+ "type": "string",
657
+ "maxLength": 40,
658
+ "default": ""
659
+ },
660
+ "ctaHref": {
661
+ "type": "string",
662
+ "maxLength": 500,
663
+ "default": "#"
664
+ }
665
+ },
666
+ "required": [
667
+ "name"
668
+ ],
669
+ "additionalProperties": false
670
+ },
671
+ "maxItems": 24
672
+ }
673
+ },
674
+ "additionalProperties": false
675
+ }
676
+ },
677
+ {
678
+ "type": "pricing",
679
+ "description": "A row of pricing/tier cards, each with a name, price, feature list, and a call-to-action button; one plan can be highlighted.",
680
+ "schema": {
681
+ "type": "object",
682
+ "properties": {
683
+ "title": {
684
+ "type": "string",
685
+ "maxLength": 120,
686
+ "default": ""
687
+ },
688
+ "subtitle": {
689
+ "type": "string",
690
+ "maxLength": 240,
691
+ "default": ""
692
+ },
693
+ "plans": {
694
+ "type": "array",
695
+ "items": {
696
+ "type": "object",
697
+ "properties": {
698
+ "name": {
699
+ "type": "string",
700
+ "maxLength": 60,
701
+ "default": ""
702
+ },
703
+ "price": {
704
+ "type": "string",
705
+ "maxLength": 24,
706
+ "default": ""
707
+ },
708
+ "period": {
709
+ "type": "string",
710
+ "maxLength": 24,
711
+ "default": ""
712
+ },
713
+ "features": {
714
+ "type": "array",
715
+ "items": {
716
+ "type": "string",
717
+ "maxLength": 120,
718
+ "default": ""
719
+ },
720
+ "maxItems": 12
721
+ },
722
+ "ctaLabel": {
723
+ "type": "string",
724
+ "maxLength": 40,
725
+ "default": "Choose"
726
+ },
727
+ "ctaHref": {
728
+ "type": "string",
729
+ "maxLength": 500,
730
+ "default": ""
731
+ },
732
+ "featured": {
733
+ "type": "boolean",
734
+ "default": false
735
+ }
736
+ },
737
+ "required": [
738
+ "name",
739
+ "price"
740
+ ],
741
+ "additionalProperties": false
742
+ },
743
+ "maxItems": 6
744
+ }
745
+ },
746
+ "additionalProperties": false
747
+ }
748
+ },
749
+ {
750
+ "type": "logos",
751
+ "description": "A centered strip of client or partner logos (grayscale until hover), each optionally linking out, under a short heading.",
752
+ "schema": {
753
+ "type": "object",
754
+ "properties": {
755
+ "title": {
756
+ "type": "string",
757
+ "maxLength": 120,
758
+ "default": "Trusted by"
759
+ },
760
+ "items": {
761
+ "type": "array",
762
+ "items": {
763
+ "type": "object",
764
+ "properties": {
765
+ "src": {
766
+ "type": "string",
767
+ "maxLength": 500,
768
+ "default": ""
769
+ },
770
+ "alt": {
771
+ "type": "string",
772
+ "maxLength": 120,
773
+ "default": ""
774
+ },
775
+ "href": {
776
+ "type": "string",
777
+ "maxLength": 500,
778
+ "default": ""
779
+ }
780
+ },
781
+ "required": [
782
+ "src"
783
+ ],
784
+ "additionalProperties": false
785
+ },
786
+ "maxItems": 24
787
+ }
788
+ },
789
+ "additionalProperties": false
790
+ }
791
+ },
792
+ {
793
+ "type": "team",
794
+ "description": "A grid of people cards with photo (or initials), name, role, a short bio, and optional social links.",
795
+ "schema": {
796
+ "type": "object",
797
+ "properties": {
798
+ "title": {
799
+ "type": "string",
800
+ "maxLength": 120,
801
+ "default": ""
802
+ },
803
+ "subtitle": {
804
+ "type": "string",
805
+ "maxLength": 240,
806
+ "default": ""
807
+ },
808
+ "columns": {
809
+ "type": "integer",
810
+ "enum": [
811
+ 2,
812
+ 3,
813
+ 4
814
+ ],
815
+ "default": 3
816
+ },
817
+ "members": {
818
+ "type": "array",
819
+ "items": {
820
+ "type": "object",
821
+ "properties": {
822
+ "name": {
823
+ "type": "string",
824
+ "maxLength": 80,
825
+ "default": ""
826
+ },
827
+ "role": {
828
+ "type": "string",
829
+ "maxLength": 80,
830
+ "default": ""
831
+ },
832
+ "photo": {
833
+ "type": "string",
834
+ "maxLength": 500,
835
+ "default": ""
836
+ },
837
+ "bio": {
838
+ "type": "string",
839
+ "maxLength": 240,
840
+ "default": ""
841
+ },
842
+ "socials": {
843
+ "type": "array",
844
+ "items": {
845
+ "type": "object",
846
+ "properties": {
847
+ "label": {
848
+ "type": "string",
849
+ "maxLength": 40,
850
+ "default": ""
851
+ },
852
+ "href": {
853
+ "type": "string",
854
+ "maxLength": 500,
855
+ "default": ""
856
+ }
857
+ },
858
+ "required": [
859
+ "label"
860
+ ],
861
+ "additionalProperties": false
862
+ },
863
+ "maxItems": 5
864
+ }
865
+ },
866
+ "required": [
867
+ "name"
868
+ ],
869
+ "additionalProperties": false
870
+ },
871
+ "maxItems": 24
872
+ }
873
+ },
874
+ "additionalProperties": false
875
+ }
876
+ },
877
+ {
878
+ "type": "gallery",
879
+ "description": "A responsive image grid (grid/masonry/carousel) with an optional click-to-zoom lightbox. Each item needs a src and alt text.",
880
+ "schema": {
881
+ "type": "object",
882
+ "properties": {
883
+ "layout": {
884
+ "enum": [
885
+ "grid",
886
+ "masonry",
887
+ "carousel"
888
+ ],
889
+ "default": "grid"
890
+ },
891
+ "columns": {
892
+ "type": "integer",
893
+ "enum": [
894
+ 2,
895
+ 3,
896
+ 4
897
+ ],
898
+ "default": 3
899
+ },
900
+ "gap": {
901
+ "enum": [
902
+ "sm",
903
+ "md",
904
+ "lg"
905
+ ],
906
+ "default": "md"
907
+ },
908
+ "lightbox": {
909
+ "type": "boolean",
910
+ "default": true
911
+ },
912
+ "items": {
913
+ "type": "array",
914
+ "items": {
915
+ "type": "object",
916
+ "properties": {
917
+ "src": {
918
+ "type": "string",
919
+ "maxLength": 500,
920
+ "default": ""
921
+ },
922
+ "alt": {
923
+ "type": "string",
924
+ "maxLength": 200,
925
+ "default": ""
926
+ },
927
+ "caption": {
928
+ "type": "string",
929
+ "maxLength": 200,
930
+ "default": ""
931
+ }
932
+ },
933
+ "required": [
934
+ "src",
935
+ "alt"
936
+ ],
937
+ "additionalProperties": false
938
+ },
939
+ "maxItems": 60
940
+ }
941
+ },
942
+ "additionalProperties": false
943
+ }
944
+ },
945
+ {
946
+ "type": "carousel",
947
+ "description": "A horizontal, swipeable carousel of image slides with optional captions; scrolls natively and can be enhanced with arrows/autoplay.",
948
+ "schema": {
949
+ "type": "object",
950
+ "properties": {
951
+ "title": {
952
+ "type": "string",
953
+ "maxLength": 120,
954
+ "default": ""
955
+ },
956
+ "items": {
957
+ "type": "array",
958
+ "items": {
959
+ "type": "object",
960
+ "properties": {
961
+ "src": {
962
+ "type": "string",
963
+ "maxLength": 500,
964
+ "default": ""
965
+ },
966
+ "alt": {
967
+ "type": "string",
968
+ "maxLength": 200,
969
+ "default": ""
970
+ },
971
+ "caption": {
972
+ "type": "string",
973
+ "maxLength": 200,
974
+ "default": ""
975
+ }
976
+ },
977
+ "additionalProperties": false
978
+ },
979
+ "maxItems": 20
980
+ },
981
+ "autoplay": {
982
+ "type": "boolean",
983
+ "default": false
984
+ }
985
+ },
986
+ "additionalProperties": false
987
+ }
988
+ },
989
+ {
990
+ "type": "video",
991
+ "description": "A responsive embedded video from YouTube or Vimeo (by id or URL) or a self-hosted file, with an optional caption.",
992
+ "schema": {
993
+ "type": "object",
994
+ "properties": {
995
+ "provider": {
996
+ "enum": [
997
+ "youtube",
998
+ "vimeo",
999
+ "file"
1000
+ ],
1001
+ "default": "youtube"
1002
+ },
1003
+ "src": {
1004
+ "type": "string",
1005
+ "maxLength": 500,
1006
+ "default": ""
1007
+ },
1008
+ "title": {
1009
+ "type": "string",
1010
+ "maxLength": 120,
1011
+ "default": "Video"
1012
+ },
1013
+ "poster": {
1014
+ "type": "string",
1015
+ "maxLength": 500,
1016
+ "default": ""
1017
+ },
1018
+ "caption": {
1019
+ "type": "string",
1020
+ "maxLength": 200,
1021
+ "default": ""
1022
+ }
1023
+ },
1024
+ "required": [
1025
+ "src"
1026
+ ],
1027
+ "additionalProperties": false
1028
+ }
1029
+ },
1030
+ {
1031
+ "type": "map",
1032
+ "description": "An embedded location map for a place or address query, with configurable zoom and height and a link to the full map.",
1033
+ "schema": {
1034
+ "type": "object",
1035
+ "properties": {
1036
+ "query": {
1037
+ "type": "string",
1038
+ "maxLength": 200,
1039
+ "default": ""
1040
+ },
1041
+ "zoom": {
1042
+ "type": "integer",
1043
+ "minimum": 1,
1044
+ "maximum": 20,
1045
+ "default": 14
1046
+ },
1047
+ "height": {
1048
+ "type": "integer",
1049
+ "minimum": 160,
1050
+ "maximum": 800,
1051
+ "default": 360
1052
+ },
1053
+ "label": {
1054
+ "type": "string",
1055
+ "maxLength": 120,
1056
+ "default": ""
1057
+ }
1058
+ },
1059
+ "required": [
1060
+ "query"
1061
+ ],
1062
+ "additionalProperties": false
1063
+ }
1064
+ },
1065
+ {
1066
+ "type": "timeline",
1067
+ "description": "A vertical timeline of chronological milestones, each with an optional date, a title, and supporting text.",
1068
+ "schema": {
1069
+ "type": "object",
1070
+ "properties": {
1071
+ "title": {
1072
+ "type": "string",
1073
+ "maxLength": 120,
1074
+ "default": ""
1075
+ },
1076
+ "items": {
1077
+ "type": "array",
1078
+ "items": {
1079
+ "type": "object",
1080
+ "properties": {
1081
+ "date": {
1082
+ "type": "string",
1083
+ "maxLength": 40,
1084
+ "default": ""
1085
+ },
1086
+ "title": {
1087
+ "type": "string",
1088
+ "maxLength": 120,
1089
+ "default": ""
1090
+ },
1091
+ "text": {
1092
+ "type": "string",
1093
+ "maxLength": 400,
1094
+ "default": ""
1095
+ }
1096
+ },
1097
+ "required": [
1098
+ "title"
1099
+ ],
1100
+ "additionalProperties": false
1101
+ },
1102
+ "maxItems": 24
1103
+ }
1104
+ },
1105
+ "additionalProperties": false
1106
+ }
1107
+ },
1108
+ {
1109
+ "type": "tabs",
1110
+ "description": "Tabbed content panels that switch with no JavaScript; each tab has a label and a text panel.",
1111
+ "schema": {
1112
+ "type": "object",
1113
+ "properties": {
1114
+ "items": {
1115
+ "type": "array",
1116
+ "items": {
1117
+ "type": "object",
1118
+ "properties": {
1119
+ "label": {
1120
+ "type": "string",
1121
+ "maxLength": 60,
1122
+ "default": ""
1123
+ },
1124
+ "text": {
1125
+ "type": "string",
1126
+ "maxLength": 2000,
1127
+ "default": ""
1128
+ }
1129
+ },
1130
+ "required": [
1131
+ "label"
1132
+ ],
1133
+ "additionalProperties": false
1134
+ },
1135
+ "maxItems": 8
1136
+ }
1137
+ },
1138
+ "additionalProperties": false
1139
+ }
1140
+ },
1141
+ {
1142
+ "type": "accordion",
1143
+ "description": "Generic collapsible disclosure panels (native details/summary, no JavaScript); each panel has a heading and body.",
1144
+ "schema": {
1145
+ "type": "object",
1146
+ "properties": {
1147
+ "title": {
1148
+ "type": "string",
1149
+ "maxLength": 120,
1150
+ "default": ""
1151
+ },
1152
+ "items": {
1153
+ "type": "array",
1154
+ "items": {
1155
+ "type": "object",
1156
+ "properties": {
1157
+ "heading": {
1158
+ "type": "string",
1159
+ "maxLength": 200,
1160
+ "default": ""
1161
+ },
1162
+ "body": {
1163
+ "type": "string",
1164
+ "maxLength": 1200,
1165
+ "default": ""
1166
+ }
1167
+ },
1168
+ "required": [
1169
+ "heading"
1170
+ ],
1171
+ "additionalProperties": false
1172
+ },
1173
+ "maxItems": 24
1174
+ }
1175
+ },
1176
+ "additionalProperties": false
1177
+ }
1178
+ },
1179
+ {
1180
+ "type": "testimonials",
1181
+ "description": "A grid of customer quotes, each with the quote text and an optional author name and role.",
1182
+ "schema": {
1183
+ "type": "object",
1184
+ "properties": {
1185
+ "title": {
1186
+ "type": "string",
1187
+ "maxLength": 120,
1188
+ "default": ""
1189
+ },
1190
+ "items": {
1191
+ "type": "array",
1192
+ "items": {
1193
+ "type": "object",
1194
+ "properties": {
1195
+ "quote": {
1196
+ "type": "string",
1197
+ "maxLength": 400,
1198
+ "default": ""
1199
+ },
1200
+ "author": {
1201
+ "type": "string",
1202
+ "maxLength": 80,
1203
+ "default": ""
1204
+ },
1205
+ "role": {
1206
+ "type": "string",
1207
+ "maxLength": 80,
1208
+ "default": ""
1209
+ }
1210
+ },
1211
+ "required": [
1212
+ "quote"
1213
+ ],
1214
+ "additionalProperties": false
1215
+ },
1216
+ "maxItems": 12
1217
+ }
1218
+ },
1219
+ "additionalProperties": false
1220
+ }
1221
+ },
1222
+ {
1223
+ "type": "faq",
1224
+ "description": "An accordion of question/answer pairs. Expands/collapses natively (no JS).",
1225
+ "schema": {
1226
+ "type": "object",
1227
+ "properties": {
1228
+ "title": {
1229
+ "type": "string",
1230
+ "maxLength": 120,
1231
+ "default": "Frequently asked questions"
1232
+ },
1233
+ "items": {
1234
+ "type": "array",
1235
+ "items": {
1236
+ "type": "object",
1237
+ "properties": {
1238
+ "question": {
1239
+ "type": "string",
1240
+ "maxLength": 200,
1241
+ "default": ""
1242
+ },
1243
+ "answer": {
1244
+ "type": "string",
1245
+ "maxLength": 800,
1246
+ "default": ""
1247
+ }
1248
+ },
1249
+ "required": [
1250
+ "question"
1251
+ ],
1252
+ "additionalProperties": false
1253
+ },
1254
+ "maxItems": 20
1255
+ }
1256
+ },
1257
+ "additionalProperties": false
1258
+ }
1259
+ },
1260
+ {
1261
+ "type": "blog-list",
1262
+ "description": "A post index as a grid of cards, each with an optional cover image, tag, date, title, and excerpt linking to the post.",
1263
+ "schema": {
1264
+ "type": "object",
1265
+ "properties": {
1266
+ "title": {
1267
+ "type": "string",
1268
+ "maxLength": 120,
1269
+ "default": ""
1270
+ },
1271
+ "columns": {
1272
+ "type": "integer",
1273
+ "enum": [
1274
+ 2,
1275
+ 3
1276
+ ],
1277
+ "default": 3
1278
+ },
1279
+ "posts": {
1280
+ "type": "array",
1281
+ "items": {
1282
+ "type": "object",
1283
+ "properties": {
1284
+ "title": {
1285
+ "type": "string",
1286
+ "maxLength": 160,
1287
+ "default": ""
1288
+ },
1289
+ "excerpt": {
1290
+ "type": "string",
1291
+ "maxLength": 280,
1292
+ "default": ""
1293
+ },
1294
+ "href": {
1295
+ "type": "string",
1296
+ "maxLength": 500,
1297
+ "default": ""
1298
+ },
1299
+ "image": {
1300
+ "type": "string",
1301
+ "maxLength": 500,
1302
+ "default": ""
1303
+ },
1304
+ "date": {
1305
+ "type": "string",
1306
+ "maxLength": 40,
1307
+ "default": ""
1308
+ },
1309
+ "tag": {
1310
+ "type": "string",
1311
+ "maxLength": 40,
1312
+ "default": ""
1313
+ }
1314
+ },
1315
+ "required": [
1316
+ "title"
1317
+ ],
1318
+ "additionalProperties": false
1319
+ },
1320
+ "maxItems": 24
1321
+ }
1322
+ },
1323
+ "additionalProperties": false
1324
+ }
1325
+ },
1326
+ {
1327
+ "type": "blog-post",
1328
+ "description": "A single article layout with an optional cover, title, author/date, and a typed body (headings, paragraphs, quotes, bullets).",
1329
+ "schema": {
1330
+ "type": "object",
1331
+ "properties": {
1332
+ "title": {
1333
+ "type": "string",
1334
+ "maxLength": 200,
1335
+ "default": ""
1336
+ },
1337
+ "date": {
1338
+ "type": "string",
1339
+ "maxLength": 40,
1340
+ "default": ""
1341
+ },
1342
+ "author": {
1343
+ "type": "string",
1344
+ "maxLength": 80,
1345
+ "default": ""
1346
+ },
1347
+ "cover": {
1348
+ "type": "string",
1349
+ "maxLength": 500,
1350
+ "default": ""
1351
+ },
1352
+ "coverAlt": {
1353
+ "type": "string",
1354
+ "maxLength": 200,
1355
+ "default": ""
1356
+ },
1357
+ "body": {
1358
+ "type": "array",
1359
+ "items": {
1360
+ "type": "object",
1361
+ "properties": {
1362
+ "kind": {
1363
+ "enum": [
1364
+ "heading",
1365
+ "paragraph",
1366
+ "quote",
1367
+ "bullet"
1368
+ ],
1369
+ "default": "paragraph"
1370
+ },
1371
+ "text": {
1372
+ "type": "string",
1373
+ "maxLength": 2000,
1374
+ "default": ""
1375
+ }
1376
+ },
1377
+ "required": [
1378
+ "text"
1379
+ ],
1380
+ "additionalProperties": false
1381
+ },
1382
+ "maxItems": 120
1383
+ }
1384
+ },
1385
+ "required": [
1386
+ "title"
1387
+ ],
1388
+ "additionalProperties": false
1389
+ }
1390
+ },
1391
+ {
1392
+ "type": "feed",
1393
+ "description": "A generic data-driven list of items in a list or card layout, each with a title, optional subtitle/text, badge, image, and link.",
1394
+ "schema": {
1395
+ "type": "object",
1396
+ "properties": {
1397
+ "title": {
1398
+ "type": "string",
1399
+ "maxLength": 120,
1400
+ "default": ""
1401
+ },
1402
+ "layout": {
1403
+ "enum": [
1404
+ "list",
1405
+ "cards"
1406
+ ],
1407
+ "default": "list"
1408
+ },
1409
+ "items": {
1410
+ "type": "array",
1411
+ "items": {
1412
+ "type": "object",
1413
+ "properties": {
1414
+ "title": {
1415
+ "type": "string",
1416
+ "maxLength": 160,
1417
+ "default": ""
1418
+ },
1419
+ "subtitle": {
1420
+ "type": "string",
1421
+ "maxLength": 120,
1422
+ "default": ""
1423
+ },
1424
+ "text": {
1425
+ "type": "string",
1426
+ "maxLength": 280,
1427
+ "default": ""
1428
+ },
1429
+ "href": {
1430
+ "type": "string",
1431
+ "maxLength": 500,
1432
+ "default": ""
1433
+ },
1434
+ "image": {
1435
+ "type": "string",
1436
+ "maxLength": 500,
1437
+ "default": ""
1438
+ },
1439
+ "badge": {
1440
+ "type": "string",
1441
+ "maxLength": 40,
1442
+ "default": ""
1443
+ }
1444
+ },
1445
+ "required": [
1446
+ "title"
1447
+ ],
1448
+ "additionalProperties": false
1449
+ },
1450
+ "maxItems": 50
1451
+ }
1452
+ },
1453
+ "additionalProperties": false
1454
+ }
1455
+ },
1456
+ {
1457
+ "type": "contact-form",
1458
+ "description": "A configurable contact form with typed fields (text, email, tel, textarea, select, checkbox) that posts to a host-provided runtime. No raw HTML.",
1459
+ "schema": {
1460
+ "type": "object",
1461
+ "properties": {
1462
+ "title": {
1463
+ "type": "string",
1464
+ "maxLength": 120,
1465
+ "default": "Get in touch"
1466
+ },
1467
+ "intro": {
1468
+ "type": "string",
1469
+ "maxLength": 280,
1470
+ "default": ""
1471
+ },
1472
+ "submitLabel": {
1473
+ "type": "string",
1474
+ "maxLength": 40,
1475
+ "default": "Send"
1476
+ },
1477
+ "successMessage": {
1478
+ "type": "string",
1479
+ "maxLength": 200,
1480
+ "default": "Thanks — we'll be in touch."
1481
+ },
1482
+ "fields": {
1483
+ "type": "array",
1484
+ "items": {
1485
+ "type": "object",
1486
+ "properties": {
1487
+ "name": {
1488
+ "type": "string",
1489
+ "maxLength": 40,
1490
+ "default": "field"
1491
+ },
1492
+ "label": {
1493
+ "type": "string",
1494
+ "maxLength": 80,
1495
+ "default": "Field"
1496
+ },
1497
+ "type": {
1498
+ "enum": [
1499
+ "text",
1500
+ "email",
1501
+ "tel",
1502
+ "textarea",
1503
+ "select",
1504
+ "checkbox"
1505
+ ],
1506
+ "default": "text"
1507
+ },
1508
+ "placeholder": {
1509
+ "type": "string",
1510
+ "maxLength": 80,
1511
+ "default": ""
1512
+ },
1513
+ "required": {
1514
+ "type": "boolean",
1515
+ "default": false
1516
+ },
1517
+ "options": {
1518
+ "type": "array",
1519
+ "items": {
1520
+ "type": "string",
1521
+ "maxLength": 80,
1522
+ "default": ""
1523
+ },
1524
+ "maxItems": 24
1525
+ }
1526
+ },
1527
+ "required": [
1528
+ "name",
1529
+ "label"
1530
+ ],
1531
+ "additionalProperties": false
1532
+ },
1533
+ "maxItems": 12
1534
+ }
1535
+ },
1536
+ "additionalProperties": false
1537
+ },
1538
+ "runtime": {
1539
+ "capabilities": [
1540
+ "contact-form.submit"
1541
+ ]
1542
+ }
1543
+ },
1544
+ {
1545
+ "type": "newsletter",
1546
+ "description": "An email-capture form that posts to a host-provided runtime; renders inert until a runtime is wired.",
1547
+ "schema": {
1548
+ "type": "object",
1549
+ "properties": {
1550
+ "title": {
1551
+ "type": "string",
1552
+ "maxLength": 120,
1553
+ "default": "Subscribe to our newsletter"
1554
+ },
1555
+ "intro": {
1556
+ "type": "string",
1557
+ "maxLength": 240,
1558
+ "default": ""
1559
+ },
1560
+ "placeholder": {
1561
+ "type": "string",
1562
+ "maxLength": 80,
1563
+ "default": "you@example.com"
1564
+ },
1565
+ "submitLabel": {
1566
+ "type": "string",
1567
+ "maxLength": 40,
1568
+ "default": "Subscribe"
1569
+ },
1570
+ "successMessage": {
1571
+ "type": "string",
1572
+ "maxLength": 200,
1573
+ "default": "You're in — check your inbox."
1574
+ }
1575
+ },
1576
+ "additionalProperties": false
1577
+ },
1578
+ "runtime": {
1579
+ "capabilities": [
1580
+ "newsletter.subscribe"
1581
+ ]
1582
+ }
1583
+ },
1584
+ {
1585
+ "type": "auth",
1586
+ "description": "A provider-agnostic sign in / sign up panel: social provider buttons and an optional email form that start auth via a host runtime.",
1587
+ "schema": {
1588
+ "type": "object",
1589
+ "properties": {
1590
+ "mode": {
1591
+ "enum": [
1592
+ "signin",
1593
+ "signup"
1594
+ ],
1595
+ "default": "signin"
1596
+ },
1597
+ "title": {
1598
+ "type": "string",
1599
+ "maxLength": 120,
1600
+ "default": ""
1601
+ },
1602
+ "providers": {
1603
+ "type": "array",
1604
+ "items": {
1605
+ "type": "object",
1606
+ "properties": {
1607
+ "label": {
1608
+ "type": "string",
1609
+ "maxLength": 40,
1610
+ "default": ""
1611
+ },
1612
+ "provider": {
1613
+ "type": "string",
1614
+ "maxLength": 40,
1615
+ "default": ""
1616
+ }
1617
+ },
1618
+ "required": [
1619
+ "label"
1620
+ ],
1621
+ "additionalProperties": false
1622
+ },
1623
+ "maxItems": 6
1624
+ },
1625
+ "showEmail": {
1626
+ "type": "boolean",
1627
+ "default": true
1628
+ }
1629
+ },
1630
+ "additionalProperties": false
1631
+ },
1632
+ "runtime": {
1633
+ "capabilities": [
1634
+ "auth.start"
1635
+ ]
1636
+ }
1637
+ },
1638
+ {
1639
+ "type": "cta",
1640
+ "description": "A full-width call-to-action band: a headline, optional subheading, and one button. Use near the bottom.",
1641
+ "schema": {
1642
+ "type": "object",
1643
+ "properties": {
1644
+ "headline": {
1645
+ "type": "string",
1646
+ "maxLength": 160,
1647
+ "default": "Ready to start?"
1648
+ },
1649
+ "subhead": {
1650
+ "type": "string",
1651
+ "maxLength": 240,
1652
+ "default": ""
1653
+ },
1654
+ "background": {
1655
+ "enum": [
1656
+ "primary",
1657
+ "accent",
1658
+ "surface"
1659
+ ],
1660
+ "default": "primary"
1661
+ },
1662
+ "button": {
1663
+ "type": "object",
1664
+ "properties": {
1665
+ "label": {
1666
+ "type": "string",
1667
+ "maxLength": 40,
1668
+ "default": "Get started"
1669
+ },
1670
+ "href": {
1671
+ "type": "string",
1672
+ "maxLength": 300,
1673
+ "default": "#"
1674
+ }
1675
+ },
1676
+ "additionalProperties": false
1677
+ }
1678
+ },
1679
+ "required": [
1680
+ "headline"
1681
+ ],
1682
+ "additionalProperties": false
1683
+ }
1684
+ },
1685
+ {
1686
+ "type": "social-links",
1687
+ "description": "A centered row of links to social or external profiles, each an optional icon plus a label.",
1688
+ "schema": {
1689
+ "type": "object",
1690
+ "properties": {
1691
+ "title": {
1692
+ "type": "string",
1693
+ "maxLength": 120,
1694
+ "default": ""
1695
+ },
1696
+ "links": {
1697
+ "type": "array",
1698
+ "items": {
1699
+ "type": "object",
1700
+ "properties": {
1701
+ "label": {
1702
+ "type": "string",
1703
+ "maxLength": 40,
1704
+ "default": ""
1705
+ },
1706
+ "href": {
1707
+ "type": "string",
1708
+ "maxLength": 500,
1709
+ "default": ""
1710
+ },
1711
+ "icon": {
1712
+ "type": "string",
1713
+ "maxLength": 8,
1714
+ "default": ""
1715
+ }
1716
+ },
1717
+ "required": [
1718
+ "label",
1719
+ "href"
1720
+ ],
1721
+ "additionalProperties": false
1722
+ },
1723
+ "maxItems": 12
1724
+ }
1725
+ },
1726
+ "additionalProperties": false
1727
+ }
1728
+ },
1729
+ {
1730
+ "type": "contact-details",
1731
+ "description": "A contact info block: address, phone, email, and opening hours (each optional). Read-only — no form.",
1732
+ "schema": {
1733
+ "type": "object",
1734
+ "properties": {
1735
+ "title": {
1736
+ "type": "string",
1737
+ "maxLength": 120,
1738
+ "default": "Get in touch"
1739
+ },
1740
+ "address": {
1741
+ "type": "string",
1742
+ "maxLength": 200,
1743
+ "default": ""
1744
+ },
1745
+ "phone": {
1746
+ "type": "string",
1747
+ "maxLength": 40,
1748
+ "default": ""
1749
+ },
1750
+ "email": {
1751
+ "type": "string",
1752
+ "maxLength": 120,
1753
+ "default": ""
1754
+ },
1755
+ "hours": {
1756
+ "type": "string",
1757
+ "maxLength": 160,
1758
+ "default": ""
1759
+ }
1760
+ },
1761
+ "additionalProperties": false
1762
+ }
1763
+ },
1764
+ {
1765
+ "type": "divider",
1766
+ "description": "A visual section break rendered as a thin line, a dotted rule, or a gradient bar.",
1767
+ "schema": {
1768
+ "type": "object",
1769
+ "properties": {
1770
+ "style": {
1771
+ "enum": [
1772
+ "line",
1773
+ "dots",
1774
+ "gradient"
1775
+ ],
1776
+ "default": "line"
1777
+ }
1778
+ },
1779
+ "additionalProperties": false
1780
+ }
1781
+ },
1782
+ {
1783
+ "type": "spacer",
1784
+ "description": "Deliberate vertical whitespace between sections, in one of four sizes (sm, md, lg, xl).",
1785
+ "schema": {
1786
+ "type": "object",
1787
+ "properties": {
1788
+ "size": {
1789
+ "enum": [
1790
+ "sm",
1791
+ "md",
1792
+ "lg",
1793
+ "xl"
1794
+ ],
1795
+ "default": "md"
1796
+ }
1797
+ },
1798
+ "additionalProperties": false
1799
+ }
1800
+ },
1801
+ {
1802
+ "type": "footer",
1803
+ "description": "Page footer: brand, tagline, a row of links, and a copyright line. Place last.",
1804
+ "schema": {
1805
+ "type": "object",
1806
+ "properties": {
1807
+ "brand": {
1808
+ "type": "string",
1809
+ "maxLength": 60,
1810
+ "default": ""
1811
+ },
1812
+ "tagline": {
1813
+ "type": "string",
1814
+ "maxLength": 160,
1815
+ "default": ""
1816
+ },
1817
+ "links": {
1818
+ "type": "array",
1819
+ "items": {
1820
+ "type": "object",
1821
+ "properties": {
1822
+ "label": {
1823
+ "type": "string",
1824
+ "maxLength": 40,
1825
+ "default": "Link"
1826
+ },
1827
+ "href": {
1828
+ "type": "string",
1829
+ "maxLength": 300,
1830
+ "default": "#"
1831
+ }
1832
+ },
1833
+ "required": [
1834
+ "label"
1835
+ ],
1836
+ "additionalProperties": false
1837
+ },
1838
+ "maxItems": 12
1839
+ },
1840
+ "copyright": {
1841
+ "type": "string",
1842
+ "maxLength": 160,
1843
+ "default": ""
1844
+ }
1845
+ },
1846
+ "additionalProperties": false
1847
+ }
1848
+ }
1849
+ ]
1850
+ }