@gradial/aci 0.1.52-rc.9 → 0.1.52

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 (254) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +86 -5
  3. package/dist/astro/error-page.js +1 -0
  4. package/dist/astro/index.js +4 -0
  5. package/dist/astro/page.d.ts +5 -2
  6. package/dist/astro/page.js +35 -23
  7. package/dist/astro/preview.js +2 -17
  8. package/dist/audience-data-models.d.ts +308 -197
  9. package/dist/audience-data-models.js +313 -51
  10. package/dist/cli/compile-registry.mjs +6 -34
  11. package/dist/cli/mintlify-render.mjs +8 -0
  12. package/dist/collect/aci.js +1 -1
  13. package/dist/collect/aci.js.sha256 +1 -1
  14. package/dist/collect/api.d.ts +6 -7
  15. package/dist/collect/api.js +21 -8
  16. package/dist/collect/assignments.d.ts +7 -9
  17. package/dist/collect/assignments.js +23 -32
  18. package/dist/collect/batcher.d.ts +9 -7
  19. package/dist/collect/batcher.js +6 -5
  20. package/dist/collect/consent/envelope.d.ts +7 -1
  21. package/dist/collect/consent/envelope.js +3 -1
  22. package/dist/collect/consent/mapping.d.ts +2 -0
  23. package/dist/collect/consent/mapping.js +1 -0
  24. package/dist/collect/consenthold.d.ts +38 -0
  25. package/dist/collect/consenthold.js +82 -0
  26. package/dist/collect/declarative.js +7 -5
  27. package/dist/collect/gapbuffer.d.ts +13 -4
  28. package/dist/collect/gapbuffer.js +21 -10
  29. package/dist/collect/index.js +78 -21
  30. package/dist/collect/pageviews.d.ts +11 -11
  31. package/dist/collect/pageviews.js +27 -22
  32. package/dist/consent-banner/index.d.ts +17 -0
  33. package/dist/consent-banner/index.js +23 -0
  34. package/dist/content/index.d.ts +2 -1
  35. package/dist/content/index.js +4 -1
  36. package/dist/content/provider.d.ts +16 -2
  37. package/dist/content/provider.js +5 -1
  38. package/dist/content/resolve-slots.d.ts +24 -2
  39. package/dist/content/resolve-slots.js +127 -21
  40. package/dist/content/types.d.ts +5 -1
  41. package/dist/edge/expression-capabilities.v1.d.ts +106 -0
  42. package/dist/edge/expression-capabilities.v1.js +165 -0
  43. package/dist/index.d.ts +1 -2
  44. package/dist/index.js +0 -1
  45. package/dist/internal/domain/edge/identity.d.ts +47 -4
  46. package/dist/internal/domain/edge/identity.js +130 -26
  47. package/dist/internal/domain/edge/index.d.ts +1 -1
  48. package/dist/internal/domain/edge/index.js +1 -1
  49. package/dist/internal/domain/edge/mimic_token.d.ts +14 -0
  50. package/dist/internal/domain/edge/mimic_token.js +125 -0
  51. package/dist/internal/domain/edge/personalization-core.d.ts +61 -22
  52. package/dist/internal/domain/edge/personalization-core.js +790 -200
  53. package/dist/internal/domain/edge/personalization_index.d.ts +17 -0
  54. package/dist/internal/domain/edge/personalization_index.js +55 -0
  55. package/dist/internal/domain/edge/resolve.js +76 -39
  56. package/dist/internal/domain/edge/testdata/flat_only_validator_v1.d.ts +10 -0
  57. package/dist/internal/domain/edge/testdata/flat_only_validator_v1.js +253 -0
  58. package/dist/internal/domain/edge/types.d.ts +82 -78
  59. package/dist/internal/domain/edge/types.js +3 -3
  60. package/dist/internal/domain/edge/variant_key.d.ts +4 -0
  61. package/dist/internal/domain/edge/variant_key.js +56 -0
  62. package/dist/internal/platform/collectionstore/errors.d.ts +24 -0
  63. package/dist/internal/platform/collectionstore/errors.js +48 -0
  64. package/dist/mintlify/blocks.d.ts +6 -0
  65. package/dist/mintlify/blocks.js +201 -0
  66. package/dist/mintlify/config.d.ts +3 -0
  67. package/dist/mintlify/config.js +77 -0
  68. package/dist/mintlify/index.d.ts +3 -0
  69. package/dist/mintlify/index.js +2 -0
  70. package/dist/mintlify/json.d.ts +8 -0
  71. package/dist/mintlify/json.js +37 -0
  72. package/dist/mintlify/materialize.d.ts +14 -0
  73. package/dist/mintlify/materialize.js +254 -0
  74. package/dist/mintlify/types.d.ts +74 -0
  75. package/dist/mintlify/types.js +1 -0
  76. package/dist/mintlify/validate.d.ts +7 -0
  77. package/dist/mintlify/validate.js +256 -0
  78. package/dist/next/assignments-navigation.d.ts +4 -0
  79. package/dist/next/assignments-navigation.js +18 -0
  80. package/dist/next/assignments-script.d.ts +3 -2
  81. package/dist/next/assignments-script.js +5 -5
  82. package/dist/next/error-pages.d.ts +4 -0
  83. package/dist/next/error-pages.js +4 -0
  84. package/dist/next/error-seat-payload.d.ts +2 -1
  85. package/dist/next/error-seat-payload.js +14 -24
  86. package/dist/next/error-seat.js +7 -2
  87. package/dist/next/index.d.ts +1 -1
  88. package/dist/next/index.js +3 -1
  89. package/dist/next/page.d.ts +2 -1
  90. package/dist/next/page.js +15 -4
  91. package/dist/next/release-context.d.ts +30 -0
  92. package/dist/next/release-context.js +56 -0
  93. package/dist/next/render.d.ts +1 -1
  94. package/dist/next/render.js +15 -5
  95. package/dist/next/server.d.ts +9 -3
  96. package/dist/next/server.js +17 -32
  97. package/dist/preview/core.d.ts +1 -0
  98. package/dist/preview/core.js +27 -0
  99. package/dist/react/VideoPlayer.d.ts +3 -3
  100. package/dist/react/index.d.ts +3 -3
  101. package/dist/registry.d.ts +4 -2
  102. package/dist/testing/conformance/checks.d.ts +2 -2
  103. package/dist/testing/conformance/checks.js +2 -0
  104. package/dist/testing/conformance/index.d.ts +1 -0
  105. package/dist/testing/conformance/index.js +1 -0
  106. package/dist/testing/conformance/next-stubs.d.ts +6 -0
  107. package/dist/testing/conformance/next-stubs.js +9 -0
  108. package/dist/testing/conformance/preset.d.ts +3 -2
  109. package/dist/testing/conformance/preset.js +15 -8
  110. package/dist/testing/conformance/root-identity.d.ts +31 -0
  111. package/dist/testing/conformance/root-identity.js +361 -0
  112. package/dist/testing/conformance/stubs/next-image.d.ts +7 -0
  113. package/dist/testing/conformance/stubs/next-image.js +5 -0
  114. package/dist/testing/conformance/stubs/next-link.d.ts +7 -0
  115. package/dist/testing/conformance/stubs/next-link.js +4 -0
  116. package/dist/testing/conformance/types.d.ts +5 -2
  117. package/dist/testing/index.d.ts +1 -1
  118. package/dist/testing/index.js +4 -3
  119. package/dist/types/block-ref.js +2 -2
  120. package/dist/types/component.d.ts +9 -0
  121. package/dist/types/config.d.ts +0 -1
  122. package/dist/types/index.d.ts +0 -1
  123. package/dist/types/index.js +0 -1
  124. package/dist/types/page.d.ts +0 -1
  125. package/migrations/conformance-registry.md +22 -0
  126. package/migrations/experiment-goal-ids.md +43 -0
  127. package/package.json +21 -7
  128. package/src/cli/compile-registry.mjs +6 -30
  129. package/src/cli/mintlify-render.mjs +9 -0
  130. package/src/types/block-ref.test.ts +16 -1
  131. package/src/types/block-ref.ts +2 -2
  132. package/src/types/component.ts +10 -0
  133. package/src/types/config.ts +0 -1
  134. package/src/types/index.ts +0 -1
  135. package/src/types/page.ts +0 -1
  136. package/templates/astro/starter-content/src/components/chrome/Footer.astro +5 -3
  137. package/templates/astro/starter-content/src/components/chrome/Header.astro +5 -3
  138. package/templates/astro/starter-content/src/components/elements/Button.astro +5 -2
  139. package/templates/astro/starter-content/src/components/elements/ButtonBlock.astro +5 -3
  140. package/templates/astro/starter-content/src/components/sections/ContainerSection.astro +4 -3
  141. package/templates/astro/starter-content/src/components/sections/FeatureCard.astro +4 -3
  142. package/templates/astro/starter-content/src/components/sections/FeatureGrid.astro +4 -3
  143. package/templates/astro/starter-content/src/components/sections/HomeHero.astro +5 -3
  144. package/templates/astro/starter-content/src/components/sections/PersonalizationChoice.astro +4 -3
  145. package/templates/astro/starter-content/src/components/sections/StatsBar.astro +4 -3
  146. package/templates/astro/starter-content/src/fixtures/sections.ts +1 -1
  147. package/templates/astro/starter-content/src/stories/CompositionStoryFrame.astro +7 -2
  148. package/templates/astro/template/.aci.yaml.tmpl +0 -1
  149. package/templates/astro/template/package.json.tmpl +5 -5
  150. package/templates/astro/template/src/layouts/SiteLayout.astro +2 -2
  151. package/templates/common/.agents/skills/aci/SKILL.md +58 -1
  152. package/templates/common/.agents/skills/authoring/SKILL.md +194 -42
  153. package/templates/common/.agents/skills/authoring/references/block-registry.md +19 -3
  154. package/templates/common/.agents/skills/authoring/references/contracts.md +9 -30
  155. package/templates/common/.agents/skills/authoring/references/repo-structure.md +5 -4
  156. package/templates/common/.agents/skills/authoring/references/sdk-server-functions.md +3 -3
  157. package/templates/common/.agents/skills/dam-delivery/SKILL.md +216 -0
  158. package/templates/common/.agents/skills/dam-delivery/references/permalink-grammar.md +167 -0
  159. package/templates/common/.agents/skills/migration/references/canon-migration.md +18 -67
  160. package/templates/common/.agents/skills/migration/references/selector-map.md +1 -1
  161. package/templates/common/.content/fragments/navbar/_index.json +24 -0
  162. package/templates/common/.content/fragments/site-footer/_index.json +61 -0
  163. package/templates/common/.content/pages/404/_index.json +4 -2
  164. package/templates/common/.content/pages/_index.json +0 -1
  165. package/templates/common/.content/pages/error/_index.json +4 -2
  166. package/templates/common/.content/schemas/site.schema.json +11 -1
  167. package/templates/common/.content/templates/error.json +24 -0
  168. package/templates/common/.content/templates/home.json +28 -0
  169. package/templates/common/.content/templates/site.json +8 -0
  170. package/templates/common/.content/templates/standard.json +24 -0
  171. package/templates/common/.nvmrc +1 -1
  172. package/templates/common/starter-content/.content/config/site.json +1 -1
  173. package/templates/common/starter-content/.content/dam/README.md +74 -0
  174. package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000101}/asset.json +1 -1
  175. package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000102}/asset.json +1 -1
  176. package/templates/common/starter-content/.content/pages/404/_index.json +1 -2
  177. package/templates/common/starter-content/.content/pages/{home/_index.json → _index.json} +14 -3
  178. package/templates/common/starter-content/.content/pages/about/_index.json +2 -2
  179. package/templates/common/starter-content/.content/pages/error/_index.json +1 -2
  180. package/templates/common/starter-content/.content/patterns/components/button.json +2 -2
  181. package/templates/common/starter-content/.content/patterns/components/container.json +8 -3
  182. package/templates/common/starter-content/.content/patterns/components/feature_card.json +2 -2
  183. package/templates/common/starter-content/.content/patterns/components/feature_grid.json +5 -3
  184. package/templates/common/starter-content/.content/patterns/components/home_hero.json +2 -2
  185. package/templates/common/starter-content/.content/patterns/components/personalization_choice.json +2 -2
  186. package/templates/common/starter-content/.content/patterns/components/site-footer.json +2 -2
  187. package/templates/common/starter-content/.content/patterns/components/site-navigation.json +2 -2
  188. package/templates/common/starter-content/.content/patterns/components/stats_bar.json +2 -2
  189. package/templates/common/starter-content/.content/schemas/site.schema.json +11 -1
  190. package/templates/nextjs/starter-content/src/components/chrome/Footer.tsx +4 -3
  191. package/templates/nextjs/starter-content/src/components/chrome/Header.tsx +4 -3
  192. package/templates/nextjs/starter-content/src/components/elements/Button.tsx +4 -3
  193. package/templates/nextjs/starter-content/src/components/elements/ButtonBlock.tsx +4 -3
  194. package/templates/nextjs/starter-content/src/components/sections/ContainerSection.tsx +4 -2
  195. package/templates/nextjs/starter-content/src/components/sections/FeatureCard.tsx +4 -3
  196. package/templates/nextjs/starter-content/src/components/sections/FeatureGrid.tsx +4 -2
  197. package/templates/nextjs/starter-content/src/components/sections/HomeHero.tsx +4 -3
  198. package/templates/nextjs/starter-content/src/components/sections/PersonalizationChoice.tsx +4 -2
  199. package/templates/nextjs/starter-content/src/components/sections/StatsBar.tsx +4 -3
  200. package/templates/nextjs/template/.aci.yaml +0 -1
  201. package/templates/nextjs/template/.aci.yaml.tmpl +0 -1
  202. package/templates/nextjs/template/package.json.tmpl +4 -3
  203. package/templates/nextjs/template/src/app/_components/c15t-bridge.ts +30 -0
  204. package/templates/nextjs/template/src/app/_components/c15t-consent-ui.tsx +37 -0
  205. package/templates/nextjs/template/src/app/_components/consent-manager.css +63 -0
  206. package/templates/nextjs/template/src/app/_components/consent-manager.tsx +76 -0
  207. package/templates/nextjs/template/src/app/fonts/inter/OFL.txt +93 -0
  208. package/templates/nextjs/template/src/app/fonts/inter/inter-latin.woff2 +0 -0
  209. package/templates/nextjs/template/src/app/fonts/space-grotesk/OFL.txt +93 -0
  210. package/templates/nextjs/template/src/app/fonts/space-grotesk/space-grotesk-latin.woff2 +0 -0
  211. package/templates/nextjs/template/src/app/layout.tsx +12 -7
  212. package/templates/nextjs/template/tests/conformance.test.ts.tmpl +1 -0
  213. package/dist/define-layout.d.ts +0 -6
  214. package/dist/define-layout.js +0 -14
  215. package/dist/edge/personalization-core.d.ts +0 -11
  216. package/dist/edge/personalization-core.js +0 -269
  217. package/dist/internal/domain/edge/compose.d.ts +0 -24
  218. package/dist/internal/domain/edge/compose.js +0 -89
  219. package/dist/internal/domain/edge/record/codec.d.ts +0 -71
  220. package/dist/internal/domain/edge/record/codec.js +0 -401
  221. package/dist/next/collect-route.d.ts +0 -19
  222. package/dist/next/collect-route.js +0 -459
  223. package/dist/next/edge-config.d.ts +0 -1
  224. package/dist/next/edge-config.js +0 -92
  225. package/dist/next/envelope-digest.d.ts +0 -21
  226. package/dist/next/envelope-digest.js +0 -58
  227. package/dist/next/middleware.d.ts +0 -40
  228. package/dist/next/middleware.js +0 -475
  229. package/dist/next/personalization-host.d.ts +0 -134
  230. package/dist/next/personalization-host.js +0 -270
  231. package/dist/next/root-layout.d.ts +0 -4
  232. package/dist/next/root-layout.js +0 -5
  233. package/dist/next/vercel-collect-sdk-route.d.ts +0 -27
  234. package/dist/next/vercel-collect-sdk-route.js +0 -181
  235. package/dist/next/vercel-edge-projection-v1.d.ts +0 -24
  236. package/dist/next/vercel-edge-projection-v1.js +0 -880
  237. package/dist/next/vercel-personalization.d.ts +0 -4
  238. package/dist/next/vercel-personalization.js +0 -4
  239. package/dist/next/vercel-s3-personalization.d.ts +0 -79
  240. package/dist/next/vercel-s3-personalization.js +0 -570
  241. package/dist/types/layout.d.ts +0 -24
  242. package/src/types/layout.ts +0 -29
  243. package/templates/astro/starter-content/src/render/RenderPage.astro +0 -67
  244. package/templates/astro/template/src/cms/contracts/layouts/index.ts +0 -18
  245. package/templates/common/starter-content/.content/patterns/layouts/default.json +0 -14
  246. package/templates/nextjs/starter-content/src/components/elements/AtomicBlock.tsx +0 -13
  247. package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +0 -16
  248. /package/dist/{types/layout.js → cli/mintlify-render.d.mts} +0 -0
  249. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/editorial.json +0 -0
  250. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000101}/governance.json +0 -0
  251. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/versions/v0001.json +0 -0
  252. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/editorial.json +0 -0
  253. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000102}/governance.json +0 -0
  254. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/versions/v0001.json +0 -0
@@ -27,7 +27,17 @@
27
27
  },
28
28
  "overlayResolution": {
29
29
  "type": "array",
30
- "items": { "enum": ["locale", "audience"] }
30
+ "items": {
31
+ "type": "string",
32
+ "minLength": 1,
33
+ "pattern": "^[^;=/\u0009-\u000d\u0020\u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]+$",
34
+ "not": {
35
+ "anyOf": [
36
+ { "enum": [".", "..", "experiment", "experimentArm"] },
37
+ { "pattern": "^experiment\\." }
38
+ ]
39
+ }
40
+ }
31
41
  },
32
42
  "brandHref": { "type": "string" },
33
43
  "brandLogo": {
@@ -0,0 +1,24 @@
1
+ {
2
+ "$type": "pageTemplate",
3
+ "name": "error",
4
+ "description": "Error pages are a single hero that points visitors back home.",
5
+ "routes": ["/404", "/error"],
6
+ "regions": [
7
+ {
8
+ "name": "header",
9
+ "defaults": ["navbar"],
10
+ "sequence": [{ "id": "navbar", "fragment": ["navbar"] }]
11
+ },
12
+ {
13
+ "name": "main",
14
+ "sequence": [
15
+ { "id": "hero", "component": "home_hero" }
16
+ ]
17
+ },
18
+ {
19
+ "name": "footer",
20
+ "defaults": ["site-footer"],
21
+ "sequence": [{ "id": "site-footer", "fragment": ["site-footer"] }]
22
+ }
23
+ ]
24
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "$type": "pageTemplate",
3
+ "name": "home",
4
+ "description": "The home page: a hero, the feature grid, the personalization choice, the stats bar, and the closing call-to-action container, in that order.",
5
+ "routes": ["/"],
6
+ "regions": [
7
+ {
8
+ "name": "header",
9
+ "defaults": ["navbar"],
10
+ "sequence": [{ "id": "navbar", "fragment": ["navbar"] }]
11
+ },
12
+ {
13
+ "name": "main",
14
+ "sequence": [
15
+ { "id": "hero", "component": "home_hero", "lock": "structure" },
16
+ { "id": "features", "component": "feature_grid" },
17
+ { "id": "choice", "component": "personalization_choice" },
18
+ { "id": "stats", "component": "stats_bar" },
19
+ { "id": "cta", "component": "container" }
20
+ ]
21
+ },
22
+ {
23
+ "name": "footer",
24
+ "defaults": ["site-footer"],
25
+ "sequence": [{ "id": "site-footer", "fragment": ["site-footer"] }]
26
+ }
27
+ ]
28
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "$type": "globalPolicy",
3
+ "name": "site",
4
+ "description": "No page carries more than two buttons, including nested blocks and rendered fragments.",
5
+ "counts": [
6
+ { "component": "button", "max": 2 }
7
+ ]
8
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "$type": "pageTemplate",
3
+ "name": "standard",
4
+ "description": "Interior pages declare this template: a hero first, then any blocks the page needs.",
5
+ "regions": [
6
+ {
7
+ "name": "header",
8
+ "defaults": ["navbar"],
9
+ "sequence": [{ "id": "navbar", "fragment": ["navbar"] }]
10
+ },
11
+ {
12
+ "name": "main",
13
+ "closed": false,
14
+ "sequence": [
15
+ { "id": "hero", "component": "home_hero" }
16
+ ]
17
+ },
18
+ {
19
+ "name": "footer",
20
+ "defaults": ["site-footer"],
21
+ "sequence": [{ "id": "site-footer", "fragment": ["site-footer"] }]
22
+ }
23
+ ]
24
+ }
@@ -1 +1 @@
1
- 22
1
+ 24
@@ -10,7 +10,7 @@
10
10
  "notFound": "/404/",
11
11
  "catchAll": "/error/"
12
12
  },
13
- "overlayResolution": ["locale", "audience"],
13
+ "overlayResolution": ["locale", "audience", "segment"],
14
14
  "brandHref": "/",
15
15
  "brandLogo": {
16
16
  "src": "/assets/meridian-logo.svg",
@@ -0,0 +1,74 @@
1
+ # Seed DAM assets
2
+
3
+ This folder is a local, file-based copy of two DAM assets. The sample pages
4
+ reference them so the starter renders images without a running DAM service.
5
+ Copy one of the seed folders to mock a new asset for a page.
6
+
7
+ ## How a page references an asset
8
+
9
+ A component prop holds a `dam.assetRef` object. The home page hero uses it:
10
+
11
+ ```json
12
+ "image": {
13
+ "$type": "dam.assetRef",
14
+ "assetId": "000000000000000000000000101",
15
+ "alt": "Light abstract hero background with satellite constellation"
16
+ }
17
+ ```
18
+
19
+ - `assetId` — must match the `assetId` in one `asset.json` under `folders/`
20
+ - `alt` — optional; omit it to use the `altText` from `editorial.json`
21
+ - `version` — optional; omit it to use the newest approved version
22
+
23
+ The component schema (see `patterns/components/home_hero.json`) declares the
24
+ prop as `gradial.image`, not `dam.assetRef`. That is expected. The content
25
+ build resolves the ref and writes the `gradial.image` shape, with `sources`
26
+ filled in, into the compiled page. You author the ref; the build materializes
27
+ the image.
28
+
29
+ ## What one seed asset contains
30
+
31
+ Each asset is one folder under `folders/<group>/<assetId>/` plus one
32
+ content-addressed blob under `blobs/`. The local build scans every
33
+ `asset.json` under `folders/`, so the group name (`seed`) does not matter
34
+ for rendering. `aci content push` does use it: the path under `folders/`
35
+ becomes the folder path in the remote DAM.
36
+
37
+ ```
38
+ folders/seed/<assetId>/asset.json dam.asset: id and audit fields
39
+ folders/seed/<assetId>/editorial.json dam.editorial: title, altText, tags
40
+ folders/seed/<assetId>/governance.json dam.governance: asset status and per-version approval
41
+ folders/seed/<assetId>/versions/v0001.json dam.assetVersion: blob key, sha256, mime, dimensions
42
+ blobs/sha256/<aa>/<bb>/<sha256> the raw image bytes
43
+ ```
44
+
45
+ ## Add a new mocked asset
46
+
47
+ This is a step-by-step procedure.
48
+
49
+ 1. Pick an asset ID. Use 27 base62 characters. The seed IDs pad a small
50
+ number with leading zeros, for example `000000000000000000000000103`.
51
+ 2. Compute the SHA-256 of the image file. Copy the file to
52
+ `blobs/sha256/<first 2 hex>/<next 2 hex>/<full sha256>` with no extension.
53
+ 3. Copy `folders/seed/000000000000000000000000101/` to a new folder named
54
+ after the new asset ID.
55
+ 4. In `asset.json`, set `assetId` to the new ID.
56
+ 5. In `versions/v0001.json`, set `blob.sha256`, `blob.key`, `blob.byteSize`,
57
+ `blob.mime`, `blob.originalFilename`, and `technical.dimensions`.
58
+ 6. In `editorial.json`, set `altText`. The build fails on an empty alt text
59
+ when the page ref does not supply its own `alt`.
60
+ 7. In `governance.json`, keep `asset.status` as `active` and the version
61
+ `status` as `approved`. The build applies the same eligibility gate as
62
+ production and rejects a draft, embargoed, or restricted version.
63
+ 8. Reference the new ID from a page prop with `"$type": "dam.assetRef"`.
64
+
65
+ ## Serving bytes locally
66
+
67
+ The content build only needs the metadata files to compile a page. To serve
68
+ the image bytes from the local object store, run from the repo root:
69
+
70
+ ```sh
71
+ scripts/seed-local-dam-minio.sh packages/sdk/templates/common/starter-content/.content
72
+ ```
73
+
74
+ The script uploads every blob referenced by a `versions/*.json` file.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "dam.asset",
3
3
  "schemaVersion": 1,
4
- "assetId": "ast_site_about_hero",
4
+ "assetId": "000000000000000000000000101",
5
5
  "createdAt": "2026-06-01T00:00:00Z",
6
6
  "createdBy": "local-seed",
7
7
  "updatedAt": "2026-06-01T00:00:00Z",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "dam.asset",
3
3
  "schemaVersion": 1,
4
- "assetId": "ast_site_home_hero",
4
+ "assetId": "000000000000000000000000102",
5
5
  "createdAt": "2026-06-01T00:00:00Z",
6
6
  "createdBy": "local-seed",
7
7
  "updatedAt": "2026-06-01T00:00:00Z",
@@ -2,7 +2,6 @@
2
2
  "$type": "page",
3
3
  "id": "meridian-not-found",
4
4
  "status": "published",
5
- "layout": "default",
6
5
  "metadata": {
7
6
  "title": "Page not found — Meridian",
8
7
  "description": "The page you are looking for does not exist.",
@@ -22,7 +21,7 @@
22
21
  "ctaHref": "/",
23
22
  "image": {
24
23
  "$type": "dam.assetRef",
25
- "assetId": "ast_site_home_hero",
24
+ "assetId": "000000000000000000000000101",
26
25
  "alt": "Light abstract background with satellite constellation"
27
26
  }
28
27
  }
@@ -2,9 +2,8 @@
2
2
  "$type": "page",
3
3
  "id": "meridian-home",
4
4
  "status": "published",
5
- "layout": "default",
6
5
  "metadata": {
7
- "title": "Meridian \u2014 Global Satellite Internet",
6
+ "title": "Meridian — Global Satellite Internet",
8
7
  "description": "Connect from anywhere on Earth. Low-latency satellite internet for homes, businesses, and beyond.",
9
8
  "canonical": "https://www.meridian.local/"
10
9
  },
@@ -22,7 +21,7 @@
22
21
  "ctaHref": "/plans/",
23
22
  "image": {
24
23
  "$type": "dam.assetRef",
25
- "assetId": "ast_site_home_hero",
24
+ "assetId": "000000000000000000000000101",
26
25
  "alt": "Light abstract hero background with satellite constellation"
27
26
  }
28
27
  }
@@ -68,6 +67,18 @@
68
67
  ]
69
68
  }
70
69
  },
70
+ {
71
+ "$type": "component",
72
+ "id": "personalization-choice",
73
+ "component": "personalization_choice",
74
+ "props": {
75
+ "title": "Choose your connection preference",
76
+ "description": "Select a preference, allow the update to process, then refresh personalization.",
77
+ "redLabel": "Choose Red",
78
+ "blueLabel": "Choose Blue",
79
+ "refreshLabel": "Refresh personalization"
80
+ }
81
+ },
71
82
  {
72
83
  "$type": "component",
73
84
  "id": "stats",
@@ -2,7 +2,7 @@
2
2
  "$type": "page",
3
3
  "id": "meridian-about",
4
4
  "status": "published",
5
- "layout": "default",
5
+ "template": "standard",
6
6
  "metadata": {
7
7
  "title": "About Meridian",
8
8
  "description": "Meridian is building the next generation of satellite internet to connect the unconnected.",
@@ -22,7 +22,7 @@
22
22
  "ctaHref": "/",
23
23
  "image": {
24
24
  "$type": "dam.assetRef",
25
- "assetId": "ast_site_about_hero",
25
+ "assetId": "000000000000000000000000102",
26
26
  "alt": "Meridian network coverage map with soft gradient"
27
27
  }
28
28
  }
@@ -2,7 +2,6 @@
2
2
  "$type": "page",
3
3
  "id": "meridian-error",
4
4
  "status": "published",
5
- "layout": "default",
6
5
  "metadata": {
7
6
  "title": "Something went wrong — Meridian",
8
7
  "description": "An unexpected error occurred while serving this page.",
@@ -22,7 +21,7 @@
22
21
  "ctaHref": "/",
23
22
  "image": {
24
23
  "$type": "dam.assetRef",
25
- "assetId": "ast_site_home_hero",
24
+ "assetId": "000000000000000000000000101",
26
25
  "alt": "Light abstract background with satellite constellation"
27
26
  }
28
27
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a017ed-c52f-703a-a6b4-a0943c057d31",
4
- "codeDigest": "sha256:119dd8414ca342ca67f4dd4703dcb504630220bbdca9130b1501ee7b25693134",
3
+ "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
+ "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
5
5
  "name": "button",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a017ed-c52f-703a-a6b4-a0943c057d31",
4
- "codeDigest": "sha256:119dd8414ca342ca67f4dd4703dcb504630220bbdca9130b1501ee7b25693134",
3
+ "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
+ "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
5
5
  "name": "container",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -34,7 +34,12 @@
34
34
  },
35
35
  "component": {
36
36
  "type": "string",
37
- "minLength": 1
37
+ "enum": [
38
+ "button",
39
+ "feature_grid",
40
+ "feature_card",
41
+ "stats_bar"
42
+ ]
38
43
  },
39
44
  "props": {
40
45
  "type": "object",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a017ed-c52f-703a-a6b4-a0943c057d31",
4
- "codeDigest": "sha256:119dd8414ca342ca67f4dd4703dcb504630220bbdca9130b1501ee7b25693134",
3
+ "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
+ "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
5
5
  "name": "feature_card",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a017ed-c52f-703a-a6b4-a0943c057d31",
4
- "codeDigest": "sha256:119dd8414ca342ca67f4dd4703dcb504630220bbdca9130b1501ee7b25693134",
3
+ "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
+ "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
5
5
  "name": "feature_grid",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -29,7 +29,9 @@
29
29
  },
30
30
  "component": {
31
31
  "type": "string",
32
- "minLength": 1
32
+ "enum": [
33
+ "feature_card"
34
+ ]
33
35
  },
34
36
  "props": {
35
37
  "type": "object",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a017ed-c52f-703a-a6b4-a0943c057d31",
4
- "codeDigest": "sha256:119dd8414ca342ca67f4dd4703dcb504630220bbdca9130b1501ee7b25693134",
3
+ "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
+ "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
5
5
  "name": "home_hero",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a017ed-c52f-703a-a6b4-a0943c057d31",
4
- "codeDigest": "sha256:119dd8414ca342ca67f4dd4703dcb504630220bbdca9130b1501ee7b25693134",
3
+ "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
+ "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
5
5
  "name": "personalization_choice",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a017ed-c52f-703a-a6b4-a0943c057d31",
4
- "codeDigest": "sha256:119dd8414ca342ca67f4dd4703dcb504630220bbdca9130b1501ee7b25693134",
3
+ "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
+ "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
5
5
  "name": "site-footer",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a017ed-c52f-703a-a6b4-a0943c057d31",
4
- "codeDigest": "sha256:119dd8414ca342ca67f4dd4703dcb504630220bbdca9130b1501ee7b25693134",
3
+ "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
+ "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
5
5
  "name": "site-navigation",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$type": "componentPattern",
3
- "buildId": "codebuild_01a017ed-c52f-703a-a6b4-a0943c057d31",
4
- "codeDigest": "sha256:119dd8414ca342ca67f4dd4703dcb504630220bbdca9130b1501ee7b25693134",
3
+ "buildId": "codebuild_01a0d03d-1243-7f49-9ead-8599ed577882",
4
+ "codeDigest": "sha256:44327370dc42bcabe39daf8b86fca1fe191e19dbd8dd39db71df2109c11b3635",
5
5
  "name": "stats_bar",
6
6
  "schema": {
7
7
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -27,7 +27,17 @@
27
27
  },
28
28
  "overlayResolution": {
29
29
  "type": "array",
30
- "items": { "enum": ["locale", "audience"] }
30
+ "items": {
31
+ "type": "string",
32
+ "minLength": 1,
33
+ "pattern": "^[^;=/\u0009-\u000d\u0020\u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]+$",
34
+ "not": {
35
+ "anyOf": [
36
+ { "enum": [".", "..", "experiment", "experimentArm"] },
37
+ { "pattern": "^experiment\\." }
38
+ ]
39
+ }
40
+ }
31
41
  },
32
42
  "brandHref": { "type": "string" },
33
43
  "brandLogo": {
@@ -1,8 +1,9 @@
1
1
  import { Container } from '@/components/elements/Container';
2
+ import type { RootIdentityProps } from '@gradial/aci';
2
3
  import { Logo } from '@/components/elements/Logo';
3
4
  import type { FooterColumn, FooterGroup, FooterLink } from '@gradial/aci/content';
4
5
 
5
- interface FooterProps {
6
+ interface FooterProps extends RootIdentityProps {
6
7
  brandHref: string;
7
8
  brandLabel: string;
8
9
  brandLogo?: { src: string; alt?: string } | null;
@@ -17,9 +18,9 @@ function columnGroups(column: FooterColumn): FooterGroup[] {
17
18
  return [{ id: column.id, title: column.title || '', links: column.links || [] }];
18
19
  }
19
20
 
20
- export function Footer({ brandHref, brandLabel, brandLogo = null, columns = [], social = [], legalLinks = [], copyright = '' }: FooterProps) {
21
+ export function Footer({ brandHref, brandLabel, brandLogo = null, columns = [], social = [], legalLinks = [], copyright = '', ...root }: FooterProps) {
21
22
  return (
22
- <footer className="bm-footer relative pt-[var(--spacing-footer-y)]" id="footer">
23
+ <footer {...root} className="bm-footer relative pt-[var(--spacing-footer-y)]" id="footer">
23
24
  <div className="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-[var(--color-brand-500)] to-transparent opacity-50" />
24
25
  <Container>
25
26
  <div className="footer-main-grid grid grid-cols-1 gap-12 lg:grid-cols-2">
@@ -2,9 +2,10 @@ import { Button } from '@/components/elements/Button';
2
2
  import { Container } from '@/components/elements/Container';
3
3
  import { Icon } from '@/components/elements/Icon';
4
4
  import { Logo } from '@/components/elements/Logo';
5
+ import type { RootIdentityProps } from '@gradial/aci';
5
6
  import type { NavItem, UtilityItem } from '@gradial/aci/content';
6
7
 
7
- interface HeaderProps {
8
+ interface HeaderProps extends RootIdentityProps {
8
9
  brandHref: string;
9
10
  brandLabel: string;
10
11
  brandLogo?: { src: string; alt?: string } | null;
@@ -12,9 +13,9 @@ interface HeaderProps {
12
13
  utilities?: UtilityItem[];
13
14
  }
14
15
 
15
- export function Header({ brandHref, brandLabel, brandLogo = null, navigation = [], utilities = [] }: HeaderProps) {
16
+ export function Header({ brandHref, brandLabel, brandLogo = null, navigation = [], utilities = [], ...root }: HeaderProps) {
16
17
  return (
17
- <header className="bm-header fixed top-0 left-0 right-0 z-[var(--z-header)] border-b border-[var(--header-border)]">
18
+ <header {...root} className="bm-header fixed top-0 left-0 right-0 z-[var(--z-header)] border-b border-[var(--header-border)]">
18
19
  <a href="#content-main" className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-[var(--z-overlay)] focus:rounded-button focus:bg-[var(--color-space-900)] focus:px-4 focus:py-2 focus:text-[var(--color-white)]">
19
20
  Skip to main content
20
21
  </a>
@@ -1,9 +1,9 @@
1
- import type { ReactNode } from 'react';
1
+ import type { AnchorHTMLAttributes, ReactNode } from 'react';
2
2
  import type { ButtonVariant } from '@gradial/aci/content';
3
3
 
4
4
  type ButtonSize = 'default' | 'lg';
5
5
 
6
- interface ButtonProps {
6
+ interface ButtonProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'className' | 'target' | 'rel' | 'children'> {
7
7
  href: string;
8
8
  variant?: ButtonVariant;
9
9
  size?: ButtonSize;
@@ -26,9 +26,10 @@ const sizeClasses: Record<ButtonSize, string> = {
26
26
  lg: 'px-7 py-3.5 min-h-[3.5rem] text-[length:var(--text-size-body-large)]',
27
27
  };
28
28
 
29
- export function Button({ href, variant = 'primary', size = 'default', className = '', target, rel, children }: ButtonProps) {
29
+ export function Button({ href, variant = 'primary', size = 'default', className = '', target, rel, children, ...root }: ButtonProps) {
30
30
  return (
31
31
  <a
32
+ {...root}
32
33
  className={`inline-flex items-center justify-center gap-2 rounded-button leading-button font-[var(--font-weight-semibold)] no-underline transition-all duration-[var(--transition-duration-fast)] ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}
33
34
  href={href}
34
35
  target={target}
@@ -1,15 +1,16 @@
1
1
  import { Button } from '@/components/elements/Button';
2
2
  import { Icon } from '@/components/elements/Icon';
3
+ import type { RootIdentityProps } from '@gradial/aci';
3
4
  import type { ContentProps } from '@/cms/contracts/components/button.contract';
4
5
 
5
- export type ButtonBlockProps = ContentProps;
6
+ export type ButtonBlockProps = ContentProps & RootIdentityProps;
6
7
 
7
- export function ButtonBlock({ label = '', href = '#', variant = 'primary', newWindow = false, icon = '', iconPosition = 'before', className = '' }: ButtonBlockProps) {
8
+ export function ButtonBlock({ label = '', href = '#', variant = 'primary', newWindow = false, icon = '', iconPosition = 'before', className = '', ...root }: ButtonBlockProps) {
8
9
  const target = newWindow ? '_blank' : undefined;
9
10
  const rel = newWindow ? 'noreferrer' : undefined;
10
11
 
11
12
  return (
12
- <Button href={href} variant={variant} target={target} rel={rel} className={className}>
13
+ <Button href={href} variant={variant} target={target} rel={rel} className={className} {...root}>
13
14
  {icon && iconPosition === 'before' ? <Icon name={icon} /> : null}
14
15
  <span>{label}</span>
15
16
  {icon && iconPosition === 'after' ? <Icon name={icon} /> : null}
@@ -1,5 +1,6 @@
1
1
  import { Container } from '@/components/elements/Container';
2
2
  import { type ContentProps } from '@/cms/contracts/components/container.contract';
3
+ import type { RootIdentityProps } from '@gradial/aci';
3
4
  import type { RenderChildren } from '@gradial/aci/react';
4
5
 
5
6
  export async function ContainerSection({
@@ -7,14 +8,15 @@ export async function ContainerSection({
7
8
  className = '',
8
9
  content,
9
10
  renderChildren,
10
- }: ContentProps & { renderChildren: RenderChildren<NonNullable<ContentProps['content']>> }) {
11
+ ...root
12
+ }: ContentProps & RootIdentityProps & { renderChildren: RenderChildren<NonNullable<ContentProps['content']>> }) {
11
13
  const buttonCount = content?.filter((b) => b.component === 'button').length ?? 0;
12
14
  const layout = buttonCount === 1
13
15
  ? 'flex-col items-center'
14
16
  : 'flex-col items-center sm:flex-row sm:justify-center sm:gap-4';
15
17
 
16
18
  return (
17
- <section className={`theme-${theme} relative overflow-hidden py-[var(--spacing-section-y)] ${className}`}>
19
+ <section className={`theme-${theme} relative overflow-hidden py-[var(--spacing-section-y)] ${className}`} {...root}>
18
20
  {theme === 'dark' ? (
19
21
  <div className="pointer-events-none absolute inset-0 bg-[image:var(--gradient-hero-base)] opacity-30" />
20
22
  ) : null}
@@ -1,11 +1,12 @@
1
1
  import { Icon } from '@/components/elements/Icon';
2
+ import type { RootIdentityProps } from '@gradial/aci';
2
3
  import type { ContentProps } from '@/cms/contracts/components/featureCard.contract';
3
4
 
4
- export type FeatureCardProps = ContentProps;
5
+ export type FeatureCardProps = ContentProps & RootIdentityProps;
5
6
 
6
- export function FeatureCard({ icon = '', title = '', description = '' }: FeatureCardProps) {
7
+ export function FeatureCard({ icon = '', title = '', description = '', ...root }: FeatureCardProps) {
7
8
  return (
8
- <div className="group relative overflow-hidden rounded-card border border-[var(--color-border-default)] bg-[var(--color-white)] p-[var(--spacing-card)] shadow-[var(--shadow-card-default)] transition-all duration-[var(--transition-duration-fast)] hover:-translate-y-1 hover:border-[var(--color-border-strong)] hover:shadow-[var(--shadow-elevated)]">
9
+ <div {...root} className="group relative overflow-hidden rounded-card border border-[var(--color-border-default)] bg-[var(--color-white)] p-[var(--spacing-card)] shadow-[var(--shadow-card-default)] transition-all duration-[var(--transition-duration-fast)] hover:-translate-y-1 hover:border-[var(--color-border-strong)] hover:shadow-[var(--shadow-elevated)]">
9
10
  <div className="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-[var(--color-brand-500)] to-transparent opacity-0 transition-opacity duration-[var(--transition-duration-fast)] group-hover:opacity-100" />
10
11
  {icon ? (
11
12
  <div className="mb-6 flex h-12 w-12 items-center justify-center rounded-button border border-[var(--color-border-default)] bg-[var(--color-surface-100)] text-[var(--color-brand-600)] shadow-[var(--shadow-glow-sm)] transition-colors group-hover:border-[var(--color-brand-500)] group-hover:text-[var(--color-brand-500)]">
@@ -1,5 +1,6 @@
1
1
  import { Container } from '@/components/elements/Container';
2
2
  import { type ContentProps } from '@/cms/contracts/components/featureGrid.contract';
3
+ import type { RootIdentityProps } from '@gradial/aci';
3
4
  import type { RenderChildren } from '@gradial/aci/react';
4
5
 
5
6
  export async function FeatureGrid({
@@ -7,12 +8,13 @@ export async function FeatureGrid({
7
8
  subtitle = '',
8
9
  features,
9
10
  renderChildren,
10
- }: ContentProps & { renderChildren: RenderChildren<NonNullable<ContentProps['features']>> }) {
11
+ ...root
12
+ }: ContentProps & RootIdentityProps & { renderChildren: RenderChildren<NonNullable<ContentProps['features']>> }) {
11
13
  const count = features?.length ?? 0;
12
14
  const cols = count <= 2 ? 'sm:grid-cols-2' : 'sm:grid-cols-2 lg:grid-cols-3';
13
15
 
14
16
  return (
15
- <section className="theme-light relative overflow-hidden py-[var(--spacing-section-y)] bg-[var(--color-white)]">
17
+ <section className="theme-light relative overflow-hidden py-[var(--spacing-section-y)] bg-[var(--color-white)]" {...root}>
16
18
  <div className="pointer-events-none absolute inset-0 bg-[image:var(--gradient-hero-base)] opacity-50" />
17
19
  <Container className="relative">
18
20
  <div className="mb-14 max-w-[var(--max-width-container-narrow)]">