@growthub/cli 0.7.9 → 0.8.1

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 (179) hide show
  1. package/assets/worker-kits/creative-strategist-v1/SKILL.md +95 -0
  2. package/assets/worker-kits/creative-strategist-v1/bundles/creative-strategist-v1.json +12 -2
  3. package/assets/worker-kits/creative-strategist-v1/helpers/README.md +29 -0
  4. package/assets/worker-kits/creative-strategist-v1/helpers/extract-muse-frames.sh +81 -0
  5. package/assets/worker-kits/creative-strategist-v1/helpers/grep-hooks.sh +62 -0
  6. package/assets/worker-kits/creative-strategist-v1/kit.json +20 -2
  7. package/assets/worker-kits/creative-strategist-v1/skills/README.md +23 -0
  8. package/assets/worker-kits/creative-strategist-v1/skills/frame-analysis/SKILL.md +88 -0
  9. package/assets/worker-kits/creative-strategist-v1/templates/project.md +48 -0
  10. package/assets/worker-kits/creative-strategist-v1/templates/self-eval.md +67 -0
  11. package/assets/worker-kits/creative-strategist-v1/workers/creative-strategist/CLAUDE.md +22 -0
  12. package/assets/worker-kits/growthub-agency-portal-starter-v1/.env.example +53 -0
  13. package/assets/worker-kits/growthub-agency-portal-starter-v1/QUICKSTART.md +98 -0
  14. package/assets/worker-kits/growthub-agency-portal-starter-v1/SKILL.md +89 -0
  15. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/.env.example +25 -0
  16. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/README.md +36 -0
  17. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/app/api/settings/integrations/route.js +13 -0
  18. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/app/api/workspace/route.js +27 -0
  19. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/app/globals.css +237 -0
  20. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/app/layout.jsx +14 -0
  21. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/app/page.jsx +165 -0
  22. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/app/settings/integrations/page.jsx +134 -0
  23. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/lib/adapters/auth/index.js +21 -0
  24. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/lib/adapters/env.js +28 -0
  25. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/lib/adapters/integrations/growthub-connection-normalizer.js +95 -0
  26. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/lib/adapters/integrations/index.js +178 -0
  27. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/lib/adapters/payments/index.js +13 -0
  28. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/lib/adapters/persistence/index.js +13 -0
  29. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/lib/adapters/persistence/postgres.js +16 -0
  30. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/lib/adapters/persistence/provider-managed.js +16 -0
  31. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/lib/adapters/persistence/qstash-kv.js +16 -0
  32. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/lib/domain/integrations.js +185 -0
  33. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/lib/domain/portal.js +16 -0
  34. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/next.config.js +10 -0
  35. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/package-lock.json +976 -0
  36. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/package.json +17 -0
  37. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/postcss.config.mjs +3 -0
  38. package/assets/worker-kits/growthub-agency-portal-starter-v1/apps/agency-portal/vercel.json +5 -0
  39. package/assets/worker-kits/growthub-agency-portal-starter-v1/brands/NEW-CLIENT.md +10 -0
  40. package/assets/worker-kits/growthub-agency-portal-starter-v1/brands/_template/brand-kit.md +27 -0
  41. package/assets/worker-kits/growthub-agency-portal-starter-v1/brands/growthub/brand-kit.md +25 -0
  42. package/assets/worker-kits/growthub-agency-portal-starter-v1/bundles/growthub-agency-portal-starter-v1.json +65 -0
  43. package/assets/worker-kits/growthub-agency-portal-starter-v1/docs/adapter-contracts.md +79 -0
  44. package/assets/worker-kits/growthub-agency-portal-starter-v1/docs/fork-sync-integration.md +32 -0
  45. package/assets/worker-kits/growthub-agency-portal-starter-v1/docs/governed-workspace-primitives.md +182 -0
  46. package/assets/worker-kits/growthub-agency-portal-starter-v1/docs/starter-kit-overview.md +30 -0
  47. package/assets/worker-kits/growthub-agency-portal-starter-v1/docs/vercel-serverless-deployment.md +46 -0
  48. package/assets/worker-kits/growthub-agency-portal-starter-v1/docs/vite-ui-shell-guide.md +24 -0
  49. package/assets/worker-kits/growthub-agency-portal-starter-v1/examples/portal-brief-sample.md +44 -0
  50. package/assets/worker-kits/growthub-agency-portal-starter-v1/examples/workspace-sample.md +10 -0
  51. package/assets/worker-kits/growthub-agency-portal-starter-v1/growthub-meta/README.md +11 -0
  52. package/assets/worker-kits/growthub-agency-portal-starter-v1/growthub-meta/kit-standard.md +16 -0
  53. package/assets/worker-kits/growthub-agency-portal-starter-v1/helpers/README.md +49 -0
  54. package/assets/worker-kits/growthub-agency-portal-starter-v1/kit.json +156 -0
  55. package/assets/worker-kits/growthub-agency-portal-starter-v1/output/README.md +13 -0
  56. package/assets/worker-kits/growthub-agency-portal-starter-v1/output-standards.md +25 -0
  57. package/assets/worker-kits/growthub-agency-portal-starter-v1/runtime-assumptions.md +15 -0
  58. package/assets/worker-kits/growthub-agency-portal-starter-v1/setup/check-deps.sh +20 -0
  59. package/assets/worker-kits/growthub-agency-portal-starter-v1/setup/verify-env.mjs +92 -0
  60. package/assets/worker-kits/growthub-agency-portal-starter-v1/skills/README.md +55 -0
  61. package/assets/worker-kits/growthub-agency-portal-starter-v1/skills.md +133 -0
  62. package/assets/worker-kits/growthub-agency-portal-starter-v1/studio/index.html +12 -0
  63. package/assets/worker-kits/growthub-agency-portal-starter-v1/studio/package-lock.json +1677 -0
  64. package/assets/worker-kits/growthub-agency-portal-starter-v1/studio/package.json +20 -0
  65. package/assets/worker-kits/growthub-agency-portal-starter-v1/studio/serve.mjs +42 -0
  66. package/assets/worker-kits/growthub-agency-portal-starter-v1/studio/src/App.jsx +162 -0
  67. package/assets/worker-kits/growthub-agency-portal-starter-v1/studio/src/app.css +138 -0
  68. package/assets/worker-kits/growthub-agency-portal-starter-v1/studio/src/main.jsx +10 -0
  69. package/assets/worker-kits/growthub-agency-portal-starter-v1/studio/vite.config.js +8 -0
  70. package/assets/worker-kits/growthub-agency-portal-starter-v1/templates/agent-contract.md +9 -0
  71. package/assets/worker-kits/growthub-agency-portal-starter-v1/templates/client-onboarding-plan.md +56 -0
  72. package/assets/worker-kits/growthub-agency-portal-starter-v1/templates/deployment-handoff.md +61 -0
  73. package/assets/worker-kits/growthub-agency-portal-starter-v1/templates/deployment-plan.md +22 -0
  74. package/assets/worker-kits/growthub-agency-portal-starter-v1/templates/portal-brief.md +65 -0
  75. package/assets/worker-kits/growthub-agency-portal-starter-v1/templates/project.md +55 -0
  76. package/assets/worker-kits/growthub-agency-portal-starter-v1/templates/self-eval.md +67 -0
  77. package/assets/worker-kits/growthub-agency-portal-starter-v1/templates/supabase-setup-plan.md +26 -0
  78. package/assets/worker-kits/growthub-agency-portal-starter-v1/templates/workspace-brief.md +11 -0
  79. package/assets/worker-kits/growthub-agency-portal-starter-v1/validation-checklist.md +32 -0
  80. package/assets/worker-kits/growthub-agency-portal-starter-v1/workers/agency-portal-operator/CLAUDE.md +75 -0
  81. package/assets/worker-kits/growthub-ai-website-cloner-v1/SKILL.md +89 -0
  82. package/assets/worker-kits/growthub-ai-website-cloner-v1/bundles/growthub-ai-website-cloner-v1.json +9 -2
  83. package/assets/worker-kits/growthub-ai-website-cloner-v1/helpers/README.md +29 -0
  84. package/assets/worker-kits/growthub-ai-website-cloner-v1/kit.json +14 -2
  85. package/assets/worker-kits/growthub-ai-website-cloner-v1/skills/README.md +23 -0
  86. package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/project.md +48 -0
  87. package/assets/worker-kits/growthub-ai-website-cloner-v1/templates/self-eval.md +67 -0
  88. package/assets/worker-kits/growthub-ai-website-cloner-v1/workers/ai-website-cloner-operator/CLAUDE.md +22 -0
  89. package/assets/worker-kits/growthub-custom-workspace-starter-v1/SKILL.md +122 -0
  90. package/assets/worker-kits/growthub-custom-workspace-starter-v1/bundles/growthub-custom-workspace-starter-v1.json +14 -2
  91. package/assets/worker-kits/growthub-custom-workspace-starter-v1/docs/governed-workspace-primitives.md +182 -0
  92. package/assets/worker-kits/growthub-custom-workspace-starter-v1/helpers/README.md +44 -0
  93. package/assets/worker-kits/growthub-custom-workspace-starter-v1/kit.json +16 -2
  94. package/assets/worker-kits/growthub-custom-workspace-starter-v1/skills/README.md +55 -0
  95. package/assets/worker-kits/growthub-custom-workspace-starter-v1/templates/project.md +55 -0
  96. package/assets/worker-kits/growthub-custom-workspace-starter-v1/templates/self-eval.md +67 -0
  97. package/assets/worker-kits/growthub-custom-workspace-starter-v1/workers/custom-workspace-operator/CLAUDE.md +24 -2
  98. package/assets/worker-kits/growthub-email-marketing-v1/SKILL.md +90 -0
  99. package/assets/worker-kits/growthub-email-marketing-v1/bundles/growthub-email-marketing-v1.json +9 -2
  100. package/assets/worker-kits/growthub-email-marketing-v1/helpers/README.md +29 -0
  101. package/assets/worker-kits/growthub-email-marketing-v1/kit.json +14 -2
  102. package/assets/worker-kits/growthub-email-marketing-v1/skills/README.md +23 -0
  103. package/assets/worker-kits/growthub-email-marketing-v1/templates/project.md +48 -0
  104. package/assets/worker-kits/growthub-email-marketing-v1/templates/self-eval.md +67 -0
  105. package/assets/worker-kits/growthub-email-marketing-v1/workers/email-marketing-strategist/CLAUDE.md +22 -0
  106. package/assets/worker-kits/growthub-geo-seo-v1/SKILL.md +90 -0
  107. package/assets/worker-kits/growthub-geo-seo-v1/bundles/growthub-geo-seo-v1.json +12 -3
  108. package/assets/worker-kits/growthub-geo-seo-v1/helpers/README.md +29 -0
  109. package/assets/worker-kits/growthub-geo-seo-v1/kit.json +23 -5
  110. package/assets/worker-kits/growthub-geo-seo-v1/skills/README.md +23 -0
  111. package/assets/worker-kits/growthub-geo-seo-v1/templates/project.md +48 -0
  112. package/assets/worker-kits/growthub-geo-seo-v1/templates/self-eval.md +67 -0
  113. package/assets/worker-kits/growthub-geo-seo-v1/workers/geo-seo-operator/CLAUDE.md +22 -0
  114. package/assets/worker-kits/growthub-hyperframes-studio-v1/SKILL.md +89 -0
  115. package/assets/worker-kits/growthub-hyperframes-studio-v1/bundles/growthub-hyperframes-studio-v1.json +6 -1
  116. package/assets/worker-kits/growthub-hyperframes-studio-v1/helpers/README.md +29 -0
  117. package/assets/worker-kits/growthub-hyperframes-studio-v1/kit.json +14 -2
  118. package/assets/worker-kits/growthub-hyperframes-studio-v1/skills/README.md +23 -0
  119. package/assets/worker-kits/growthub-hyperframes-studio-v1/templates/project.md +48 -0
  120. package/assets/worker-kits/growthub-hyperframes-studio-v1/templates/self-eval.md +67 -0
  121. package/assets/worker-kits/growthub-hyperframes-studio-v1/workers/hyperframes-studio-operator/CLAUDE.md +22 -0
  122. package/assets/worker-kits/growthub-marketing-skills-v1/SKILL.md +90 -0
  123. package/assets/worker-kits/growthub-marketing-skills-v1/bundles/growthub-marketing-skills-v1.json +12 -3
  124. package/assets/worker-kits/growthub-marketing-skills-v1/helpers/README.md +29 -0
  125. package/assets/worker-kits/growthub-marketing-skills-v1/kit.json +23 -5
  126. package/assets/worker-kits/growthub-marketing-skills-v1/skills/README.md +23 -0
  127. package/assets/worker-kits/growthub-marketing-skills-v1/templates/project.md +48 -0
  128. package/assets/worker-kits/growthub-marketing-skills-v1/templates/self-eval.md +67 -0
  129. package/assets/worker-kits/growthub-marketing-skills-v1/workers/marketing-operator/CLAUDE.md +22 -0
  130. package/assets/worker-kits/growthub-open-higgsfield-studio-v1/SKILL.md +89 -0
  131. package/assets/worker-kits/growthub-open-higgsfield-studio-v1/bundles/growthub-open-higgsfield-studio-v1.json +9 -2
  132. package/assets/worker-kits/growthub-open-higgsfield-studio-v1/helpers/README.md +29 -0
  133. package/assets/worker-kits/growthub-open-higgsfield-studio-v1/kit.json +14 -2
  134. package/assets/worker-kits/growthub-open-higgsfield-studio-v1/skills/README.md +23 -0
  135. package/assets/worker-kits/growthub-open-higgsfield-studio-v1/templates/project.md +48 -0
  136. package/assets/worker-kits/growthub-open-higgsfield-studio-v1/templates/self-eval.md +67 -0
  137. package/assets/worker-kits/growthub-open-higgsfield-studio-v1/workers/open-higgsfield-studio-operator/CLAUDE.md +22 -0
  138. package/assets/worker-kits/growthub-open-montage-studio-v1/SKILL.md +89 -0
  139. package/assets/worker-kits/growthub-open-montage-studio-v1/bundles/growthub-open-montage-studio-v1.json +9 -2
  140. package/assets/worker-kits/growthub-open-montage-studio-v1/helpers/README.md +29 -0
  141. package/assets/worker-kits/growthub-open-montage-studio-v1/kit.json +14 -2
  142. package/assets/worker-kits/growthub-open-montage-studio-v1/skills/README.md +23 -0
  143. package/assets/worker-kits/growthub-open-montage-studio-v1/templates/project.md +48 -0
  144. package/assets/worker-kits/growthub-open-montage-studio-v1/templates/self-eval.md +67 -0
  145. package/assets/worker-kits/growthub-open-montage-studio-v1/workers/open-montage-studio-operator/CLAUDE.md +22 -0
  146. package/assets/worker-kits/growthub-postiz-social-v1/SKILL.md +90 -0
  147. package/assets/worker-kits/growthub-postiz-social-v1/bundles/growthub-postiz-social-v1.json +9 -2
  148. package/assets/worker-kits/growthub-postiz-social-v1/helpers/README.md +29 -0
  149. package/assets/worker-kits/growthub-postiz-social-v1/kit.json +14 -2
  150. package/assets/worker-kits/growthub-postiz-social-v1/skills/README.md +23 -0
  151. package/assets/worker-kits/growthub-postiz-social-v1/templates/project.md +48 -0
  152. package/assets/worker-kits/growthub-postiz-social-v1/templates/self-eval.md +67 -0
  153. package/assets/worker-kits/growthub-postiz-social-v1/workers/postiz-social-operator/CLAUDE.md +22 -0
  154. package/assets/worker-kits/growthub-twenty-crm-v1/SKILL.md +89 -0
  155. package/assets/worker-kits/growthub-twenty-crm-v1/bundles/growthub-twenty-crm-v1.json +9 -2
  156. package/assets/worker-kits/growthub-twenty-crm-v1/helpers/README.md +29 -0
  157. package/assets/worker-kits/growthub-twenty-crm-v1/kit.json +14 -2
  158. package/assets/worker-kits/growthub-twenty-crm-v1/skills/README.md +23 -0
  159. package/assets/worker-kits/growthub-twenty-crm-v1/templates/project.md +48 -0
  160. package/assets/worker-kits/growthub-twenty-crm-v1/templates/self-eval.md +67 -0
  161. package/assets/worker-kits/growthub-twenty-crm-v1/workers/twenty-crm-operator/CLAUDE.md +22 -0
  162. package/assets/worker-kits/growthub-video-use-studio-v1/SKILL.md +89 -0
  163. package/assets/worker-kits/growthub-video-use-studio-v1/bundles/growthub-video-use-studio-v1.json +6 -1
  164. package/assets/worker-kits/growthub-video-use-studio-v1/helpers/README.md +29 -0
  165. package/assets/worker-kits/growthub-video-use-studio-v1/kit.json +14 -2
  166. package/assets/worker-kits/growthub-video-use-studio-v1/skills/README.md +23 -0
  167. package/assets/worker-kits/growthub-video-use-studio-v1/templates/project.md +48 -0
  168. package/assets/worker-kits/growthub-video-use-studio-v1/templates/self-eval.md +67 -0
  169. package/assets/worker-kits/growthub-video-use-studio-v1/workers/video-use-studio-operator/CLAUDE.md +22 -0
  170. package/assets/worker-kits/growthub-zernio-social-v1/SKILL.md +90 -0
  171. package/assets/worker-kits/growthub-zernio-social-v1/bundles/growthub-zernio-social-v1.json +9 -2
  172. package/assets/worker-kits/growthub-zernio-social-v1/helpers/README.md +29 -0
  173. package/assets/worker-kits/growthub-zernio-social-v1/kit.json +14 -2
  174. package/assets/worker-kits/growthub-zernio-social-v1/skills/README.md +23 -0
  175. package/assets/worker-kits/growthub-zernio-social-v1/templates/project.md +48 -0
  176. package/assets/worker-kits/growthub-zernio-social-v1/templates/self-eval.md +67 -0
  177. package/assets/worker-kits/growthub-zernio-social-v1/workers/zernio-social-operator/CLAUDE.md +22 -0
  178. package/dist/index.js +970 -241
  179. package/package.json +2 -2
@@ -0,0 +1,165 @@
1
+ import { describeAuthAdapter } from "@/lib/adapters/auth";
2
+ import { readAdapterConfig } from "@/lib/adapters/env";
3
+ import { describePaymentAdapter } from "@/lib/adapters/payments";
4
+ import { describePersistenceAdapter } from "@/lib/adapters/persistence";
5
+ import { portalCapabilities } from "@/lib/domain/portal";
6
+ import Link from "next/link";
7
+ const nav = [
8
+ ...portalCapabilities.map((item) => ({ href: `#${item.id}`, label: item.label })),
9
+ { href: "/settings/integrations", label: "Integrations" }
10
+ ];
11
+ const quickActions = [
12
+ "Client onboarding",
13
+ "Publish report",
14
+ "Sync Windsor data",
15
+ "Review open tasks"
16
+ ];
17
+ function Home() {
18
+ const config = readAdapterConfig();
19
+ const persistence = describePersistenceAdapter();
20
+ const auth = describeAuthAdapter();
21
+ const payments = describePaymentAdapter();
22
+ return <main className="shell">
23
+ <aside className="sidebar">
24
+ <div className="brand">
25
+ <span className="brand-mark">GH</span>
26
+ <span>Agency Portal</span>
27
+ </div>
28
+ <nav className="nav">
29
+ {nav.map((item, index) => <Link className={index === 0 ? "active" : ""} href={item.href} key={item.href}>{item.label}</Link>)}
30
+ </nav>
31
+ <div className="sidebar-footer">
32
+ <span className="status-dot" />
33
+ Governed worker kit
34
+ </div>
35
+ </aside>
36
+
37
+ <section className="main">
38
+ <div className="utility-bar">
39
+ <div>
40
+ <strong>Production workspace</strong>
41
+ <span>Local customization, Vercel deployment, bridge-ready integrations.</span>
42
+ </div>
43
+ <div className="utility-actions">
44
+ <Link href="/settings/integrations">Integrations</Link>
45
+ <span className="pill">v1 kit</span>
46
+ </div>
47
+ </div>
48
+
49
+ <div className="page-heading">
50
+ <div>
51
+ <p className="eyebrow">Growthub Local + Vercel</p>
52
+ <h1>Composable Agency Workspace</h1>
53
+ <p>
54
+ A production starter for agency portals with local-first Vite operation, Vercel
55
+ deployment, thin adapter contracts, Windsor data pipelines, and Growthub MCP
56
+ connection authority.
57
+ </p>
58
+ </div>
59
+ <span className="badge">deploy: {config.deployTarget}</span>
60
+ </div>
61
+
62
+ <section className="hero-grid" id="dashboard">
63
+ <article className="hero-card wide">
64
+ <p className="card-label">Monthly Revenue</p>
65
+ <strong>$0</strong>
66
+ <div className="progress"><span style={{ width: "0%" }} /></div>
67
+ <p className="muted">Connect persistence to populate invoices, retainers, and margin reporting.</p>
68
+ </article>
69
+ <article className="hero-card">
70
+ <p className="card-label">MCP Connections</p>
71
+ <strong>{config.integrationAdapter}</strong>
72
+ <p className="muted">Growthub bridge and BYO API key paths normalize into one object model.</p>
73
+ </article>
74
+ <article className="hero-card">
75
+ <p className="card-label">Client Results</p>
76
+ <strong>Windsor</strong>
77
+ <p className="muted">First-class Windsor AI and Google Sheets blended data pipeline support.</p>
78
+ </article>
79
+ </section>
80
+
81
+ <section className="ops-strip" aria-label="Setup paths">
82
+ <article>
83
+ <span>01</span>
84
+ <strong>Local Vite shell</strong>
85
+ <p>Use the same portal frame for agent-led local customization.</p>
86
+ </article>
87
+ <article>
88
+ <span>02</span>
89
+ <strong>Vercel app</strong>
90
+ <p>Deploy the Next app without binding persistence to a single provider.</p>
91
+ </article>
92
+ <article>
93
+ <span>03</span>
94
+ <strong>Growthub bridge</strong>
95
+ <p>Resolve hosted MCP accounts when the user connects Growthub authority.</p>
96
+ </article>
97
+ <article>
98
+ <span>04</span>
99
+ <strong>BYO keys</strong>
100
+ <p>Support Windsor and external provider keys through the same object contract.</p>
101
+ </article>
102
+ </section>
103
+
104
+ <section className="grid compact-grid">
105
+ {portalCapabilities.map((capability) => <article className="card" id={capability.id} key={capability.id}>
106
+ <h3>{capability.label}</h3>
107
+ <div className="metric">{capability.metric}</div>
108
+ <p>{capability.description}</p>
109
+ </article>)}
110
+ </section>
111
+
112
+ <section className="adapter" aria-label="Adapter contracts">
113
+ <article className="card">
114
+ <h3>Persistence</h3>
115
+ <p><strong>{persistence.label}</strong></p>
116
+ <p>Postgres, Qstash KV, or provider-managed.</p>
117
+ </article>
118
+ <article className="card">
119
+ <h3>Auth</h3>
120
+ <p><strong>{auth.id}</strong></p>
121
+ <p>{auth.requiredEnv.length ? auth.requiredEnv.join(", ") : "provider-defined"}</p>
122
+ </article>
123
+ <article className="card">
124
+ <h3>Payments</h3>
125
+ <p><strong>{payments.id}</strong></p>
126
+ <p>{payments.enabled ? "enabled" : "disabled"}</p>
127
+ </article>
128
+ <article className="card">
129
+ <h3>Integrations</h3>
130
+ <p><strong>{config.integrationAdapter}</strong></p>
131
+ <p><Link href="/settings/integrations">Open setup surface</Link></p>
132
+ </article>
133
+ <article className="card">
134
+ <h3>Worker API</h3>
135
+ <p><code>GET /api/workspace</code></p>
136
+ <p>Adapter and capability metadata for agents.</p>
137
+ </article>
138
+ </section>
139
+
140
+ <section className="results-panel" id="client-results">
141
+ <div>
142
+ <p className="eyebrow">Client Results</p>
143
+ <h2>Windsor AI + blended data ready</h2>
144
+ <p>
145
+ Windsor is a data pipeline object, not a database choice. Google Sheets blended
146
+ exports, GA4, Shopify, and Meta data stay composable through the integrations surface.
147
+ </p>
148
+ </div>
149
+ <div className="results-metrics">
150
+ <span>Meta</span>
151
+ <span>Shopify</span>
152
+ <span>GA4</span>
153
+ <span>Sheets</span>
154
+ </div>
155
+ </section>
156
+ </section>
157
+
158
+ <aside className="quick-actions" aria-label="Quick actions">
159
+ {quickActions.map((action) => <button type="button" key={action}>{action}</button>)}
160
+ </aside>
161
+ </main>;
162
+ }
163
+ export {
164
+ Home as default
165
+ };
@@ -0,0 +1,134 @@
1
+ import { describeIntegrationAdapter, listAgencyPortalIntegrations } from "@/lib/adapters/integrations";
2
+ import { portalCapabilities } from "@/lib/domain/portal";
3
+ import { groupIntegrationsByLane } from "@/lib/domain/integrations";
4
+ import Link from "next/link";
5
+ const nav = [
6
+ ...portalCapabilities.map((item) => ({ href: `/#${item.id}`, label: item.label })),
7
+ { href: "/settings/integrations", label: "Integrations" }
8
+ ];
9
+ async function IntegrationsSettingsPage() {
10
+ const adapter = describeIntegrationAdapter();
11
+ const grouped = groupIntegrationsByLane(await listAgencyPortalIntegrations());
12
+ const allIntegrations = [...grouped.dataSources, ...grouped.workspaceIntegrations];
13
+ const connectedCount = allIntegrations.filter((item) => item.isConnected).length;
14
+ return <main className="shell">
15
+ <aside className="sidebar">
16
+ <div className="brand">
17
+ <span className="brand-mark">GH</span>
18
+ <span>Agency Portal</span>
19
+ </div>
20
+ <nav className="nav">
21
+ {nav.map((item) => <Link className={item.href === "/settings/integrations" ? "active" : ""} key={item.href} href={item.href}>
22
+ {item.label}
23
+ </Link>)}
24
+ </nav>
25
+ <div className="sidebar-footer">
26
+ <span className="status-dot" />
27
+ {connectedCount} connected
28
+ </div>
29
+ </aside>
30
+
31
+ <section className="main">
32
+ <div className="utility-bar">
33
+ <div>
34
+ <strong>Integration setup</strong>
35
+ <span>Growthub bridge, BYO API keys, and Windsor data pipelines normalize into one worker-kit object model.</span>
36
+ </div>
37
+ <div className="utility-actions">
38
+ <span className="pill">{adapter.authority}</span>
39
+ <span className="pill">{adapter.source}</span>
40
+ </div>
41
+ </div>
42
+
43
+ <div className="page-heading">
44
+ <span className="eyebrow">Settings</span>
45
+ <h1>Integrations</h1>
46
+ <p>
47
+ Configure the portal through the hosted Growthub auth bridge or through explicit bring-your-own credentials.
48
+ Data pipeline objects stay separate from workspace integrations while sharing one normalized surface.
49
+ </p>
50
+ <span className="badge">{adapter.label}</span>
51
+ </div>
52
+
53
+ <section className="setup-grid" aria-label="Integration setup paths">
54
+ <article className="setup-card">
55
+ <span>01</span>
56
+ <strong>Growthub Bridge</strong>
57
+ <p>Uses the authenticated Growthub account to resolve already-connected MCP accounts for this portal.</p>
58
+ <code>GROWTHUB_BRIDGE_ACCESS_TOKEN</code>
59
+ </article>
60
+ <article className="setup-card">
61
+ <span>02</span>
62
+ <strong>BYO API Key</strong>
63
+ <p>Supports direct provider keys without binding the kit to a database, vendor, or hosted account.</p>
64
+ <code>AGENCY_PORTAL_BYO_CONNECTIONS_JSON</code>
65
+ </article>
66
+ <article className="setup-card">
67
+ <span>03</span>
68
+ <strong>Windsor Data</strong>
69
+ <p>First-class reporting pipeline for blended Meta, Shopify, GA4, and Google Sheets data sources.</p>
70
+ <code>WINDSOR_API_KEY</code>
71
+ </article>
72
+ </section>
73
+
74
+ <section className="integration-board">
75
+ <div className="integration-toolbar">
76
+ <div>
77
+ <strong>Connection authority</strong>
78
+ <p>{adapter.description}</p>
79
+ </div>
80
+ <code>GET /api/settings/integrations</code>
81
+ </div>
82
+
83
+ <IntegrationPanel
84
+ title="Data pipeline objects"
85
+ intro="Meta, Shopify, GA4, Windsor AI, and Google Sheets blended data feed reporting and analytics workflows."
86
+ items={grouped.dataSources}
87
+ />
88
+ <IntegrationPanel
89
+ title="MCP connection integrations"
90
+ intro="Asana, Slack, GHL, Google Drive, and Notion are operational integrations resolved through MCP connection authority or explicit BYO setup."
91
+ items={grouped.workspaceIntegrations}
92
+ />
93
+ </section>
94
+ </section>
95
+ </main>;
96
+ }
97
+ function IntegrationPanel({
98
+ title,
99
+ intro,
100
+ items
101
+ }) {
102
+ const connected = items.filter((item) => item.isConnected).length;
103
+ return <article className="integration-section">
104
+ <div className="section-heading">
105
+ <div>
106
+ <h2>{title}</h2>
107
+ <p className="panel-copy">{intro}</p>
108
+ </div>
109
+ <span className="badge">{connected}/{items.length} connected</span>
110
+ </div>
111
+ <div className="integration-list">
112
+ {items.map((item) => <article className="integration-card" key={item.id}>
113
+ <div className="integration-card-top">
114
+ <div className="provider-mark">{item.label.slice(0, 1)}</div>
115
+ <div>
116
+ <strong>{item.label}</strong>
117
+ <p>{item.description}</p>
118
+ </div>
119
+ <span className={`status ${item.status}`}>{item.status}</span>
120
+ </div>
121
+ <div className="integration-card-meta">
122
+ <span>{item.provider}</span>
123
+ <span>{item.objectType}</span>
124
+ <span>{item.authPath}</span>
125
+ <span>{item.setupMode}</span>
126
+ {item.secretEnvName ? <span>{item.secretEnvName}</span> : null}
127
+ </div>
128
+ </article>)}
129
+ </div>
130
+ </article>;
131
+ }
132
+ export {
133
+ IntegrationsSettingsPage as default
134
+ };
@@ -0,0 +1,21 @@
1
+ import { readAdapterConfig } from "../env";
2
+ function describeAuthAdapter() {
3
+ const { authAdapter } = readAdapterConfig();
4
+ if (authAdapter === "oidc") {
5
+ return {
6
+ id: "oidc",
7
+ requiredEnv: ["AUTH_SECRET", "AUTH_ISSUER", "AUTH_CLIENT_ID", "AUTH_CLIENT_SECRET"],
8
+ notes: ["Default portable auth contract for Vercel and local serverless use."]
9
+ };
10
+ }
11
+ if (authAdapter === "clerk") {
12
+ return { id: "clerk", requiredEnv: [], notes: ["Configure Clerk-specific env in the deployment target."] };
13
+ }
14
+ if (authAdapter === "authjs") {
15
+ return { id: "authjs", requiredEnv: ["AUTH_SECRET"], notes: ["Use Auth.js provider configuration in app code."] };
16
+ }
17
+ return { id: "provider-managed", requiredEnv: [], notes: ["Auth is managed outside the kit contract."] };
18
+ }
19
+ export {
20
+ describeAuthAdapter
21
+ };
@@ -0,0 +1,28 @@
1
+ function readAdapterConfig() {
2
+ return {
3
+ deployTarget: "vercel",
4
+ dataAdapter: readEnum("AGENCY_PORTAL_DATA_ADAPTER", ["postgres", "qstash-kv", "provider-managed"], "provider-managed"),
5
+ authAdapter: readEnum("AGENCY_PORTAL_AUTH_ADAPTER", ["oidc", "clerk", "authjs", "provider-managed"], "provider-managed"),
6
+ paymentAdapter: readEnum("AGENCY_PORTAL_PAYMENT_ADAPTER", ["none", "stripe", "polar"], "none"),
7
+ integrationAdapter: readEnum("AGENCY_PORTAL_INTEGRATION_ADAPTER", ["growthub-bridge", "byo-api-key", "static"], "static"),
8
+ reportingAdapter: process.env.AGENCY_PORTAL_REPORTING_ADAPTER || void 0,
9
+ growthubBridge: {
10
+ baseUrl: process.env.GROWTHUB_BRIDGE_BASE_URL || void 0,
11
+ integrationsPath: process.env.GROWTHUB_BRIDGE_INTEGRATIONS_PATH || "/api/mcp/accounts",
12
+ userId: process.env.GROWTHUB_BRIDGE_USER_ID || void 0,
13
+ hasAccessToken: Boolean(process.env.GROWTHUB_BRIDGE_ACCESS_TOKEN)
14
+ },
15
+ dataSources: {
16
+ hasWindsorApiKey: Boolean(process.env.WINDSOR_API_KEY)
17
+ }
18
+ };
19
+ }
20
+ function readEnum(key, allowed, fallback) {
21
+ const value = process.env[key];
22
+ if (!value) return fallback;
23
+ if (allowed.includes(value)) return value;
24
+ throw new Error(`${key} must be one of: ${allowed.join(", ")}`);
25
+ }
26
+ export {
27
+ readAdapterConfig
28
+ };
@@ -0,0 +1,95 @@
1
+ const providerAliases = {
2
+ ga4: "google-analytics",
3
+ google_analytics: "google-analytics",
4
+ google_drive: "google-drive",
5
+ ghl: "go-high-level",
6
+ gohighlevel: "go-high-level",
7
+ meta: "meta-ads",
8
+ meta_ads: "meta-ads"
9
+ };
10
+ function normalizeProviderId(provider) {
11
+ const normalized = provider.trim().toLowerCase().replaceAll("_", "-");
12
+ return providerAliases[normalized] || normalized;
13
+ }
14
+ function isHostedRecord(row) {
15
+ return "provider" in row && ("ready" in row || "connectedAt" in row || "scopes" in row || "handle" in row);
16
+ }
17
+ function normalizeHostedIntegration(row) {
18
+ const provider = normalizeProviderId(row.provider);
19
+ const ready = row.ready !== false;
20
+ return {
21
+ id: provider,
22
+ provider,
23
+ label: row.label,
24
+ name: row.label,
25
+ status: ready ? "connected" : "needs-connection",
26
+ isConnected: ready,
27
+ isActive: ready,
28
+ authPath: "growthub-mcp-bridge",
29
+ setupMode: "hosted-authority",
30
+ connectionMetadata: {
31
+ source: "growthub-cli-profile",
32
+ connectedAt: row.connectedAt,
33
+ scopes: row.scopes,
34
+ handle: row.handle
35
+ }
36
+ };
37
+ }
38
+ function normalizeMcpAccount(account) {
39
+ const provider = normalizeProviderId(account.provider);
40
+ const isActive = account.isActive === true;
41
+ const isVerified = account.isVerified === true;
42
+ const isConnected = isActive;
43
+ return {
44
+ id: provider,
45
+ provider,
46
+ label: account.connectionName || void 0,
47
+ name: account.connectionName || void 0,
48
+ authType: normalizeConnectionType(account.connectionType),
49
+ status: isConnected ? "connected" : "needs-connection",
50
+ isConnected,
51
+ isActive,
52
+ connectionId: account.id,
53
+ authPath: "growthub-mcp-bridge",
54
+ setupMode: "hosted-authority",
55
+ connectionMetadata: {
56
+ source: "growthub-mcp-accounts",
57
+ accountId: account.id,
58
+ connectionName: account.connectionName,
59
+ connectionType: account.connectionType,
60
+ isVerified,
61
+ appSlug: account.appSlug,
62
+ createdAt: account.createdAt,
63
+ updatedAt: account.updatedAt,
64
+ metadata: account.metadata || void 0
65
+ }
66
+ };
67
+ }
68
+ function normalizeConnectionType(connectionType) {
69
+ if (connectionType === "api_token" || connectionType === "api_key") return "api_token";
70
+ if (connectionType === "webhook") return "webhook";
71
+ return "oauth_first_party";
72
+ }
73
+ function normalizeBridgeRow(row) {
74
+ if (isHostedRecord(row)) return normalizeHostedIntegration(row);
75
+ const provider = normalizeProviderId(row.provider || row.id || "");
76
+ return {
77
+ ...row,
78
+ id: row.id || provider,
79
+ provider
80
+ };
81
+ }
82
+ function normalizeGrowthubBridgePayload(payload) {
83
+ if (Array.isArray(payload)) {
84
+ return payload.map(normalizeBridgeRow);
85
+ }
86
+ return [
87
+ ...(payload.integrations || []).map(normalizeBridgeRow),
88
+ ...(payload.accounts || []).map(normalizeMcpAccount),
89
+ ...(payload.dataSources || []).map(normalizeBridgeRow),
90
+ ...(payload.workspaceIntegrations || []).map(normalizeBridgeRow)
91
+ ];
92
+ }
93
+ export {
94
+ normalizeGrowthubBridgePayload
95
+ };
@@ -0,0 +1,178 @@
1
+ import { readAdapterConfig } from "@/lib/adapters/env";
2
+ import {
3
+ agencyPortalIntegrationCatalog
4
+ } from "@/lib/domain/integrations";
5
+ import {
6
+ normalizeGrowthubBridgePayload
7
+ } from "./growthub-connection-normalizer";
8
+ function describeIntegrationAdapter() {
9
+ const config = readAdapterConfig();
10
+ if (config.integrationAdapter === "growthub-bridge") {
11
+ return {
12
+ id: "growthub-bridge",
13
+ label: "Growthub MCP bridge",
14
+ requiredEnv: ["GROWTHUB_BRIDGE_BASE_URL", "GROWTHUB_BRIDGE_ACCESS_TOKEN"],
15
+ authority: "growthub-gh-app"
16
+ };
17
+ }
18
+ if (config.integrationAdapter === "byo-api-key") {
19
+ return {
20
+ id: "byo-api-key",
21
+ label: "Bring your own API key",
22
+ requiredEnv: ["AGENCY_PORTAL_BYO_CONNECTIONS_JSON"],
23
+ authority: "workspace-env"
24
+ };
25
+ }
26
+ return {
27
+ id: "static",
28
+ label: "Static starter catalog",
29
+ requiredEnv: [],
30
+ authority: "local-catalog"
31
+ };
32
+ }
33
+ async function listAgencyPortalIntegrations() {
34
+ const config = readAdapterConfig();
35
+ if (config.integrationAdapter !== "growthub-bridge") {
36
+ if (config.integrationAdapter === "byo-api-key") {
37
+ return mergeBringYourOwnRows(readBringYourOwnRows());
38
+ }
39
+ return agencyPortalIntegrationCatalog;
40
+ }
41
+ if (!config.growthubBridge.baseUrl || !process.env.GROWTHUB_BRIDGE_ACCESS_TOKEN) {
42
+ return agencyPortalIntegrationCatalog;
43
+ }
44
+ const url = new URL(config.growthubBridge.integrationsPath, config.growthubBridge.baseUrl);
45
+ const headers = {
46
+ accept: "application/json",
47
+ authorization: `Bearer ${process.env.GROWTHUB_BRIDGE_ACCESS_TOKEN}`
48
+ };
49
+ if (config.growthubBridge.userId) {
50
+ headers["x-user-id"] = config.growthubBridge.userId;
51
+ }
52
+ const response = await fetch(url, {
53
+ headers,
54
+ next: { revalidate: 30 }
55
+ });
56
+ if (!response.ok) {
57
+ return agencyPortalIntegrationCatalog;
58
+ }
59
+ const payload = await response.json();
60
+ return mergeBridgeRows(normalizeGrowthubBridgePayload(payload));
61
+ }
62
+ function readBringYourOwnRows() {
63
+ const raw = process.env.AGENCY_PORTAL_BYO_CONNECTIONS_JSON;
64
+ const rows = [];
65
+ if (process.env.WINDSOR_API_KEY) {
66
+ rows.push({
67
+ id: "windsor-ai",
68
+ provider: "windsor-ai",
69
+ name: "Windsor AI",
70
+ label: "Windsor AI",
71
+ category: "api_key",
72
+ authType: "api_token",
73
+ status: "connected",
74
+ isConnected: true,
75
+ isActive: true,
76
+ authPath: "byo-api-key",
77
+ setupMode: "bring-your-own-key",
78
+ secretEnvName: "WINDSOR_API_KEY",
79
+ connectionMetadata: {
80
+ source: "workspace-env",
81
+ secretEnvName: "WINDSOR_API_KEY"
82
+ }
83
+ });
84
+ }
85
+ if (!raw) return rows;
86
+ try {
87
+ const parsed = JSON.parse(raw);
88
+ return [...rows, ...normalizeGrowthubBridgePayload(parsed)];
89
+ } catch {
90
+ return rows;
91
+ }
92
+ }
93
+ function mergeBringYourOwnRows(rows) {
94
+ const merged = mergeBridgeRows(rows);
95
+ return merged.map((item) => {
96
+ const row = rows.find((candidate) => {
97
+ const provider = candidate.provider || candidate.id;
98
+ return provider === item.provider || candidate.id === item.id;
99
+ });
100
+ if (!row) return item;
101
+ return {
102
+ ...item,
103
+ authPath: "byo-api-key",
104
+ setupMode: "bring-your-own-key",
105
+ secretEnvName: typeof row.secretEnvName === "string" ? row.secretEnvName : void 0,
106
+ status: row.status || "connected"
107
+ };
108
+ });
109
+ }
110
+ function mergeBridgeRows(rows) {
111
+ const seenProviders = /* @__PURE__ */ new Set();
112
+ const merged = agencyPortalIntegrationCatalog.map((catalogItem) => {
113
+ const row = rows.find((item) => {
114
+ const provider = item.provider || item.id;
115
+ return provider === catalogItem.provider || item.id === catalogItem.id;
116
+ });
117
+ if (!row) return catalogItem;
118
+ seenProviders.add(row.provider || row.id || catalogItem.provider);
119
+ return {
120
+ ...catalogItem,
121
+ label: row.label || row.name || catalogItem.label,
122
+ name: row.name || row.label || catalogItem.name,
123
+ icon: row.icon || catalogItem.icon,
124
+ description: row.description || catalogItem.description,
125
+ category: row.category || catalogItem.category,
126
+ authType: row.authType || catalogItem.authType,
127
+ isConnected: row.isConnected ?? (row.status === "connected" ? true : catalogItem.isConnected),
128
+ isActive: row.isActive ?? (row.status === "connected" ? true : catalogItem.isActive),
129
+ authPath: row.authPath || catalogItem.authPath,
130
+ setupMode: row.setupMode || catalogItem.setupMode,
131
+ status: row.status || (row.isConnected || row.isActive ? "connected" : catalogItem.status),
132
+ connectionId: row.connectionId,
133
+ accountId: row.accountId,
134
+ secretEnvName: row.secretEnvName,
135
+ connectionMetadata: row.connectionMetadata || row.metadata,
136
+ metadata: row.metadata || row.connectionMetadata
137
+ };
138
+ });
139
+ const discoveredRows = rows.filter((row) => {
140
+ const provider = row.provider || row.id;
141
+ if (!provider) return false;
142
+ if (seenProviders.has(provider)) return false;
143
+ return !agencyPortalIntegrationCatalog.some((item) => item.provider === provider || item.id === row.id);
144
+ });
145
+ return [...merged, ...discoveredRows.map(toDiscoveredIntegration)];
146
+ }
147
+ function toDiscoveredIntegration(row) {
148
+ const provider = row.provider || row.id || "unknown-provider";
149
+ const label = row.label || row.name || provider;
150
+ const isDataPipeline = ["windsor-ai", "google-sheets", "google-analytics", "shopify", "meta-ads"].includes(provider);
151
+ const isConnected = row.isConnected ?? row.status === "connected";
152
+ return {
153
+ id: row.id || provider,
154
+ label,
155
+ name: row.name || label,
156
+ icon: row.icon || label.slice(0, 1).toUpperCase(),
157
+ provider,
158
+ description: row.description || "Connected through the Growthub account bridge.",
159
+ category: row.category || "mcp_connector",
160
+ authType: row.authType || "oauth_first_party",
161
+ isConnected,
162
+ isActive: row.isActive ?? isConnected,
163
+ lane: isDataPipeline ? "data-source" : "workspace-integration",
164
+ objectType: isDataPipeline ? "data-pipeline" : "mcp-connection",
165
+ status: row.status || (isConnected ? "connected" : "needs-connection"),
166
+ authPath: row.authPath || "growthub-mcp-bridge",
167
+ setupMode: row.setupMode || "hosted-authority",
168
+ connectionId: row.connectionId,
169
+ accountId: row.accountId,
170
+ secretEnvName: row.secretEnvName,
171
+ connectionMetadata: row.connectionMetadata || row.metadata,
172
+ metadata: row.metadata || row.connectionMetadata
173
+ };
174
+ }
175
+ export {
176
+ describeIntegrationAdapter,
177
+ listAgencyPortalIntegrations
178
+ };
@@ -0,0 +1,13 @@
1
+ import { readAdapterConfig } from "../env";
2
+ function describePaymentAdapter() {
3
+ const { paymentAdapter } = readAdapterConfig();
4
+ if (paymentAdapter === "none") return { id: "none", requiredEnv: [], enabled: false };
5
+ return {
6
+ id: paymentAdapter,
7
+ requiredEnv: ["PAYMENT_SECRET_KEY", "PAYMENT_WEBHOOK_SECRET"],
8
+ enabled: true
9
+ };
10
+ }
11
+ export {
12
+ describePaymentAdapter
13
+ };
@@ -0,0 +1,13 @@
1
+ import { readAdapterConfig } from "../env";
2
+ import { describePostgresAdapter } from "./postgres";
3
+ import { describeProviderManagedAdapter } from "./provider-managed";
4
+ import { describeQstashKvAdapter } from "./qstash-kv";
5
+ function describePersistenceAdapter() {
6
+ const config = readAdapterConfig();
7
+ if (config.dataAdapter === "postgres") return describePostgresAdapter();
8
+ if (config.dataAdapter === "qstash-kv") return describeQstashKvAdapter();
9
+ return describeProviderManagedAdapter();
10
+ }
11
+ export {
12
+ describePersistenceAdapter
13
+ };
@@ -0,0 +1,16 @@
1
+ function describePostgresAdapter() {
2
+ return {
3
+ id: "postgres",
4
+ label: "Postgres",
5
+ requiredEnv: ["DATABASE_URL"],
6
+ mode: "sql",
7
+ notes: [
8
+ "Use any Postgres-compatible provider.",
9
+ "Keep provider-specific pooling, SSL, and migration tooling outside the kit contract.",
10
+ "Application repositories should depend on this descriptor, not a provider SDK directly."
11
+ ]
12
+ };
13
+ }
14
+ export {
15
+ describePostgresAdapter
16
+ };