@woodsportal/hubspot-kit 1.0.4 → 1.0.26

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 (217) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +4 -2
  3. package/dist/{chunk-JDGIAYHX.js → chunk-GTTIJVAR.js} +43 -3
  4. package/dist/chunk-GTTIJVAR.js.map +1 -0
  5. package/dist/cli.js +1400 -338
  6. package/dist/cli.js.map +1 -1
  7. package/dist/exec-U2OJATR3.js +12 -0
  8. package/dist/index.d.ts +20 -0
  9. package/dist/index.js +8 -1
  10. package/dist/index.js.map +1 -1
  11. package/examples/greenfield/module-hybrid-cdn/README.md +40 -3
  12. package/examples/greenfield/module-hybrid-cdn/public/fields.json +44 -1
  13. package/examples/greenfield/module-hybrid-cdn/src/app.tsx +8 -0
  14. package/examples/greenfield/module-hybrid-cdn/src/assets/css/main.dev.css +6 -1
  15. package/examples/greenfield/module-hybrid-cdn/src/cdn/app-entry.ts +32 -0
  16. package/examples/greenfield/module-hybrid-cdn/src/cdn/vendor-entry.ts +28 -0
  17. package/examples/greenfield/module-hybrid-cdn/src/components/layout/section-card.tsx +20 -0
  18. package/examples/greenfield/module-hybrid-cdn/src/components/layout/starter-nav.tsx +28 -0
  19. package/examples/greenfield/module-hybrid-cdn/src/components/layout/starter-shell.tsx +18 -0
  20. package/examples/greenfield/module-hybrid-cdn/src/config/router.ts +4 -0
  21. package/examples/greenfield/module-hybrid-cdn/src/config/routes.ts +5 -0
  22. package/examples/greenfield/module-hybrid-cdn/src/defaultData.ts +2 -7
  23. package/examples/greenfield/module-hybrid-cdn/src/features/starter/components/starter-guide-page.tsx +93 -0
  24. package/examples/greenfield/module-hybrid-cdn/src/features/starter/components/starter-home-page.tsx +21 -0
  25. package/examples/greenfield/module-hybrid-cdn/src/features/starter/components/starter-home.tsx +52 -0
  26. package/examples/greenfield/module-hybrid-cdn/src/features/starter/components/starter-single-page.tsx +17 -0
  27. package/examples/greenfield/module-hybrid-cdn/src/features/starter/content/woodscli-guide-content.ts +86 -0
  28. package/examples/greenfield/module-hybrid-cdn/src/features/starter/hooks/use-starter-preview.ts +47 -0
  29. package/examples/greenfield/module-hybrid-cdn/src/features/starter/index.ts +6 -0
  30. package/examples/greenfield/module-hybrid-cdn/src/hubspot/bootstrap.ts +10 -0
  31. package/examples/greenfield/module-hybrid-cdn/src/hubspot/default-data.ts +7 -0
  32. package/examples/greenfield/module-hybrid-cdn/src/integrations/tanstack-router/router.tsx +25 -0
  33. package/examples/greenfield/module-hybrid-cdn/src/main.tsx +4 -3
  34. package/examples/greenfield/module-hybrid-cdn/src/portal/mount-dev-preview.tsx +8 -0
  35. package/examples/greenfield/module-hybrid-cdn/src/portal/mount-portal.tsx +12 -0
  36. package/examples/greenfield/module-hybrid-cdn/src/routeTree.gen.ts +77 -0
  37. package/examples/greenfield/module-hybrid-cdn/src/routes/__root.tsx +15 -0
  38. package/examples/greenfield/module-hybrid-cdn/src/routes/guide.tsx +7 -0
  39. package/examples/greenfield/module-hybrid-cdn/src/routes/index.tsx +7 -0
  40. package/examples/greenfield/module-hybrid-cdn/tsconfig.json +20 -0
  41. package/examples/greenfield/module-monolith/public/fields.json +44 -1
  42. package/examples/greenfield/module-monolith/src/app.tsx +8 -0
  43. package/examples/greenfield/module-monolith/src/assets/css/main.dev.css +8 -0
  44. package/examples/greenfield/module-monolith/src/components/layout/section-card.tsx +20 -0
  45. package/examples/greenfield/module-monolith/src/components/layout/starter-nav.tsx +28 -0
  46. package/examples/greenfield/module-monolith/src/components/layout/starter-shell.tsx +18 -0
  47. package/examples/greenfield/module-monolith/src/config/router.ts +4 -0
  48. package/examples/greenfield/module-monolith/src/config/routes.ts +5 -0
  49. package/examples/greenfield/module-monolith/src/defaultData.ts +2 -7
  50. package/examples/greenfield/module-monolith/src/features/starter/components/starter-guide-page.tsx +93 -0
  51. package/examples/greenfield/module-monolith/src/features/starter/components/starter-home-page.tsx +21 -0
  52. package/examples/greenfield/module-monolith/src/features/starter/components/starter-home.tsx +52 -0
  53. package/examples/greenfield/module-monolith/src/features/starter/components/starter-single-page.tsx +17 -0
  54. package/examples/greenfield/module-monolith/src/features/starter/content/woodscli-guide-content.ts +86 -0
  55. package/examples/greenfield/module-monolith/src/features/starter/hooks/use-starter-preview.ts +47 -0
  56. package/examples/greenfield/module-monolith/src/features/starter/index.ts +6 -0
  57. package/examples/greenfield/module-monolith/src/hubspot/default-data.ts +7 -0
  58. package/examples/greenfield/module-monolith/src/hubspot/types.ts +17 -0
  59. package/examples/greenfield/module-monolith/src/integrations/tanstack-router/router.tsx +25 -0
  60. package/examples/greenfield/module-monolith/src/main.tsx +5 -0
  61. package/examples/greenfield/module-monolith/src/portal/mount-dev-preview.tsx +8 -0
  62. package/examples/greenfield/module-monolith/src/portal/mount-portal.tsx +12 -0
  63. package/examples/greenfield/module-monolith/src/routeTree.gen.ts +77 -0
  64. package/examples/greenfield/module-monolith/src/routes/__root.tsx +15 -0
  65. package/examples/greenfield/module-monolith/src/routes/guide.tsx +7 -0
  66. package/examples/greenfield/module-monolith/src/routes/index.tsx +7 -0
  67. package/examples/greenfield/module-monolith/tsconfig.json +20 -0
  68. package/package.json +4 -1
  69. package/scripts/check-hubspot-bundle-size.mjs +5 -2
  70. package/scripts/ensure-wphs-workspace.mjs +2 -1
  71. package/scripts/hubspot-module-postbuild.mjs +1 -1
  72. package/scripts/read-woodsportal-config.mjs +4 -1
  73. package/scripts/run-hubspot-module-postbuild.mjs +9 -4
  74. package/scripts/vite/bootstrap-shim-resolver.js +47 -0
  75. package/scripts/vite/ensure-dev-kit-shims.js +7 -1
  76. package/scripts/vite/react-dev-plugin-options.js +2 -1
  77. package/scripts/watch-hubspot.mjs +107 -17
  78. package/scripts/wphs-paths.mjs +1 -0
  79. package/scripts/write-audit-artifacts.mjs +2 -1
  80. package/src/dev/bootstrap-greenfield.tsx +59 -0
  81. package/src/dev/bootstrap.tsx +46 -0
  82. package/src/dev-module-config/__tests__/fixtures/fields.json +3014 -0
  83. package/src/dev-module-config/__tests__/fixtures/golden-module.fixture.ts +102 -0
  84. package/src/dev-module-config/__tests__/module-config-storage.test.ts +40 -0
  85. package/src/dev-module-config/__tests__/module-config-transform.test.ts +55 -0
  86. package/src/dev-module-config/__tests__/normalize-repeater-items.test.ts +46 -0
  87. package/src/dev-module-config/dev-module-display-name.ts +5 -0
  88. package/src/dev-module-config/runtime/module-config-bridge.ts +27 -0
  89. package/src/dev-module-config/runtime/module-config-runtime.ts +185 -0
  90. package/src/dev-module-config/schema/build-default-item.ts +7 -0
  91. package/src/dev-module-config/schema/deep-merge.ts +27 -0
  92. package/src/dev-module-config/schema/extract-defaults.ts +62 -0
  93. package/src/dev-module-config/schema/normalize-choices.ts +18 -0
  94. package/src/dev-module-config/schema/normalize-repeater-items.ts +31 -0
  95. package/src/dev-module-config/schema/parse-fields-json.ts +2 -0
  96. package/src/dev-module-config/schema/types.ts +75 -0
  97. package/src/dev-module-config/schema/validate-module-config.ts +81 -0
  98. package/src/dev-module-config/schema/visibility.ts +130 -0
  99. package/src/dev-module-config/storage/config-json.ts +46 -0
  100. package/src/dev-module-config/storage/workspace-store.ts +139 -0
  101. package/src/dev-module-config/transform/build-hubspot-data.ts +409 -0
  102. package/src/dev-module-config/ui/FieldRenderer.tsx +353 -0
  103. package/src/dev-module-config/ui/ModuleConfigAnimatedPresence.tsx +72 -0
  104. package/src/dev-module-config/ui/ModuleConfigCollapsible.tsx +43 -0
  105. package/src/dev-module-config/ui/ModuleConfigDockSideIcon.tsx +27 -0
  106. package/src/dev-module-config/ui/ModuleConfigOverlay.tsx +134 -0
  107. package/src/dev-module-config/ui/ModuleConfigPersistenceStatus.tsx +89 -0
  108. package/src/dev-module-config/ui/ModuleConfigShell.tsx +355 -0
  109. package/src/dev-module-config/ui/ModuleConfigThemeToggle.tsx +32 -0
  110. package/src/dev-module-config/ui/ModuleConfigUiContext.tsx +65 -0
  111. package/src/dev-module-config/ui/editors/DeveloperOptionsEditor.tsx +61 -0
  112. package/src/dev-module-config/ui/editors/MenuOptionsEditor.tsx +103 -0
  113. package/src/dev-module-config/ui/hubspot/HsColorField.tsx +106 -0
  114. package/src/dev-module-config/ui/hubspot/HsColorPickerPopover.tsx +210 -0
  115. package/src/dev-module-config/ui/hubspot/HsFieldLabel.tsx +24 -0
  116. package/src/dev-module-config/ui/hubspot/HsFieldWidgets.tsx +248 -0
  117. package/src/dev-module-config/ui/hubspot/HsImageField.tsx +112 -0
  118. package/src/dev-module-config/ui/hubspot/HsOccurrenceGroupEditor.tsx +243 -0
  119. package/src/dev-module-config/ui/hubspot/HsRepeaterList.tsx +178 -0
  120. package/src/dev-module-config/ui/hubspot/HsSectionHeader.tsx +20 -0
  121. package/src/dev-module-config/ui/hubspot/HsToggle.tsx +39 -0
  122. package/src/dev-module-config/ui/hubspot/HsToggleRow.tsx +30 -0
  123. package/src/dev-module-config/ui/hubspot/hs-color-palette.ts +11 -0
  124. package/src/dev-module-config/ui/hubspot/module-config-typography.ts +26 -0
  125. package/src/dev-module-config/ui/module-config-motion.css +134 -0
  126. package/src/dev-module-config/ui/module-config-motion.ts +28 -0
  127. package/src/dev-module-config/ui/module-config-overlay-side.ts +29 -0
  128. package/src/dev-module-config/ui/module-config-surfaces.ts +27 -0
  129. package/src/dev-module-config/ui/module-config-theme.css +489 -0
  130. package/src/dev-module-config/ui/module-config-toolbar-theme.ts +35 -0
  131. package/src/dev-module-config/ui/navigation/ModuleConfigNavContext.tsx +194 -0
  132. package/src/dev-module-config/ui/use-dev-module-config-live-revision.ts +22 -0
  133. package/src/dev-module-config/ui/use-hubspot-live-exports.ts +27 -0
  134. package/src/dev-module-config/ui/use-module-config.ts +124 -0
  135. package/src/routing/build-api-routes.ts +37 -0
  136. package/src/routing/route-format.ts +19 -0
  137. package/templates/module-hybrid-cdn/README.md +53 -3
  138. package/templates/module-hybrid-cdn/index.html +12 -1
  139. package/templates/module-hybrid-cdn/package.json +6 -2
  140. package/templates/module-hybrid-cdn/public/fields.json +44 -1
  141. package/templates/module-hybrid-cdn/src/app.tsx +8 -0
  142. package/templates/module-hybrid-cdn/src/assets/css/main.dev.css +6 -1
  143. package/templates/module-hybrid-cdn/src/cdn/app-entry.ts +32 -0
  144. package/templates/module-hybrid-cdn/src/cdn/vendor-entry.ts +28 -0
  145. package/templates/module-hybrid-cdn/src/components/layout/section-card.tsx +20 -0
  146. package/templates/module-hybrid-cdn/src/components/layout/starter-nav.tsx +28 -0
  147. package/templates/module-hybrid-cdn/src/components/layout/starter-shell.tsx +18 -0
  148. package/templates/module-hybrid-cdn/src/config/router.ts +4 -0
  149. package/templates/module-hybrid-cdn/src/config/routes.ts +5 -0
  150. package/templates/module-hybrid-cdn/src/defaultData.ts +2 -7
  151. package/templates/module-hybrid-cdn/src/features/starter/components/starter-guide-page.tsx +93 -0
  152. package/templates/module-hybrid-cdn/src/features/starter/components/starter-home-page.tsx +21 -0
  153. package/templates/module-hybrid-cdn/src/features/starter/components/starter-home.tsx +52 -0
  154. package/templates/module-hybrid-cdn/src/features/starter/components/starter-single-page.tsx +17 -0
  155. package/templates/module-hybrid-cdn/src/features/starter/content/woodscli-guide-content.ts +86 -0
  156. package/templates/module-hybrid-cdn/src/features/starter/hooks/starter-preview-values.ts +42 -0
  157. package/templates/module-hybrid-cdn/src/features/starter/hooks/use-starter-preview.dev.ts +17 -0
  158. package/templates/module-hybrid-cdn/src/features/starter/hooks/use-starter-preview.ts +30 -0
  159. package/templates/module-hybrid-cdn/src/features/starter/index.ts +6 -0
  160. package/templates/module-hybrid-cdn/src/hubspot/bootstrap.ts +10 -0
  161. package/templates/module-hybrid-cdn/src/hubspot/default-data.ts +7 -0
  162. package/templates/module-hybrid-cdn/src/hubspot/module-entry.tsx +9 -0
  163. package/templates/module-hybrid-cdn/src/integrations/tanstack-router/router.tsx +25 -0
  164. package/templates/module-hybrid-cdn/src/main.tsx +4 -3
  165. package/templates/module-hybrid-cdn/src/portal/mount-dev-preview.tsx +8 -0
  166. package/templates/module-hybrid-cdn/src/portal/mount-portal.tsx +12 -0
  167. package/templates/module-hybrid-cdn/src/routeTree.gen.ts +77 -0
  168. package/templates/module-hybrid-cdn/src/routes/__root.tsx +15 -0
  169. package/templates/module-hybrid-cdn/src/routes/guide.tsx +7 -0
  170. package/templates/module-hybrid-cdn/src/routes/index.tsx +7 -0
  171. package/templates/module-hybrid-cdn/tsconfig.json +20 -0
  172. package/templates/module-hybrid-cdn/vite.config.monolith.mjs +8 -0
  173. package/templates/module-monolith/README.md +59 -0
  174. package/templates/module-monolith/index.html +12 -0
  175. package/templates/module-monolith/package.json +10 -3
  176. package/templates/module-monolith/public/fields.json +44 -1
  177. package/templates/module-monolith/public/module.html +1 -0
  178. package/templates/module-monolith/src/app.tsx +8 -0
  179. package/templates/module-monolith/src/assets/css/main.dev.css +6 -1
  180. package/templates/module-monolith/src/components/layout/section-card.tsx +20 -0
  181. package/templates/module-monolith/src/components/layout/starter-nav.tsx +28 -0
  182. package/templates/module-monolith/src/components/layout/starter-shell.tsx +18 -0
  183. package/templates/module-monolith/src/config/router.ts +4 -0
  184. package/templates/module-monolith/src/config/routes.ts +5 -0
  185. package/templates/module-monolith/src/defaultData.ts +2 -7
  186. package/templates/module-monolith/src/features/starter/components/starter-guide-page.tsx +93 -0
  187. package/templates/module-monolith/src/features/starter/components/starter-home-page.tsx +21 -0
  188. package/templates/module-monolith/src/features/starter/components/starter-home.tsx +52 -0
  189. package/templates/module-monolith/src/features/starter/components/starter-single-page.tsx +17 -0
  190. package/templates/module-monolith/src/features/starter/content/woodscli-guide-content.ts +86 -0
  191. package/templates/module-monolith/src/features/starter/hooks/starter-preview-values.ts +42 -0
  192. package/templates/module-monolith/src/features/starter/hooks/use-starter-preview.dev.ts +17 -0
  193. package/templates/module-monolith/src/features/starter/hooks/use-starter-preview.ts +30 -0
  194. package/templates/module-monolith/src/features/starter/index.ts +6 -0
  195. package/templates/module-monolith/src/hubspot/default-data.ts +7 -0
  196. package/templates/module-monolith/src/hubspot/module-entry.tsx +9 -0
  197. package/templates/module-monolith/src/integrations/tanstack-router/router.tsx +25 -0
  198. package/templates/module-monolith/src/main.tsx +4 -3
  199. package/templates/module-monolith/src/portal/mount-dev-preview.tsx +8 -0
  200. package/templates/module-monolith/src/portal/mount-portal.tsx +12 -0
  201. package/templates/module-monolith/src/routeTree.gen.ts +77 -0
  202. package/templates/module-monolith/src/routes/__root.tsx +15 -0
  203. package/templates/module-monolith/src/routes/guide.tsx +7 -0
  204. package/templates/module-monolith/src/routes/index.tsx +7 -0
  205. package/templates/module-monolith/tsconfig.json +20 -0
  206. package/templates/module-monolith/vite.config.monolith.mjs +8 -0
  207. package/templates/module-monolith/woodscli.json +1 -0
  208. package/templates/shared/.env.dev.example +5 -0
  209. package/templates/shared/.env.prod.example +5 -0
  210. package/templates/shared/.env.stg.example +3 -0
  211. package/templates/shared/portal.cdn.json.example +8 -0
  212. package/templates/theme-starter/package.json +5 -2
  213. package/vite/vite.config.dev.mjs +9 -1
  214. package/vite/vite.config.monolith.mjs +22 -17
  215. package/dist/chunk-JDGIAYHX.js.map +0 -1
  216. package/dist/exec-K5C6LZP4.js +0 -10
  217. /package/dist/{exec-K5C6LZP4.js.map → exec-U2OJATR3.js.map} +0 -0
@@ -0,0 +1,7 @@
1
+ import { createFileRoute } from '@tanstack/react-router'
2
+
3
+ import { StarterHomePage } from '@/features/starter'
4
+
5
+ export const Route = createFileRoute('/')({
6
+ component: StarterHomePage,
7
+ })
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "jsx": "react-jsx",
5
+ "module": "ESNext",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "types": ["vite/client"],
8
+ "moduleResolution": "bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "verbatimModuleSyntax": true,
11
+ "noEmit": true,
12
+ "skipLibCheck": true,
13
+ "strict": true,
14
+ "baseUrl": ".",
15
+ "paths": {
16
+ "@/*": ["./src/*"]
17
+ }
18
+ },
19
+ "include": ["src/**/*.ts", "src/**/*.tsx", "wphs.adapter.ts"]
20
+ }
@@ -0,0 +1,8 @@
1
+ import { dirname, resolve } from 'node:path'
2
+ import { fileURLToPath } from 'node:url'
3
+
4
+ if (!process.env.WP_HS_PROJECT_ROOT?.trim()) {
5
+ process.env.WP_HS_PROJECT_ROOT = resolve(dirname(fileURLToPath(import.meta.url)))
6
+ }
7
+
8
+ export { default } from '@woodsportal/hubspot-kit/vite/vite.config.monolith.mjs'
@@ -0,0 +1,59 @@
1
+ # Getting started
2
+
3
+ This project was scaffolded with **WoodsCLI** (`@woodsportal/hubspot-kit`).
4
+
5
+ ## Daily dev
6
+
7
+ ```bash
8
+ yarn install
9
+ wp doctor
10
+ wp dev
11
+ ```
12
+
13
+ Open the local URL, then **Ctrl+Shift+Z** (Mac **⌃⇧Z**) to edit module fields. Click **Apply changes** to refresh the starter preview.
14
+
15
+ ## Routing (`wp init`)
16
+
17
+ Default is **hash history** — same as `woodsportal-client-frontend` (`#/guide` URLs work in HubSpot CMS).
18
+
19
+ | `wp init --router` | Behavior |
20
+ |--------------------|----------|
21
+ | `hash` (default) | `createHashHistory()` — production-safe in HubSpot embeds |
22
+ | `browser` | Clean `/guide` URLs for local dev only |
23
+ | `none` | Single-page starter, no TanStack Router |
24
+
25
+ Recorded in `woodscli.json` → `scaffold.router`.
26
+
27
+ ## `src/` layout
28
+
29
+ | Path | Purpose |
30
+ |------|---------|
31
+ | `main.tsx` | Dev entry — loads styles and `mountDevPreview()` |
32
+ | `app.tsx` | `RouterProvider` shell (client-frontend pattern) |
33
+ | `config/router.ts` | Hash vs browser history |
34
+ | `portal/` | Dev vs production mount (`mount-dev-preview`, `mount-portal`) |
35
+ | `routes/` | TanStack file routes — keep thin; import from `features/` |
36
+ | `features/starter/` | Demo home + developer guide (replace with your app) |
37
+ | `components/` | Shared layout and UI |
38
+ | `integrations/` | Router and third-party wiring |
39
+ | `hubspot/` | HubSpot types and dev fixtures |
40
+ | `config/` | Route constants and app config |
41
+ | `assets/css/` | Tailwind entry for local dev |
42
+
43
+ Kit runtime expects `src/defaultData.ts` (re-exports `hubspot/default-data.ts`).
44
+
45
+ ## Docs (in the kit package)
46
+
47
+ After `npm install`, see:
48
+
49
+ - `node_modules/@woodsportal/hubspot-kit/docs/CLI-REFERENCE.md`
50
+ - `node_modules/@woodsportal/hubspot-kit/docs/MODULES.md`
51
+ - `node_modules/@woodsportal/hubspot-kit/docs/HUBSPOT-CLI-SETUP.md`
52
+
53
+ ## HubSpot upload
54
+
55
+ ```bash
56
+ cp hubspot.config.yml.example hubspot.config.yml
57
+ # add portal + personal access key
58
+ wp upload
59
+ ```
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>WoodsCLI dev preview</title>
7
+ </head>
8
+ <body>
9
+ <div id="app"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -5,15 +5,22 @@
5
5
  "scripts": {
6
6
  "local": "wp dev",
7
7
  "doctor": "wp doctor",
8
+ "build:dev": "wp build --tier dev",
8
9
  "build:prod": "wp build --tier prod",
9
- "deploy:prod": "wp deploy --tier prod"
10
+ "deploy:dev": "wp deploy --tier dev --yes",
11
+ "deploy:prod": "wp deploy --tier prod --yes",
12
+ "watch": "wp watch --rebuild"
10
13
  },
11
14
  "devDependencies": {
12
- "@woodsportal/hubspot-kit": "^1.0.4",
15
+ "@woodsportal/hubspot-kit": "^1.0.11",
16
+ "@dnd-kit/core": "^6.3.1",
17
+ "@dnd-kit/sortable": "^10.0.0",
18
+ "@dnd-kit/utilities": "^3.2.2",
13
19
  "@tailwindcss/vite": "^4.0.6",
20
+ "@tanstack/react-router": "^1.121.2",
14
21
  "@tanstack/router-plugin": "^1.121.2",
15
22
  "@vitejs/plugin-react": "^4.3.4",
16
- "babel-plugin-react-compiler": "^1.0.0",
23
+ "babel-plugin-react-compiler": "^1.0.11",
17
24
  "react": "^19.0.0",
18
25
  "react-dom": "^19.0.0",
19
26
  "tailwindcss": "^4.0.6",
@@ -1 +1,44 @@
1
- [{"name":"title","label":"Title","type":"text","default":"WoodsCLI module"}]
1
+ [
2
+ {
3
+ "name": "title",
4
+ "label": "Portal title",
5
+ "type": "text",
6
+ "tab": "CONTENT",
7
+ "default": "My HubSpot Portal"
8
+ },
9
+ {
10
+ "name": "tagline",
11
+ "label": "Tagline",
12
+ "type": "text",
13
+ "tab": "CONTENT",
14
+ "help_text": "Subtitle shown under the hero title in the local dev preview.",
15
+ "default": "Customize this preview with Ctrl+Shift+Z, then replace StarterPage with your portal app."
16
+ },
17
+ {
18
+ "name": "show_feature_cards",
19
+ "label": "Show feature cards",
20
+ "type": "boolean",
21
+ "display": "toggle",
22
+ "tab": "CONTENT",
23
+ "default": true
24
+ },
25
+ {
26
+ "name": "accent_color",
27
+ "label": "Accent color",
28
+ "type": "color",
29
+ "tab": "STYLE",
30
+ "default": { "color": "#0091ae", "opacity": 100 }
31
+ },
32
+ {
33
+ "name": "hero_style",
34
+ "label": "Hero style",
35
+ "type": "choice",
36
+ "tab": "STYLE",
37
+ "choices": [
38
+ ["gradient", "Gradient"],
39
+ ["minimal", "Minimal"],
40
+ ["bold", "Bold"]
41
+ ],
42
+ "default": "gradient"
43
+ }
44
+ ]
@@ -0,0 +1 @@
1
+ <div id="app"></div>
@@ -0,0 +1,8 @@
1
+ import { RouterProvider } from '@tanstack/react-router'
2
+
3
+ import { router } from '@/integrations/tanstack-router/router'
4
+
5
+ /** Root app shell — same pattern as woodsportal-client-frontend `App`. */
6
+ export function App() {
7
+ return <RouterProvider router={router} />
8
+ }
@@ -1,3 +1,8 @@
1
1
  @import 'tailwindcss';
2
2
 
3
- @source '../../.wphs/**/*.{js,jsx,ts,tsx}';
3
+ /* Kit dev-module-config — paths relative to this file (src/assets/css/) */
4
+ @source '../../../.wphs/.kit-module-config/**/*.{ts,tsx}';
5
+ @source '../../../.wphs/.kit-bootstrap.tsx';
6
+ @source '../../../.wphs/.kit-bootstrap-greenfield.tsx';
7
+ @source '../../../src/**/*.{ts,tsx}';
8
+ @source '../../../node_modules/@woodsportal/hubspot-kit/src/dev-module-config/**/*.{ts,tsx}';
@@ -0,0 +1,20 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ export function SectionCard({
4
+ title,
5
+ children,
6
+ className = '',
7
+ }: {
8
+ title: string
9
+ children: ReactNode
10
+ className?: string
11
+ }) {
12
+ return (
13
+ <section
14
+ className={`rounded-lg border border-[#cbd6e2] bg-white p-6 shadow-sm ${className}`}
15
+ >
16
+ <h2 className="text-base font-semibold text-[#33475b]">{title}</h2>
17
+ <div className="mt-4">{children}</div>
18
+ </section>
19
+ )
20
+ }
@@ -0,0 +1,28 @@
1
+ import { Link } from '@tanstack/react-router'
2
+
3
+ import { ROUTES } from '@/config/routes'
4
+
5
+ export function StarterNav() {
6
+ return (
7
+ <header className="border-b border-[#cbd6e2] bg-white/90 backdrop-blur">
8
+ <div className="mx-auto flex max-w-4xl items-center justify-between gap-4 px-6 py-3 sm:px-10">
9
+ <span className="text-sm font-semibold text-[#0091ae]">WoodsCLI starter</span>
10
+ <nav className="flex gap-4 text-sm font-medium">
11
+ <Link
12
+ to={ROUTES.home}
13
+ className="text-[#516f90] hover:text-[#0091ae] [&.active]:text-[#0091ae]"
14
+ activeOptions={{ exact: true }}
15
+ >
16
+ Home
17
+ </Link>
18
+ <Link
19
+ to={ROUTES.guide}
20
+ className="text-[#516f90] hover:text-[#0091ae] [&.active]:text-[#0091ae]"
21
+ >
22
+ Developer guide
23
+ </Link>
24
+ </nav>
25
+ </div>
26
+ </header>
27
+ )
28
+ }
@@ -0,0 +1,18 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ import { StarterNav } from './starter-nav'
4
+
5
+ export function StarterShell({
6
+ children,
7
+ showNav = true,
8
+ }: {
9
+ children: ReactNode
10
+ showNav?: boolean
11
+ }) {
12
+ return (
13
+ <div className="min-h-screen bg-[#eaf0f6] text-[#33475b]">
14
+ {showNav ? <StarterNav /> : null}
15
+ {children}
16
+ </div>
17
+ )
18
+ }
@@ -0,0 +1,4 @@
1
+ /** Router history — set by `wp init`. Hash matches woodsportal-client-frontend (HubSpot CMS embeds). */
2
+ export type RouterHistoryMode = 'hash' | 'browser'
3
+
4
+ export const ROUTER_HISTORY: RouterHistoryMode = 'hash'
@@ -0,0 +1,5 @@
1
+ /** Route paths — keep in sync with `src/routes/` file routes. */
2
+ export const ROUTES = {
3
+ home: '/',
4
+ guide: '/guide',
5
+ } as const
@@ -1,7 +1,2 @@
1
- /** Local dev fixtures for module-config runtime (greenfield wp init). */
2
- export const defaultData = {
3
- dataSourceSet: [],
4
- hubId: 'dev',
5
- userData: {},
6
- objectList: [] as unknown[],
7
- }
1
+ /** Kit runtime imports `@/defaultData` — re-export from the hubspot slice. */
2
+ export { devDefaultData as defaultData } from './hubspot/default-data'
@@ -0,0 +1,93 @@
1
+ import { SectionCard } from '@/components/layout/section-card'
2
+
3
+ import {
4
+ DEV_WORKFLOW,
5
+ PROJECT_LAYOUT,
6
+ WOODSCLI_ABOUT,
7
+ WOODSCLI_COMMANDS,
8
+ } from '../content/woodscli-guide-content'
9
+
10
+ export function StarterGuidePage() {
11
+ return (
12
+ <main className="mx-auto max-w-4xl space-y-8 px-6 py-10 sm:px-10">
13
+ <div>
14
+ <h1 className="text-2xl font-semibold tracking-tight">Developer guide</h1>
15
+ <p className="mt-2 text-sm leading-relaxed text-[#516f90]">
16
+ Commands, project layout, and workflow for this WoodsCLI module. Routes live in{' '}
17
+ <code className="font-mono text-xs">src/routes/</code> and delegate to{' '}
18
+ <code className="font-mono text-xs">src/features/</code>.
19
+ </p>
20
+ </div>
21
+
22
+ <SectionCard title="About WoodsCLI">
23
+ <p className="text-sm leading-relaxed text-[#516f90]">{WOODSCLI_ABOUT.tagline}</p>
24
+ <p className="mt-3 text-sm leading-relaxed text-[#516f90]">{WOODSCLI_ABOUT.docsHint}</p>
25
+ </SectionCard>
26
+
27
+ <SectionCard title="Essential commands">
28
+ <ul className="divide-y divide-[#eaf0f6]">
29
+ {WOODSCLI_COMMANDS.map(({ cmd, desc }) => (
30
+ <li key={cmd} className="flex flex-col gap-1 py-3 first:pt-0 last:pb-0 sm:flex-row sm:gap-4">
31
+ <code className="shrink-0 rounded bg-[#eaf0f6] px-2 py-1 font-mono text-xs text-[#0091ae]">
32
+ {cmd}
33
+ </code>
34
+ <span className="text-sm leading-relaxed text-[#516f90]">{desc}</span>
35
+ </li>
36
+ ))}
37
+ </ul>
38
+ </SectionCard>
39
+
40
+ <SectionCard title="Project layout">
41
+ <ul className="space-y-3">
42
+ {PROJECT_LAYOUT.map(({ path, note }) => (
43
+ <li key={path} className="text-sm leading-relaxed">
44
+ <code className="rounded bg-[#eaf0f6] px-1.5 py-0.5 font-mono text-xs text-[#33475b]">
45
+ {path}
46
+ </code>
47
+ <span className="mt-1 block text-[#516f90] sm:mt-0 sm:inline sm:before:content-['—_']">
48
+ {note}
49
+ </span>
50
+ </li>
51
+ ))}
52
+ </ul>
53
+ </SectionCard>
54
+
55
+ <SectionCard title="Developer workflow">
56
+ <ol className="space-y-4">
57
+ {DEV_WORKFLOW.map(({ title: stepTitle, body }) => (
58
+ <li key={stepTitle}>
59
+ <h3 className="text-sm font-medium text-[#33475b]">{stepTitle}</h3>
60
+ <p className="mt-1 text-sm leading-relaxed text-[#516f90]">{body}</p>
61
+ </li>
62
+ ))}
63
+ </ol>
64
+ </SectionCard>
65
+
66
+ <SectionCard title="Routing">
67
+ <p className="text-sm leading-relaxed text-[#516f90]">
68
+ This starter uses the same TanStack Router setup as{' '}
69
+ <code className="font-mono text-xs">woodsportal-client-frontend</code>: file routes under{' '}
70
+ <code className="font-mono text-xs">src/routes/</code>,{' '}
71
+ <code className="font-mono text-xs">src/app.tsx</code> with{' '}
72
+ <code className="font-mono text-xs">RouterProvider</code>, and{' '}
73
+ <strong>hash history</strong> by default (
74
+ <code className="font-mono text-xs">src/config/router.ts</code>) so routes work inside
75
+ HubSpot CMS embeds. Run <code className="font-mono text-xs">wp init</code> again on a new
76
+ folder to choose browser history or no router. Add{' '}
77
+ <code className="font-mono text-xs">src/routes/about.tsx</code> and restart{' '}
78
+ <code className="font-mono text-xs">wp dev</code> to regenerate{' '}
79
+ <code className="font-mono text-xs">routeTree.gen.ts</code>.
80
+ </p>
81
+ </SectionCard>
82
+
83
+ <SectionCard title="Customize this preview">
84
+ <p className="text-sm leading-relaxed text-[#516f90]">
85
+ Edit <code className="font-mono text-xs">public/fields.json</code> to add module fields,
86
+ then adjust <code className="font-mono text-xs">src/features/starter/</code> to bind them.
87
+ Replace the starter feature with your own under{' '}
88
+ <code className="font-mono text-xs">src/features/</code> when you outgrow the demo.
89
+ </p>
90
+ </SectionCard>
91
+ </main>
92
+ )
93
+ }
@@ -0,0 +1,21 @@
1
+ import { Link } from '@tanstack/react-router'
2
+
3
+ import { ROUTES } from '@/config/routes'
4
+
5
+ import { StarterHome } from './starter-home'
6
+
7
+ export function StarterHomePage() {
8
+ return (
9
+ <>
10
+ <StarterHome />
11
+ <div className="mx-auto max-w-4xl px-6 pb-10 sm:px-10">
12
+ <Link
13
+ to={ROUTES.guide}
14
+ className="inline-flex items-center rounded-md bg-[#0091ae] px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-[#007a8c]"
15
+ >
16
+ Open developer guide →
17
+ </Link>
18
+ </div>
19
+ </>
20
+ )
21
+ }
@@ -0,0 +1,52 @@
1
+ import { useStarterPreview } from '../hooks/use-starter-preview'
2
+ import { STARTER_FEATURES, WOODSCLI_ABOUT } from '../content/woodscli-guide-content'
3
+
4
+ function heroClass(style: ReturnType<typeof useStarterPreview>['heroStyle']): string {
5
+ if (style === 'minimal') {
6
+ return 'bg-[var(--mc-bg-shell,#f5f8fa)] text-[var(--mc-text,#33475b)] border-b border-[var(--mc-border,#cbd6e2)]'
7
+ }
8
+ if (style === 'bold') {
9
+ return 'bg-[#1c1c1f] text-white'
10
+ }
11
+ return 'bg-gradient-to-br from-[var(--starter-accent,#0091ae)] to-[#ff7a59] text-white'
12
+ }
13
+
14
+ export function StarterHome() {
15
+ const { title, tagline, showFeatureCards, accentColor, heroStyle } = useStarterPreview()
16
+
17
+ return (
18
+ <>
19
+ <div style={{ ['--starter-accent' as string]: accentColor }}>
20
+ <section className={`px-6 py-14 sm:px-10 sm:py-16 ${heroClass(heroStyle)}`}>
21
+ <div className="mx-auto max-w-4xl">
22
+ <p className="mb-2 text-xs font-semibold uppercase tracking-widest opacity-80">
23
+ {WOODSCLI_ABOUT.package} · local dev
24
+ </p>
25
+ <h1 className="text-3xl font-semibold tracking-tight sm:text-4xl">{title}</h1>
26
+ <p className="mt-4 max-w-2xl text-base leading-relaxed opacity-90 sm:text-lg">{tagline}</p>
27
+ <p className="mt-6 text-sm opacity-75">
28
+ Module config overlay:{' '}
29
+ <kbd className="rounded bg-black/10 px-1.5 py-0.5 font-mono text-xs">Ctrl+Shift+Z</kbd>
30
+ {' · '}
31
+ Mac: <kbd className="rounded bg-black/10 px-1.5 py-0.5 font-mono text-xs">⌃⇧Z</kbd>
32
+ </p>
33
+ </div>
34
+ </section>
35
+ </div>
36
+
37
+ {showFeatureCards ? (
38
+ <div className="mx-auto grid max-w-4xl gap-4 px-6 py-10 sm:grid-cols-3 sm:px-10">
39
+ {STARTER_FEATURES.map((feature) => (
40
+ <article
41
+ key={feature.title}
42
+ className="rounded-lg border border-[#cbd6e2] bg-white p-5 shadow-sm"
43
+ >
44
+ <h2 className="text-sm font-semibold text-[#0091ae]">{feature.title}</h2>
45
+ <p className="mt-2 text-sm leading-relaxed text-[#516f90]">{feature.body}</p>
46
+ </article>
47
+ ))}
48
+ </div>
49
+ ) : null}
50
+ </>
51
+ )
52
+ }
@@ -0,0 +1,17 @@
1
+ import { StarterShell } from '@/components/layout/starter-shell'
2
+
3
+ import { StarterGuidePage } from './starter-guide-page'
4
+ import { StarterHome } from './starter-home'
5
+
6
+ /** Single-page starter when `wp init --router none` (no TanStack Router). */
7
+ export function StarterSinglePage() {
8
+ return (
9
+ <StarterShell showNav={false}>
10
+ <StarterHome />
11
+ <div className="mx-auto max-w-4xl px-6 sm:px-10">
12
+ <hr className="my-10 border-[#cbd6e2]" />
13
+ </div>
14
+ <StarterGuidePage />
15
+ </StarterShell>
16
+ )
17
+ }
@@ -0,0 +1,86 @@
1
+ /** Static WoodsCLI developer reference — shown on the wp init starter pages. */
2
+
3
+ export const WOODSCLI_COMMANDS = [
4
+ {
5
+ cmd: 'wp dev',
6
+ desc: 'Local Vite preview + module-config overlay (this page). Alias: wp local.',
7
+ },
8
+ {
9
+ cmd: 'wp doctor',
10
+ desc: 'Validate Node, deps, .wphs/, index.html, fields.json, and HubSpot CLI setup.',
11
+ },
12
+ {
13
+ cmd: 'wp build --tier prod',
14
+ desc: 'Production build (CDN bundle and/or HubSpot module, per projectType).',
15
+ },
16
+ {
17
+ cmd: 'wp deploy --tier prod',
18
+ desc: 'Build, publish CDN artifacts, and upload the module to HubSpot.',
19
+ },
20
+ {
21
+ cmd: 'wp adopt',
22
+ desc: 'Add woodscli.json + .wphs/ to an existing module or theme repo.',
23
+ },
24
+ {
25
+ cmd: 'wp migrate --yes',
26
+ desc: 'Move legacy .dev/ or woodsportal.hs.json to .wphs/ + woodscli.json.',
27
+ },
28
+ ] as const
29
+
30
+ export const PROJECT_LAYOUT = [
31
+ { path: 'woodscli.json', note: 'Project config — module paths, entries, dev.adapter' },
32
+ { path: 'public/fields.json', note: 'HubSpot module field schema (Content / Styles tabs)' },
33
+ { path: '.wphs/', note: 'Local workspace — config, fixtures, kit symlinks (gitignore most)' },
34
+ { path: 'wphs.adapter.ts', note: 'Syncs module field values → window.__WPHS_DATA__ in dev' },
35
+ { path: 'src/config/router.ts', note: 'Hash vs browser history — set by wp init (hash = client-frontend)' },
36
+ { path: 'src/routes/', note: 'TanStack Router file routes (thin — delegate to features/)' },
37
+ { path: 'src/app.tsx', note: 'RouterProvider shell — same role as woodsportal-client-frontend App' },
38
+ { path: 'src/features/starter/', note: 'Starter demo UI — replace with your portal features' },
39
+ { path: 'src/portal/', note: 'Dev vs production mount (mount-dev-preview, mount-portal)' },
40
+ { path: 'src/integrations/', note: 'Third-party wiring (TanStack Router, SDK, etc.)' },
41
+ { path: 'src/hubspot/', note: 'HubSpot runtime types and dev fixtures' },
42
+ { path: 'src/main.tsx', note: 'Dev entry — mounts overlay + routed preview' },
43
+ { path: 'hubspot.config.yml', note: 'HubSpot CLI portal + PAT (copy from .example)' },
44
+ ] as const
45
+
46
+ export const DEV_WORKFLOW = [
47
+ {
48
+ title: '1 · Edit module fields',
49
+ body: 'Press Ctrl+Shift+Z (Mac ⌃⇧Z) to open the HubSpot-style Content / Styles panel. Changes apply to the preview after you click Apply changes.',
50
+ },
51
+ {
52
+ title: '2 · Iterate in src/',
53
+ body: 'Add features under src/features/, shared UI under src/components/, and wire HubSpot data via wphs.adapter.ts and public/fields.json.',
54
+ },
55
+ {
56
+ title: '3 · Connect HubSpot',
57
+ body: 'Copy hubspot.config.yml.example → hubspot.config.yml, add a personal access key, then wp upload or wp watch for CMS sync.',
58
+ },
59
+ {
60
+ title: '4 · Ship',
61
+ body: 'Hybrid CDN: wp deploy. Monolith: wp build --hubspot-only then wp upload. Advanced apps: wp adopt on woodsportal-client-frontend.',
62
+ },
63
+ ] as const
64
+
65
+ export const WOODSCLI_ABOUT = {
66
+ package: '@woodsportal/hubspot-kit',
67
+ tagline:
68
+ 'WoodsCLI is WoodsPortal’s dev kit for HubSpot CMS modules and themes — Vite local preview, fields.json editing, CDN + module build pipelines, and HubSpot CLI integration.',
69
+ docsHint:
70
+ 'Full command list and guides ship in node_modules/@woodsportal/hubspot-kit/docs/ (CLI-REFERENCE.md, MODULES.md, HUBSPOT-CLI-SETUP.md).',
71
+ } as const
72
+
73
+ export const STARTER_FEATURES = [
74
+ {
75
+ title: 'Module fields',
76
+ body: 'Content and Styles tabs mirror HubSpot’s module editor. Apply changes to refresh this preview.',
77
+ },
78
+ {
79
+ title: 'Local persistence',
80
+ body: 'Saved values land in .wphs/config/module-config.local.json — safe to gitignore.',
81
+ },
82
+ {
83
+ title: 'Ship when ready',
84
+ body: 'Run wp build and wp deploy, or wp adopt to merge into the full WoodsPortal client app.',
85
+ },
86
+ ] as const
@@ -0,0 +1,42 @@
1
+ export type StarterPreviewValues = {
2
+ title: string
3
+ tagline: string
4
+ showFeatureCards: boolean
5
+ accentColor: string
6
+ heroStyle: 'gradient' | 'minimal' | 'bold'
7
+ }
8
+
9
+ function normalizeHeroStyle(raw: unknown): StarterPreviewValues['heroStyle'] {
10
+ const key = String(raw ?? 'gradient').toLowerCase()
11
+ if (key === 'minimal' || key === 'bold') return key
12
+ return 'gradient'
13
+ }
14
+
15
+ export function mapStarterPreviewValues(module: Record<string, unknown>): StarterPreviewValues {
16
+ const accent = module.accent_color as { color?: string } | undefined
17
+
18
+ return {
19
+ title: String(module.title ?? 'My HubSpot Portal'),
20
+ tagline: String(
21
+ module.tagline ??
22
+ 'Customize this preview with Ctrl+Shift+Z, then replace this page with your portal app.',
23
+ ),
24
+ showFeatureCards: module.show_feature_cards !== false,
25
+ accentColor: accent?.color ?? '#0091ae',
26
+ heroStyle: normalizeHeroStyle(module.hero_style),
27
+ }
28
+ }
29
+
30
+ /** HubSpot module field blob on window (dev adapter + CMS runtime). */
31
+ export function readStarterModuleFields(): Record<string, unknown> {
32
+ const win = window as Window & {
33
+ __WPHS_DATA__?: Record<string, unknown>
34
+ hubSpotData?: Record<string, unknown>
35
+ }
36
+ const blob = win.__WPHS_DATA__ ?? win.hubSpotData ?? {}
37
+ const nested = blob.module
38
+ if (nested && typeof nested === 'object') {
39
+ return nested as Record<string, unknown>
40
+ }
41
+ return blob
42
+ }
@@ -0,0 +1,17 @@
1
+ import { MODULE_CONFIG_CHANGED } from '@/dev/module-config/schema/types'
2
+ import { getModuleFieldValues } from '@/dev/module-config/runtime/module-config-runtime'
3
+
4
+ import {
5
+ mapStarterPreviewValues,
6
+ type StarterPreviewValues,
7
+ } from './starter-preview-values'
8
+
9
+ /** Dev-only: refresh when module-config overlay applies changes. */
10
+ export function subscribeStarterPreview(
11
+ onChange: (values: StarterPreviewValues) => void,
12
+ ): () => void {
13
+ const refresh = () => onChange(mapStarterPreviewValues(getModuleFieldValues()))
14
+
15
+ window.addEventListener(MODULE_CONFIG_CHANGED, refresh)
16
+ return () => window.removeEventListener(MODULE_CONFIG_CHANGED, refresh)
17
+ }