@forumone/create-throughline 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/generator.d.ts +2 -0
  3. package/dist/generator.d.ts.map +1 -1
  4. package/dist/generator.js +21 -4
  5. package/dist/generator.js.map +1 -1
  6. package/dist/templates/base/apps/web/package.json.template +2 -1
  7. package/dist/templates/base/apps/web/src/app/api/inngest/route.ts.template +2 -2
  8. package/dist/templates/base/apps/web/src/payload.config.ts.template +7 -5
  9. package/dist/templates/base/apps/web/tsconfig.json +2 -1
  10. package/dist/templates/base/gitignore +15 -0
  11. package/dist/templates/base/package.json.template +4 -1
  12. package/dist/templates/base/pnpm-workspace.yaml +1 -0
  13. package/dist/templates/base/turbo.json +11 -0
  14. package/dist/templates/with-reference-ds/design-system/.storybook/main.ts +21 -0
  15. package/dist/templates/with-reference-ds/design-system/.storybook/preview.ts +19 -0
  16. package/dist/templates/with-reference-ds/design-system/README.md +33 -0
  17. package/dist/templates/with-reference-ds/design-system/gitignore +5 -0
  18. package/dist/templates/with-reference-ds/design-system/package.json.template +62 -0
  19. package/dist/templates/with-reference-ds/design-system/scripts/build-manifest.ts +89 -0
  20. package/dist/templates/with-reference-ds/design-system/scripts/build-styles.ts +28 -0
  21. package/dist/templates/with-reference-ds/design-system/scripts/build-tokens-css.ts +43 -0
  22. package/dist/templates/with-reference-ds/design-system/scripts/validate.ts +58 -0
  23. package/dist/templates/with-reference-ds/design-system/src/components/CTASection/CTASection.contract.ts +128 -0
  24. package/dist/templates/with-reference-ds/design-system/src/components/CTASection/CTASection.module.css +83 -0
  25. package/dist/templates/with-reference-ds/design-system/src/components/CTASection/CTASection.stories.tsx +39 -0
  26. package/dist/templates/with-reference-ds/design-system/src/components/CTASection/CTASection.test.tsx +27 -0
  27. package/dist/templates/with-reference-ds/design-system/src/components/CTASection/CTASection.tsx +41 -0
  28. package/dist/templates/with-reference-ds/design-system/src/components/CTASection/index.ts +2 -0
  29. package/dist/templates/with-reference-ds/design-system/src/components/Card/Card.contract.ts +122 -0
  30. package/dist/templates/with-reference-ds/design-system/src/components/Card/Card.module.css +64 -0
  31. package/dist/templates/with-reference-ds/design-system/src/components/Card/Card.stories.tsx +45 -0
  32. package/dist/templates/with-reference-ds/design-system/src/components/Card/Card.test.tsx +37 -0
  33. package/dist/templates/with-reference-ds/design-system/src/components/Card/Card.tsx +39 -0
  34. package/dist/templates/with-reference-ds/design-system/src/components/Card/index.ts +2 -0
  35. package/dist/templates/with-reference-ds/design-system/src/components/CardGrid/CardGrid.contract.ts +78 -0
  36. package/dist/templates/with-reference-ds/design-system/src/components/CardGrid/CardGrid.module.css +34 -0
  37. package/dist/templates/with-reference-ds/design-system/src/components/CardGrid/CardGrid.stories.tsx +36 -0
  38. package/dist/templates/with-reference-ds/design-system/src/components/CardGrid/CardGrid.test.tsx +25 -0
  39. package/dist/templates/with-reference-ds/design-system/src/components/CardGrid/CardGrid.tsx +19 -0
  40. package/dist/templates/with-reference-ds/design-system/src/components/CardGrid/index.ts +2 -0
  41. package/dist/templates/with-reference-ds/design-system/src/components/Divider/Divider.contract.ts +87 -0
  42. package/dist/templates/with-reference-ds/design-system/src/components/Divider/Divider.module.css +18 -0
  43. package/dist/templates/with-reference-ds/design-system/src/components/Divider/Divider.stories.tsx +35 -0
  44. package/dist/templates/with-reference-ds/design-system/src/components/Divider/Divider.test.tsx +20 -0
  45. package/dist/templates/with-reference-ds/design-system/src/components/Divider/Divider.tsx +17 -0
  46. package/dist/templates/with-reference-ds/design-system/src/components/Divider/index.ts +2 -0
  47. package/dist/templates/with-reference-ds/design-system/src/components/FAQ/FAQ.contract.ts +104 -0
  48. package/dist/templates/with-reference-ds/design-system/src/components/FAQ/FAQ.module.css +66 -0
  49. package/dist/templates/with-reference-ds/design-system/src/components/FAQ/FAQ.stories.tsx +61 -0
  50. package/dist/templates/with-reference-ds/design-system/src/components/FAQ/FAQ.test.tsx +30 -0
  51. package/dist/templates/with-reference-ds/design-system/src/components/FAQ/FAQ.tsx +41 -0
  52. package/dist/templates/with-reference-ds/design-system/src/components/FAQ/index.ts +2 -0
  53. package/dist/templates/with-reference-ds/design-system/src/components/Hero/Hero.contract.ts +182 -0
  54. package/dist/templates/with-reference-ds/design-system/src/components/Hero/Hero.module.css +124 -0
  55. package/dist/templates/with-reference-ds/design-system/src/components/Hero/Hero.stories.tsx +58 -0
  56. package/dist/templates/with-reference-ds/design-system/src/components/Hero/Hero.test.tsx +49 -0
  57. package/dist/templates/with-reference-ds/design-system/src/components/Hero/Hero.tsx +67 -0
  58. package/dist/templates/with-reference-ds/design-system/src/components/Hero/index.ts +2 -0
  59. package/dist/templates/with-reference-ds/design-system/src/components/MediaBlock/MediaBlock.contract.ts +94 -0
  60. package/dist/templates/with-reference-ds/design-system/src/components/MediaBlock/MediaBlock.module.css +49 -0
  61. package/dist/templates/with-reference-ds/design-system/src/components/MediaBlock/MediaBlock.stories.tsx +37 -0
  62. package/dist/templates/with-reference-ds/design-system/src/components/MediaBlock/MediaBlock.test.tsx +35 -0
  63. package/dist/templates/with-reference-ds/design-system/src/components/MediaBlock/MediaBlock.tsx +49 -0
  64. package/dist/templates/with-reference-ds/design-system/src/components/MediaBlock/index.ts +7 -0
  65. package/dist/templates/with-reference-ds/design-system/src/components/Prose/Prose.contract.ts +107 -0
  66. package/dist/templates/with-reference-ds/design-system/src/components/Prose/Prose.module.css +72 -0
  67. package/dist/templates/with-reference-ds/design-system/src/components/Prose/Prose.stories.tsx +39 -0
  68. package/dist/templates/with-reference-ds/design-system/src/components/Prose/Prose.test.tsx +26 -0
  69. package/dist/templates/with-reference-ds/design-system/src/components/Prose/Prose.tsx +15 -0
  70. package/dist/templates/with-reference-ds/design-system/src/components/Prose/index.ts +2 -0
  71. package/dist/templates/with-reference-ds/design-system/src/components/Quote/Quote.contract.ts +101 -0
  72. package/dist/templates/with-reference-ds/design-system/src/components/Quote/Quote.module.css +59 -0
  73. package/dist/templates/with-reference-ds/design-system/src/components/Quote/Quote.stories.tsx +44 -0
  74. package/dist/templates/with-reference-ds/design-system/src/components/Quote/Quote.test.tsx +37 -0
  75. package/dist/templates/with-reference-ds/design-system/src/components/Quote/Quote.tsx +40 -0
  76. package/dist/templates/with-reference-ds/design-system/src/components/Quote/index.ts +2 -0
  77. package/dist/templates/with-reference-ds/design-system/src/components/SectionIntro/SectionIntro.contract.ts +108 -0
  78. package/dist/templates/with-reference-ds/design-system/src/components/SectionIntro/SectionIntro.module.css +36 -0
  79. package/dist/templates/with-reference-ds/design-system/src/components/SectionIntro/SectionIntro.stories.tsx +33 -0
  80. package/dist/templates/with-reference-ds/design-system/src/components/SectionIntro/SectionIntro.test.tsx +28 -0
  81. package/dist/templates/with-reference-ds/design-system/src/components/SectionIntro/SectionIntro.tsx +28 -0
  82. package/dist/templates/with-reference-ds/design-system/src/components/SectionIntro/index.ts +2 -0
  83. package/dist/templates/with-reference-ds/design-system/src/components/Spacer/Spacer.contract.ts +76 -0
  84. package/dist/templates/with-reference-ds/design-system/src/components/Spacer/Spacer.module.css +23 -0
  85. package/dist/templates/with-reference-ds/design-system/src/components/Spacer/Spacer.stories.tsx +25 -0
  86. package/dist/templates/with-reference-ds/design-system/src/components/Spacer/Spacer.test.tsx +17 -0
  87. package/dist/templates/with-reference-ds/design-system/src/components/Spacer/Spacer.tsx +19 -0
  88. package/dist/templates/with-reference-ds/design-system/src/components/Spacer/index.ts +2 -0
  89. package/dist/templates/with-reference-ds/design-system/src/components/Stats/Stats.contract.ts +103 -0
  90. package/dist/templates/with-reference-ds/design-system/src/components/Stats/Stats.module.css +88 -0
  91. package/dist/templates/with-reference-ds/design-system/src/components/Stats/Stats.stories.tsx +44 -0
  92. package/dist/templates/with-reference-ds/design-system/src/components/Stats/Stats.test.tsx +44 -0
  93. package/dist/templates/with-reference-ds/design-system/src/components/Stats/Stats.tsx +39 -0
  94. package/dist/templates/with-reference-ds/design-system/src/components/Stats/index.ts +2 -0
  95. package/dist/templates/with-reference-ds/design-system/src/css-modules.d.ts +5 -0
  96. package/dist/templates/with-reference-ds/design-system/src/foundations/Colors.stories.tsx +46 -0
  97. package/dist/templates/with-reference-ds/design-system/src/foundations/Elevation.stories.tsx +37 -0
  98. package/dist/templates/with-reference-ds/design-system/src/foundations/LayoutContainers.stories.tsx +86 -0
  99. package/dist/templates/with-reference-ds/design-system/src/foundations/Radii.stories.tsx +38 -0
  100. package/dist/templates/with-reference-ds/design-system/src/foundations/Spacing.stories.tsx +33 -0
  101. package/dist/templates/with-reference-ds/design-system/src/foundations/Typography.stories.tsx +55 -0
  102. package/dist/templates/with-reference-ds/design-system/src/foundations/_helpers.tsx +82 -0
  103. package/dist/templates/with-reference-ds/design-system/src/index.ts +14 -0
  104. package/dist/templates/with-reference-ds/design-system/src/styles/base.css +55 -0
  105. package/dist/templates/with-reference-ds/design-system/src/styles/reset.css +48 -0
  106. package/dist/templates/with-reference-ds/design-system/src/styles/tokens.css +116 -0
  107. package/dist/templates/with-reference-ds/design-system/src/tokens/colors.ts +54 -0
  108. package/dist/templates/with-reference-ds/design-system/src/tokens/index.ts +32 -0
  109. package/dist/templates/with-reference-ds/design-system/src/tokens/layout.ts +26 -0
  110. package/dist/templates/with-reference-ds/design-system/src/tokens/radii.ts +11 -0
  111. package/dist/templates/with-reference-ds/design-system/src/tokens/spacing.ts +26 -0
  112. package/dist/templates/with-reference-ds/design-system/src/tokens/typography.ts +32 -0
  113. package/dist/templates/with-reference-ds/design-system/tsconfig.json +24 -0
  114. package/dist/templates/with-reference-ds/design-system/vitest.config.ts +15 -0
  115. package/dist/templates/with-reference-ds/design-system/vitest.setup.ts +7 -0
  116. package/dist/templates/without-reference-ds/design-system/.storybook/main.ts +21 -0
  117. package/dist/templates/without-reference-ds/design-system/.storybook/preview.ts +16 -0
  118. package/dist/templates/without-reference-ds/design-system/README.md +20 -0
  119. package/dist/templates/without-reference-ds/design-system/gitignore +5 -0
  120. package/dist/templates/without-reference-ds/design-system/package.json.template +33 -0
  121. package/dist/templates/without-reference-ds/design-system/src/foundations/Welcome.stories.tsx +24 -0
  122. package/dist/templates/without-reference-ds/design-system/src/index.ts +9 -0
  123. package/dist/templates/without-reference-ds/design-system/tsconfig.json +11 -0
  124. package/package.json +3 -1
  125. package/dist/templates/with-reference-ds/packages/design-system/package.json.template +0 -18
  126. package/dist/templates/with-reference-ds/packages/design-system/src/index.ts +0 -6
  127. package/dist/templates/with-reference-ds/packages/design-system/src/manifest.ts +0 -6
  128. package/dist/templates/with-reference-ds/packages/design-system/tsconfig.json +0 -9
  129. package/dist/templates/without-reference-ds/packages/design-system/README.md +0 -19
  130. package/dist/templates/without-reference-ds/packages/design-system/package.json.template +0 -14
  131. package/dist/templates/without-reference-ds/packages/design-system/src/index.ts +0 -8
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @forumone/create-throughline
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - e994176: Scaffold a real Storybook authoring environment for the design system.
8
+
9
+ When you scaffold with the reference design system, the generator now creates a top-level `design-system/` workspace (a sibling of `apps/`, matching the Forum One `forumone.com-2026` layout) that vendors the reference DS's **editable source** — 12 components with `.stories.tsx`, `.contract.ts`, tokens, and a Storybook instance — instead of re-exporting the compiled npm package. New projects can run `pnpm storybook` immediately, author components, and `pnpm validate` to cross-check every contract `storyId` against the built Storybook.
10
+
11
+ Also:
12
+ - The web app now imports the workspace design system's built manifest (`<scope>/design-system/manifest`) instead of the npm reference-ds manifest, and the root `pnpm dev` builds the design system first so the manifest exists.
13
+ - Root scripts `storybook`, `build-storybook`, and `validate`; turbo tasks to match; `design-system` added to the workspace globs.
14
+ - Fix: template `.gitignore` files are now authored as `gitignore` and restored on output, so they survive npm publish (previously the generated project shipped without a root `.gitignore`).
15
+ - Fix: the generated web app now typechecks clean. Adds the `@payload-config` tsconfig path; corrects drifted plugin APIs in `route.ts` (`publishingApiKey`, `createPayloadReachableCheck()`) and `payload.config.ts` (`auditQueryPlugin({})`, `buildActionUrl` async `{ approvalId, action, approverId }`, manifest typed as `Manifest`).
16
+
3
17
  ## 0.2.1
4
18
 
5
19
  ### Patch Changes
@@ -37,9 +37,11 @@ interface RenderArgs {
37
37
  */
38
38
  declare function renderDirectory({ source, target, data }: RenderArgs): Promise<void>;
39
39
  declare function isBinary(filename: string): boolean;
40
+ declare function applyDotfileRename(name: string): string;
40
41
  export declare const __testing: {
41
42
  renderDirectory: typeof renderDirectory;
42
43
  isBinary: typeof isBinary;
44
+ applyDotfileRename: typeof applyDotfileRename;
43
45
  rename: typeof rename;
44
46
  rm: typeof rm;
45
47
  stat: typeof stat;
@@ -1 +1 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AACA,OAAO,EAAgC,MAAM,EAAE,EAAE,EAAE,IAAI,EAAa,MAAM,kBAAkB,CAAA;AAI5F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAK3C,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,qEAAqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACpC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B7F;AAED,UAAU,UAAU;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B;AAED;;;;;;;;;GASG;AACH,iBAAe,eAAe,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAmClF;AAiBD,iBAAS,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI3C;AA6BD,eAAO,MAAM,SAAS;;;;;;CAAkD,CAAA"}
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AACA,OAAO,EAAgC,MAAM,EAAE,EAAE,EAAE,IAAI,EAAa,MAAM,kBAAkB,CAAA;AAI5F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAK3C,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,qEAAqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACpC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC7F;AAED,UAAU,UAAU;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B;AAED;;;;;;;;;GASG;AACH,iBAAe,eAAe,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAmClF;AAiBD,iBAAS,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI3C;AAUD,iBAAS,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AA6BD,eAAO,MAAM,SAAS;;;;;;;CAAsE,CAAA"}
package/dist/generator.js CHANGED
@@ -19,19 +19,26 @@ const DEFAULT_TEMPLATES_DIR = resolve(__dirname, 'templates');
19
19
  export async function generate(answers, options = {}) {
20
20
  const templatesDir = options.templatesDir ?? DEFAULT_TEMPLATES_DIR;
21
21
  const onProgress = options.onProgress ?? (() => { });
22
+ // Precompute the design-system package name. The renderer has no nesting, so
23
+ // we can't put `{{#if packageScope}}...{{/if}}` inside another `{{#if}}`
24
+ // block (e.g. inside `{{#if useReferenceDs}}` in payload.config).
25
+ const designSystemName = answers.packageScope
26
+ ? `@${answers.packageScope}/design-system`
27
+ : `${answers.projectName}-design-system`;
28
+ const data = { ...answers, designSystemName };
22
29
  onProgress('Creating project structure');
23
30
  await mkdir(answers.targetDir, { recursive: true });
24
31
  await renderDirectory({
25
32
  source: join(templatesDir, 'base'),
26
33
  target: answers.targetDir,
27
- data: answers,
34
+ data,
28
35
  });
29
36
  onProgress(answers.useReferenceDs ? 'Wiring reference design system' : 'Preparing design system placeholder');
30
37
  const overlay = answers.useReferenceDs ? 'with-reference-ds' : 'without-reference-ds';
31
38
  await renderDirectory({
32
39
  source: join(templatesDir, overlay),
33
40
  target: answers.targetDir,
34
- data: answers,
41
+ data,
35
42
  });
36
43
  if (answers.initializeGit && !options.skipSideEffects) {
37
44
  onProgress('Initializing git');
@@ -64,7 +71,7 @@ async function renderDirectory({ source, target, data }) {
64
71
  }
65
72
  await mkdir(target, { recursive: true });
66
73
  for (const entry of entries) {
67
- const renderedName = renderTemplate(entry.name, data);
74
+ const renderedName = applyDotfileRename(renderTemplate(entry.name, data));
68
75
  const sourcePath = join(source, entry.name);
69
76
  const targetPath = join(target, renderedName);
70
77
  if (entry.isDirectory()) {
@@ -105,6 +112,16 @@ function isBinary(filename) {
105
112
  return false;
106
113
  return BINARY_EXTENSIONS.has(filename.slice(dot).toLowerCase());
107
114
  }
115
+ /**
116
+ * npm strips files literally named `.gitignore` from a published tarball, so
117
+ * we author them as `gitignore` in templates and restore the dot on output.
118
+ */
119
+ const DOTFILE_RENAMES = {
120
+ gitignore: '.gitignore',
121
+ };
122
+ function applyDotfileRename(name) {
123
+ return DOTFILE_RENAMES[name] ?? name;
124
+ }
108
125
  async function initGit(dir) {
109
126
  await runCommand('git', ['init'], dir);
110
127
  await runCommand('git', ['add', '.'], dir);
@@ -127,5 +144,5 @@ function runCommand(cmd, args, cwd) {
127
144
  }
128
145
  // Re-exports kept around so tests in adjacent packages can stub these without
129
146
  // reaching into the implementation. Not part of the public API surface.
130
- export const __testing = { renderDirectory, isBinary, rename, rm, stat };
147
+ export const __testing = { renderDirectory, isBinary, applyDotfileRename, rename, rm, stat };
131
148
  //# sourceMappingURL=generator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
@@ -21,7 +21,8 @@
21
21
  "@forumone/throughline-integrations": "^0.2.0",
22
22
  "@forumone/throughline-publishing": "^0.2.0",
23
23
  "@forumone/throughline-workflows": "^0.2.0",
24
- {{#if useReferenceDs}}"@forumone/throughline-reference-ds": "^0.2.0",
24
+ {{#if useReferenceDs}}"@forumone/throughline-design-contract": "^0.2.0",
25
+ "{{designSystemName}}": "workspace:*",
25
26
  {{/if}}"@payloadcms/db-postgres": "^3.83.0",
26
27
  "@payloadcms/next": "^3.83.0",
27
28
  "@payloadcms/plugin-form-builder": "3.83.0",
@@ -40,14 +40,14 @@ export const { GET, POST, PUT } = serve({
40
40
  payload,
41
41
  collections: [{ slug: 'pages' }],
42
42
  publishingServerUrl: process.env.NEXT_PUBLIC_SERVER_URL!,
43
- systemApiKey: process.env.PUBLISHING_SYSTEM_API_KEY!,
43
+ publishingApiKey: process.env.PUBLISHING_SYSTEM_API_KEY!,
44
44
  }),
45
45
  createExpireStaleApprovalsFunction({ inngest, payload }),
46
46
  createAuditEventEchoFunction({ inngest }),
47
47
  createHealthcheckFunction({
48
48
  inngest,
49
49
  payload,
50
- checks: [createPayloadReachableCheck({ payload })],
50
+ checks: [createPayloadReachableCheck()],
51
51
  }),
52
52
  ...emailFunctions,
53
53
  ...formsFunctions,
@@ -16,7 +16,8 @@ import { auditQueryPlugin } from '@forumone/throughline-audit'
16
16
  import { integrationsPlugin } from '@forumone/throughline-integrations'
17
17
  import { emailPlugin } from '@forumone/throughline-email'
18
18
  import { formsPlugin } from '@forumone/throughline-forms'
19
- {{#if useReferenceDs}}import referenceManifest from '@forumone/throughline-reference-ds/manifest' with { type: 'json' }
19
+ {{#if useReferenceDs}}import type { Manifest } from '@forumone/throughline-design-contract'
20
+ import designSystemManifest from '{{designSystemName}}/manifest' with { type: 'json' }
20
21
  {{/if}}
21
22
 
22
23
  const __filename = fileURLToPath(import.meta.url)
@@ -101,7 +102,7 @@ export default buildConfig({
101
102
  auditPlugin({ inngest }),
102
103
 
103
104
  componentsPlugin({
104
- {{#if useReferenceDs}}manifest: { type: 'object', manifest: referenceManifest },
105
+ {{#if useReferenceDs}}manifest: { type: 'object', manifest: designSystemManifest as unknown as Manifest },
105
106
  {{else}}// TODO: point at your design system manifest
106
107
  manifest: { type: 'url', url: 'https://your-design-system.example.com/manifest.json' },
107
108
  {{/if}}matching: { strategy: 'tfidf' },
@@ -132,15 +133,16 @@ export default buildConfig({
132
133
  },
133
134
  }),
134
135
 
135
- auditQueryPlugin(),
136
+ auditQueryPlugin({}),
136
137
 
137
138
  emailPlugin({
138
139
  inngest,
139
140
  // TODO: replace with your real user lookups
140
141
  resolveApprover: async (_userId) => null,
141
142
  resolveRequester: async (_userId) => null,
142
- buildActionUrl: ({ token, action }) =>
143
- `${process.env.NEXT_PUBLIC_SERVER_URL}/api/approvals/decision?token=${token}&action=${action}`,
143
+ // TODO: sign these URLs (HMAC) so an approval decision can't be forged.
144
+ buildActionUrl: async ({ approvalId, action, approverId }) =>
145
+ `${process.env.NEXT_PUBLIC_SERVER_URL}/api/approvals/decision?approval=${approvalId}&action=${action}&approver=${approverId}`,
144
146
  tokens: { brandName: '{{projectName}}' },
145
147
  }),
146
148
 
@@ -11,7 +11,8 @@
11
11
  "isolatedModules": true,
12
12
  "plugins": [{ "name": "next" }],
13
13
  "paths": {
14
- "@/*": ["./src/*"]
14
+ "@/*": ["./src/*"],
15
+ "@payload-config": ["./src/payload.config.ts"]
15
16
  }
16
17
  },
17
18
  "include": [
@@ -0,0 +1,15 @@
1
+ node_modules/
2
+ .next/
3
+ .turbo/
4
+ dist/
5
+ *.tsbuildinfo
6
+
7
+ .env
8
+ .env.local
9
+ .env.*.local
10
+
11
+ .DS_Store
12
+ .idea/
13
+ .vscode/
14
+
15
+ coverage/
@@ -4,7 +4,10 @@
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "turbo run build",
7
- "dev": "turbo run dev",
7
+ "dev": "{{#if useReferenceDs}}pnpm --filter \"./design-system\" build && {{/if}}turbo run dev",
8
+ "storybook": "turbo run storybook",
9
+ "build-storybook": "turbo run build-storybook",
10
+ "validate": "turbo run validate",
8
11
  "lint": "turbo run lint",
9
12
  "typecheck": "turbo run typecheck",
10
13
  "test": "turbo run test",
@@ -1,3 +1,4 @@
1
1
  packages:
2
2
  - apps/*
3
+ - design-system
3
4
  - packages/*
@@ -7,6 +7,17 @@
7
7
  "outputs": ["dist/**", ".next/**", "!.next/cache/**"],
8
8
  "env": ["NODE_ENV"]
9
9
  },
10
+ "build-storybook": {
11
+ "dependsOn": ["^build"],
12
+ "outputs": ["storybook-static/**"]
13
+ },
14
+ "storybook": {
15
+ "cache": false,
16
+ "persistent": true
17
+ },
18
+ "validate": {
19
+ "dependsOn": ["build"]
20
+ },
10
21
  "dev": {
11
22
  "cache": false,
12
23
  "persistent": true
@@ -0,0 +1,21 @@
1
+ import type { StorybookConfig } from '@storybook/react-vite'
2
+
3
+ const config: StorybookConfig = {
4
+ stories: [
5
+ '../src/foundations/**/*.stories.@(ts|tsx)',
6
+ '../src/components/**/*.stories.@(ts|tsx)',
7
+ ],
8
+ addons: ['@storybook/addon-a11y'],
9
+ framework: {
10
+ name: '@storybook/react-vite',
11
+ options: {},
12
+ },
13
+ typescript: {
14
+ reactDocgen: 'react-docgen-typescript',
15
+ },
16
+ docs: {
17
+ autodocs: true,
18
+ },
19
+ }
20
+
21
+ export default config
@@ -0,0 +1,19 @@
1
+ import type { Preview } from '@storybook/react-vite'
2
+ import '../src/styles/reset.css'
3
+ import '../src/styles/tokens.css'
4
+ import '../src/styles/base.css'
5
+
6
+ const preview: Preview = {
7
+ parameters: {
8
+ controls: {
9
+ matchers: { color: /(background|color)$/i, date: /Date$/i },
10
+ },
11
+ a11y: {
12
+ config: {},
13
+ options: {},
14
+ manual: false,
15
+ },
16
+ },
17
+ }
18
+
19
+ export default preview
@@ -0,0 +1,33 @@
1
+ # Design system
2
+
3
+ Your project's design system and its Storybook authoring environment. It started as a vendored copy of the Throughline reference DS — a working, brand-neutral set of 12 components with contracts — so you can edit it directly and make it your own.
4
+
5
+ ```
6
+ src/
7
+ tokens/ Design tokens (colors, typography, spacing, radii, layout) → CSS custom properties
8
+ styles/ reset.css, generated tokens.css, base.css
9
+ foundations/ Storybook "Foundations" pages (Colors, Typography, Spacing, Radii, Elevation, Layout & Containers)
10
+ components/ One folder per component: .tsx, .module.css, .stories.tsx, .test.tsx, .contract.ts
11
+ scripts/ build-tokens-css, build-styles, build-manifest, validate
12
+ .storybook/ Storybook (react-vite) config
13
+ ```
14
+
15
+ ## Commands
16
+
17
+ ```bash
18
+ pnpm --filter "./design-system" storybook # author components at http://localhost:6006
19
+ pnpm --filter "./design-system" build # tokens → tsc → styles → dist/manifest.json
20
+ pnpm --filter "./design-system" build-storybook # static Storybook (produces storybook-static/index.json)
21
+ pnpm --filter "./design-system" validate # lint contracts + cross-check every storyId against the built Storybook
22
+ pnpm --filter "./design-system" test # component tests (vitest + testing-library)
23
+ ```
24
+
25
+ The web app imports `./manifest` (the built `dist/manifest.json`) and feeds it to the Components MCP server. The root `pnpm dev` builds the design system first so the manifest exists.
26
+
27
+ ## Branding
28
+
29
+ 1. Edit `src/tokens/*` — components read tokens as CSS variables, so re-theming doesn't touch component code.
30
+ 2. Edit or add components under `src/components/`. Keep each component's `.contract.ts` and `.stories.tsx` in sync; `storyId` must point at a real story (the `validate` script enforces this).
31
+ 3. Update the **Foundations** pages in `src/foundations/` as your tokens change.
32
+
33
+ See the Throughline docs: `concepts/design-system-contracts.md` and `guides/authoring-component-contracts.md`.
@@ -0,0 +1,5 @@
1
+ dist
2
+ storybook-static
3
+ node_modules
4
+ *.tsbuildinfo
5
+ .turbo
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "{{designSystemName}}",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "./manifest": "./dist/manifest.json",
14
+ "./styles.css": "./dist/styles/index.css",
15
+ "./styles/tokens.css": "./dist/styles/tokens.css",
16
+ "./styles/reset.css": "./dist/styles/reset.css",
17
+ "./styles/base.css": "./dist/styles/base.css",
18
+ "./tokens": {
19
+ "types": "./dist/tokens/index.d.ts",
20
+ "default": "./dist/tokens/index.js"
21
+ }
22
+ },
23
+ "scripts": {
24
+ "build": "pnpm build:tokens-css && tsc -b && pnpm build:styles && pnpm build:manifest",
25
+ "build:tokens-css": "tsx scripts/build-tokens-css.ts",
26
+ "build:styles": "tsx scripts/build-styles.ts",
27
+ "build:manifest": "tsx scripts/build-manifest.ts",
28
+ "build-storybook": "storybook build",
29
+ "storybook": "storybook dev -p 6006",
30
+ "dev": "tsc -b -w",
31
+ "typecheck": "tsc --noEmit",
32
+ "test": "vitest run",
33
+ "validate": "tsx scripts/validate.ts",
34
+ "clean": "rm -rf dist .turbo storybook-static *.tsbuildinfo"
35
+ },
36
+ "dependencies": {
37
+ "@forumone/throughline-design-contract": "^0.2.0",
38
+ "clsx": "^2.1.1"
39
+ },
40
+ "peerDependencies": {
41
+ "react": "^18.0.0 || ^19.0.0",
42
+ "react-dom": "^18.0.0 || ^19.0.0"
43
+ },
44
+ "devDependencies": {
45
+ "@storybook/addon-a11y": "^10.3.5",
46
+ "@storybook/react-vite": "^10.3.5",
47
+ "@testing-library/jest-dom": "^6.9.1",
48
+ "@testing-library/react": "^16.3.2",
49
+ "@types/node": "^20.17.0",
50
+ "@types/react": "^19.2.0",
51
+ "@types/react-dom": "^19.2.0",
52
+ "@vitejs/plugin-react": "^6.0.1",
53
+ "jsdom": "^29.0.2",
54
+ "react": "^19.2.0",
55
+ "react-dom": "^19.2.0",
56
+ "storybook": "^10.3.5",
57
+ "tsx": "^4.21.0",
58
+ "typescript": "^5.6.0",
59
+ "vite": "^8.0.9",
60
+ "vitest": "^2.1.0"
61
+ }
62
+ }
@@ -0,0 +1,89 @@
1
+ import { readFile, readdir, stat, writeFile, mkdir } from 'node:fs/promises'
2
+ import { dirname, join, resolve } from 'node:path'
3
+ import { pathToFileURL, fileURLToPath } from 'node:url'
4
+ import {
5
+ CONTRACT_VERSION,
6
+ ManifestSchema,
7
+ type ComponentContract,
8
+ } from '@forumone/throughline-design-contract'
9
+ import { getTokenList } from '../src/tokens/index.ts'
10
+
11
+ const __dirname = dirname(fileURLToPath(import.meta.url))
12
+ const packageRoot = resolve(__dirname, '..')
13
+ const componentsDir = resolve(packageRoot, 'src/components')
14
+ const outputDir = resolve(packageRoot, 'dist')
15
+ const outputFile = resolve(outputDir, 'manifest.json')
16
+
17
+ async function readPackageVersion(): Promise<string> {
18
+ const raw = await readFile(resolve(packageRoot, 'package.json'), 'utf8')
19
+ const parsed = JSON.parse(raw) as { version?: string }
20
+ return parsed.version ?? '0.0.0'
21
+ }
22
+
23
+ async function collectContracts(): Promise<Record<string, ComponentContract>> {
24
+ const components: Record<string, ComponentContract> = {}
25
+
26
+ let entries: string[]
27
+ try {
28
+ entries = await readdir(componentsDir)
29
+ } catch {
30
+ return components
31
+ }
32
+
33
+ for (const name of entries) {
34
+ const dir = resolve(componentsDir, name)
35
+ const dirStat = await stat(dir).catch(() => null)
36
+ if (!dirStat?.isDirectory()) continue
37
+
38
+ const contractPath = join(dir, `${name}.contract.ts`)
39
+ const contractStat = await stat(contractPath).catch(() => null)
40
+ if (!contractStat?.isFile()) continue
41
+
42
+ const module = (await import(pathToFileURL(contractPath).href)) as {
43
+ contract?: ComponentContract
44
+ }
45
+ if (!module.contract) {
46
+ throw new Error(`${name}.contract.ts does not export "contract"`)
47
+ }
48
+ components[name] = module.contract
49
+ }
50
+
51
+ return components
52
+ }
53
+
54
+ async function main() {
55
+ const components = await collectContracts()
56
+
57
+ const manifest = {
58
+ contractVersion: CONTRACT_VERSION,
59
+ designSystem: {
60
+ name: '@forumone/throughline-reference-ds',
61
+ version: await readPackageVersion(),
62
+ description:
63
+ 'A brand-neutral reference design system demonstrating contract compliance for Throughline.',
64
+ },
65
+ tokens: getTokenList(),
66
+ components,
67
+ build: {
68
+ timestamp: new Date().toISOString(),
69
+ source: 'scripts/build-manifest.ts',
70
+ },
71
+ }
72
+
73
+ const result = ManifestSchema.safeParse(manifest)
74
+ if (!result.success) {
75
+ console.error('Generated manifest failed validation:')
76
+ for (const issue of result.error.issues) {
77
+ console.error(` - ${issue.path.join('.') || '(root)'}: ${issue.message}`)
78
+ }
79
+ process.exit(1)
80
+ }
81
+
82
+ await mkdir(outputDir, { recursive: true })
83
+ await writeFile(outputFile, JSON.stringify(result.data, null, 2), 'utf8')
84
+
85
+ const componentCount = Object.keys(components).length
86
+ console.log(`Wrote ${outputFile} (${componentCount} components)`)
87
+ }
88
+
89
+ await main()
@@ -0,0 +1,28 @@
1
+ import { copyFile, mkdir, readdir, readFile, writeFile } from 'node:fs/promises'
2
+ import { basename, dirname, resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url))
6
+ const stylesSrc = resolve(__dirname, '../src/styles')
7
+ const stylesDist = resolve(__dirname, '../dist/styles')
8
+
9
+ await mkdir(stylesDist, { recursive: true })
10
+
11
+ const entries = await readdir(stylesSrc)
12
+ const cssFiles = entries.filter((f) => f.endsWith('.css'))
13
+
14
+ for (const file of cssFiles) {
15
+ await copyFile(resolve(stylesSrc, file), resolve(stylesDist, file))
16
+ }
17
+
18
+ // Also emit a combined bundle so consumers can import `@forumone/throughline-reference-ds/styles.css`.
19
+ const bundleParts: string[] = []
20
+ for (const file of ['reset.css', 'tokens.css', 'base.css']) {
21
+ if (cssFiles.includes(file)) {
22
+ const content = await readFile(resolve(stylesSrc, file), 'utf8')
23
+ bundleParts.push(`/* ${basename(file)} */\n${content.trim()}\n`)
24
+ }
25
+ }
26
+ await writeFile(resolve(stylesDist, 'index.css'), bundleParts.join('\n'), 'utf8')
27
+
28
+ console.log(`Copied ${cssFiles.length} CSS files to dist/styles`)
@@ -0,0 +1,43 @@
1
+ import { mkdir, writeFile } from 'node:fs/promises'
2
+ import { dirname, resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { colors, darkOverrides } from '../src/tokens/colors.ts'
5
+ import { layout } from '../src/tokens/layout.ts'
6
+ import { radii } from '../src/tokens/radii.ts'
7
+ import { spacing } from '../src/tokens/spacing.ts'
8
+ import { typography } from '../src/tokens/typography.ts'
9
+
10
+ const __dirname = dirname(fileURLToPath(import.meta.url))
11
+ const outputPath = resolve(__dirname, '../src/styles/tokens.css')
12
+
13
+ /** Turns `color.brand.primaryHover` into `--color-brand-primary-hover`. */
14
+ function tokenToVariable(name: string): string {
15
+ const kebab = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()
16
+ return `--${kebab.replace(/\./g, '-')}`
17
+ }
18
+
19
+ function section(title: string, entries: Array<readonly [string, string]>): string {
20
+ const rules = entries.map(([name, value]) => ` ${tokenToVariable(name)}: ${value};`).join('\n')
21
+ return ` /* ${title} */\n${rules}`
22
+ }
23
+
24
+ const light = [
25
+ section('Colors', Object.entries(colors)),
26
+ section('Typography', Object.entries(typography)),
27
+ section('Spacing', Object.entries(spacing)),
28
+ section('Radii', Object.entries(radii)),
29
+ section('Layout & Containers', Object.entries(layout)),
30
+ ].join('\n\n')
31
+
32
+ const dark = Object.entries(darkOverrides)
33
+ .map(([name, value]) => ` ${tokenToVariable(name)}: ${value};`)
34
+ .join('\n')
35
+
36
+ const banner = '/* Auto-generated by scripts/build-tokens-css.ts. Do not edit by hand. */'
37
+
38
+ const output = `${banner}\n\n:root {\n${light}\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n${dark}\n }\n}\n`
39
+
40
+ await mkdir(dirname(outputPath), { recursive: true })
41
+ await writeFile(outputPath, output, 'utf8')
42
+
43
+ console.log(`Wrote ${outputPath}`)
@@ -0,0 +1,58 @@
1
+ import { readFile, stat } from 'node:fs/promises'
2
+ import { dirname, resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { loadManifest } from '@forumone/throughline-design-contract'
5
+ import { formatLintIssues, lintManifest } from '@forumone/throughline-design-contract/lint'
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url))
8
+ const packageRoot = resolve(__dirname, '..')
9
+ const manifestPath = resolve(packageRoot, 'dist/manifest.json')
10
+ const storybookIndexPath = resolve(packageRoot, 'storybook-static/index.json')
11
+
12
+ async function readJson<T>(path: string): Promise<T> {
13
+ const raw = await readFile(path, 'utf8')
14
+ return JSON.parse(raw) as T
15
+ }
16
+
17
+ async function collectStoryIds(): Promise<Set<string> | undefined> {
18
+ const exists = await stat(storybookIndexPath).catch(() => null)
19
+ if (!exists) {
20
+ console.warn(
21
+ `No storybook-static/index.json found; skipping storyId lint. Run \`pnpm build-storybook\` first to enable it.`,
22
+ )
23
+ return undefined
24
+ }
25
+ const index = await readJson<{ entries: Record<string, { id: string; type: string }> }>(
26
+ storybookIndexPath,
27
+ )
28
+ const ids = new Set<string>()
29
+ for (const entry of Object.values(index.entries)) {
30
+ if (entry.type === 'story') ids.add(entry.id)
31
+ }
32
+ return ids
33
+ }
34
+
35
+ async function main() {
36
+ const raw = await readJson<unknown>(manifestPath)
37
+ const loaded = loadManifest(raw)
38
+
39
+ const availableStoryIds = await collectStoryIds()
40
+ const lintOptions = availableStoryIds ? { availableStoryIds } : {}
41
+
42
+ const issues = lintManifest(loaded.raw, lintOptions)
43
+ const errors = issues.filter((i) => i.severity === 'error')
44
+ const warnings = issues.filter((i) => i.severity === 'warning')
45
+
46
+ if (errors.length > 0) {
47
+ console.error(formatLintIssues(errors))
48
+ process.exit(1)
49
+ }
50
+
51
+ if (warnings.length > 0) {
52
+ console.warn(formatLintIssues(warnings))
53
+ } else {
54
+ console.log(`Manifest is clean (${loaded.listComponents().length} components).`)
55
+ }
56
+ }
57
+
58
+ await main()