handoff-app 2.0.0-8 → 2.0.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 (322) hide show
  1. package/{Changelog.md → CHANGELOG.md} +85 -1
  2. package/{License.md → LICENSE.md} +1 -1
  3. package/README.md +816 -393
  4. package/RECIPES.md +975 -0
  5. package/UPGRADE.md +57 -9
  6. package/components.json +20 -20
  7. package/config/docs/foundations/colors/guidelines.md +0 -1
  8. package/config/docs/foundations/colors.md +0 -1
  9. package/config/docs/foundations/effects/guidelines.md +0 -1
  10. package/config/docs/foundations/effects/resources.md +0 -1
  11. package/config/docs/foundations/effects.md +0 -1
  12. package/config/docs/foundations/fonts.md +0 -1
  13. package/config/docs/foundations/grid.md +0 -1
  14. package/config/docs/foundations/icon.md +0 -1
  15. package/config/docs/foundations/icons/guidelines.md +0 -1
  16. package/config/docs/foundations/icons.md +0 -1
  17. package/config/docs/foundations/images/guidelines.md +0 -1
  18. package/config/docs/foundations/images/resources.md +0 -1
  19. package/config/docs/foundations/images.md +0 -1
  20. package/config/docs/foundations/logo/resources.md +0 -1
  21. package/config/docs/foundations/logo.md +0 -1
  22. package/config/docs/foundations/typography/guidelines.md +0 -1
  23. package/config/docs/foundations/typography/resources.md +0 -1
  24. package/config/docs/foundations/typography.md +0 -1
  25. package/config/docs/foundations.md +0 -1
  26. package/config/docs/guidelines.md +0 -1
  27. package/config/docs/index.md +0 -1
  28. package/config/docs/system/tokens/foundations/colors.md +0 -4
  29. package/config/docs/system/tokens/foundations/effects.md +0 -4
  30. package/config/docs/system/tokens/foundations/typography.md +0 -2
  31. package/config/docs/system.md +0 -2
  32. package/config/templates/page.md +2 -1
  33. package/config/templates/page.mdx +2 -1
  34. package/dist/ai/connections.d.ts +66 -0
  35. package/dist/ai/connections.js +149 -0
  36. package/dist/ai/define.d.ts +10 -0
  37. package/dist/ai/define.js +13 -0
  38. package/dist/ai/types.d.ts +26 -0
  39. package/dist/ai/types.js +10 -0
  40. package/dist/app-builder/build.d.ts +14 -7
  41. package/dist/app-builder/build.js +195 -66
  42. package/dist/app-builder/client-config.js +3 -2
  43. package/dist/app-builder/paths.d.ts +0 -12
  44. package/dist/app-builder/paths.js +3 -20
  45. package/dist/app-builder/static-export.js +1 -1
  46. package/dist/app-builder/vercel-output.d.ts +1 -1
  47. package/dist/app-builder/vercel-output.js +5 -4
  48. package/dist/cache/build-cache.d.ts +27 -4
  49. package/dist/cache/build-cache.js +114 -47
  50. package/dist/cache/build-inputs.d.ts +13 -0
  51. package/dist/cache/build-inputs.js +19 -0
  52. package/dist/cache/index.d.ts +2 -1
  53. package/dist/cache/index.js +5 -1
  54. package/dist/catalog/normalize.js +3 -0
  55. package/dist/catalog/previews.js +5 -4
  56. package/dist/catalog/types.d.ts +8 -0
  57. package/dist/cli/create.js +1 -2
  58. package/dist/commands/build/index.d.ts +1 -1
  59. package/dist/commands/build/index.js +1 -1
  60. package/dist/commands/utils.d.ts +3 -3
  61. package/dist/config/defaults.js +7 -4
  62. package/dist/config/from-env.d.ts +4 -0
  63. package/dist/config/from-env.js +38 -1
  64. package/dist/config/helpers.js +2 -2
  65. package/dist/config/index.d.ts +0 -1
  66. package/dist/config/index.js +1 -4
  67. package/dist/config/loader.js +28 -2
  68. package/dist/config/resolve-env.d.ts +2 -1
  69. package/dist/config/resolve-env.js +28 -12
  70. package/dist/config/runtime.js +9 -11
  71. package/dist/handlebars.d.ts +10 -2
  72. package/dist/index.d.ts +12 -7
  73. package/dist/index.js +18 -22
  74. package/dist/nav/index.d.ts +2 -2
  75. package/dist/nav/registry.d.ts +3 -3
  76. package/dist/nav/registry.js +1 -1
  77. package/dist/nav/workspace.d.ts +3 -3
  78. package/dist/nav/workspace.js +1 -1
  79. package/dist/pipeline/figma.d.ts +13 -2
  80. package/dist/pipeline/figma.js +86 -46
  81. package/dist/pipeline/styles.js +1 -1
  82. package/dist/pipeline/validation.d.ts +1 -1
  83. package/dist/pipeline/validation.js +3 -3
  84. package/dist/providers.d.ts +10 -0
  85. package/dist/providers.js +13 -0
  86. package/dist/registry/asset-storage/define.d.ts +5 -5
  87. package/dist/registry/asset-storage/define.js +4 -4
  88. package/dist/registry/asset-storage/resolve.d.ts +9 -19
  89. package/dist/registry/asset-storage/resolve.js +33 -21
  90. package/dist/registry/asset-storage/types.d.ts +37 -17
  91. package/dist/registry/asset-storage/types.js +5 -5
  92. package/dist/registry/auth/ai-keys.d.ts +32 -0
  93. package/dist/registry/auth/ai-keys.js +69 -0
  94. package/dist/registry/auth/crypto.d.ts +17 -0
  95. package/dist/registry/auth/crypto.js +61 -1
  96. package/dist/registry/auth/index.d.ts +2 -1
  97. package/dist/registry/auth/index.js +11 -2
  98. package/dist/registry/checkout/index.d.ts +2 -1
  99. package/dist/registry/checkout/index.js +57 -127
  100. package/dist/registry/client.js +53 -17
  101. package/dist/registry/db/driver.js +3 -3
  102. package/dist/registry/db/schema.d.ts +261 -3
  103. package/dist/registry/db/schema.js +29 -4
  104. package/dist/registry/email/define.d.ts +10 -0
  105. package/dist/registry/email/define.js +13 -0
  106. package/dist/registry/email/providers/smtp.d.ts +10 -0
  107. package/dist/registry/email/providers/smtp.js +73 -0
  108. package/dist/registry/email/resolve.d.ts +28 -0
  109. package/dist/registry/email/resolve.js +74 -0
  110. package/dist/registry/email/types.d.ts +24 -0
  111. package/dist/registry/email/types.js +6 -0
  112. package/dist/registry/path.d.ts +2 -0
  113. package/dist/registry/path.js +11 -1
  114. package/dist/registry/publish/package.js +8 -0
  115. package/dist/registry/transfer.d.ts +4 -0
  116. package/dist/store/registry.d.ts +3 -3
  117. package/dist/store/registry.js +4 -4
  118. package/dist/transformers/plugins/ssr-render.js +40 -15
  119. package/dist/transformers/preview/component/builder.d.ts +1 -9
  120. package/dist/transformers/preview/component/builder.js +17 -17
  121. package/dist/transformers/preview/component/css.d.ts +3 -1
  122. package/dist/transformers/preview/component/css.js +92 -51
  123. package/dist/transformers/preview/component/html.d.ts +3 -1
  124. package/dist/transformers/preview/component/html.js +6 -2
  125. package/dist/transformers/preview/component/javascript.d.ts +2 -1
  126. package/dist/transformers/preview/component/javascript.js +10 -4
  127. package/dist/transformers/preview/pattern/html.js +3 -1
  128. package/dist/transformers/preview/types.d.ts +13 -0
  129. package/dist/transformers/utils/build.d.ts +24 -0
  130. package/dist/transformers/utils/build.js +100 -1
  131. package/dist/transformers/utils/module.js +2 -1
  132. package/dist/types/config.d.ts +135 -18
  133. package/dist/utils/path.d.ts +1 -5
  134. package/dist/utils/path.js +6 -23
  135. package/docs/api.md +6 -4
  136. package/docs/cli.md +275 -54
  137. package/drizzle/0007_add_ai_keys.sql +11 -0
  138. package/drizzle/0008_add_source_dir.sql +2 -0
  139. package/drizzle/meta/0007_snapshot.json +2013 -0
  140. package/drizzle/meta/0008_snapshot.json +2025 -0
  141. package/drizzle/meta/_journal.json +14 -0
  142. package/package.json +19 -8
  143. package/src/ai/README.md +42 -0
  144. package/src/ai/connections.ts +189 -0
  145. package/src/ai/define.ts +15 -0
  146. package/src/ai/types.ts +30 -0
  147. package/src/app/components/AiAssistant/AiAssistantPanel.tsx +144 -0
  148. package/src/app/components/AiAssistant/AiAssistantProvider.tsx +215 -0
  149. package/src/app/components/AiAssistant/AiConversation.tsx +737 -0
  150. package/src/app/components/AiAssistant/AiToolResult.tsx +99 -0
  151. package/src/app/components/AiAssistant/dockState.ts +86 -0
  152. package/src/app/components/AiAssistant/toolLabel.ts +24 -0
  153. package/src/app/components/AiAssistant/useAiChat.ts +147 -0
  154. package/src/app/components/AiAssistant/useAiConnections.ts +86 -0
  155. package/src/app/components/AiAssistant/usePageContext.ts +63 -0
  156. package/src/app/components/Auth/AccountLayout.tsx +58 -19
  157. package/src/app/components/Auth/AuthShell.tsx +27 -33
  158. package/src/app/components/Auth/RegistryInstallGate.tsx +4 -8
  159. package/src/app/components/Auth/installStatus.ts +29 -0
  160. package/src/app/components/Component/PageSliceResolver.tsx +1 -0
  161. package/src/app/components/Component/Preview.tsx +383 -189
  162. package/src/app/components/Component/slices/ComponentDisplaySlice.tsx +4 -0
  163. package/src/app/components/Foundations/ColorGrid.tsx +13 -14
  164. package/src/app/components/Layout/Header.tsx +21 -15
  165. package/src/app/components/Layout/Main.tsx +2 -2
  166. package/src/app/components/Markdown/MarkdownComponents.tsx +30 -32
  167. package/src/app/components/McpIntegration/McpConfigDialog.tsx +12 -51
  168. package/src/app/components/Navigation/MobileNav.tsx +2 -2
  169. package/src/app/components/Navigation/SideNav.tsx +1 -15
  170. package/src/app/components/context/NavProvider.tsx +7 -3
  171. package/src/app/components/ui/attachment.tsx +50 -0
  172. package/src/app/components/ui/bubble.tsx +57 -0
  173. package/src/app/components/ui/button.tsx +3 -1
  174. package/src/app/components/ui/confirm-dialog.tsx +87 -0
  175. package/src/app/components/ui/dialog.tsx +7 -2
  176. package/src/app/components/ui/marker.tsx +56 -0
  177. package/src/app/components/ui/sidebar.tsx +3 -1
  178. package/src/app/components/util/index.ts +3 -12
  179. package/src/app/css/index.css +64 -0
  180. package/src/app/lib/ai/auth.ts +33 -0
  181. package/src/app/lib/ai/context.ts +99 -0
  182. package/src/app/lib/ai/model.ts +79 -0
  183. package/src/app/lib/ai/prompt.ts +36 -0
  184. package/src/app/lib/ai/resolve.ts +97 -0
  185. package/src/app/lib/ai/tools.ts +120 -0
  186. package/src/app/lib/api/methods.ts +13 -0
  187. package/src/app/lib/asset-storage.ts +35 -36
  188. package/src/app/lib/auth/api.ts +4 -12
  189. package/src/app/lib/auth/email.ts +96 -23
  190. package/src/app/lib/docs-api/page-rendering.ts +1 -1
  191. package/src/app/lib/docs-api/registry.ts +2 -3
  192. package/src/app/lib/docs-api/runtime-config.ts +47 -21
  193. package/src/app/lib/mcp/components.ts +523 -0
  194. package/src/app/lib/mcp/page-url.ts +24 -0
  195. package/src/app/lib/mcp/pages.ts +84 -0
  196. package/src/app/lib/mcp/result.ts +33 -0
  197. package/src/app/lib/mcp/server.ts +39 -318
  198. package/src/app/lib/mcp/tokens.ts +334 -0
  199. package/src/app/lib/mcp/tool.ts +19 -0
  200. package/src/app/lib/registry-api/asset-transfer.ts +119 -11
  201. package/src/app/lib/registry-api/errors.ts +2 -0
  202. package/src/app/lib/registry-api/handler.ts +7 -1
  203. package/src/app/lib/registry-api/transfer.ts +28 -6
  204. package/src/app/lib/server-module.ts +34 -0
  205. package/src/app/lib/utils.ts +20 -0
  206. package/src/app/next.config.mjs +26 -24
  207. package/src/app/pages/[...slug]/index.tsx +2 -1
  208. package/src/app/pages/_app.tsx +6 -2
  209. package/src/app/pages/_document.tsx +6 -0
  210. package/src/app/pages/account/ai.tsx +183 -0
  211. package/src/app/pages/account/index.tsx +68 -68
  212. package/src/app/pages/account/tokens.tsx +37 -7
  213. package/src/app/pages/account/users.tsx +75 -15
  214. package/src/app/pages/api/account/ai/keys/[connectionId].ts +60 -0
  215. package/src/app/pages/api/account/ai/keys/index.ts +20 -0
  216. package/src/app/pages/api/admin/users/[id]/[action].ts +80 -11
  217. package/src/app/pages/api/admin/users/index.ts +2 -2
  218. package/src/app/pages/api/ai/chat.ts +115 -0
  219. package/src/app/pages/api/ai/connections.ts +23 -0
  220. package/src/app/pages/api/auth/request-reset.ts +14 -16
  221. package/src/app/pages/api/docs/nav.json.ts +1 -1
  222. package/src/app/pages/api/install.ts +3 -3
  223. package/src/app/pages/api/mcp.ts +6 -0
  224. package/src/app/pages/api/registry/transfer/assets/blobs/[hash]/complete.ts +11 -0
  225. package/src/app/pages/api/registry/transfer/assets/blobs/[hash]/upload.ts +12 -0
  226. package/src/app/pages/api/registry/transfer/assets/blobs/[hash].ts +1 -1
  227. package/src/app/pages/cli/device.tsx +10 -5
  228. package/src/app/pages/foundations/colors.tsx +9 -8
  229. package/src/app/pages/foundations/index.tsx +3 -3
  230. package/src/app/pages/index.tsx +2 -2
  231. package/src/app/pages/install.tsx +7 -2
  232. package/src/app/pages/login.tsx +32 -27
  233. package/src/app/pages/reset-password.tsx +21 -20
  234. package/src/app/pages/system/component/[component]/index.tsx +2 -5
  235. package/src/app/pages/system/index.tsx +11 -11
  236. package/src/app/pages/system/pattern/[pattern]/index.tsx +2 -2
  237. package/src/app/pages/system/tokens/components/[component]/index.tsx +0 -4
  238. package/src/app-builder/README.md +2 -1
  239. package/src/app-builder/build.ts +218 -73
  240. package/src/app-builder/client-config.ts +3 -2
  241. package/src/app-builder/paths.ts +3 -22
  242. package/src/app-builder/static-export.ts +1 -1
  243. package/src/app-builder/vercel-output.ts +5 -4
  244. package/src/cache/README.md +4 -1
  245. package/src/cache/build-cache.ts +128 -43
  246. package/src/cache/build-inputs.ts +28 -0
  247. package/src/cache/index.ts +4 -0
  248. package/src/catalog/README.md +3 -0
  249. package/src/catalog/normalize.ts +2 -0
  250. package/src/catalog/previews.ts +6 -3
  251. package/src/catalog/types.ts +8 -0
  252. package/src/cli/create.ts +1 -2
  253. package/src/commands/build/index.ts +1 -1
  254. package/src/config/README.md +10 -9
  255. package/src/config/defaults.ts +7 -4
  256. package/src/config/from-env.ts +33 -0
  257. package/src/config/helpers.ts +1 -3
  258. package/src/config/index.ts +0 -3
  259. package/src/config/loader.ts +27 -3
  260. package/src/config/resolve-env.ts +28 -15
  261. package/src/config/runtime.ts +10 -5
  262. package/src/handlebars.ts +8 -2
  263. package/src/index.ts +33 -29
  264. package/src/nav/index.ts +2 -2
  265. package/src/nav/registry.ts +3 -3
  266. package/src/nav/workspace.ts +3 -3
  267. package/src/pipeline/README.md +1 -1
  268. package/src/pipeline/figma.ts +98 -49
  269. package/src/pipeline/styles.ts +1 -1
  270. package/src/pipeline/validation.ts +3 -3
  271. package/src/providers.ts +18 -0
  272. package/src/registry/asset-storage/define.ts +6 -6
  273. package/src/registry/asset-storage/resolve.ts +38 -37
  274. package/src/registry/asset-storage/types.ts +39 -17
  275. package/src/registry/auth/ai-keys.ts +62 -0
  276. package/src/registry/auth/crypto.ts +63 -1
  277. package/src/registry/auth/index.ts +11 -1
  278. package/src/registry/checkout/index.ts +60 -138
  279. package/src/registry/client.ts +60 -20
  280. package/src/registry/db/driver.ts +2 -2
  281. package/src/registry/db/schema.ts +49 -22
  282. package/src/registry/email/define.ts +15 -0
  283. package/src/registry/email/providers/smtp.ts +39 -0
  284. package/src/registry/email/resolve.ts +94 -0
  285. package/src/registry/email/types.ts +28 -0
  286. package/src/registry/path.ts +11 -0
  287. package/src/registry/publish/package.ts +9 -0
  288. package/src/registry/transfer.ts +4 -0
  289. package/src/store/registry.ts +7 -7
  290. package/src/transformers/plugins/ssr-render.ts +53 -16
  291. package/src/transformers/preview/component/builder.ts +19 -25
  292. package/src/transformers/preview/component/css.ts +101 -53
  293. package/src/transformers/preview/component/html.ts +6 -2
  294. package/src/transformers/preview/component/javascript.ts +14 -4
  295. package/src/transformers/preview/pattern/html.ts +3 -1
  296. package/src/transformers/preview/types.ts +14 -0
  297. package/src/transformers/utils/build.ts +93 -0
  298. package/src/transformers/utils/module.ts +4 -2
  299. package/src/types/config.ts +148 -20
  300. package/src/utils/README.md +1 -1
  301. package/src/utils/path.ts +6 -29
  302. package/templates/default/handoff.config.js.tpl +10 -2
  303. package/templates/default/handoff.config.ts.tpl +10 -2
  304. package/templates/default/handoff.config.with-examples.js.tpl +10 -2
  305. package/templates/default/handoff.config.with-examples.ts.tpl +10 -2
  306. package/templates/default/package.json.tpl +2 -2
  307. package/.editorconfig +0 -19
  308. package/.eslintrc.json +0 -4
  309. package/.prettierignore +0 -0
  310. package/.prettierrc.json +0 -8
  311. package/.vscode/settings.json +0 -17
  312. package/dist/config/validator.d.ts +0 -9
  313. package/dist/config/validator.js +0 -24
  314. package/dist/registry/asset-storage/adapters/vercel-blob.d.ts +0 -17
  315. package/dist/registry/asset-storage/adapters/vercel-blob.js +0 -87
  316. package/src/app/components/old/Header.tsx +0 -89
  317. package/src/app/lib/mcp/shape.ts +0 -596
  318. package/src/app/pages/assets/fonts.tsx +0 -129
  319. package/src/app/pages/assets/index.tsx +0 -91
  320. package/src/app/pages/assets/logos.tsx +0 -75
  321. package/src/config/validator.ts +0 -22
  322. package/src/registry/asset-storage/adapters/vercel-blob.ts +0 -51
@@ -1,129 +0,0 @@
1
- import * as fs from 'fs-extra';
2
- import uniq from 'lodash/uniq';
3
- import { FileArchive } from 'lucide-react';
4
- import type { GetStaticProps } from 'next';
5
- import Head from 'next/head';
6
- import path from 'path';
7
- import * as React from 'react';
8
- import ReactMarkdown from 'react-markdown';
9
- import rehypeRaw from 'rehype-raw';
10
- import remarkGfm from 'remark-gfm';
11
- import Footer from '../../components/Footer';
12
- import { MarkdownComponents, remarkCodeMeta } from '../../components/Markdown/MarkdownComponents';
13
- import Header from '../../components/old/Header';
14
- import { buildTimeFoundationDesign, fetchDocPageMarkdown, FontDocumentationProps, getClientRuntimeConfig } from '../../components/util';
15
- import { useFoundationTokens } from '../../components/util/useFoundationTokens';
16
-
17
- const basePath = process.env.HANDOFF_APP_BASE_PATH ?? '';
18
- const isRegistry = process.env.HANDOFF_RUNTIME_MODE === 'registry';
19
-
20
- /**
21
- * This statically renders content from the markdown, creating menu and providing
22
- * metadata
23
- *
24
- * This is all done statically at build time
25
- * @param context GetStaticProps
26
- * @returns
27
- */
28
- export const getStaticProps: GetStaticProps = async () => {
29
- // Workspace/static reads the mirrored font archives; a registry build has none (hydrated at runtime).
30
- const customFonts: string[] = [];
31
- try {
32
- const fontDir = path.resolve(process.env.HANDOFF_MODULE_PATH ?? '', '.handoff', `${process.env.HANDOFF_PROJECT_ID}`, 'public', 'fonts');
33
- for (const font of fs.readdirSync(fontDir)) {
34
- if (font.endsWith('.zip')) customFonts.push(font.replace('.zip', ''));
35
- }
36
- } catch {
37
- // No local font archives (e.g. a registry build), so customFonts stays empty.
38
- }
39
-
40
- return {
41
- props: {
42
- ...(await fetchDocPageMarkdown('docs/assets/', 'fonts', `/assets`)).props,
43
- design: buildTimeFoundationDesign(),
44
- config: getClientRuntimeConfig(),
45
- customFonts,
46
- },
47
- };
48
- };
49
-
50
- const FontsPage = ({ content, menu, metadata, customFonts, design, config }: FontDocumentationProps) => {
51
- // Registry hydrates typography tokens (for the family list) + the published font archives at runtime.
52
- const tokens = useFoundationTokens('typography', { design });
53
- const [hydratedFonts, setHydratedFonts] = React.useState<string[]>(customFonts);
54
- React.useEffect(() => {
55
- if (!isRegistry) return;
56
- let active = true;
57
- fetch(`${basePath}/api/docs/assets/fonts`)
58
- .then((res) => (res.ok ? res.json() : null))
59
- .then((data) => {
60
- if (!active || !data?.assets) return;
61
- const names = (data.assets as { path: string }[])
62
- .filter((a) => typeof a.path === 'string' && /^fonts\/.+\.zip$/i.test(a.path))
63
- .map((a) => a.path.slice('fonts/'.length).replace(/\.zip$/i, ''));
64
- setHydratedFonts(names);
65
- })
66
- .catch(() => {});
67
- return () => {
68
- active = false;
69
- };
70
- }, []);
71
-
72
- const typography = tokens.design?.typography ?? [];
73
- const fontFamilies: string[] = uniq(typography.map((type) => type.values.fontFamily));
74
- const fontLinks: string[] = fontFamilies.map((fontFamily) => {
75
- const machineName = fontFamily.replace(/\s/g, '');
76
- const custom = hydratedFonts.find((font) => font === machineName);
77
- if (custom) {
78
- return isRegistry ? `${basePath}/api/docs/assets/fonts/fonts/${machineName}.zip` : `/fonts/${machineName}.zip`;
79
- }
80
- return `https://fonts.google.com/specimen/${fontFamily}`;
81
- });
82
- return (
83
- <div className="c-page">
84
- <Head>
85
- <title>{metadata.metaTitle}</title>
86
- <meta name="description" content={metadata.metaDescription} />
87
- </Head>
88
- <Header config={config} />
89
- <section className="c-content">
90
- <div className="o-container-fluid">
91
- <div className="c-hero">
92
- <div>
93
- <h1>{metadata.title}</h1>
94
- <p>{metadata.description}</p>
95
- </div>
96
- </div>
97
- {fontFamilies.map((fontFamily, i) => (
98
- <React.Fragment key={fontFamily}>
99
- <div className="o-row u-justify-between">
100
- <div className="o-col-5@md">
101
- <h4>{fontFamily}</h4>
102
- </div>
103
- <div className="o-col-6@md">
104
- <div className="c-card">
105
- <FileArchive />
106
- <h4>{fontFamily}</h4>
107
- <p>Font files for installing on a local machine.</p>
108
- <p>
109
- <a href={fontLinks[i]}>Download Font</a>
110
- </p>
111
- </div>
112
- </div>
113
- </div>
114
- <hr />
115
- </React.Fragment>
116
- ))}
117
-
118
- <div className="prose">
119
- <ReactMarkdown components={MarkdownComponents} remarkPlugins={[remarkGfm, remarkCodeMeta]} rehypePlugins={[rehypeRaw]}>
120
- {content}
121
- </ReactMarkdown>
122
- </div>
123
- </div>
124
- </section>
125
- <Footer config={config} />
126
- </div>
127
- );
128
- };
129
- export default FontsPage;
@@ -1,91 +0,0 @@
1
- import { File, FileArchive } from 'lucide-react';
2
- import type { GetStaticProps } from 'next';
3
- import Head from 'next/head';
4
- import ReactMarkdown from 'react-markdown';
5
- import rehypeRaw from 'rehype-raw';
6
- import remarkGfm from 'remark-gfm';
7
- import Footer from '../../components/Footer';
8
- import { MarkdownComponents, remarkCodeMeta } from '../../components/Markdown/MarkdownComponents';
9
- import NavLink from '../../components/NavLink';
10
- import Header from '../../components/old/Header';
11
- import { DocumentationProps, fetchDocPageMarkdown, getClientRuntimeConfig } from '../../components/util';
12
-
13
- /**
14
- * This statically renders content from the markdown, creating menu and providing
15
- * metadata
16
- *
17
- * This is all done statically at build time
18
- * @param context GetStaticProps
19
- * @returns
20
- */
21
- export const getStaticProps: GetStaticProps = async () => {
22
- return {
23
- props: {
24
- ...(await fetchDocPageMarkdown('docs/', 'assets', `/assets`)).props,
25
- config: getClientRuntimeConfig(),
26
- },
27
- };
28
- };
29
-
30
- const AssetsPage = ({ content, menu, metadata, config }: DocumentationProps) => {
31
- return (
32
- <div className="c-page">
33
- <Head>
34
- <title>{metadata.metaTitle}</title>
35
- <meta name="description" content={metadata.metaDescription} />
36
- </Head>
37
- <Header config={config} />
38
- <section className="c-content">
39
- <div className="o-container-fluid">
40
- <div className="c-hero c-hero--boxed c-hero--bg-red">
41
- <div>
42
- <h1 className="c-title--extra-large">{metadata.title}</h1>
43
- <p>{metadata.description}</p>
44
- </div>
45
- </div>
46
-
47
- <div className="o-row">
48
- <div className="o-col-6@md">
49
- <div className="c-card">
50
- <FileArchive />
51
- <h4>Logos</h4>
52
- <p>Official logo used for all digital and offline materials.</p>
53
- <p>
54
- <NavLink href="/assets/logos">View Logos</NavLink>
55
- </p>
56
- </div>
57
- </div>
58
- <div className="o-col-6@md">
59
- <div className="c-card">
60
- <FileArchive />
61
- <h4>Fonts</h4>
62
- <p>Font family and weights for all {config?.app?.client} visuals.</p>
63
- <p>
64
- <NavLink href="/assets/fonts">View Fonts</NavLink>
65
- </p>
66
- </div>
67
- </div>
68
- <div className="o-col-6@md">
69
- <div className="c-card">
70
- <File />
71
- <h4>Iconography</h4>
72
- <p>Library of approved vector iconography.</p>
73
- <p>
74
- <NavLink href="/assets/icons">View Icons</NavLink>
75
- </p>
76
- </div>
77
- </div>
78
- </div>
79
-
80
- <div className="prose">
81
- <ReactMarkdown components={MarkdownComponents} remarkPlugins={[remarkGfm, remarkCodeMeta]} rehypePlugins={[rehypeRaw]}>
82
- {content}
83
- </ReactMarkdown>
84
- </div>
85
- </div>
86
- </section>
87
- <Footer config={config} />
88
- </div>
89
- );
90
- };
91
- export default AssetsPage;
@@ -1,75 +0,0 @@
1
- import { FileArchive } from 'lucide-react';
2
- import type { GetStaticProps } from 'next';
3
- import Head from 'next/head';
4
- import ReactMarkdown from 'react-markdown';
5
- import rehypeRaw from 'rehype-raw';
6
- import remarkGfm from 'remark-gfm';
7
- import Footer from '../../components/Footer';
8
- import { MarkdownComponents, remarkCodeMeta } from '../../components/Markdown/MarkdownComponents';
9
- import { buildAssetDownloadUrl } from '@handoff/artifacts/url';
10
- import Header from '../../components/old/Header';
11
- import { DocumentationProps, fetchDocPageMarkdown, getClientRuntimeConfig } from '../../components/util';
12
-
13
- /**
14
- * This statically renders content from the markdown, creating menu and providing
15
- * metadata
16
- *
17
- * This is all done statically at build time
18
- * @param context GetStaticProps
19
- * @returns
20
- */
21
- export const getStaticProps: GetStaticProps = async () => {
22
- return {
23
- props: {
24
- ...(await fetchDocPageMarkdown('docs/assets/', 'logos', `/assets`)).props,
25
- config: getClientRuntimeConfig(),
26
- },
27
- };
28
- };
29
-
30
- const AssetsLogosPage = ({ content, menu, metadata, config }: DocumentationProps) => {
31
- return (
32
- <div className="c-page">
33
- <Head>
34
- <title>{metadata.metaTitle}</title>
35
- <meta name="description" content={metadata.metaDescription} />
36
- </Head>
37
- <Header config={config} />
38
- <section className="c-content">
39
- <div className="o-container-fluid">
40
- <div className="c-hero">
41
- <div>
42
- <h1>{metadata.title}</h1>
43
- <p>{metadata.description}</p>
44
- </div>
45
- </div>
46
- <div className="o-row u-justify-between">
47
- <div className="o-col-5@md">
48
- <h4>{config?.app?.client} Logo</h4>
49
- </div>
50
- <div className="o-col-6@md">
51
- <div className="c-card">
52
- <FileArchive />
53
- <h4>{config?.app?.client} Logo</h4>
54
- <p>Vector files of approved {config?.app?.client} logos.</p>
55
- <p>
56
- <a href={config?.assets_zip_links?.logos ?? buildAssetDownloadUrl('logos', process.env.HANDOFF_APP_BASE_PATH)} download>
57
- Download Logos
58
- </a>
59
- </p>
60
- </div>
61
- </div>
62
- </div>
63
- <div className="prose">
64
- <ReactMarkdown components={MarkdownComponents} remarkPlugins={[remarkGfm, remarkCodeMeta]} rehypePlugins={[rehypeRaw]}>
65
- {content}
66
- </ReactMarkdown>
67
- </div>
68
- <hr />
69
- </div>
70
- </section>
71
- <Footer config={config} />
72
- </div>
73
- );
74
- };
75
- export default AssetsLogosPage;
@@ -1,22 +0,0 @@
1
- import { ResolvedConfig } from '../types/config';
2
- import { Logger } from '../utils/logger';
3
-
4
- /**
5
- * Validates that the configuration has the required Figma credentials.
6
- *
7
- * @param config - The config to validate.
8
- * @returns The validated config (same reference).
9
- * @throws {Error} If required Figma credentials are missing.
10
- */
11
- export const validateConfig = (config: ResolvedConfig): ResolvedConfig => {
12
- // TODO: Check to see if the exported folder exists before we run start
13
- if (!config.figma_project_id) {
14
- Logger.error('Figma Project ID missing. Please set HANDOFF_FIGMA_PROJECT_ID or run "handoff-app fetch".');
15
- throw new Error('Cannot initialize configuration');
16
- }
17
- if (!config.dev_access_token) {
18
- Logger.error('Figma Access Token missing. Please set HANDOFF_DEV_ACCESS_TOKEN or run "handoff-app fetch".');
19
- throw new Error('Cannot initialize configuration');
20
- }
21
- return config;
22
- };
@@ -1,51 +0,0 @@
1
- /**
2
- * Pre-packaged Vercel Blob asset storage adapter.
3
- *
4
- * Ships with Handoff and is selected via `runtime.registry.assetStorage.adapter: "vercel-blob"`. The
5
- * read/write token is read from `process.env[tokenEnv]` at request time (never persisted in config).
6
- * Blobs are stored public and content-addressed by hash, so reads resolve to a direct provider URL
7
- * (a `redirect` result), keeping large payloads out of the serverless function body/response.
8
- *
9
- * The `@vercel/blob` SDK is loaded lazily so it is only pulled into memory (and traced into the
10
- * registry bundle) when this adapter is actually used.
11
- */
12
-
13
- import type { AssetStorage } from '../types';
14
-
15
- /** Build a Vercel Blob storage adapter bound to a token env-var name + non-secret options. */
16
- export const createVercelBlobStorage = (params: { tokenEnv: string; options: Record<string, unknown> }): AssetStorage => {
17
- const prefix = typeof params.options.prefix === 'string' && params.options.prefix.trim() ? params.options.prefix.trim() : 'handoff/assets';
18
-
19
- const resolveToken = (): string => {
20
- const token = process.env[params.tokenEnv]?.trim();
21
- if (!token) {
22
- throw new Error(
23
- `Vercel Blob storage is configured but the token env var "${params.tokenEnv}" is not set. ` +
24
- 'Set it to a Blob read/write token, or change runtime.registry.assetStorage.token.'
25
- );
26
- }
27
- return token;
28
- };
29
-
30
- return {
31
- async put({ hash, bytes, contentType }) {
32
- const { put } = await import('@vercel/blob');
33
- // Content-addressed pathname + no random suffix so the same bytes map to a stable, dedupable key.
34
- const result = await put(`${prefix}/${hash}`, bytes, {
35
- access: 'public',
36
- token: resolveToken(),
37
- contentType,
38
- addRandomSuffix: false,
39
- });
40
- return { storageRef: result.url };
41
- },
42
- async get(storageRef) {
43
- // Public blob URLs are directly fetchable; redirect the client to avoid proxying bytes.
44
- return { kind: 'redirect', url: storageRef };
45
- },
46
- async delete(storageRef) {
47
- const { del } = await import('@vercel/blob');
48
- await del(storageRef, { token: resolveToken() });
49
- },
50
- };
51
- };