@forgespace/branding-mcp 0.4.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 (244) hide show
  1. package/.env.example +3 -0
  2. package/.github/PULL_REQUEST_TEMPLATE.md +22 -0
  3. package/.github/workflows/ci.yml +73 -0
  4. package/.github/workflows/release-automation.yml +56 -0
  5. package/.github/workflows/security-scan.yml +37 -0
  6. package/.gitleaks.toml +14 -0
  7. package/.prettierrc.json +10 -0
  8. package/CHANGELOG.md +66 -0
  9. package/CONTRIBUTING.md +203 -0
  10. package/LICENSE +21 -0
  11. package/README.md +105 -0
  12. package/data/README.md +13 -0
  13. package/dist/index.d.ts +3 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +49 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/lib/branding-core/ai/brand-interpreter.d.ts +5 -0
  18. package/dist/lib/branding-core/ai/brand-interpreter.d.ts.map +1 -0
  19. package/dist/lib/branding-core/ai/brand-interpreter.js +16 -0
  20. package/dist/lib/branding-core/ai/brand-interpreter.js.map +1 -0
  21. package/dist/lib/branding-core/ai/claude-interpreter.d.ts +5 -0
  22. package/dist/lib/branding-core/ai/claude-interpreter.d.ts.map +1 -0
  23. package/dist/lib/branding-core/ai/claude-interpreter.js +55 -0
  24. package/dist/lib/branding-core/ai/claude-interpreter.js.map +1 -0
  25. package/dist/lib/branding-core/ai/intent-applier.d.ts +4 -0
  26. package/dist/lib/branding-core/ai/intent-applier.d.ts.map +1 -0
  27. package/dist/lib/branding-core/ai/intent-applier.js +29 -0
  28. package/dist/lib/branding-core/ai/intent-applier.js.map +1 -0
  29. package/dist/lib/branding-core/ai/keyword-interpreter.d.ts +4 -0
  30. package/dist/lib/branding-core/ai/keyword-interpreter.d.ts.map +1 -0
  31. package/dist/lib/branding-core/ai/keyword-interpreter.js +85 -0
  32. package/dist/lib/branding-core/ai/keyword-interpreter.js.map +1 -0
  33. package/dist/lib/branding-core/ai/prompts.d.ts +4 -0
  34. package/dist/lib/branding-core/ai/prompts.d.ts.map +1 -0
  35. package/dist/lib/branding-core/ai/prompts.js +79 -0
  36. package/dist/lib/branding-core/ai/prompts.js.map +1 -0
  37. package/dist/lib/branding-core/ai/types.d.ts +27 -0
  38. package/dist/lib/branding-core/ai/types.d.ts.map +1 -0
  39. package/dist/lib/branding-core/ai/types.js +2 -0
  40. package/dist/lib/branding-core/ai/types.js.map +1 -0
  41. package/dist/lib/branding-core/documents/html-generator.d.ts +3 -0
  42. package/dist/lib/branding-core/documents/html-generator.d.ts.map +1 -0
  43. package/dist/lib/branding-core/documents/html-generator.js +31 -0
  44. package/dist/lib/branding-core/documents/html-generator.js.map +1 -0
  45. package/dist/lib/branding-core/documents/pdf-generator.d.ts +3 -0
  46. package/dist/lib/branding-core/documents/pdf-generator.d.ts.map +1 -0
  47. package/dist/lib/branding-core/documents/pdf-generator.js +20 -0
  48. package/dist/lib/branding-core/documents/pdf-generator.js.map +1 -0
  49. package/dist/lib/branding-core/exporters/css-variables.d.ts +3 -0
  50. package/dist/lib/branding-core/exporters/css-variables.d.ts.map +1 -0
  51. package/dist/lib/branding-core/exporters/css-variables.js +62 -0
  52. package/dist/lib/branding-core/exporters/css-variables.js.map +1 -0
  53. package/dist/lib/branding-core/exporters/design-tokens.d.ts +3 -0
  54. package/dist/lib/branding-core/exporters/design-tokens.d.ts.map +1 -0
  55. package/dist/lib/branding-core/exporters/design-tokens.js +75 -0
  56. package/dist/lib/branding-core/exporters/design-tokens.js.map +1 -0
  57. package/dist/lib/branding-core/exporters/figma-tokens.d.ts +9 -0
  58. package/dist/lib/branding-core/exporters/figma-tokens.d.ts.map +1 -0
  59. package/dist/lib/branding-core/exporters/figma-tokens.js +69 -0
  60. package/dist/lib/branding-core/exporters/figma-tokens.js.map +1 -0
  61. package/dist/lib/branding-core/exporters/react-theme.d.ts +3 -0
  62. package/dist/lib/branding-core/exporters/react-theme.d.ts.map +1 -0
  63. package/dist/lib/branding-core/exporters/react-theme.js +61 -0
  64. package/dist/lib/branding-core/exporters/react-theme.js.map +1 -0
  65. package/dist/lib/branding-core/exporters/sass-variables.d.ts +3 -0
  66. package/dist/lib/branding-core/exporters/sass-variables.d.ts.map +1 -0
  67. package/dist/lib/branding-core/exporters/sass-variables.js +65 -0
  68. package/dist/lib/branding-core/exporters/sass-variables.js.map +1 -0
  69. package/dist/lib/branding-core/exporters/tailwind-preset.d.ts +3 -0
  70. package/dist/lib/branding-core/exporters/tailwind-preset.d.ts.map +1 -0
  71. package/dist/lib/branding-core/exporters/tailwind-preset.js +55 -0
  72. package/dist/lib/branding-core/exporters/tailwind-preset.js.map +1 -0
  73. package/dist/lib/branding-core/generators/border-system.d.ts +3 -0
  74. package/dist/lib/branding-core/generators/border-system.d.ts.map +1 -0
  75. package/dist/lib/branding-core/generators/border-system.js +37 -0
  76. package/dist/lib/branding-core/generators/border-system.js.map +1 -0
  77. package/dist/lib/branding-core/generators/color-palette.d.ts +7 -0
  78. package/dist/lib/branding-core/generators/color-palette.d.ts.map +1 -0
  79. package/dist/lib/branding-core/generators/color-palette.js +117 -0
  80. package/dist/lib/branding-core/generators/color-palette.js.map +1 -0
  81. package/dist/lib/branding-core/generators/favicon-generator.d.ts +3 -0
  82. package/dist/lib/branding-core/generators/favicon-generator.d.ts.map +1 -0
  83. package/dist/lib/branding-core/generators/favicon-generator.js +23 -0
  84. package/dist/lib/branding-core/generators/favicon-generator.js.map +1 -0
  85. package/dist/lib/branding-core/generators/gradient-system.d.ts +3 -0
  86. package/dist/lib/branding-core/generators/gradient-system.d.ts.map +1 -0
  87. package/dist/lib/branding-core/generators/gradient-system.js +74 -0
  88. package/dist/lib/branding-core/generators/gradient-system.js.map +1 -0
  89. package/dist/lib/branding-core/generators/logo-generator.d.ts +4 -0
  90. package/dist/lib/branding-core/generators/logo-generator.d.ts.map +1 -0
  91. package/dist/lib/branding-core/generators/logo-generator.js +130 -0
  92. package/dist/lib/branding-core/generators/logo-generator.js.map +1 -0
  93. package/dist/lib/branding-core/generators/motion-system.d.ts +3 -0
  94. package/dist/lib/branding-core/generators/motion-system.d.ts.map +1 -0
  95. package/dist/lib/branding-core/generators/motion-system.js +91 -0
  96. package/dist/lib/branding-core/generators/motion-system.js.map +1 -0
  97. package/dist/lib/branding-core/generators/og-image-generator.d.ts +3 -0
  98. package/dist/lib/branding-core/generators/og-image-generator.d.ts.map +1 -0
  99. package/dist/lib/branding-core/generators/og-image-generator.js +72 -0
  100. package/dist/lib/branding-core/generators/og-image-generator.js.map +1 -0
  101. package/dist/lib/branding-core/generators/shadow-system.d.ts +3 -0
  102. package/dist/lib/branding-core/generators/shadow-system.d.ts.map +1 -0
  103. package/dist/lib/branding-core/generators/shadow-system.js +44 -0
  104. package/dist/lib/branding-core/generators/shadow-system.js.map +1 -0
  105. package/dist/lib/branding-core/generators/spacing-scale.d.ts +3 -0
  106. package/dist/lib/branding-core/generators/spacing-scale.d.ts.map +1 -0
  107. package/dist/lib/branding-core/generators/spacing-scale.js +27 -0
  108. package/dist/lib/branding-core/generators/spacing-scale.js.map +1 -0
  109. package/dist/lib/branding-core/generators/typography-system.d.ts +3 -0
  110. package/dist/lib/branding-core/generators/typography-system.d.ts.map +1 -0
  111. package/dist/lib/branding-core/generators/typography-system.js +121 -0
  112. package/dist/lib/branding-core/generators/typography-system.js.map +1 -0
  113. package/dist/lib/branding-core/index.d.ts +24 -0
  114. package/dist/lib/branding-core/index.d.ts.map +1 -0
  115. package/dist/lib/branding-core/index.js +22 -0
  116. package/dist/lib/branding-core/index.js.map +1 -0
  117. package/dist/lib/branding-core/validators/brand-consistency.d.ts +3 -0
  118. package/dist/lib/branding-core/validators/brand-consistency.d.ts.map +1 -0
  119. package/dist/lib/branding-core/validators/brand-consistency.js +70 -0
  120. package/dist/lib/branding-core/validators/brand-consistency.js.map +1 -0
  121. package/dist/lib/branding-core/validators/contrast-checker.d.ts +3 -0
  122. package/dist/lib/branding-core/validators/contrast-checker.d.ts.map +1 -0
  123. package/dist/lib/branding-core/validators/contrast-checker.js +33 -0
  124. package/dist/lib/branding-core/validators/contrast-checker.js.map +1 -0
  125. package/dist/lib/branding-core/validators/token-schema.d.ts +10 -0
  126. package/dist/lib/branding-core/validators/token-schema.d.ts.map +1 -0
  127. package/dist/lib/branding-core/validators/token-schema.js +43 -0
  128. package/dist/lib/branding-core/validators/token-schema.js.map +1 -0
  129. package/dist/lib/config.d.ts +7 -0
  130. package/dist/lib/config.d.ts.map +1 -0
  131. package/dist/lib/config.js +8 -0
  132. package/dist/lib/config.js.map +1 -0
  133. package/dist/lib/logger.d.ts +3 -0
  134. package/dist/lib/logger.d.ts.map +1 -0
  135. package/dist/lib/logger.js +10 -0
  136. package/dist/lib/logger.js.map +1 -0
  137. package/dist/lib/types.d.ts +208 -0
  138. package/dist/lib/types.d.ts.map +1 -0
  139. package/dist/lib/types.js +2 -0
  140. package/dist/lib/types.js.map +1 -0
  141. package/dist/resources/brand-knowledge.d.ts +3 -0
  142. package/dist/resources/brand-knowledge.d.ts.map +1 -0
  143. package/dist/resources/brand-knowledge.js +53 -0
  144. package/dist/resources/brand-knowledge.js.map +1 -0
  145. package/dist/resources/brand-templates.d.ts +3 -0
  146. package/dist/resources/brand-templates.d.ts.map +1 -0
  147. package/dist/resources/brand-templates.js +68 -0
  148. package/dist/resources/brand-templates.js.map +1 -0
  149. package/dist/tools/create-brand-guidelines.d.ts +3 -0
  150. package/dist/tools/create-brand-guidelines.d.ts.map +1 -0
  151. package/dist/tools/create-brand-guidelines.js +85 -0
  152. package/dist/tools/create-brand-guidelines.js.map +1 -0
  153. package/dist/tools/export-design-tokens.d.ts +3 -0
  154. package/dist/tools/export-design-tokens.d.ts.map +1 -0
  155. package/dist/tools/export-design-tokens.js +37 -0
  156. package/dist/tools/export-design-tokens.js.map +1 -0
  157. package/dist/tools/generate-brand-assets.d.ts +3 -0
  158. package/dist/tools/generate-brand-assets.d.ts.map +1 -0
  159. package/dist/tools/generate-brand-assets.js +37 -0
  160. package/dist/tools/generate-brand-assets.js.map +1 -0
  161. package/dist/tools/generate-brand-identity.d.ts +3 -0
  162. package/dist/tools/generate-brand-identity.d.ts.map +1 -0
  163. package/dist/tools/generate-brand-identity.js +73 -0
  164. package/dist/tools/generate-brand-identity.js.map +1 -0
  165. package/dist/tools/generate-color-palette.d.ts +3 -0
  166. package/dist/tools/generate-color-palette.d.ts.map +1 -0
  167. package/dist/tools/generate-color-palette.js +33 -0
  168. package/dist/tools/generate-color-palette.js.map +1 -0
  169. package/dist/tools/generate-typography-system.d.ts +3 -0
  170. package/dist/tools/generate-typography-system.d.ts.map +1 -0
  171. package/dist/tools/generate-typography-system.js +28 -0
  172. package/dist/tools/generate-typography-system.js.map +1 -0
  173. package/dist/tools/refine-brand-element.d.ts +3 -0
  174. package/dist/tools/refine-brand-element.d.ts.map +1 -0
  175. package/dist/tools/refine-brand-element.js +41 -0
  176. package/dist/tools/refine-brand-element.js.map +1 -0
  177. package/dist/tools/validate-brand-consistency.d.ts +3 -0
  178. package/dist/tools/validate-brand-consistency.d.ts.map +1 -0
  179. package/dist/tools/validate-brand-consistency.js +25 -0
  180. package/dist/tools/validate-brand-consistency.js.map +1 -0
  181. package/docs/API.md +110 -0
  182. package/docs/DATA_SOURCES.md +69 -0
  183. package/docs/INTEGRATION.md +58 -0
  184. package/eslint.config.js +52 -0
  185. package/jest.config.js +40 -0
  186. package/package.json +78 -0
  187. package/src/__tests__/integration/brand-generation.test.ts +84 -0
  188. package/src/__tests__/integration/mcp-server.test.ts +18 -0
  189. package/src/__tests__/unit/ai-interpreter.test.ts +172 -0
  190. package/src/__tests__/unit/border-system.test.ts +77 -0
  191. package/src/__tests__/unit/color-palette.test.ts +161 -0
  192. package/src/__tests__/unit/contrast-checker.test.ts +124 -0
  193. package/src/__tests__/unit/design-tokens.test.ts +184 -0
  194. package/src/__tests__/unit/favicon-generator.test.ts +80 -0
  195. package/src/__tests__/unit/gradient-system.test.ts +122 -0
  196. package/src/__tests__/unit/logo-generator.test.ts +146 -0
  197. package/src/__tests__/unit/motion-system.test.ts +91 -0
  198. package/src/__tests__/unit/og-image-generator.test.ts +115 -0
  199. package/src/__tests__/unit/shadow-system.test.ts +63 -0
  200. package/src/__tests__/unit/spacing-scale.test.ts +60 -0
  201. package/src/__tests__/unit/typography-system.test.ts +71 -0
  202. package/src/index.ts +59 -0
  203. package/src/lib/branding-core/ai/brand-interpreter.ts +30 -0
  204. package/src/lib/branding-core/ai/claude-interpreter.ts +76 -0
  205. package/src/lib/branding-core/ai/intent-applier.ts +59 -0
  206. package/src/lib/branding-core/ai/keyword-interpreter.ts +95 -0
  207. package/src/lib/branding-core/ai/prompts.ts +93 -0
  208. package/src/lib/branding-core/ai/types.ts +36 -0
  209. package/src/lib/branding-core/documents/html-generator.ts +32 -0
  210. package/src/lib/branding-core/documents/pdf-generator.ts +21 -0
  211. package/src/lib/branding-core/exporters/css-variables.ts +71 -0
  212. package/src/lib/branding-core/exporters/design-tokens.ts +86 -0
  213. package/src/lib/branding-core/exporters/figma-tokens.ts +87 -0
  214. package/src/lib/branding-core/exporters/react-theme.ts +69 -0
  215. package/src/lib/branding-core/exporters/sass-variables.ts +74 -0
  216. package/src/lib/branding-core/exporters/tailwind-preset.ts +67 -0
  217. package/src/lib/branding-core/generators/border-system.ts +41 -0
  218. package/src/lib/branding-core/generators/color-palette.ts +147 -0
  219. package/src/lib/branding-core/generators/favicon-generator.ts +33 -0
  220. package/src/lib/branding-core/generators/gradient-system.ts +120 -0
  221. package/src/lib/branding-core/generators/logo-generator.ts +152 -0
  222. package/src/lib/branding-core/generators/motion-system.ts +98 -0
  223. package/src/lib/branding-core/generators/og-image-generator.ts +97 -0
  224. package/src/lib/branding-core/generators/shadow-system.ts +66 -0
  225. package/src/lib/branding-core/generators/spacing-scale.ts +29 -0
  226. package/src/lib/branding-core/generators/typography-system.ts +128 -0
  227. package/src/lib/branding-core/index.ts +28 -0
  228. package/src/lib/branding-core/validators/brand-consistency.ts +79 -0
  229. package/src/lib/branding-core/validators/contrast-checker.ts +37 -0
  230. package/src/lib/branding-core/validators/token-schema.ts +50 -0
  231. package/src/lib/config.ts +13 -0
  232. package/src/lib/logger.ts +12 -0
  233. package/src/lib/types.ts +236 -0
  234. package/src/resources/brand-knowledge.ts +60 -0
  235. package/src/resources/brand-templates.ts +70 -0
  236. package/src/tools/create-brand-guidelines.ts +94 -0
  237. package/src/tools/export-design-tokens.ts +52 -0
  238. package/src/tools/generate-brand-assets.ts +48 -0
  239. package/src/tools/generate-brand-identity.ts +115 -0
  240. package/src/tools/generate-color-palette.ts +43 -0
  241. package/src/tools/generate-typography-system.ts +42 -0
  242. package/src/tools/refine-brand-element.ts +65 -0
  243. package/src/tools/validate-brand-consistency.ts +32 -0
  244. package/tsconfig.json +21 -0
@@ -0,0 +1,66 @@
1
+ import type {
2
+ BrandStyle,
3
+ ColorTheme,
4
+ ShadowLevel,
5
+ ShadowLevelName,
6
+ ShadowSystem,
7
+ } from '../../types.js';
8
+ import { hexToHsl, hslToHex } from './color-palette.js';
9
+
10
+ const LEVEL_CONFIGS: Record<
11
+ ShadowLevelName,
12
+ { y: number; blur: number; spread: number; opacity: number }
13
+ > = {
14
+ none: { y: 0, blur: 0, spread: 0, opacity: 0 },
15
+ sm: { y: 1, blur: 2, spread: 0, opacity: 0.05 },
16
+ md: { y: 2, blur: 4, spread: -1, opacity: 0.08 },
17
+ lg: { y: 4, blur: 8, spread: -2, opacity: 0.1 },
18
+ xl: { y: 8, blur: 16, spread: -4, opacity: 0.12 },
19
+ '2xl': { y: 16, blur: 32, spread: -8, opacity: 0.15 },
20
+ };
21
+
22
+ function makeShadowColor(primaryHex: string, opacity: number): string {
23
+ const hsl = hexToHsl(primaryHex);
24
+ const tinted = hslToHex(hsl.h, Math.min(hsl.s, 30), 20);
25
+ const r = parseInt(tinted.slice(1, 3), 16);
26
+ const g = parseInt(tinted.slice(3, 5), 16);
27
+ const b = parseInt(tinted.slice(5, 7), 16);
28
+ return `rgba(${r}, ${g}, ${b}, ${opacity})`;
29
+ }
30
+
31
+ function buildLevel(
32
+ cfg: (typeof LEVEL_CONFIGS)[ShadowLevelName],
33
+ primaryHex: string,
34
+ dark: boolean
35
+ ): ShadowLevel {
36
+ const sign = dark ? -1 : 1;
37
+ const adjustedOpacity = dark ? cfg.opacity * 1.5 : cfg.opacity;
38
+ const color = makeShadowColor(primaryHex, adjustedOpacity);
39
+ const oY = cfg.y * sign;
40
+ const cssValue =
41
+ cfg.blur === 0
42
+ ? 'none'
43
+ : `${cfg.y === 0 ? 0 : `${oY}px`} ${oY === 0 ? '' : `${Math.abs(oY)}px `}${cfg.blur}px ${cfg.spread}px ${color}`.trim();
44
+ return {
45
+ offsetX: 0,
46
+ offsetY: oY,
47
+ blur: cfg.blur,
48
+ spread: cfg.spread,
49
+ color,
50
+ opacity: adjustedOpacity,
51
+ cssValue,
52
+ };
53
+ }
54
+
55
+ export function generateShadowSystem(
56
+ primaryHex = '#6B4CE6',
57
+ theme: ColorTheme = 'light',
58
+ _style?: BrandStyle
59
+ ): ShadowSystem {
60
+ const dark = theme === 'dark';
61
+ const levels = {} as Record<ShadowLevelName, ShadowLevel>;
62
+ for (const [name, cfg] of Object.entries(LEVEL_CONFIGS)) {
63
+ levels[name as ShadowLevelName] = buildLevel(cfg, primaryHex, dark);
64
+ }
65
+ return { levels };
66
+ }
@@ -0,0 +1,29 @@
1
+ import type { SpacingScale } from '../../types.js';
2
+
3
+ const SPACING_NAMES = [
4
+ '0',
5
+ '0.5',
6
+ '1',
7
+ '1.5',
8
+ '2',
9
+ '2.5',
10
+ '3',
11
+ '4',
12
+ '5',
13
+ '6',
14
+ '8',
15
+ '10',
16
+ '12',
17
+ '16',
18
+ '20',
19
+ '24',
20
+ ];
21
+
22
+ export function generateSpacingScale(baseUnit = 4): SpacingScale {
23
+ const values: Record<string, string> = {};
24
+ for (const name of SPACING_NAMES) {
25
+ const multiplier = parseFloat(name);
26
+ values[name] = `${multiplier * baseUnit}px`;
27
+ }
28
+ return { unit: baseUnit, values };
29
+ }
@@ -0,0 +1,128 @@
1
+ import type { FontCategory, TypeScaleRatio, TypeStep, TypographySystem } from '../../types.js';
2
+
3
+ const SCALE_RATIOS: Record<TypeScaleRatio, number> = {
4
+ 'minor-second': 1.067,
5
+ 'major-second': 1.125,
6
+ 'minor-third': 1.2,
7
+ 'major-third': 1.25,
8
+ 'perfect-fourth': 1.333,
9
+ 'augmented-fourth': 1.414,
10
+ 'perfect-fifth': 1.5,
11
+ 'golden-ratio': 1.618,
12
+ };
13
+
14
+ const FONT_PAIRINGS: Record<FontCategory, Record<FontCategory, [string, string][]>> = {
15
+ 'sans-serif': {
16
+ serif: [
17
+ ['Inter', 'Merriweather'],
18
+ ['Helvetica Neue', 'Georgia'],
19
+ ['Open Sans', 'Lora'],
20
+ ],
21
+ 'sans-serif': [
22
+ ['Montserrat', 'Open Sans'],
23
+ ['Poppins', 'Inter'],
24
+ ['Raleway', 'Nunito'],
25
+ ],
26
+ monospace: [['Inter', 'JetBrains Mono']],
27
+ display: [['Inter', 'Playfair Display']],
28
+ handwriting: [['Inter', 'Caveat']],
29
+ },
30
+ serif: {
31
+ 'sans-serif': [
32
+ ['Playfair Display', 'Source Sans 3'],
33
+ ['Merriweather', 'Open Sans'],
34
+ ['Lora', 'Inter'],
35
+ ],
36
+ serif: [
37
+ ['Playfair Display', 'Merriweather'],
38
+ ['Lora', 'Georgia'],
39
+ ],
40
+ monospace: [['Merriweather', 'Fira Code']],
41
+ display: [['Merriweather', 'Playfair Display']],
42
+ handwriting: [['Merriweather', 'Caveat']],
43
+ },
44
+ monospace: {
45
+ 'sans-serif': [['JetBrains Mono', 'Inter']],
46
+ serif: [['Fira Code', 'Merriweather']],
47
+ monospace: [['JetBrains Mono', 'Fira Code']],
48
+ display: [['JetBrains Mono', 'Playfair Display']],
49
+ handwriting: [['JetBrains Mono', 'Caveat']],
50
+ },
51
+ display: {
52
+ 'sans-serif': [
53
+ ['Playfair Display', 'Inter'],
54
+ ['Bebas Neue', 'Open Sans'],
55
+ ],
56
+ serif: [['Playfair Display', 'Merriweather']],
57
+ monospace: [['Playfair Display', 'JetBrains Mono']],
58
+ display: [['Bebas Neue', 'Playfair Display']],
59
+ handwriting: [['Playfair Display', 'Caveat']],
60
+ },
61
+ handwriting: {
62
+ 'sans-serif': [['Caveat', 'Inter']],
63
+ serif: [['Caveat', 'Merriweather']],
64
+ monospace: [['Caveat', 'JetBrains Mono']],
65
+ display: [['Caveat', 'Playfair Display']],
66
+ handwriting: [['Caveat', 'Dancing Script']],
67
+ },
68
+ };
69
+
70
+ const STEP_NAMES = ['xs', 'sm', 'base', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl'];
71
+
72
+ function pickPairing(headingCat: FontCategory, bodyCat: FontCategory): [string, string] {
73
+ const options = FONT_PAIRINGS[headingCat]?.[bodyCat];
74
+ if (!options?.length) return ['Inter', 'Inter'];
75
+ return options[Math.floor(Math.random() * options.length)];
76
+ }
77
+
78
+ function lineHeightForSize(size: number): string {
79
+ if (size <= 16) return '1.6';
80
+ if (size <= 24) return '1.5';
81
+ if (size <= 36) return '1.3';
82
+ return '1.2';
83
+ }
84
+
85
+ function letterSpacingForSize(size: number): string {
86
+ if (size <= 14) return '0.02em';
87
+ if (size <= 20) return '0em';
88
+ return '-0.01em';
89
+ }
90
+
91
+ function weightForStep(index: number, totalSteps: number): number {
92
+ const mid = Math.floor(totalSteps / 2);
93
+ if (index <= mid) return 400;
94
+ if (index <= mid + 2) return 600;
95
+ return 700;
96
+ }
97
+
98
+ export function generateTypographySystem(
99
+ headingCategory: FontCategory = 'sans-serif',
100
+ bodyCategory: FontCategory = 'serif',
101
+ scaleRatio: TypeScaleRatio = 'major-third',
102
+ baseSize = 16
103
+ ): TypographySystem {
104
+ const ratio = SCALE_RATIOS[scaleRatio];
105
+ const [headingFont, bodyFont] = pickPairing(headingCategory, bodyCategory);
106
+
107
+ const baseIndex = 2;
108
+ const steps: TypeStep[] = STEP_NAMES.map((name, i) => {
109
+ const exponent = i - baseIndex;
110
+ const size = Math.round(baseSize * Math.pow(ratio, exponent) * 100) / 100;
111
+ return {
112
+ name,
113
+ size: `${size}px`,
114
+ lineHeight: lineHeightForSize(size),
115
+ letterSpacing: letterSpacingForSize(size),
116
+ weight: weightForStep(i, STEP_NAMES.length),
117
+ };
118
+ });
119
+
120
+ return {
121
+ headingFont,
122
+ bodyFont,
123
+ monoFont: 'JetBrains Mono',
124
+ baseSize,
125
+ scaleRatio: ratio,
126
+ steps,
127
+ };
128
+ }
@@ -0,0 +1,28 @@
1
+ export {
2
+ generateColorPalette,
3
+ checkContrast,
4
+ hslToHex,
5
+ hexToHsl,
6
+ } from './generators/color-palette.js';
7
+ export { generateTypographySystem } from './generators/typography-system.js';
8
+ export { generateSpacingScale } from './generators/spacing-scale.js';
9
+ export { generateShadowSystem } from './generators/shadow-system.js';
10
+ export { generateBorderSystem } from './generators/border-system.js';
11
+ export { generateMotionSystem } from './generators/motion-system.js';
12
+ export { generateSvgLogo, defaultLogoConfig } from './generators/logo-generator.js';
13
+ export { generateGradientSystem } from './generators/gradient-system.js';
14
+ export { generateFavicons } from './generators/favicon-generator.js';
15
+ export { generateOgImage } from './generators/og-image-generator.js';
16
+ export { exportDesignTokens } from './exporters/design-tokens.js';
17
+ export { exportCssVariables } from './exporters/css-variables.js';
18
+ export { exportTailwindPreset } from './exporters/tailwind-preset.js';
19
+ export { exportFigmaTokens } from './exporters/figma-tokens.js';
20
+ export { exportReactTheme } from './exporters/react-theme.js';
21
+ export { exportSassVariables } from './exporters/sass-variables.js';
22
+ export { validateBrandConsistency } from './validators/brand-consistency.js';
23
+ export { validateContrast } from './validators/contrast-checker.js';
24
+ export { interpretFeedback } from './ai/brand-interpreter.js';
25
+ export { interpretWithKeywords } from './ai/keyword-interpreter.js';
26
+ export { applyIntent } from './ai/intent-applier.js';
27
+ export type { BrandIntent, ColorIntent, TypographyIntent, InterpreterOptions } from './ai/types.js';
28
+ export type { InterpreterStrategy } from './ai/brand-interpreter.js';
@@ -0,0 +1,79 @@
1
+ import type { BrandIdentity, BrandValidationIssue, BrandValidationResult } from '../../types.js';
2
+ import { validateContrast } from './contrast-checker.js';
3
+
4
+ function validateColorCompleteness(brand: BrandIdentity): BrandValidationIssue[] {
5
+ const issues: BrandValidationIssue[] = [];
6
+ const { colors } = brand;
7
+
8
+ if (!colors.primary.hex) {
9
+ issues.push({
10
+ severity: 'error',
11
+ element: 'color.primary',
12
+ message: 'Primary color is missing',
13
+ });
14
+ }
15
+ if (!colors.secondary.hex) {
16
+ issues.push({
17
+ severity: 'error',
18
+ element: 'color.secondary',
19
+ message: 'Secondary color is missing',
20
+ });
21
+ }
22
+ if (colors.neutral.length < 4) {
23
+ issues.push({
24
+ severity: 'warning',
25
+ element: 'color.neutral',
26
+ message: `Only ${colors.neutral.length} neutral shades defined (recommend 6-10)`,
27
+ });
28
+ }
29
+
30
+ return issues;
31
+ }
32
+
33
+ function validateTypography(brand: BrandIdentity): BrandValidationIssue[] {
34
+ const issues: BrandValidationIssue[] = [];
35
+ const { typography } = brand;
36
+
37
+ if (!typography.headingFont) {
38
+ issues.push({
39
+ severity: 'error',
40
+ element: 'typography.headingFont',
41
+ message: 'Heading font is missing',
42
+ });
43
+ }
44
+ if (!typography.bodyFont) {
45
+ issues.push({
46
+ severity: 'error',
47
+ element: 'typography.bodyFont',
48
+ message: 'Body font is missing',
49
+ });
50
+ }
51
+ if (typography.baseSize < 14 || typography.baseSize > 20) {
52
+ issues.push({
53
+ severity: 'warning',
54
+ element: 'typography.baseSize',
55
+ message: `Base size ${typography.baseSize}px is outside recommended range (14-20px)`,
56
+ });
57
+ }
58
+
59
+ return issues;
60
+ }
61
+
62
+ export function validateBrandConsistency(brand: BrandIdentity): BrandValidationResult {
63
+ const issues: BrandValidationIssue[] = [
64
+ ...validateColorCompleteness(brand),
65
+ ...validateContrast(brand),
66
+ ...validateTypography(brand),
67
+ ];
68
+
69
+ const errorCount = issues.filter((i) => i.severity === 'error').length;
70
+ const warningCount = issues.filter((i) => i.severity === 'warning').length;
71
+ const maxScore = 100;
72
+ const score = Math.max(0, maxScore - errorCount * 20 - warningCount * 5);
73
+
74
+ return {
75
+ valid: errorCount === 0,
76
+ score,
77
+ issues,
78
+ };
79
+ }
@@ -0,0 +1,37 @@
1
+ import type { BrandIdentity, BrandValidationIssue } from '../../types.js';
2
+ import { checkContrast } from '../generators/color-palette.js';
3
+
4
+ export function validateContrast(brand: BrandIdentity): BrandValidationIssue[] {
5
+ const issues: BrandValidationIssue[] = [];
6
+ const white = '#ffffff';
7
+ const dark = '#1a1a1a';
8
+
9
+ const colorChecks = [
10
+ { name: 'primary', hex: brand.colors.primary.hex },
11
+ { name: 'secondary', hex: brand.colors.secondary.hex },
12
+ { name: 'accent', hex: brand.colors.accent.hex },
13
+ ];
14
+
15
+ for (const { name, hex } of colorChecks) {
16
+ const onWhite = checkContrast(hex, white);
17
+ const onDark = checkContrast(hex, dark);
18
+
19
+ if (!onWhite.aa && !onDark.aa) {
20
+ issues.push({
21
+ severity: 'error',
22
+ element: `color.${name}`,
23
+ message: `${name} color (${hex}) fails WCAG AA on both white and dark backgrounds`,
24
+ suggestion: 'Adjust lightness to achieve at least 4.5:1 contrast ratio',
25
+ });
26
+ } else if (!onWhite.aa) {
27
+ issues.push({
28
+ severity: 'warning',
29
+ element: `color.${name}`,
30
+ message: `${name} color (${hex}) fails WCAG AA on white (ratio: ${onWhite.ratio})`,
31
+ suggestion: 'Darken the color for better contrast on light backgrounds',
32
+ });
33
+ }
34
+ }
35
+
36
+ return issues;
37
+ }
@@ -0,0 +1,50 @@
1
+ import { z } from 'zod';
2
+
3
+ export const hexColorSchema = z
4
+ .string()
5
+ .regex(/^#[0-9a-fA-F]{6}$/, 'Must be a valid hex color (#RRGGBB)');
6
+
7
+ export const colorHarmonySchema = z.enum([
8
+ 'complementary',
9
+ 'analogous',
10
+ 'triadic',
11
+ 'split-complementary',
12
+ 'tetradic',
13
+ 'monochromatic',
14
+ ]);
15
+
16
+ export const colorThemeSchema = z.enum(['light', 'dark', 'both']);
17
+
18
+ export const fontCategorySchema = z.enum([
19
+ 'serif',
20
+ 'sans-serif',
21
+ 'monospace',
22
+ 'display',
23
+ 'handwriting',
24
+ ]);
25
+
26
+ export const typeScaleRatioSchema = z.enum([
27
+ 'minor-second',
28
+ 'major-second',
29
+ 'minor-third',
30
+ 'major-third',
31
+ 'perfect-fourth',
32
+ 'augmented-fourth',
33
+ 'perfect-fifth',
34
+ 'golden-ratio',
35
+ ]);
36
+
37
+ export const exportFormatSchema = z.enum(['json', 'css', 'tailwind', 'figma', 'react', 'sass']);
38
+
39
+ export const brandStyleSchema = z.enum([
40
+ 'minimal',
41
+ 'bold',
42
+ 'elegant',
43
+ 'playful',
44
+ 'corporate',
45
+ 'tech',
46
+ 'organic',
47
+ 'retro',
48
+ ]);
49
+
50
+ export const brandDocFormatSchema = z.enum(['pdf', 'html']);
@@ -0,0 +1,13 @@
1
+ export interface AppConfig {
2
+ logLevel: string;
3
+ nodeEnv: string;
4
+ anthropicApiKey?: string;
5
+ }
6
+
7
+ export function loadConfig(): AppConfig {
8
+ return {
9
+ logLevel: process.env.LOG_LEVEL ?? 'info',
10
+ nodeEnv: process.env.NODE_ENV ?? 'development',
11
+ anthropicApiKey: process.env.ANTHROPIC_API_KEY,
12
+ };
13
+ }
@@ -0,0 +1,12 @@
1
+ import pino from 'pino';
2
+ import { loadConfig } from './config.js';
3
+
4
+ const config = loadConfig();
5
+
6
+ export const logger = pino({
7
+ level: config.logLevel,
8
+ transport:
9
+ config.nodeEnv === 'development'
10
+ ? { target: 'pino/file', options: { destination: 2 } }
11
+ : undefined,
12
+ });
@@ -0,0 +1,236 @@
1
+ export type ColorHarmony =
2
+ | 'complementary'
3
+ | 'analogous'
4
+ | 'triadic'
5
+ | 'split-complementary'
6
+ | 'tetradic'
7
+ | 'monochromatic';
8
+
9
+ export type ColorTheme = 'light' | 'dark' | 'both';
10
+
11
+ export type FontCategory = 'serif' | 'sans-serif' | 'monospace' | 'display' | 'handwriting';
12
+
13
+ export type TypeScaleRatio =
14
+ | 'minor-second'
15
+ | 'major-second'
16
+ | 'minor-third'
17
+ | 'major-third'
18
+ | 'perfect-fourth'
19
+ | 'augmented-fourth'
20
+ | 'perfect-fifth'
21
+ | 'golden-ratio';
22
+
23
+ export type ExportFormat = 'json' | 'css' | 'tailwind' | 'figma' | 'react' | 'sass';
24
+
25
+ export type BrandDocFormat = 'pdf' | 'html';
26
+
27
+ export type BrandStyle =
28
+ | 'minimal'
29
+ | 'bold'
30
+ | 'elegant'
31
+ | 'playful'
32
+ | 'corporate'
33
+ | 'tech'
34
+ | 'organic'
35
+ | 'retro';
36
+
37
+ export interface HslColor {
38
+ h: number;
39
+ s: number;
40
+ l: number;
41
+ }
42
+
43
+ export interface ColorSwatch {
44
+ name: string;
45
+ hex: string;
46
+ hsl: HslColor;
47
+ oklch?: { l: number; c: number; h: number };
48
+ usage: string;
49
+ }
50
+
51
+ export interface ContrastResult {
52
+ ratio: number;
53
+ aa: boolean;
54
+ aaLarge: boolean;
55
+ aaa: boolean;
56
+ aaaLarge: boolean;
57
+ }
58
+
59
+ export interface ColorPalette {
60
+ primary: ColorSwatch;
61
+ secondary: ColorSwatch;
62
+ accent: ColorSwatch;
63
+ neutral: ColorSwatch[];
64
+ semantic: {
65
+ success: ColorSwatch;
66
+ warning: ColorSwatch;
67
+ error: ColorSwatch;
68
+ info: ColorSwatch;
69
+ };
70
+ contrast: Record<string, ContrastResult>;
71
+ }
72
+
73
+ export interface TypeStep {
74
+ name: string;
75
+ size: string;
76
+ lineHeight: string;
77
+ letterSpacing: string;
78
+ weight: number;
79
+ }
80
+
81
+ export interface TypographySystem {
82
+ headingFont: string;
83
+ bodyFont: string;
84
+ monoFont: string;
85
+ baseSize: number;
86
+ scaleRatio: number;
87
+ steps: TypeStep[];
88
+ }
89
+
90
+ export interface SpacingScale {
91
+ unit: number;
92
+ values: Record<string, string>;
93
+ }
94
+
95
+ export interface LogoConfig {
96
+ text: string;
97
+ font: string;
98
+ fontSize: number;
99
+ color: string;
100
+ backgroundColor: string;
101
+ width: number;
102
+ height: number;
103
+ style?: BrandStyle;
104
+ }
105
+
106
+ export type LogoVariant = 'wordmark' | 'monogram' | 'abstract' | 'icon';
107
+
108
+ export interface LogoOutput {
109
+ svg: string;
110
+ variants: Record<LogoVariant, string>;
111
+ }
112
+
113
+ export type GradientType = 'linear' | 'radial' | 'conic';
114
+ export type GradientPresetName = 'hero' | 'button' | 'card' | 'text' | 'background';
115
+
116
+ export interface GradientStop {
117
+ color: string;
118
+ position: number;
119
+ }
120
+
121
+ export interface Gradient {
122
+ type: GradientType;
123
+ angle?: number;
124
+ stops: GradientStop[];
125
+ cssValue: string;
126
+ }
127
+
128
+ export interface GradientSystem {
129
+ presets: Record<GradientPresetName, Gradient>;
130
+ }
131
+
132
+ export type FaviconSize = 16 | 32 | 180 | 512;
133
+
134
+ export interface FaviconSet {
135
+ sizes: Record<FaviconSize, string>;
136
+ }
137
+
138
+ export type OgTemplate = 'default' | 'article' | 'social';
139
+
140
+ export interface OgImageOutput {
141
+ template: OgTemplate;
142
+ svg: string;
143
+ width: number;
144
+ height: number;
145
+ }
146
+
147
+ export type ShadowLevelName = 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
148
+
149
+ export interface ShadowLevel {
150
+ offsetX: number;
151
+ offsetY: number;
152
+ blur: number;
153
+ spread: number;
154
+ color: string;
155
+ opacity: number;
156
+ cssValue: string;
157
+ }
158
+
159
+ export interface ShadowSystem {
160
+ levels: Record<ShadowLevelName, ShadowLevel>;
161
+ }
162
+
163
+ export type BorderRadiusName = 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full' | 'circle';
164
+
165
+ export interface BorderSystem {
166
+ radii: Record<BorderRadiusName, string>;
167
+ widths: { thin: string; medium: string; thick: string };
168
+ }
169
+
170
+ export type DurationName = 'instant' | 'fast' | 'normal' | 'slow' | 'slower';
171
+ export type EasingName = 'ease-in' | 'ease-out' | 'ease-in-out' | 'spring' | 'bounce';
172
+
173
+ export interface MotionSystem {
174
+ durations: Record<DurationName, string>;
175
+ easings: Record<EasingName, string>;
176
+ transitions: Record<string, string>;
177
+ }
178
+
179
+ export interface BrandIdentity {
180
+ id: string;
181
+ name: string;
182
+ tagline?: string;
183
+ industry: string;
184
+ style: BrandStyle;
185
+ colors: ColorPalette;
186
+ typography: TypographySystem;
187
+ spacing: SpacingScale;
188
+ shadows?: ShadowSystem;
189
+ borders?: BorderSystem;
190
+ motion?: MotionSystem;
191
+ gradients?: GradientSystem;
192
+ logo?: LogoOutput;
193
+ createdAt: string;
194
+ }
195
+
196
+ export interface DesignTokens {
197
+ $schema?: string;
198
+ color: Record<string, Record<string, { $value: string; $type: string }>>;
199
+ typography: Record<string, Record<string, { $value: string | number; $type: string }>>;
200
+ spacing: Record<string, { $value: string; $type: string }>;
201
+ shadow?: Record<string, { $value: string; $type: string }>;
202
+ border?: Record<string, { $value: string; $type: string }>;
203
+ motion?: Record<string, { $value: string; $type: string }>;
204
+ gradient?: Record<string, { $value: string; $type: string }>;
205
+ }
206
+
207
+ export interface BrandGenerationInput {
208
+ brandName: string;
209
+ industry: string;
210
+ style: BrandStyle;
211
+ tagline?: string;
212
+ colorPrefs?: {
213
+ baseColor?: string;
214
+ harmony?: ColorHarmony;
215
+ theme?: ColorTheme;
216
+ };
217
+ typographyPrefs?: {
218
+ mood?: string;
219
+ headingCategory?: FontCategory;
220
+ bodyCategory?: FontCategory;
221
+ scaleRatio?: TypeScaleRatio;
222
+ };
223
+ }
224
+
225
+ export interface BrandValidationResult {
226
+ valid: boolean;
227
+ score: number;
228
+ issues: BrandValidationIssue[];
229
+ }
230
+
231
+ export interface BrandValidationIssue {
232
+ severity: 'error' | 'warning' | 'info';
233
+ element: string;
234
+ message: string;
235
+ suggestion?: string;
236
+ }