@gradial/aci 0.1.20-preview.3 → 0.1.20

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 (224) hide show
  1. package/README.md +48 -108
  2. package/bin/{aci → aci-darwin-arm64} +0 -0
  3. package/bin/aci.js +99 -6
  4. package/dist/assets/index.d.ts +3 -3
  5. package/dist/assets/index.js +3 -3
  6. package/dist/astro/index.d.ts +12 -3
  7. package/dist/astro/index.js +20 -5
  8. package/dist/content/assets.d.ts +17 -0
  9. package/dist/content/assets.js +65 -0
  10. package/dist/content/index.d.ts +1 -0
  11. package/dist/content/index.js +1 -0
  12. package/dist/define-component.d.ts +1 -2
  13. package/dist/define-component.js +73 -5
  14. package/dist/dev/content-watch.d.ts +37 -0
  15. package/dist/dev/content-watch.js +154 -0
  16. package/dist/dev/index.d.ts +24 -43
  17. package/dist/dev/index.js +4 -169
  18. package/dist/index.d.ts +14 -6
  19. package/dist/index.js +8 -9
  20. package/dist/next/asset-route.js +2 -2
  21. package/dist/next/config.d.ts +2 -2
  22. package/dist/next/config.js +5 -5
  23. package/dist/next/content-watch.js +6 -1
  24. package/dist/next/index.d.ts +2 -2
  25. package/dist/next/index.js +2 -2
  26. package/dist/next/middleware.d.ts +2 -2
  27. package/dist/next/middleware.js +6 -6
  28. package/dist/next/page.d.ts +1 -1
  29. package/dist/next/page.js +14 -12
  30. package/dist/next/render.d.ts +3 -3
  31. package/dist/next/render.js +11 -9
  32. package/dist/next/server.d.ts +12 -12
  33. package/dist/next/server.js +1 -1
  34. package/dist/react/Media.d.ts +24 -0
  35. package/dist/react/Media.js +30 -0
  36. package/dist/react/Picture.d.ts +12 -0
  37. package/dist/react/Picture.js +11 -0
  38. package/dist/react/VideoPlayer.d.ts +13 -0
  39. package/dist/react/{GradialVideoPlayer.js → VideoPlayer.js} +6 -5
  40. package/dist/react/index.d.ts +333 -3
  41. package/dist/react/index.js +89 -3
  42. package/dist/registry.d.ts +2 -2
  43. package/dist/registry.js +3 -3
  44. package/dist/types/block-ref.d.ts +26 -0
  45. package/dist/types/block-ref.js +28 -0
  46. package/dist/types/component.d.ts +36 -32
  47. package/dist/types/config.d.ts +1 -1
  48. package/dist/types/image.d.ts +33 -20
  49. package/dist/types/image.js +42 -50
  50. package/dist/types/index.d.ts +1 -0
  51. package/dist/types/index.js +1 -0
  52. package/dist/types/link.d.ts +38 -0
  53. package/dist/types/link.js +58 -0
  54. package/dist/types/media.d.ts +16 -35
  55. package/dist/types/media.js +15 -84
  56. package/dist/types/renderer.d.ts +1 -1
  57. package/dist/types/rich-text.d.ts +40 -0
  58. package/dist/types/rich-text.js +39 -0
  59. package/dist/types/video.d.ts +7 -13
  60. package/dist/types/video.js +3 -3
  61. package/package.json +28 -76
  62. package/src/cli/compile-registry.mjs +120 -63
  63. package/src/cli/validate-content.mjs +38 -75
  64. package/src/types/image.ts +79 -60
  65. package/templates/astro/template/.aci.yaml +27 -0
  66. package/templates/astro/template/.storybook/main.ts +79 -0
  67. package/templates/astro/template/.storybook/manager.ts +6 -0
  68. package/templates/astro/template/.storybook/preview.ts +33 -0
  69. package/templates/astro/template/astro.config.mjs +37 -0
  70. package/templates/astro/template/package.json.tmpl +41 -0
  71. package/templates/astro/template/src/cms/contracts/layouts/index.ts +18 -0
  72. package/templates/astro/template/src/cms/registry.ts +28 -0
  73. package/templates/astro/template/src/components/chrome/Footer.astro +107 -0
  74. package/templates/astro/template/src/components/chrome/Header.astro +94 -0
  75. package/templates/astro/template/src/components/elements/AtomicBlock.astro +15 -0
  76. package/templates/astro/template/src/components/elements/AtomicBlocks.astro +16 -0
  77. package/templates/astro/template/src/components/elements/Button.astro +51 -0
  78. package/templates/astro/template/src/components/elements/ButtonBlock.astro +25 -0
  79. package/templates/astro/template/src/components/elements/Container.astro +11 -0
  80. package/templates/astro/template/src/components/elements/Icon.astro +31 -0
  81. package/templates/astro/template/src/components/elements/Logo.astro +29 -0
  82. package/templates/astro/template/src/components/elements/RemoteImage.astro +41 -0
  83. package/templates/astro/template/src/components/sections/ContainerSection.astro +32 -0
  84. package/templates/astro/template/src/components/sections/FeatureCard.astro +23 -0
  85. package/templates/astro/template/src/components/sections/FeatureGrid.astro +35 -0
  86. package/templates/astro/template/src/components/sections/HomeHero.astro +51 -0
  87. package/templates/astro/template/src/components/sections/StatsBar.astro +33 -0
  88. package/templates/astro/template/src/design-system/styles.css +399 -0
  89. package/templates/astro/template/src/design-system/tokens/colors.css +60 -0
  90. package/templates/astro/template/src/design-system/tokens/components.css +69 -0
  91. package/templates/astro/template/src/design-system/tokens/index.css +6 -0
  92. package/templates/astro/template/src/design-system/tokens/radii.css +5 -0
  93. package/templates/astro/template/src/design-system/tokens/shadows.css +5 -0
  94. package/templates/astro/template/src/design-system/tokens/spacing.css +13 -0
  95. package/templates/astro/template/src/design-system/tokens/typography.css +24 -0
  96. package/templates/astro/template/src/env.d.ts +1 -0
  97. package/templates/astro/template/src/fixtures/atomicBlocks.ts +33 -0
  98. package/templates/astro/template/src/fixtures/composition.ts +31 -0
  99. package/templates/astro/template/src/fixtures/index.ts +17 -0
  100. package/templates/astro/template/src/fixtures/sections.ts +39 -0
  101. package/templates/astro/template/src/layouts/SiteLayout.astro +30 -0
  102. package/templates/astro/template/src/pages/[...slug].astro +61 -0
  103. package/templates/astro/template/src/render/RenderPage.astro +66 -0
  104. package/templates/astro/template/src/stories/CompositionStoryFrame.astro +15 -0
  105. package/templates/astro/template/src/stories/HomeHero.stories.ts +24 -0
  106. package/templates/astro/template/src/stories/SectionStoryFrame.astro +16 -0
  107. package/templates/astro/template/src/stories/StoryDocFrame.astro +31 -0
  108. package/templates/astro/template/tsconfig.json +11 -0
  109. package/templates/common/.agents/AGENTS.md +37 -0
  110. package/templates/common/.agents/skills/aci/SKILL.md +162 -0
  111. package/templates/common/.agents/skills/authoring/SKILL.md +590 -0
  112. package/templates/common/.agents/skills/authoring/references/block-registry.md +151 -0
  113. package/templates/common/.agents/skills/authoring/references/contracts.md +153 -0
  114. package/templates/common/.agents/skills/authoring/references/design-system.md +171 -0
  115. package/templates/common/.agents/skills/authoring/references/image-assets.md +73 -0
  116. package/templates/common/.agents/skills/authoring/references/repo-structure.md +157 -0
  117. package/templates/common/.agents/skills/migration/SKILL.md +160 -0
  118. package/templates/common/.agents/skills/migration/references/analyzing-source.md +215 -0
  119. package/templates/common/.agents/skills/migration/references/component-migration.md +200 -0
  120. package/templates/common/.agents/skills/migration/references/selector-map.md +31 -0
  121. package/templates/common/.content/.gradial-dam/blobs/sha256/7f/bf/7fbfc7fe230ff12688c496f660119e41d9725c4504d82e310c15665c73c09292 +0 -0
  122. package/templates/common/.content/.gradial-dam/blobs/sha256/a0/f5/a0f506689de9b15a7055f70103a3f02cd3ba105771ae2de6754df2ede1210d3a +0 -0
  123. package/templates/common/.content/.gradial-dam/blobs/sha256/dd/b7/ddb7e9642be08317bcd4b2bd26b58ba8d0d34dd7239e03e684a4f3634fa3845b +0 -0
  124. package/templates/common/.content/.gradial-dam/blobs/sha256/fb/32/fb3260e8286ea8231ea1c77b9c0be92d6edd9026565731eb14cfdcfd6b1b75b3 +0 -0
  125. package/templates/common/.content/config/site.json +192 -0
  126. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/asset.json +9 -0
  127. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/editorial.json +14 -0
  128. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/governance.json +23 -0
  129. package/templates/common/.content/dam/folders/seed/ast_site_about_hero/versions/v0001.json +37 -0
  130. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/asset.json +9 -0
  131. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/editorial.json +14 -0
  132. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/governance.json +23 -0
  133. package/templates/common/.content/dam/folders/seed/ast_site_home_hero/versions/v0001.json +37 -0
  134. package/templates/common/.content/fragments/navbar/_index.json +25 -0
  135. package/templates/common/.content/fragments/site-footer/_index.json +62 -0
  136. package/templates/common/.content/pages/about/_index.json +51 -0
  137. package/templates/common/.content/pages/home/_index.json +112 -0
  138. package/templates/common/.content/schemas/site.schema.json +123 -0
  139. package/templates/common/README.md.tmpl +45 -0
  140. package/templates/common/contracts/components/button.contract.ts +19 -0
  141. package/templates/common/contracts/components/container.contract.ts +19 -0
  142. package/templates/common/contracts/components/featureCard.contract.ts +15 -0
  143. package/templates/common/contracts/components/featureGrid.contract.ts +16 -0
  144. package/templates/common/contracts/components/homeHero.contract.ts +36 -0
  145. package/templates/common/contracts/components/index.ts +21 -0
  146. package/templates/common/contracts/components/siteFooter.contract.ts +45 -0
  147. package/templates/common/contracts/components/siteNavigation.contract.ts +30 -0
  148. package/templates/common/contracts/components/statsBar.contract.ts +19 -0
  149. package/templates/common/design-system/styles.css +346 -0
  150. package/templates/common/design-system/tokens/colors.css +110 -0
  151. package/templates/common/design-system/tokens/components.css +86 -0
  152. package/templates/common/design-system/tokens/index.css +6 -0
  153. package/templates/common/design-system/tokens/radii.css +5 -0
  154. package/templates/common/design-system/tokens/shadows.css +9 -0
  155. package/templates/common/design-system/tokens/spacing.css +26 -0
  156. package/templates/common/design-system/tokens/typography.css +32 -0
  157. package/templates/common/eslint-rules/no-raw-tailwind-values.js +127 -0
  158. package/templates/common/public/assets/Dwire-model.png +0 -0
  159. package/templates/common/public/assets/bare-metal-logo.png +0 -0
  160. package/templates/common/public/assets/meridian-logo.svg +8 -0
  161. package/templates/common/public/assets/seattle.avif +0 -0
  162. package/templates/nextjs/template/.aci.yaml +25 -0
  163. package/templates/nextjs/template/.storybook/main.ts +13 -0
  164. package/templates/nextjs/template/.storybook/preview.ts +34 -0
  165. package/templates/nextjs/template/eslint.config.mjs +36 -0
  166. package/templates/nextjs/template/next-env.d.ts +6 -0
  167. package/templates/nextjs/template/next.config.ts +8 -0
  168. package/templates/nextjs/template/package.json.tmpl +46 -0
  169. package/templates/nextjs/template/postcss.config.mjs +7 -0
  170. package/templates/nextjs/template/src/app/[[...slug]]/page.tsx +8 -0
  171. package/templates/nextjs/template/src/app/gradial/assets/[releaseId]/[...path]/route.ts +31 -0
  172. package/templates/nextjs/template/src/app/layout.tsx +29 -0
  173. package/templates/nextjs/template/src/cms/contracts/components/button.contract.ts +19 -0
  174. package/templates/nextjs/template/src/cms/contracts/components/container.contract.ts +20 -0
  175. package/templates/nextjs/template/src/cms/contracts/components/homeHero.contract.ts +36 -0
  176. package/templates/nextjs/template/src/cms/contracts/components/index.ts +15 -0
  177. package/templates/nextjs/template/src/cms/contracts/components/siteFooter.contract.ts +45 -0
  178. package/templates/nextjs/template/src/cms/contracts/components/siteNavigation.contract.ts +30 -0
  179. package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +16 -0
  180. package/templates/nextjs/template/src/cms/registry.ts +28 -0
  181. package/templates/nextjs/template/src/components/chrome/Footer.tsx +86 -0
  182. package/templates/nextjs/template/src/components/chrome/Header.tsx +74 -0
  183. package/templates/nextjs/template/src/components/elements/AtomicBlock.tsx +13 -0
  184. package/templates/nextjs/template/src/components/elements/Button.tsx +40 -0
  185. package/templates/nextjs/template/src/components/elements/ButtonBlock.tsx +18 -0
  186. package/templates/nextjs/template/src/components/elements/Container.tsx +14 -0
  187. package/templates/nextjs/template/src/components/elements/Icon.tsx +29 -0
  188. package/templates/nextjs/template/src/components/elements/Logo.tsx +38 -0
  189. package/templates/nextjs/template/src/components/sections/ContainerSection.tsx +28 -0
  190. package/templates/nextjs/template/src/components/sections/FeatureCard.tsx +25 -0
  191. package/templates/nextjs/template/src/components/sections/FeatureGrid.tsx +36 -0
  192. package/templates/nextjs/template/src/components/sections/HomeHero.tsx +62 -0
  193. package/templates/nextjs/template/src/components/sections/StatsBar.tsx +30 -0
  194. package/templates/nextjs/template/src/middleware.ts +4 -0
  195. package/templates/nextjs/template/src/stories/Button.stories.tsx +38 -0
  196. package/templates/nextjs/template/src/stories/Header.stories.tsx +30 -0
  197. package/templates/nextjs/template/src/stories/HomeHero.stories.tsx +33 -0
  198. package/templates/nextjs/template/tsconfig.json +23 -0
  199. package/templates/nextjs/template/vercel.json +6 -0
  200. package/dist/content/contract.d.ts +0 -83
  201. package/dist/content/contract.js +0 -104
  202. package/dist/content/tailwind-validator.d.ts +0 -6
  203. package/dist/content/tailwind-validator.js +0 -31
  204. package/dist/content/validation.d.ts +0 -108
  205. package/dist/content/validation.js +0 -183
  206. package/dist/react/GradialMedia.d.ts +0 -24
  207. package/dist/react/GradialMedia.js +0 -31
  208. package/dist/react/GradialPicture.d.ts +0 -14
  209. package/dist/react/GradialPicture.js +0 -30
  210. package/dist/react/GradialVideoPlayer.d.ts +0 -13
  211. package/dist/sveltekit/index.d.ts +0 -25
  212. package/dist/sveltekit/index.js +0 -66
  213. package/dist/sveltekit/preview.d.ts +0 -5
  214. package/dist/sveltekit/preview.js +0 -33
  215. package/src/types/component.ts +0 -49
  216. package/src/types/config.ts +0 -37
  217. package/src/types/data.ts +0 -47
  218. package/src/types/index.ts +0 -10
  219. package/src/types/layout.ts +0 -29
  220. package/src/types/media.ts +0 -125
  221. package/src/types/page.ts +0 -47
  222. package/src/types/render-mode.ts +0 -10
  223. package/src/types/renderer.ts +0 -83
  224. package/src/types/video.ts +0 -66
@@ -0,0 +1,69 @@
1
+ @theme {
2
+ --width-logo-mobile: calc(var(--spacing) * 31);
3
+ --width-logo: calc(var(--spacing) * 52);
4
+ --width-logo-footer-mobile: calc(var(--spacing) * 37);
5
+ --width-logo-footer: calc(var(--spacing) * 56);
6
+ --logo-filter: brightness(1.18) saturate(1.14);
7
+ --text-button: var(--text-size-body-small);
8
+ --leading-button: 1;
9
+ --spacing-button-x: calc(var(--spacing) * 4);
10
+ --spacing-button-y: calc(var(--spacing) * 3);
11
+ --height-button-min: calc(var(--spacing) * 10);
12
+ --button-hover-opacity: 0.85;
13
+ --transition-duration-fast: 200ms;
14
+ --button-primary-bg: var(--color-black);
15
+ --button-primary-text: var(--color-white);
16
+ --button-primary-border: var(--color-black);
17
+ --button-secondary-bg: transparent;
18
+ --button-secondary-text: var(--color-black);
19
+ --button-secondary-border: var(--color-black);
20
+ --button-outline-bg: transparent;
21
+ --button-outline-text: var(--color-black);
22
+ --button-outline-border: var(--color-border);
23
+ --button-tertiary-bg: transparent;
24
+ --button-tertiary-text: var(--color-accent-primary);
25
+ --button-tertiary-border: transparent;
26
+ --header-bg: var(--color-chrome-surface-default);
27
+ --header-text: var(--color-fg-inverse);
28
+ --header-muted: var(--color-fg-inverse-soft);
29
+ --header-border: var(--color-edge-inverse);
30
+ --header-link-hover: var(--color-accent-secondary);
31
+ --header-icon: var(--color-fg-inverse-muted);
32
+ --mobile-nav-bg: var(--color-chrome-surface-default);
33
+ --mobile-nav-text: var(--color-fg-inverse);
34
+ --mobile-nav-muted: var(--color-fg-inverse-muted);
35
+ --mobile-nav-border: var(--color-edge-inverse);
36
+ --mobile-nav-link-hover: var(--color-accent-secondary);
37
+ --mobile-nav-link-size: calc(var(--spacing) * 12);
38
+ --mobile-nav-link-line-height: 1.05;
39
+ --footer-bg: var(--color-chrome-surface-default);
40
+ --footer-text: var(--color-fg-inverse);
41
+ --footer-muted: var(--color-fg-inverse-muted);
42
+ --footer-border: var(--color-edge-inverse);
43
+ --footer-link-hover: var(--color-accent-secondary);
44
+ --footer-grid-columns: 1fr 2fr;
45
+ --color-callout-icon-bg-light: color-mix(in srgb, var(--color-accent-primary) 8%, var(--color-white));
46
+ --color-callout-icon-bg-dark: color-mix(in srgb, var(--color-accent-primary) 18%, transparent);
47
+ --color-callout-icon-bg: var(--color-callout-icon-bg-light);
48
+ --callout-icon-color: var(--color-accent-primary);
49
+ --max-width-rich-text: var(--max-width-container-narrow);
50
+ --max-width-rich-text-wide: calc(var(--spacing) * 216);
51
+ --rich-text-flow-space: calc(var(--spacing) * 6);
52
+ --rich-text-heading-space: calc(var(--spacing) * 10);
53
+ --rich-text-link-decoration-thickness: 0.09em;
54
+ --rich-text-link-underline-offset: 0.18em;
55
+ --rich-text-list-indent: 1.4em;
56
+ --rich-text-blockquote-border-width: calc(var(--spacing) * 1.2);
57
+ --rich-text-inline-code-padding: 0.08em 0.32em;
58
+ --rich-text-quote-border: var(--color-accent-primary);
59
+ --rich-text-quote-bg: color-mix(in srgb, var(--color-accent-primary) 6%, var(--color-white));
60
+ --rich-text-quote-bg-dark: color-mix(in srgb, var(--color-accent-primary) 16%, transparent);
61
+ --rich-text-quote-bg-default: var(--rich-text-quote-bg);
62
+ --rich-text-inline-code-bg: color-mix(in srgb, var(--color-fg-base-muted) 8%, var(--color-white));
63
+ --rich-text-inline-code-bg-dark: color-mix(in srgb, var(--color-white) 12%, transparent);
64
+ --rich-text-inline-code-bg-default: var(--rich-text-inline-code-bg);
65
+ --rich-text-inline-code-text: var(--color-fg);
66
+ --max-width-cta: calc(var(--spacing) * 304);
67
+ --z-header: 50;
68
+ --z-overlay: 60;
69
+ }
@@ -0,0 +1,6 @@
1
+ @import "./colors.css";
2
+ @import "./typography.css";
3
+ @import "./spacing.css";
4
+ @import "./shadows.css";
5
+ @import "./radii.css";
6
+ @import "./components.css";
@@ -0,0 +1,5 @@
1
+ @theme {
2
+ --radius-button: calc(var(--spacing) * 2);
3
+ --radius-card: calc(var(--spacing) * 3);
4
+ --radius-cta: calc(var(--spacing) * 2);
5
+ }
@@ -0,0 +1,5 @@
1
+ @theme {
2
+ --shadow-card: 0 calc(var(--spacing) * 5.5) calc(var(--spacing) * 15) color-mix(in srgb, var(--color-black) 8%, transparent);
3
+ --shadow-card-dark: 0 calc(var(--spacing) * 5.5) calc(var(--spacing) * 15) color-mix(in srgb, var(--color-black) 36%, transparent);
4
+ --shadow-card-default: var(--shadow-card);
5
+ }
@@ -0,0 +1,13 @@
1
+ @theme {
2
+ --max-width-container: calc(var(--spacing) * 352);
3
+ --max-width-container-narrow: calc(var(--spacing) * 208);
4
+ --spacing-container: clamp(calc(var(--spacing) * 4), 4vw, calc(var(--spacing) * 11));
5
+ --spacing-section-y: clamp(calc(var(--spacing) * 18), 7vw, calc(var(--spacing) * 32));
6
+ --height-header: calc(var(--spacing) * 20);
7
+ --spacing-footer-y: clamp(calc(var(--spacing) * 18), 8vw, calc(var(--spacing) * 32));
8
+ --height-hero-min: clamp(calc(var(--spacing) * 144), 68vw, calc(var(--spacing) * 192));
9
+ --width-hero-content: calc(var(--spacing) * 180);
10
+ --spacing-card: clamp(calc(var(--spacing) * 5.5), 2vw, calc(var(--spacing) * 8));
11
+ --spacing-cta-y: clamp(calc(var(--spacing) * 17), 8vw, calc(var(--spacing) * 29));
12
+ --spacing-cta-x: clamp(calc(var(--spacing) * 6), 5vw, calc(var(--spacing) * 20));
13
+ }
@@ -0,0 +1,24 @@
1
+ @theme {
2
+ --font-family-base: "Inter", "Helvetica Neue", Arial, sans-serif;
3
+ --font-family-heading: "Inter", "Helvetica Neue", Arial, sans-serif;
4
+ --font-weight-regular: 400;
5
+ --font-weight-medium: 560;
6
+ --font-weight-semibold: 650;
7
+ --font-weight-bold: 760;
8
+ --text-size-brand: 1.5rem;
9
+ --text-size-eyebrow: 0.8125rem;
10
+ --text-size-caption: 0.8125rem;
11
+ --text-size-body-small: 0.9375rem;
12
+ --text-size-body: 1.0625rem;
13
+ --text-size-body-large: 1.25rem;
14
+ --text-size-h1-mobile: 3.25rem;
15
+ --text-size-h1: 5rem;
16
+ --text-size-h2-mobile: 2.5rem;
17
+ --text-size-h2: 3.25rem;
18
+ --text-size-h3: 1.75rem;
19
+ --leading-tight: 0.96;
20
+ --leading-heading: 1.08;
21
+ --leading-body: 1.5;
22
+ --leading-relaxed: 1.68;
23
+ --letter-spacing-label: 0;
24
+ }
@@ -0,0 +1 @@
1
+ /// <reference types="astro/client" />
@@ -0,0 +1,33 @@
1
+ import type { KernelPageBlock } from '@gradial/aci/content';
2
+
3
+ export interface AtomicBlockStoryFixture {
4
+ id: string;
5
+ storybookId: string;
6
+ title: string;
7
+ block: KernelPageBlock;
8
+ }
9
+
10
+ export const atomicBlockStoryFixtures: AtomicBlockStoryFixture[] = [
11
+ {
12
+ id: 'button-variants',
13
+ storybookId: 'core-atomic-blocks-button--variants',
14
+ title: 'Button / All Variants',
15
+ block: {
16
+ id: 'fixture-button-variants',
17
+ component: 'container',
18
+ props: {
19
+ theme: 'auto',
20
+ blocks: [
21
+ { id: 'btn-primary', component: 'button', props: { label: 'Primary button', href: '#', variant: 'primary' } },
22
+ { id: 'btn-secondary', component: 'button', props: { label: 'Secondary button', href: '#', variant: 'secondary' } },
23
+ { id: 'btn-tertiary', component: 'button', props: { label: 'Tertiary button', href: '#', variant: 'tertiary' } },
24
+ { id: 'btn-icon-before', component: 'button', props: { label: 'Icon before', href: '#', variant: 'primary', icon: 'arrow-right', iconPosition: 'before' } },
25
+ { id: 'btn-icon-after', component: 'button', props: { label: 'Icon after', href: '#', variant: 'secondary', icon: 'arrow-right', iconPosition: 'after' } },
26
+ { id: 'btn-new-window', component: 'button', props: { label: 'Opens in new tab', href: 'https://example.com', variant: 'primary', newWindow: true, icon: 'arrow-right', iconPosition: 'after' } }
27
+ ]
28
+ }
29
+ }
30
+ }
31
+ ];
32
+
33
+ export const atomicBlockVisualStoryIds = atomicBlockStoryFixtures.map((fixture) => fixture.storybookId);
@@ -0,0 +1,31 @@
1
+ import type { KernelPageBlock } from '@gradial/aci/content';
2
+
3
+ export interface CompositionStoryFixture {
4
+ id: string;
5
+ storybookId: string;
6
+ title: string;
7
+ direction?: 'ltr' | 'rtl';
8
+ block: KernelPageBlock;
9
+ }
10
+
11
+ export const compositionStoryFixtures: CompositionStoryFixture[] = [
12
+ {
13
+ id: 'container-buttons',
14
+ storybookId: 'composition-container--buttons',
15
+ title: 'Container / Buttons',
16
+ block: {
17
+ id: 'fixture-container-buttons',
18
+ component: 'container',
19
+ props: {
20
+ theme: 'auto',
21
+ className: 'space-y-4',
22
+ blocks: [
23
+ { id: 'btn-1', component: 'button', props: { label: 'Primary action', href: '#', variant: 'primary', icon: 'arrow_forward', iconPosition: 'after' } },
24
+ { id: 'btn-2', component: 'button', props: { label: 'Secondary action', href: '#', variant: 'secondary' } }
25
+ ]
26
+ }
27
+ }
28
+ }
29
+ ];
30
+
31
+ export const compositionVisualStoryIds = compositionStoryFixtures.map((fixture) => fixture.storybookId);
@@ -0,0 +1,17 @@
1
+ export {
2
+ compositionStoryFixtures,
3
+ compositionVisualStoryIds,
4
+ type CompositionStoryFixture
5
+ } from './composition';
6
+
7
+ export {
8
+ sectionStoryFixtures,
9
+ sectionVisualStoryIds,
10
+ type SectionStoryFixture
11
+ } from './sections';
12
+
13
+ export {
14
+ atomicBlockStoryFixtures,
15
+ atomicBlockVisualStoryIds,
16
+ type AtomicBlockStoryFixture
17
+ } from './atomicBlocks';
@@ -0,0 +1,39 @@
1
+ import type { KernelPageBlock } from '@gradial/aci/content';
2
+
3
+ export interface SectionStoryFixture {
4
+ id: string;
5
+ storybookId: string;
6
+ title: string;
7
+ direction?: 'ltr' | 'rtl';
8
+ block: KernelPageBlock;
9
+ }
10
+
11
+ export const sectionStoryFixtures: SectionStoryFixture[] = [
12
+ {
13
+ id: 'home-hero',
14
+ storybookId: 'sections-home-hero--default',
15
+ title: 'Home Hero',
16
+ block: {
17
+ id: 'fixture-home-hero',
18
+ component: 'home_hero',
19
+ props: {
20
+ eyebrow: 'Bare Metal Learn',
21
+ headline: 'Ship the same site on every framework.',
22
+ description: 'One content model, three renderers. Build once in Next.js, Astro, and SvelteKit—then prove parity with shared fixtures.',
23
+ ctaLabel: 'Get started',
24
+ ctaHref: '/docs',
25
+ image: {
26
+ $type: 'gradial.image',
27
+ assetId: 'fixture_seattle',
28
+ versionId: 'v0001',
29
+ alt: 'Seattle skyline at dusk',
30
+ sources: [
31
+ { src: '/assets/seattle.avif', width: 1920, height: 1280, type: 'image/avif' }
32
+ ]
33
+ }
34
+ }
35
+ }
36
+ }
37
+ ];
38
+
39
+ export const sectionVisualStoryIds = sectionStoryFixtures.map((fixture) => fixture.storybookId);
@@ -0,0 +1,30 @@
1
+ ---
2
+ import '../design-system/styles.css';
3
+
4
+ interface Props {
5
+ title: string;
6
+ description: string;
7
+ canonical?: string;
8
+ siteName?: string;
9
+ }
10
+
11
+ const { title, description, canonical, siteName = 'Gradial' } = Astro.props;
12
+ ---
13
+
14
+ <!doctype html>
15
+ <html lang="en">
16
+ <head>
17
+ <meta charset="utf-8" />
18
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
19
+ <title>{title}</title>
20
+ <link rel="icon" type="image/png" href="/assets/bare-metal-logo.png" />
21
+ <meta name="description" content={description} />
22
+ {canonical ? <link rel="canonical" href={canonical} /> : null}
23
+ <meta property="og:title" content={title} />
24
+ <meta property="og:description" content={description} />
25
+ <meta property="og:site_name" content={siteName} />
26
+ </head>
27
+ <body>
28
+ <slot />
29
+ </body>
30
+ </html>
@@ -0,0 +1,61 @@
1
+ ---
2
+ import { getGradialStaticPaths, getPageRuntimeRenderInput, createRenderChildren } from '@gradial/aci/astro';
3
+ import { normalizeRoute, routeMetadataForContent, resolveSlots } from '@gradial/aci/content';
4
+ import { FileContentProvider } from '@gradial/aci/providers/file';
5
+ import type { KernelPage, KernelSiteConfig, LayoutEntry, FragmentData } from '@gradial/aci/content';
6
+ import { registry } from '../cms/registry';
7
+ import SiteLayout from '../layouts/SiteLayout.astro';
8
+
9
+ export const getStaticPaths = getGradialStaticPaths;
10
+
11
+ const route = normalizeRoute(Astro.params.slug ? `/${Astro.params.slug}` : '/');
12
+ const runtimeInput = getPageRuntimeRenderInput(Astro.request);
13
+ let siteConfig: KernelSiteConfig;
14
+ let page: KernelPage;
15
+ let provider: FileContentProvider;
16
+ if (runtimeInput) {
17
+ siteConfig = runtimeInput.siteConfig as KernelSiteConfig;
18
+ page = runtimeInput.page as KernelPage;
19
+ } else {
20
+ provider = new FileContentProvider();
21
+ [siteConfig, page] = await Promise.all([
22
+ provider.getSiteConfig<KernelSiteConfig>(),
23
+ provider.getPage<KernelPage>(route),
24
+ ]);
25
+ }
26
+
27
+ const meta = routeMetadataForContent(siteConfig, page);
28
+ const layout = (runtimeInput?.layouts?.[page.layout] ?? await (provider ?? new FileContentProvider()).getLayout<LayoutEntry>(page.layout)) as LayoutEntry;
29
+ const resolvedSlots = await resolveSlots(
30
+ layout,
31
+ page?.regions || {},
32
+ async (id) => {
33
+ if (runtimeInput?.fragments?.[id]) return runtimeInput.fragments[id] as FragmentData;
34
+ return await (provider ?? new FileContentProvider()).getFragment<FragmentData>(id);
35
+ }
36
+ );
37
+
38
+ const renderChildren = createRenderChildren(registry);
39
+ ---
40
+
41
+ <SiteLayout title={meta.title} description={meta.description} canonical={meta.canonical} siteName={meta.siteName}>
42
+ {layout.slots.map((slot) => {
43
+ const blocks = resolvedSlots[slot.name];
44
+ if (!blocks?.length) return null;
45
+ const rendered = renderChildren(blocks);
46
+ if (slot.name === 'main') {
47
+ return (
48
+ <main id="content-main">
49
+ {rendered.map((child) => {
50
+ const Comp = child.Component as any;
51
+ return Comp ? <Comp {...child.props} /> : null;
52
+ })}
53
+ </main>
54
+ );
55
+ }
56
+ return rendered.map((child) => {
57
+ const Comp = child.Component as any;
58
+ return Comp ? <Comp {...child.props} /> : null;
59
+ });
60
+ })}
61
+ </SiteLayout>
@@ -0,0 +1,66 @@
1
+ ---
2
+ import SiteLayout from '../layouts/SiteLayout.astro';
3
+ import type { KernelPage, KernelSiteConfig } from '@gradial/aci/content';
4
+ import { registryLookup } from '@gradial/aci/astro';
5
+ import { registry } from '../cms/registry';
6
+ import Header from '../components/chrome/Header.astro';
7
+ import Footer from '../components/chrome/Footer.astro';
8
+
9
+ interface RenderInput {
10
+ route: string;
11
+ domain: string;
12
+ locale: string;
13
+ siteConfig: KernelSiteConfig;
14
+ page: KernelPage;
15
+ }
16
+
17
+ interface Props {
18
+ input: RenderInput;
19
+ }
20
+
21
+ const { input } = Astro.props;
22
+ const { siteConfig, page } = input;
23
+ const title = page.metadata?.title || siteConfig.seo?.title || siteConfig.title;
24
+ const description = page.metadata?.description || siteConfig.seo?.description || '';
25
+ const canonical = page.metadata?.canonical;
26
+ const siteName = siteConfig.seo?.siteName || siteConfig.title;
27
+
28
+ const footer = siteConfig.footer || {};
29
+ const blocks = page?.regions?.main || [];
30
+ ---
31
+
32
+ <SiteLayout {title} {description} {canonical} {siteName}>
33
+ <Header
34
+ brandHref={siteConfig.brandHref || '/'}
35
+ brandLabel={siteConfig.title || 'Gradial'}
36
+ brandLogo={siteConfig.brandLogo || null}
37
+ navigation={(siteConfig.navigation || []) as any}
38
+ utilities={(siteConfig.utilities || []) as any}
39
+ />
40
+
41
+ <main id="content-main">
42
+ {page && page.status === 'published' ? (
43
+ blocks.map((block) => {
44
+ // Astro's type checker can't validate dynamically resolved components,
45
+ // so we cast to any. The registry is type-safe at registration time.
46
+ const Component = registryLookup(registry, block.component) as any;
47
+ return Component ? <Component {...block.props} /> : null;
48
+ })
49
+ ) : (
50
+ <section class="mx-auto max-w-container-narrow px-[var(--spacing-container)] py-[var(--spacing-section-y)] text-center">
51
+ <h1 class="[font-family:var(--font-family-heading)] text-[length:var(--text-size-h2-mobile)] font-[var(--font-weight-semibold)] leading-heading md:text-[length:var(--text-size-h2)]">Page not found</h1>
52
+ <p class="mt-5 text-[length:var(--text-size-body)] text-[color:var(--color-fg-secondary)]">The requested content route is not available in the local content kernel.</p>
53
+ </section>
54
+ )}
55
+ </main>
56
+
57
+ <Footer
58
+ brandHref={siteConfig.brandHref || '/'}
59
+ brandLabel={siteConfig.title || 'Gradial'}
60
+ brandLogo={siteConfig.brandLogo || null}
61
+ social={(footer.social || []) as any}
62
+ columns={(footer.columns || []) as any}
63
+ legalLinks={(footer.legalLinks || []) as any}
64
+ copyright={String(footer.copyright || '')}
65
+ />
66
+ </SiteLayout>
@@ -0,0 +1,15 @@
1
+ ---
2
+ import type { KernelPageBlock } from '@gradial/aci/content';
3
+ import ContainerSection from '../components/sections/ContainerSection.astro';
4
+
5
+ interface Props {
6
+ block: KernelPageBlock;
7
+ direction?: 'ltr' | 'rtl';
8
+ }
9
+
10
+ const { block, direction = 'ltr' } = Astro.props;
11
+ ---
12
+
13
+ <div dir={direction}>
14
+ {block.component === 'container' ? <ContainerSection {...block.props} /> : null}
15
+ </div>
@@ -0,0 +1,24 @@
1
+ import { sectionStoryFixtures } from '../fixtures/sections';
2
+ import SectionStoryFrame from './SectionStoryFrame.astro';
3
+
4
+ const fixtureById = Object.fromEntries(
5
+ sectionStoryFixtures.map((fixture) => [fixture.id, fixture])
6
+ );
7
+
8
+ export default {
9
+ title: 'Sections/Home Hero',
10
+ component: SectionStoryFrame,
11
+ parameters: {
12
+ docs: {
13
+ description: {
14
+ component: 'Image-backed homepage hero with headline, body copy, and primary CTA.'
15
+ }
16
+ }
17
+ }
18
+ };
19
+
20
+ export const Default = {
21
+ args: {
22
+ block: fixtureById['home-hero'].block
23
+ }
24
+ };
@@ -0,0 +1,16 @@
1
+ ---
2
+ import type { KernelPageBlock } from '@gradial/aci/content';
3
+ import HomeHero from '../components/sections/HomeHero.astro';
4
+
5
+ interface Props {
6
+ block: KernelPageBlock;
7
+ direction?: 'ltr' | 'rtl';
8
+ }
9
+
10
+ const { block, direction = 'ltr' } = Astro.props;
11
+ const props = block.props as any;
12
+ ---
13
+
14
+ <div dir={direction}>
15
+ {block.component === 'home_hero' ? <HomeHero {...props} /> : null}
16
+ </div>
@@ -0,0 +1,31 @@
1
+ ---
2
+ import type { KernelPageBlock } from '@gradial/aci/content';
3
+ import CompositionStoryFrame from './CompositionStoryFrame.astro';
4
+
5
+ interface Props {
6
+ heading?: string;
7
+ description?: string;
8
+ block: KernelPageBlock;
9
+ direction?: 'ltr' | 'rtl';
10
+ }
11
+
12
+ const { heading, description, block, direction = 'ltr' } = Astro.props;
13
+ ---
14
+
15
+ <div>
16
+ {(heading || description) && (
17
+ <div class="theme-auto bg-surface-default px-8 pt-8 pb-4">
18
+ {heading && (
19
+ <h2 class="[font-family:var(--font-family-heading)] text-[length:var(--text-size-h3)] font-[var(--font-weight-semibold)] leading-heading text-fg">
20
+ {heading}
21
+ </h2>
22
+ )}
23
+ {description && (
24
+ <p class="mt-2 max-w-3xl text-[length:var(--text-size-body)] leading-body text-fg-muted">
25
+ {description}
26
+ </p>
27
+ )}
28
+ </div>
29
+ )}
30
+ <CompositionStoryFrame block={block} direction={direction} />
31
+ </div>
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "astro/tsconfigs/base",
3
+ "include": [
4
+ ".astro/types.d.ts",
5
+ "src/**/*"
6
+ ],
7
+ "exclude": [
8
+ "node_modules",
9
+ "dist"
10
+ ]
11
+ }
@@ -0,0 +1,37 @@
1
+ # ACI Site Agent Guide
2
+
3
+ This is an ACI (Agentic Content Infrastructure) frontend project. Agents
4
+ working in this repo should load skills before making changes.
5
+
6
+ ## Skills
7
+
8
+ | Skill | Load when |
9
+ |-------|-----------|
10
+ | `aci` | Onboarding, running builds, validating, troubleshooting |
11
+ | `authoring` | Creating or editing content, adding components, design tokens |
12
+ | `migration` | Reverse-engineering a live site or design into ACI |
13
+
14
+ Skills live in `.agents/skills/`. Each has a `SKILL.md` entry point and
15
+ `references/` for deeper topics.
16
+
17
+ ## Quick Reference
18
+
19
+ - Content lives in `.content/` as JSON.
20
+ - Contracts live in `src/cms/contracts/` (Zod schemas, no framework imports).
21
+ - Runtime components live in `src/components/` (framework code).
22
+ - Registry lives in `src/cms/registry.ts` (`createRegistry` with `[contract, component]` tuples).
23
+ - Compiled output goes to `.aci/compiled/` (generated, not checked in).
24
+ - Framework integration via `withAci()` in the framework config.
25
+ - Supported frameworks: Astro and Next.js (SvelteKit removed).
26
+
27
+ ## Commands
28
+
29
+ ```bash
30
+ npm install
31
+ npm run dev # Start dev server
32
+ npm run aci:validate # Validate content
33
+ npm run aci:compile # Compile contracts
34
+ npm run content:compile # Compile content
35
+ npm run build # Framework build
36
+ npm run aci:doctor # Health check
37
+ ```