vibecarbon 0.1.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 (495) hide show
  1. package/LICENSE +663 -0
  2. package/README.md +188 -0
  3. package/carbon/.claude/hooks/task-completed-gate.sh +19 -0
  4. package/carbon/.claude/hooks/teammate-idle-gate.sh +29 -0
  5. package/carbon/.claude/settings.json +29 -0
  6. package/carbon/.cursor/rules/vibecarbon.mdc +6 -0
  7. package/carbon/.dockerignore +57 -0
  8. package/carbon/.env.example +219 -0
  9. package/carbon/.github/copilot-instructions.md +3 -0
  10. package/carbon/.github/workflows/deploy.yml +346 -0
  11. package/carbon/.github/workflows/vibecarbon-build.yml +81 -0
  12. package/carbon/.windsurfrules +74 -0
  13. package/carbon/AGENTS.md +422 -0
  14. package/carbon/CLAUDE.md +3 -0
  15. package/carbon/DEVELOPMENT.md +187 -0
  16. package/carbon/Dockerfile +98 -0
  17. package/carbon/LICENSE +21 -0
  18. package/carbon/PRODUCTION.md +364 -0
  19. package/carbon/README.md +193 -0
  20. package/carbon/TESTING.md +138 -0
  21. package/carbon/backup/Dockerfile +75 -0
  22. package/carbon/backup/backup.sh +95 -0
  23. package/carbon/backup/compose-backup.sh +140 -0
  24. package/carbon/biome.json +83 -0
  25. package/carbon/cloud-init/docker-ce-setup.yaml +55 -0
  26. package/carbon/cloud-init/k3s/master-init.sh +215 -0
  27. package/carbon/cloud-init/k3s/supabase-init.sh +167 -0
  28. package/carbon/cloud-init/k3s/worker-init.sh +147 -0
  29. package/carbon/components.json +24 -0
  30. package/carbon/content/blog/authentication-guide.mdx +34 -0
  31. package/carbon/content/blog/getting-started.mdx +41 -0
  32. package/carbon/content/changelog/v0-1-0.mdx +40 -0
  33. package/carbon/content/docs/analytics.mdx +90 -0
  34. package/carbon/content/docs/authentication.mdx +231 -0
  35. package/carbon/content/docs/background-jobs.mdx +116 -0
  36. package/carbon/content/docs/cli.mdx +630 -0
  37. package/carbon/content/docs/database.mdx +236 -0
  38. package/carbon/content/docs/deployment.mdx +227 -0
  39. package/carbon/content/docs/development.mdx +238 -0
  40. package/carbon/content/docs/environments.mdx +84 -0
  41. package/carbon/content/docs/getting-started.mdx +112 -0
  42. package/carbon/content/docs/legal/privacy-policy.mdx +89 -0
  43. package/carbon/content/docs/legal/terms-of-service.mdx +99 -0
  44. package/carbon/content/docs/optional-services.mdx +160 -0
  45. package/carbon/db/Dockerfile +23 -0
  46. package/carbon/docker-compose.dev-init.yml +5 -0
  47. package/carbon/docker-compose.metabase.override.yml +14 -0
  48. package/carbon/docker-compose.metabase.prod.yml +28 -0
  49. package/carbon/docker-compose.metabase.yml +84 -0
  50. package/carbon/docker-compose.n8n.override.yml +14 -0
  51. package/carbon/docker-compose.n8n.prod.yml +31 -0
  52. package/carbon/docker-compose.n8n.yml +97 -0
  53. package/carbon/docker-compose.observability.override.yml +18 -0
  54. package/carbon/docker-compose.observability.prod.yml +28 -0
  55. package/carbon/docker-compose.observability.yml +125 -0
  56. package/carbon/docker-compose.override.yml +28 -0
  57. package/carbon/docker-compose.prod.yml +294 -0
  58. package/carbon/docker-compose.yml +508 -0
  59. package/carbon/docker-entrypoint.sh +12 -0
  60. package/carbon/ha/activate-standby.sh +52 -0
  61. package/carbon/ha/primary-init.sql +36 -0
  62. package/carbon/ha/standby-init.sh +74 -0
  63. package/carbon/k8s/LICENSE +99 -0
  64. package/carbon/k8s/README.md +272 -0
  65. package/carbon/k8s/base/app/deployment.yaml +130 -0
  66. package/carbon/k8s/base/app/hpa.yaml +44 -0
  67. package/carbon/k8s/base/app/kustomization.yaml +10 -0
  68. package/carbon/k8s/base/app/network-policy.yaml +124 -0
  69. package/carbon/k8s/base/app/pdb.yaml +14 -0
  70. package/carbon/k8s/base/app/rbac.yaml +36 -0
  71. package/carbon/k8s/base/app/service.yaml +16 -0
  72. package/carbon/k8s/base/backup/cronjob.yaml +120 -0
  73. package/carbon/k8s/base/backup/kustomization.yaml +7 -0
  74. package/carbon/k8s/base/backup/network-policy.yaml +31 -0
  75. package/carbon/k8s/base/backup/rbac.yaml +7 -0
  76. package/carbon/k8s/base/cluster-autoscaler/deployment.yaml +103 -0
  77. package/carbon/k8s/base/cluster-autoscaler/kustomization.yaml +17 -0
  78. package/carbon/k8s/base/cluster-autoscaler/rbac.yaml +109 -0
  79. package/carbon/k8s/base/config/configmap.yaml +48 -0
  80. package/carbon/k8s/base/config/kustomization.yaml +8 -0
  81. package/carbon/k8s/base/hetzner-ccm/kustomization.yaml +9 -0
  82. package/carbon/k8s/base/hetzner-csi/kustomization.yaml +9 -0
  83. package/carbon/k8s/base/kustomization.yaml +43 -0
  84. package/carbon/k8s/base/namespace.yaml +7 -0
  85. package/carbon/k8s/base/network-policies.yaml +95 -0
  86. package/carbon/k8s/base/registry/kustomization.yaml +5 -0
  87. package/carbon/k8s/base/registry/local-registry.yaml +193 -0
  88. package/carbon/k8s/base/traefik/certificate.yaml +21 -0
  89. package/carbon/k8s/base/traefik/configmap.yaml +13 -0
  90. package/carbon/k8s/base/traefik/deployment.yaml +165 -0
  91. package/carbon/k8s/base/traefik/ingressroute.yaml +141 -0
  92. package/carbon/k8s/base/traefik/kustomization.yaml +11 -0
  93. package/carbon/k8s/base/traefik/middleware.yaml +109 -0
  94. package/carbon/k8s/base/traefik/network-policy.yaml +92 -0
  95. package/carbon/k8s/base/traefik/service.yaml +38 -0
  96. package/carbon/k8s/flux/README.md +49 -0
  97. package/carbon/k8s/flux/clusters/primary/vibecarbon.yaml +128 -0
  98. package/carbon/k8s/flux/clusters/standby/vibecarbon.yaml +83 -0
  99. package/carbon/k8s/gitops/cert-manager-webhook-hetzner/helm-release.yaml +38 -0
  100. package/carbon/k8s/gitops/cert-manager-webhook-hetzner/helm-repository.yaml +16 -0
  101. package/carbon/k8s/gitops/cert-manager-webhook-hetzner/kustomization.yaml +10 -0
  102. package/carbon/k8s/gitops/supabase/helm-release.yaml +66 -0
  103. package/carbon/k8s/gitops/supabase/helm-repository.yaml +18 -0
  104. package/carbon/k8s/gitops/supabase/kustomization.yaml +33 -0
  105. package/carbon/k8s/infra/cert-manager-resources/cluster-issuers-cloudflare.yaml +51 -0
  106. package/carbon/k8s/infra/cert-manager-resources/cluster-issuers-hetzner.yaml +59 -0
  107. package/carbon/k8s/infra/cert-manager-resources/cluster-issuers-manual.yaml +43 -0
  108. package/carbon/k8s/infra/cert-manager-resources/kustomization.yaml +15 -0
  109. package/carbon/k8s/infra/kustomization.yaml +21 -0
  110. package/carbon/k8s/infra/traefik-crds/kustomization.yaml +10 -0
  111. package/carbon/k8s/overlays/local/configmap.yaml +23 -0
  112. package/carbon/k8s/overlays/local/ingressroute-studio.yaml +104 -0
  113. package/carbon/k8s/overlays/local/kustomization.yaml +215 -0
  114. package/carbon/k8s/overlays/local/namespace.yaml +8 -0
  115. package/carbon/k8s/overlays/local/secrets.yaml +32 -0
  116. package/carbon/k8s/overlays/production/kustomization.yaml +34 -0
  117. package/carbon/k8s/test-local.sh +318 -0
  118. package/carbon/k8s/values/supabase.values.yaml +133 -0
  119. package/carbon/package.json +154 -0
  120. package/carbon/runtime.Dockerfile +17 -0
  121. package/carbon/scripts/_dev-jwt.mjs +45 -0
  122. package/carbon/scripts/check-rls.ts +53 -0
  123. package/carbon/scripts/dev-init.js +191 -0
  124. package/carbon/scripts/dev.js +191 -0
  125. package/carbon/scripts/docker-down.js +63 -0
  126. package/carbon/scripts/docker-logs.js +59 -0
  127. package/carbon/scripts/docker-up.js +222 -0
  128. package/carbon/scripts/generate-dev-configs.sh +131 -0
  129. package/carbon/scripts/generate-rss.ts +116 -0
  130. package/carbon/scripts/generate-sitemap.ts +102 -0
  131. package/carbon/scripts/k8s-apply.js +71 -0
  132. package/carbon/scripts/k8s-delete.js +75 -0
  133. package/carbon/scripts/lib/manifest.js +176 -0
  134. package/carbon/scripts/secret-scan.mjs +278 -0
  135. package/carbon/scripts/validate-dev-configs.sh +101 -0
  136. package/carbon/src/client/App.tsx +202 -0
  137. package/carbon/src/client/assets/hyperformant-dark.svg +29 -0
  138. package/carbon/src/client/assets/hyperformant-light.svg +29 -0
  139. package/carbon/src/client/assets/logos/aider.svg +1 -0
  140. package/carbon/src/client/assets/logos/antigravity.svg +1 -0
  141. package/carbon/src/client/assets/logos/bolt.svg +1 -0
  142. package/carbon/src/client/assets/logos/claude-code.svg +1 -0
  143. package/carbon/src/client/assets/logos/copilot.svg +1 -0
  144. package/carbon/src/client/assets/logos/cursor.svg +1 -0
  145. package/carbon/src/client/assets/logos/gemini-cli.svg +1 -0
  146. package/carbon/src/client/assets/logos/lovable.svg +1 -0
  147. package/carbon/src/client/assets/logos/openai-codex.svg +1 -0
  148. package/carbon/src/client/assets/logos/v0.svg +1 -0
  149. package/carbon/src/client/assets/logos/windsurf.svg +1 -0
  150. package/carbon/src/client/assets/vibecarbon-icon.svg +19 -0
  151. package/carbon/src/client/assets/vibecarbon-logo-dark.svg +29 -0
  152. package/carbon/src/client/assets/vibecarbon-logo-light.svg +29 -0
  153. package/carbon/src/client/components/AIIntegrationSection.tsx +120 -0
  154. package/carbon/src/client/components/AppSidebar.tsx +760 -0
  155. package/carbon/src/client/components/ArchitectureSection.tsx +46 -0
  156. package/carbon/src/client/components/CTAFooter.tsx +59 -0
  157. package/carbon/src/client/components/ComparisonSection.tsx +132 -0
  158. package/carbon/src/client/components/ContentPanel.tsx +66 -0
  159. package/carbon/src/client/components/ContentSkeleton.tsx +21 -0
  160. package/carbon/src/client/components/ErrorBoundary.tsx +46 -0
  161. package/carbon/src/client/components/FAQSection.tsx +76 -0
  162. package/carbon/src/client/components/FileUpload.tsx +210 -0
  163. package/carbon/src/client/components/HeaderActions.tsx +17 -0
  164. package/carbon/src/client/components/Hero.tsx +608 -0
  165. package/carbon/src/client/components/ImpersonationBanner.tsx +31 -0
  166. package/carbon/src/client/components/LanguageSwitcher.tsx +67 -0
  167. package/carbon/src/client/components/Logo.tsx +87 -0
  168. package/carbon/src/client/components/LogoStrip.tsx +76 -0
  169. package/carbon/src/client/components/MetricsStrip.tsx +48 -0
  170. package/carbon/src/client/components/Nav.tsx +195 -0
  171. package/carbon/src/client/components/NewsletterSignup.tsx +147 -0
  172. package/carbon/src/client/components/NotificationDrawer.tsx +171 -0
  173. package/carbon/src/client/components/PageHeader.tsx +24 -0
  174. package/carbon/src/client/components/PlanGate.tsx +36 -0
  175. package/carbon/src/client/components/PricingSection.tsx +371 -0
  176. package/carbon/src/client/components/SEO.tsx +34 -0
  177. package/carbon/src/client/components/SmoothScroll.tsx +45 -0
  178. package/carbon/src/client/components/TechStackSection.tsx +165 -0
  179. package/carbon/src/client/components/WorkflowSection.tsx +604 -0
  180. package/carbon/src/client/components/admin/DockerLogs.tsx +276 -0
  181. package/carbon/src/client/components/admin/PerformanceMetrics.tsx +230 -0
  182. package/carbon/src/client/components/admin/ServiceCard.tsx +45 -0
  183. package/carbon/src/client/components/admin/ServicesStatus.tsx +296 -0
  184. package/carbon/src/client/components/architecture/ArchitectureDiagram.tsx +413 -0
  185. package/carbon/src/client/components/auth/AuthProvider.tsx +466 -0
  186. package/carbon/src/client/components/effects/FilmGrainOverlay.tsx +35 -0
  187. package/carbon/src/client/components/effects/FresnelEdge.tsx +49 -0
  188. package/carbon/src/client/components/effects/GlowTracker.tsx +46 -0
  189. package/carbon/src/client/components/effects/SparkBurst.tsx +145 -0
  190. package/carbon/src/client/components/effects/VGlowEffect.tsx +83 -0
  191. package/carbon/src/client/components/effects/index.ts +2 -0
  192. package/carbon/src/client/components/layouts/SidebarLayout.tsx +20 -0
  193. package/carbon/src/client/components/scroll/ScrollSection.tsx +76 -0
  194. package/carbon/src/client/components/scroll/ScrollytellingProvider.tsx +81 -0
  195. package/carbon/src/client/components/scroll/index.ts +2 -0
  196. package/carbon/src/client/components/ui/accordion.tsx +71 -0
  197. package/carbon/src/client/components/ui/alert-dialog.tsx +162 -0
  198. package/carbon/src/client/components/ui/alert.tsx +73 -0
  199. package/carbon/src/client/components/ui/aspect-ratio.tsx +22 -0
  200. package/carbon/src/client/components/ui/avatar.tsx +91 -0
  201. package/carbon/src/client/components/ui/badge.tsx +50 -0
  202. package/carbon/src/client/components/ui/breadcrumb.tsx +100 -0
  203. package/carbon/src/client/components/ui/button-group.tsx +78 -0
  204. package/carbon/src/client/components/ui/button.tsx +120 -0
  205. package/carbon/src/client/components/ui/calendar.tsx +182 -0
  206. package/carbon/src/client/components/ui/card.tsx +85 -0
  207. package/carbon/src/client/components/ui/carousel.tsx +227 -0
  208. package/carbon/src/client/components/ui/chart.tsx +357 -0
  209. package/carbon/src/client/components/ui/checkbox.tsx +27 -0
  210. package/carbon/src/client/components/ui/collapsible.tsx +15 -0
  211. package/carbon/src/client/components/ui/command.tsx +178 -0
  212. package/carbon/src/client/components/ui/context-menu.tsx +233 -0
  213. package/carbon/src/client/components/ui/dialog.tsx +132 -0
  214. package/carbon/src/client/components/ui/drawer.tsx +118 -0
  215. package/carbon/src/client/components/ui/dropdown-menu.tsx +242 -0
  216. package/carbon/src/client/components/ui/empty.tsx +94 -0
  217. package/carbon/src/client/components/ui/field.tsx +226 -0
  218. package/carbon/src/client/components/ui/hover-card.tsx +44 -0
  219. package/carbon/src/client/components/ui/input-group.tsx +146 -0
  220. package/carbon/src/client/components/ui/input-otp.tsx +83 -0
  221. package/carbon/src/client/components/ui/input.tsx +20 -0
  222. package/carbon/src/client/components/ui/item.tsx +188 -0
  223. package/carbon/src/client/components/ui/kbd.tsx +26 -0
  224. package/carbon/src/client/components/ui/label.tsx +21 -0
  225. package/carbon/src/client/components/ui/menubar.tsx +250 -0
  226. package/carbon/src/client/components/ui/navigation-menu.tsx +155 -0
  227. package/carbon/src/client/components/ui/pagination.tsx +102 -0
  228. package/carbon/src/client/components/ui/popover.tsx +75 -0
  229. package/carbon/src/client/components/ui/progress.tsx +66 -0
  230. package/carbon/src/client/components/ui/radio-group.tsx +36 -0
  231. package/carbon/src/client/components/ui/resizable.tsx +46 -0
  232. package/carbon/src/client/components/ui/scroll-area.tsx +48 -0
  233. package/carbon/src/client/components/ui/select.tsx +186 -0
  234. package/carbon/src/client/components/ui/separator.tsx +21 -0
  235. package/carbon/src/client/components/ui/sheet.tsx +124 -0
  236. package/carbon/src/client/components/ui/sidebar.tsx +702 -0
  237. package/carbon/src/client/components/ui/skeleton.tsx +13 -0
  238. package/carbon/src/client/components/ui/slider.tsx +57 -0
  239. package/carbon/src/client/components/ui/sonner.tsx +45 -0
  240. package/carbon/src/client/components/ui/spinner.tsx +15 -0
  241. package/carbon/src/client/components/ui/switch.tsx +30 -0
  242. package/carbon/src/client/components/ui/table.tsx +89 -0
  243. package/carbon/src/client/components/ui/tabs.tsx +73 -0
  244. package/carbon/src/client/components/ui/textarea.tsx +18 -0
  245. package/carbon/src/client/components/ui/toggle-group.tsx +87 -0
  246. package/carbon/src/client/components/ui/toggle.tsx +44 -0
  247. package/carbon/src/client/components/ui/tooltip.tsx +56 -0
  248. package/carbon/src/client/hooks/api/index.ts +14 -0
  249. package/carbon/src/client/hooks/api/useAuthSettings.ts +80 -0
  250. package/carbon/src/client/hooks/api/useSubscription.ts +87 -0
  251. package/carbon/src/client/hooks/use-mobile.ts +21 -0
  252. package/carbon/src/client/hooks/useMousePosition.ts +91 -0
  253. package/carbon/src/client/hooks/useNotifications.tsx +124 -0
  254. package/carbon/src/client/hooks/useOrganizationMembers.ts +127 -0
  255. package/carbon/src/client/hooks/useOrganizations.tsx +230 -0
  256. package/carbon/src/client/hooks/usePackageManager.ts +69 -0
  257. package/carbon/src/client/hooks/useReducedMotion.ts +20 -0
  258. package/carbon/src/client/hooks/useRunningServices.ts +114 -0
  259. package/carbon/src/client/hooks/useScrollProgress.ts +56 -0
  260. package/carbon/src/client/index.css +467 -0
  261. package/carbon/src/client/index.html +56 -0
  262. package/carbon/src/client/lib/admin-services.ts +151 -0
  263. package/carbon/src/client/lib/api.ts +32 -0
  264. package/carbon/src/client/lib/blog.ts +35 -0
  265. package/carbon/src/client/lib/changelog.ts +33 -0
  266. package/carbon/src/client/lib/docs-search.ts +101 -0
  267. package/carbon/src/client/lib/docs.ts +37 -0
  268. package/carbon/src/client/lib/i18n.ts +32 -0
  269. package/carbon/src/client/lib/supabase.ts +72 -0
  270. package/carbon/src/client/lib/tailwind-colors.ts +357 -0
  271. package/carbon/src/client/lib/theme.ts +117 -0
  272. package/carbon/src/client/lib/utils.ts +22 -0
  273. package/carbon/src/client/locales/de.json +529 -0
  274. package/carbon/src/client/locales/en.json +461 -0
  275. package/carbon/src/client/locales/es.json +529 -0
  276. package/carbon/src/client/locales/fr.json +529 -0
  277. package/carbon/src/client/locales/pt.json +529 -0
  278. package/carbon/src/client/main.tsx +56 -0
  279. package/carbon/src/client/mdx.d.ts +13 -0
  280. package/carbon/src/client/pages/ApiDocs.tsx +76 -0
  281. package/carbon/src/client/pages/AuthCallback.tsx +34 -0
  282. package/carbon/src/client/pages/Blog.tsx +167 -0
  283. package/carbon/src/client/pages/Changelog.tsx +171 -0
  284. package/carbon/src/client/pages/Charts.tsx +388 -0
  285. package/carbon/src/client/pages/Checkout.tsx +227 -0
  286. package/carbon/src/client/pages/Contact.tsx +174 -0
  287. package/carbon/src/client/pages/Dashboard.tsx +368 -0
  288. package/carbon/src/client/pages/Docs.tsx +372 -0
  289. package/carbon/src/client/pages/ForgotPassword.tsx +111 -0
  290. package/carbon/src/client/pages/Home.tsx +187 -0
  291. package/carbon/src/client/pages/Legal.tsx +100 -0
  292. package/carbon/src/client/pages/Login.tsx +408 -0
  293. package/carbon/src/client/pages/MFAVerify.tsx +156 -0
  294. package/carbon/src/client/pages/NotFound.tsx +21 -0
  295. package/carbon/src/client/pages/Onboarding.tsx +246 -0
  296. package/carbon/src/client/pages/ResetPassword.tsx +200 -0
  297. package/carbon/src/client/pages/UIComponents.tsx +390 -0
  298. package/carbon/src/client/pages/admin/ContactSubmissions.tsx +220 -0
  299. package/carbon/src/client/pages/admin/Dashboard.tsx +24 -0
  300. package/carbon/src/client/pages/admin/Infrastructure.tsx +257 -0
  301. package/carbon/src/client/pages/admin/Jobs.tsx +225 -0
  302. package/carbon/src/client/pages/admin/Logs.tsx +18 -0
  303. package/carbon/src/client/pages/admin/Newsletter.tsx +300 -0
  304. package/carbon/src/client/pages/admin/Notifications.tsx +603 -0
  305. package/carbon/src/client/pages/admin/Organizations.tsx +306 -0
  306. package/carbon/src/client/pages/admin/Settings.tsx +314 -0
  307. package/carbon/src/client/pages/admin/Theme.tsx +465 -0
  308. package/carbon/src/client/pages/admin/Users.tsx +365 -0
  309. package/carbon/src/client/pages/api-docs.css +156 -0
  310. package/carbon/src/client/pages/organizations/Details.tsx +200 -0
  311. package/carbon/src/client/pages/organizations/Members.tsx +402 -0
  312. package/carbon/src/client/pages/settings/Billing.tsx +473 -0
  313. package/carbon/src/client/pages/settings/Profile.tsx +160 -0
  314. package/carbon/src/client/pages/settings/Security.tsx +341 -0
  315. package/carbon/src/client/public/favicon.svg +19 -0
  316. package/carbon/src/client/public/robots.txt +8 -0
  317. package/carbon/src/server/billing/index.ts +104 -0
  318. package/carbon/src/server/billing/provider.ts +81 -0
  319. package/carbon/src/server/billing/providers/paddle.ts +314 -0
  320. package/carbon/src/server/billing/providers/polar.ts +325 -0
  321. package/carbon/src/server/billing/providers/stripe.ts +233 -0
  322. package/carbon/src/server/emails/templates.ts +116 -0
  323. package/carbon/src/server/index.ts +554 -0
  324. package/carbon/src/server/lib/auth.ts +6 -0
  325. package/carbon/src/server/lib/email.ts +64 -0
  326. package/carbon/src/server/lib/env.ts +112 -0
  327. package/carbon/src/server/lib/errors.ts +21 -0
  328. package/carbon/src/server/lib/logger.ts +17 -0
  329. package/carbon/src/server/lib/rate-limiter.ts +288 -0
  330. package/carbon/src/server/lib/request.ts +34 -0
  331. package/carbon/src/server/lib/stripe.ts +42 -0
  332. package/carbon/src/server/lib/supabase.ts +65 -0
  333. package/carbon/src/server/middleware/requirePlan.ts +80 -0
  334. package/carbon/src/server/routes/_internal/services-status.ts +958 -0
  335. package/carbon/src/server/routes/_internal/verify-role.ts +185 -0
  336. package/carbon/src/server/routes/health.ts +48 -0
  337. package/carbon/src/server/routes/v1/admin/contact.ts +128 -0
  338. package/carbon/src/server/routes/v1/admin/jobs.ts +171 -0
  339. package/carbon/src/server/routes/v1/admin/newsletter.ts +237 -0
  340. package/carbon/src/server/routes/v1/auth.ts +390 -0
  341. package/carbon/src/server/routes/v1/billing.ts +718 -0
  342. package/carbon/src/server/routes/v1/contact.ts +93 -0
  343. package/carbon/src/server/routes/v1/index.ts +1333 -0
  344. package/carbon/src/server/routes/v1/newsletter.ts +181 -0
  345. package/carbon/src/server/routes/v1/performance.ts +157 -0
  346. package/carbon/src/server/routes/v1/stats.ts +170 -0
  347. package/carbon/src/server/routes/v1/theme.ts +106 -0
  348. package/carbon/src/server/routes/webhooks/billing.ts +376 -0
  349. package/carbon/src/server/routes/webhooks/stripe.ts +276 -0
  350. package/carbon/src/server/types.ts +11 -0
  351. package/carbon/src/shared/pricing.ts +155 -0
  352. package/carbon/src/shared/types.ts +338 -0
  353. package/carbon/supabase/migrations/00001_init.sql +717 -0
  354. package/carbon/supabase/migrations/00002_theme_settings.sql +13 -0
  355. package/carbon/supabase/migrations/00003_pg_cron.sql +121 -0
  356. package/carbon/supabase/migrations/00004_contact_newsletter.sql +81 -0
  357. package/carbon/supabase/migrations/00005_localization_languages.sql +22 -0
  358. package/carbon/supabase/seed.sql +16 -0
  359. package/carbon/tests/_helpers/app.ts +45 -0
  360. package/carbon/tests/_helpers/env.ts +37 -0
  361. package/carbon/tests/_helpers/factories.ts +69 -0
  362. package/carbon/tests/_helpers/jwt.ts +23 -0
  363. package/carbon/tests/_helpers/setup-integration.ts +20 -0
  364. package/carbon/tests/_helpers/setup-rtl.ts +12 -0
  365. package/carbon/tests/component/ErrorBoundary.test.tsx +53 -0
  366. package/carbon/tests/component/use-auth-settings.test.tsx +119 -0
  367. package/carbon/tests/integration/server/routes/contact.test.ts +162 -0
  368. package/carbon/tests/integration/server/routes/health.test.ts +61 -0
  369. package/carbon/tests/structural/i18n-parity.test.ts +42 -0
  370. package/carbon/tests/unit/client/utils.test.ts +49 -0
  371. package/carbon/tests/unit/shared/pricing.test.ts +93 -0
  372. package/carbon/tsconfig.json +27 -0
  373. package/carbon/tsconfig.server.json +27 -0
  374. package/carbon/tsconfig.test.json +9 -0
  375. package/carbon/vite.config.ts +110 -0
  376. package/carbon/vitest.config.ts +74 -0
  377. package/carbon/volumes/db/jwt.sql +57 -0
  378. package/carbon/volumes/db/metabase-init.sh +29 -0
  379. package/carbon/volumes/db/n8n-init.sh +25 -0
  380. package/carbon/volumes/db/realtime.sql +33 -0
  381. package/carbon/volumes/db/roles.sql +93 -0
  382. package/carbon/volumes/db/set-passwords.sh +12 -0
  383. package/carbon/volumes/db/super-admin.dev.sql +113 -0
  384. package/carbon/volumes/db/super-admin.generated.sql +113 -0
  385. package/carbon/volumes/db/super-admin.sql +114 -0
  386. package/carbon/volumes/grafana/dashboards/logs.json +179 -0
  387. package/carbon/volumes/grafana/dashboards/overview.json +523 -0
  388. package/carbon/volumes/grafana/dashboards/postgresql.json +337 -0
  389. package/carbon/volumes/grafana/dashboards.dev/logs.json +179 -0
  390. package/carbon/volumes/grafana/dashboards.dev/overview.json +156 -0
  391. package/carbon/volumes/grafana/dashboards.dev/postgresql.json +337 -0
  392. package/carbon/volumes/grafana/provisioning/dashboards/dashboards.dev.yml +16 -0
  393. package/carbon/volumes/grafana/provisioning/dashboards/dashboards.yml +16 -0
  394. package/carbon/volumes/grafana/provisioning/datasources/datasources.yml +43 -0
  395. package/carbon/volumes/kong/docker-entrypoint.sh +9 -0
  396. package/carbon/volumes/kong/kong.yml +208 -0
  397. package/carbon/volumes/loki/loki-config.yml +58 -0
  398. package/carbon/volumes/n8n/hooks.js +131 -0
  399. package/carbon/volumes/n8n/scripts/setup.sh +66 -0
  400. package/carbon/volumes/prometheus/prometheus.yml +43 -0
  401. package/carbon/volumes/promtail/promtail-config.yml +64 -0
  402. package/carbon/volumes/traefik/middlewares.dev.yml +83 -0
  403. package/carbon/volumes/traefik/middlewares.yml +95 -0
  404. package/carbon/volumes/traefik/vite-dev.yml +20 -0
  405. package/package.json +95 -0
  406. package/src/access.js +354 -0
  407. package/src/activate.js +187 -0
  408. package/src/add.js +718 -0
  409. package/src/backup.js +786 -0
  410. package/src/cli.js +350 -0
  411. package/src/configure.js +967 -0
  412. package/src/console.js +155 -0
  413. package/src/create.js +1499 -0
  414. package/src/deploy.js +311 -0
  415. package/src/destroy.js +2033 -0
  416. package/src/diagnose.js +735 -0
  417. package/src/down.js +80 -0
  418. package/src/failover.js +1032 -0
  419. package/src/lib/backup-s3.js +179 -0
  420. package/src/lib/build.js +33 -0
  421. package/src/lib/checksum.js +28 -0
  422. package/src/lib/ci-setup.js +666 -0
  423. package/src/lib/cli/help.js +129 -0
  424. package/src/lib/cli/parse-flags.js +160 -0
  425. package/src/lib/cli/select-action.js +65 -0
  426. package/src/lib/cli/select-environment.js +108 -0
  427. package/src/lib/cli/tty-guard.js +75 -0
  428. package/src/lib/cloudflare.js +447 -0
  429. package/src/lib/colors.js +52 -0
  430. package/src/lib/command.js +361 -0
  431. package/src/lib/config.js +359 -0
  432. package/src/lib/cost.js +103 -0
  433. package/src/lib/deploy/bundle.js +231 -0
  434. package/src/lib/deploy/compose/acme-verify.js +121 -0
  435. package/src/lib/deploy/compose/build-args.js +78 -0
  436. package/src/lib/deploy/compose/ha.js +1874 -0
  437. package/src/lib/deploy/compose/index.js +1294 -0
  438. package/src/lib/deploy/compose/reconcile.js +74 -0
  439. package/src/lib/deploy/github.js +382 -0
  440. package/src/lib/deploy/image.js +191 -0
  441. package/src/lib/deploy/index.js +119 -0
  442. package/src/lib/deploy/k8s/LICENSE +99 -0
  443. package/src/lib/deploy/k8s/gitops-deploy.js +298 -0
  444. package/src/lib/deploy/k8s/ha/index.js +1000 -0
  445. package/src/lib/deploy/k8s/index.js +62 -0
  446. package/src/lib/deploy/k8s/k3s.js +2515 -0
  447. package/src/lib/deploy/orchestrator.js +1401 -0
  448. package/src/lib/deploy/prompts.js +545 -0
  449. package/src/lib/deploy/remote-build.js +130 -0
  450. package/src/lib/deploy/state.js +120 -0
  451. package/src/lib/deploy/utils.js +328 -0
  452. package/src/lib/deploy-logger.js +93 -0
  453. package/src/lib/dns-propagation.js +48 -0
  454. package/src/lib/environment.js +58 -0
  455. package/src/lib/fetch-retry.js +103 -0
  456. package/src/lib/github-environments.js +335 -0
  457. package/src/lib/hetzner-dns.js +377 -0
  458. package/src/lib/hetzner-guided-setup.js +275 -0
  459. package/src/lib/host-keys.js +37 -0
  460. package/src/lib/iac/cloud-init.js +52 -0
  461. package/src/lib/iac/index.js +325 -0
  462. package/src/lib/iac/programs/hetzner-compose.js +130 -0
  463. package/src/lib/iac/programs/hetzner-k8s.js +320 -0
  464. package/src/lib/kubectl.js +81 -0
  465. package/src/lib/licensing/index.js +259 -0
  466. package/src/lib/licensing/tiers.js +181 -0
  467. package/src/lib/licensing/validator.js +171 -0
  468. package/src/lib/merge-package-json.js +90 -0
  469. package/src/lib/operator-ip.js +381 -0
  470. package/src/lib/package-manager.js +111 -0
  471. package/src/lib/perf.js +71 -0
  472. package/src/lib/project-guard.js +39 -0
  473. package/src/lib/project.js +334 -0
  474. package/src/lib/providers/base.js +276 -0
  475. package/src/lib/providers/hetzner-s3.js +656 -0
  476. package/src/lib/providers/hetzner.js +755 -0
  477. package/src/lib/providers/index.js +164 -0
  478. package/src/lib/s3.js +510 -0
  479. package/src/lib/secret-scan.js +583 -0
  480. package/src/lib/secrets.js +63 -0
  481. package/src/lib/server-types.js +195 -0
  482. package/src/lib/shell.js +91 -0
  483. package/src/lib/ssh.js +241 -0
  484. package/src/lib/tracker.js +242 -0
  485. package/src/lib/upgrade-policy.js +170 -0
  486. package/src/lib/validators.js +105 -0
  487. package/src/lib/version.js +5 -0
  488. package/src/remove.js +292 -0
  489. package/src/reset.js +97 -0
  490. package/src/restore.js +871 -0
  491. package/src/scale.js +1734 -0
  492. package/src/shell.js +222 -0
  493. package/src/status.js +981 -0
  494. package/src/up.js +264 -0
  495. package/src/upgrade.js +721 -0
@@ -0,0 +1,236 @@
1
+ ---
2
+ title: "Database"
3
+ description: "Work with Supabase PostgreSQL, migrations, and row-level security."
4
+ order: 5
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ Your application uses self-hosted Supabase with PostgreSQL. All database operations go through Supabase's client libraries, which provide built-in support for row-level security (RLS).
10
+
11
+ ## Schema Overview
12
+
13
+ The initial migration (`supabase/migrations/00001_init.sql`) creates the following tables:
14
+
15
+ | Table | Purpose |
16
+ |-------|---------|
17
+ | `organizations` | Multi-tenant orgs with name, slug, and plan (FREE, STARTER, PRO, ENTERPRISE) |
18
+ | `memberships` | User-org relationships with role (OWNER, ADMIN, MEMBER) |
19
+ | `customers` | Billing customer records, linked to a user or organization (any provider) |
20
+ | `subscriptions` | Billing subscription data (status, period, cancellation) |
21
+ | `notifications` | System-wide or org-specific notifications with scheduling |
22
+ | `notification_dismissals` | Tracks which notifications each user has dismissed |
23
+ | `failed_login_attempts` | Brute force protection (email, IP, timestamp) |
24
+ | `app_settings` | Key-value store for global config (e.g., MFA enforcement) |
25
+ | `cron_job_history` | Background job execution tracking (pg_cron, see [Background Jobs](/docs/background-jobs)) |
26
+ | `contact_submissions` | Contact form submissions (name, email, subject, message, status) |
27
+ | `newsletter_subscribers` | Newsletter subscribers with double opt-in (email, status, confirmation token) |
28
+
29
+ ## Migrations
30
+
31
+ SQL migrations live in `supabase/migrations/`. Run them with:
32
+
33
+ ```bash
34
+ pnpm db:migrate
35
+ ```
36
+
37
+ ### Conventions
38
+
39
+ - **Naming**: Use zero-padded sequential numbering — `00001_init.sql`, `00002_my_feature.sql`
40
+ - **RLS**: Always enable RLS on new tables and add policies
41
+ - **Timestamps**: Include `created_at` and `updated_at` columns with `TIMESTAMPTZ DEFAULT NOW()`
42
+ - **Triggers**: Always add the `update_updated_at()` trigger for auto-updating `updated_at`
43
+ - **Indexes**: Add indexes for foreign keys and frequently queried columns
44
+
45
+ ### Creating a New Table
46
+
47
+ Create a migration file with the table, index, RLS policies, and trigger:
48
+
49
+ ```sql
50
+ -- supabase/migrations/00002_my_table.sql
51
+
52
+ CREATE TABLE IF NOT EXISTS my_table (
53
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
54
+ user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
55
+ name TEXT NOT NULL,
56
+ created_at TIMESTAMPTZ DEFAULT NOW(),
57
+ updated_at TIMESTAMPTZ DEFAULT NOW()
58
+ );
59
+
60
+ CREATE INDEX IF NOT EXISTS idx_my_table_user_id ON my_table(user_id);
61
+
62
+ -- Enable RLS
63
+ ALTER TABLE my_table ENABLE ROW LEVEL SECURITY;
64
+
65
+ -- CRUD policies
66
+ CREATE POLICY "Users can view their own items"
67
+ ON my_table FOR SELECT
68
+ USING (user_id = (SELECT auth.uid()));
69
+
70
+ CREATE POLICY "Users can create their own items"
71
+ ON my_table FOR INSERT
72
+ WITH CHECK (user_id = (SELECT auth.uid()));
73
+
74
+ CREATE POLICY "Users can update their own items"
75
+ ON my_table FOR UPDATE
76
+ USING (user_id = (SELECT auth.uid()));
77
+
78
+ CREATE POLICY "Users can delete their own items"
79
+ ON my_table FOR DELETE
80
+ USING (user_id = (SELECT auth.uid()));
81
+
82
+ -- Auto-update updated_at
83
+ CREATE TRIGGER my_table_updated_at
84
+ BEFORE UPDATE ON my_table
85
+ FOR EACH ROW
86
+ EXECUTE FUNCTION update_updated_at();
87
+ ```
88
+
89
+ ## Row-Level Security
90
+
91
+ Every table has RLS enabled. Policies use helper functions defined in the initial migration:
92
+
93
+ ### RLS Helper Functions
94
+
95
+ | Function | Returns | Description |
96
+ |----------|---------|-------------|
97
+ | `get_user_org_ids()` | `SETOF UUID` | Org IDs where the user is a member (any role) |
98
+ | `get_user_admin_org_ids()` | `SETOF UUID` | Org IDs where the user is OWNER or ADMIN |
99
+ | `get_user_owner_org_ids()` | `SETOF UUID` | Org IDs where the user is OWNER |
100
+ | `get_user_customer_ids()` | `SETOF UUID` | Customer IDs for the user or their orgs |
101
+ | `is_super_admin()` | `BOOLEAN` | `true` if user's `app_metadata.role` is `super_admin` |
102
+
103
+ All helper functions use `SECURITY DEFINER` so they can read the `memberships` table regardless of the calling user's permissions.
104
+
105
+ ### Common Policy Patterns
106
+
107
+ **User-owned data** — rows belong to a specific user:
108
+
109
+ ```sql
110
+ CREATE POLICY "Users can view their own items"
111
+ ON my_table FOR SELECT
112
+ USING (user_id = (SELECT auth.uid()));
113
+ ```
114
+
115
+ **Organization data** — rows belong to an org the user is a member of:
116
+
117
+ ```sql
118
+ CREATE POLICY "Members can view org data"
119
+ ON my_table FOR SELECT
120
+ USING (organization_id IN (SELECT get_user_org_ids()));
121
+ ```
122
+
123
+ **Admin-only writes** — only org owners/admins can modify:
124
+
125
+ ```sql
126
+ CREATE POLICY "Admins can update org data"
127
+ ON my_table FOR UPDATE
128
+ USING (organization_id IN (SELECT get_user_admin_org_ids()));
129
+ ```
130
+
131
+ **Super admin access** — full access for super admins:
132
+
133
+ ```sql
134
+ CREATE POLICY "Super admins can do anything"
135
+ ON my_table FOR ALL
136
+ USING (is_super_admin());
137
+ ```
138
+
139
+ ## Client-Side Queries
140
+
141
+ ```typescript
142
+ import { supabase } from '@/lib/supabase';
143
+
144
+ // Fetch data (RLS enforced automatically)
145
+ const { data: items, error: fetchError } = await supabase
146
+ .from('my_table')
147
+ .select('*');
148
+
149
+ // Insert data
150
+ const { data: newItem, error: insertError } = await supabase
151
+ .from('my_table')
152
+ .insert({ name: 'New item' })
153
+ .select()
154
+ .single();
155
+ ```
156
+
157
+ ## Server-Side Queries
158
+
159
+ ```typescript
160
+ // User-context (respects RLS)
161
+ const supabase = c.get('supabase');
162
+ const { data } = await supabase.from('my_table').select('*');
163
+
164
+ // Admin operations (bypasses RLS)
165
+ import { supabaseAdmin } from '@/server/lib/supabase';
166
+ const { data } = await supabaseAdmin.from('my_table').select('*');
167
+ ```
168
+
169
+ ## TanStack Query
170
+
171
+ Use TanStack Query for client-side data fetching with caching, deduplication, and automatic refetching.
172
+
173
+ ### Fetching Data
174
+
175
+ ```typescript
176
+ import { useQuery } from '@tanstack/react-query';
177
+ import { supabase } from '@/lib/supabase';
178
+
179
+ export function useItems() {
180
+ return useQuery({
181
+ queryKey: ['items'],
182
+ queryFn: async () => {
183
+ const { data, error } = await supabase.from('items').select('*');
184
+ if (error) throw error;
185
+ return data;
186
+ },
187
+ });
188
+ }
189
+ ```
190
+
191
+ ### Mutations with Cache Invalidation
192
+
193
+ ```typescript
194
+ import { useMutation, useQueryClient } from '@tanstack/react-query';
195
+ import { supabase } from '@/lib/supabase';
196
+
197
+ export function useCreateItem() {
198
+ const queryClient = useQueryClient();
199
+
200
+ return useMutation({
201
+ mutationFn: async (item: { name: string }) => {
202
+ const { data, error } = await supabase
203
+ .from('items')
204
+ .insert(item)
205
+ .select()
206
+ .single();
207
+ if (error) throw error;
208
+ return data;
209
+ },
210
+ onSuccess: () => {
211
+ queryClient.invalidateQueries({ queryKey: ['items'] });
212
+ },
213
+ });
214
+ }
215
+ ```
216
+
217
+ ### Usage in Components
218
+
219
+ ```tsx
220
+ function ItemList() {
221
+ const { data: items, isLoading, error } = useItems();
222
+ const createItem = useCreateItem();
223
+
224
+ if (isLoading) return <p>Loading...</p>;
225
+ if (error) return <p>Error: {error.message}</p>;
226
+
227
+ return (
228
+ <div>
229
+ {items?.map((item) => <p key={item.id}>{item.name}</p>)}
230
+ <button onClick={() => createItem.mutate({ name: 'New item' })}>
231
+ Add Item
232
+ </button>
233
+ </div>
234
+ );
235
+ }
236
+ ```
@@ -0,0 +1,227 @@
1
+ ---
2
+ title: "Deployment"
3
+ description: "Deploy your application to production with Docker or Kubernetes."
4
+ order: 6
5
+ ---
6
+
7
+ > **Deployment requires a Diamond or Fullerene license.** `create` and local development (`up`, `down`) are always free. See [Getting Started](/docs/getting-started) for licensing details.
8
+
9
+ ## Overview
10
+
11
+ Your application can be deployed using Docker Compose, Compose HA, or Kubernetes — all available with a Diamond or Fullerene license. Fullerene is the commercial license for agencies and enterprise.
12
+
13
+ ## Prerequisites
14
+
15
+ **Always required (all deploy modes):**
16
+ - **GitHub CLI** (`gh`) — authenticated with `read:packages` + `delete_repo` scopes. Images are built by GitHub Actions and published to ghcr.io; deploy waits for the tagged image to appear before provisioning the cluster.
17
+ - **Pulumi** (`curl -fsSL https://get.pulumi.com | sh`) — drives Hetzner VM provisioning.
18
+ - A **domain name** with DNS access (Cloudflare or Hetzner DNS).
19
+ - **SMTP credentials** for transactional email (auth confirmations, magic links, invitations).
20
+ - (Optional) **Stripe API keys** for billing.
21
+
22
+ **Additional for `-mode k8s` / `-mode k8s-ha`:**
23
+ - **kubectl** — applies manifests + waits for the app rollout.
24
+ - **docker** + **ssh** — image is built locally and sideloaded to each k3s node via `docker save | ssh node 'k3s ctr images import -'`. No registry round-trip on the deploy path.
25
+
26
+ **Optional:**
27
+ - `helm` — only required if you layer GitOps on top via [`vibecarbon configure cicd <env>`](/docs/cli#configure-cicd-env-subcommand) (Flux-managed Helm releases). The default deploy path doesn't use it.
28
+
29
+ ## Build
30
+
31
+ Build the client and server for production:
32
+
33
+ ```bash
34
+ pnpm build
35
+ ```
36
+
37
+ This produces:
38
+ - `dist/client/` — Static assets (Vite build with hashed filenames)
39
+ - `dist/server/` — Bundled API server (esbuild output)
40
+
41
+ The `Dockerfile` uses a multi-stage build: a Node.js build stage compiles both client and server, then copies the output into a slim runtime image.
42
+
43
+ ## Docker Compose
44
+
45
+ For a single-server deployment:
46
+
47
+ ```bash
48
+ docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
49
+ ```
50
+
51
+ The production overlay (`docker-compose.prod.yml`) adds:
52
+ - Production environment variables (`NODE_ENV=production`)
53
+ - Resource limits for containers
54
+ - Restart policies (`unless-stopped`)
55
+ - Traefik SSL configuration with Let's Encrypt
56
+ - Host-based routing for your domain
57
+
58
+ Verify the deployment:
59
+
60
+ ```bash
61
+ curl -s https://your-domain.com/api/health | jq
62
+ ```
63
+
64
+ ## Kubernetes
65
+
66
+ For production deployments with auto-scaling and monitoring (requires Diamond or Fullerene license):
67
+
68
+ ```bash
69
+ # Bare command opens a guided prompt for env, mode, region, etc.
70
+ npx vibecarbon deploy
71
+
72
+ # Or seed env + mode for a scripted deploy
73
+ npx vibecarbon deploy prod -mode k8s
74
+ ```
75
+
76
+ This command:
77
+ 1. Builds the app and sideloads images to every k3s node via SSH (no registry round-trip)
78
+ 2. Applies Kubernetes manifests with Kustomize overlays
79
+ 3. Configures Traefik ingress with automatic SSL
80
+ 4. Sets up monitoring (Grafana, Prometheus, Loki) if observability is enabled
81
+
82
+ The `k8s/` directory structure:
83
+
84
+ ```
85
+ k8s/
86
+ ├── base/ # Shared manifests
87
+ │ ├── app/ # App deployment, service, ingress
88
+ │ ├── supabase/ # Supabase services
89
+ │ └── kustomization.yaml
90
+ └── overlays/
91
+ ├── staging/ # Staging-specific config
92
+ └── production/ # Production-specific config
93
+ ```
94
+
95
+ ### Node Scaling
96
+
97
+ Worker nodes are bounds-controlled at deploy time — the default is `min=1, max=3` (cluster-autoscaler scales 0..(max-min) workers on top of the static floor). Worker bounds and server types are configured interactively during `vibecarbon deploy` or in `.vibecarbon.json`; they don't have CLI flags (the design principle is "things you set once and forget belong in the config file").
98
+
99
+ To re-tune bounds or worker server types on an existing cluster, run `npx vibecarbon scale` — the wizard walks you through what's changeable for your topology. Power users can seed a server-type change with `-type` (e.g. `npx vibecarbon scale prod -type cx33 -y`). Pod-level autoscaling (HPA) is configured for the app and rest services and scales pods within the existing worker pool based on CPU.
100
+
101
+ > **Note**: k3s masters have no `NoSchedule` taint by default, so all application pods run on the master node when no workers are present.
102
+
103
+ ### High Availability
104
+
105
+ **Compose HA** — multi-region Docker Compose with PostgreSQL streaming replication:
106
+
107
+ ```bash
108
+ npx vibecarbon deploy prod -mode compose-ha
109
+ ```
110
+
111
+ This adds:
112
+ - PostgreSQL streaming replication across regions
113
+ - DNS-based health checks with one-command failover (`vibecarbon failover`)
114
+ - Primary + standby VPS architecture
115
+
116
+ **Kubernetes HA** — full K8s clusters per region:
117
+
118
+ ```bash
119
+ npx vibecarbon deploy prod -mode k8s-ha
120
+ ```
121
+
122
+ This additionally includes:
123
+ - Kubernetes HPA (pod-level autoscaling) per region
124
+ - Cluster Autoscaler (VPS-level autoscaling) per region
125
+ - Health monitoring across replicas
126
+
127
+ ## Environment Variables
128
+
129
+ Production requires these environment variables in `.env.production` or your deployment secrets:
130
+
131
+ | Variable | Required | Description |
132
+ |----------|----------|-------------|
133
+ | `SUPABASE_URL` | Yes | Your Supabase API URL |
134
+ | `SUPABASE_ANON_KEY` | Yes | Public anonymous key |
135
+ | `SUPABASE_SERVICE_ROLE_KEY` | Yes | Server-side service role key |
136
+ | `SITE_URL` | Yes | Your production URL (e.g., `https://app.example.com`) |
137
+ | `DOMAIN` | Yes | Your root domain (e.g., `example.com`) |
138
+ | `SMTP_HOST` | Yes | SMTP server hostname |
139
+ | `SMTP_PORT` | No | SMTP port (default: 587) |
140
+ | `SMTP_USER` | Yes | SMTP username |
141
+ | `SMTP_PASS` | Yes | SMTP password |
142
+ | `SMTP_SENDER_NAME` | No | Display name for outgoing emails |
143
+ | `SMTP_ADMIN_EMAIL` | No | Admin contact email for system notifications |
144
+ | `BILLING_PROVIDER` | No | Payment provider: `stripe` (default), `paddle`, or `polar` |
145
+ | `STRIPE_SECRET_KEY` | No | Stripe API key (required if using Stripe) |
146
+ | `STRIPE_WEBHOOK_SECRET` | No | Stripe webhook signing secret |
147
+ | `STRIPE_PRICE_STARTER` | No | Stripe price ID for the Startup plan |
148
+ | `STRIPE_PRICE_PRO` | No | Stripe price ID for the Pro plan |
149
+ | `PADDLE_API_KEY` | No | Paddle API key (required if using Paddle) |
150
+ | `PADDLE_WEBHOOK_SECRET` | No | Paddle webhook signing secret |
151
+ | `PADDLE_ENVIRONMENT` | No | `sandbox` or `production` (default: sandbox) |
152
+ | `PADDLE_PRICE_STARTER` | No | Paddle price ID for the Startup plan |
153
+ | `PADDLE_PRICE_PRO` | No | Paddle price ID for the Pro plan |
154
+ | `POLAR_ACCESS_TOKEN` | No | Polar access token (required if using Polar) |
155
+ | `POLAR_WEBHOOK_SECRET` | No | Polar webhook signing secret |
156
+ | `POLAR_ORGANIZATION_ID` | No | Polar organization ID |
157
+ | `POLAR_PRICE_STARTER` | No | Polar product ID for the Startup plan |
158
+ | `POLAR_PRICE_PRO` | No | Polar product ID for the Pro plan |
159
+ | `VITE_PLAUSIBLE_DOMAIN` | No | Plausible analytics domain (e.g., `myapp.com`) |
160
+ | `VITE_PLAUSIBLE_SCRIPT_URL` | No | Plausible script URL (default: Plausible Cloud) |
161
+ | `REDIS_URL` | No | Redis connection URL (for distributed rate limiting) |
162
+
163
+ ## SMTP Configuration
164
+
165
+ SMTP credentials are shared between Supabase Auth (for email confirmation, password reset, magic links) and the application's email service (for welcome emails, team invitations, billing notifications).
166
+
167
+ **Required variables**: `SMTP_HOST`, `SMTP_USER`, `SMTP_PASS`
168
+
169
+ **Optional variables**: `SMTP_PORT` (defaults to 587), `SMTP_SENDER_NAME`, `SMTP_ADMIN_EMAIL`
170
+
171
+ Without SMTP configured:
172
+ - Email confirmation is disabled — users can sign in immediately after sign-up
173
+ - Magic link authentication is unavailable
174
+ - Team invitation emails won't send (invitations still work via shareable link)
175
+ - Transactional emails (welcome, billing) are skipped silently
176
+
177
+ ## DNS Configuration
178
+
179
+ Point your domain to the server's IP address:
180
+
181
+ | Record | Name | Value |
182
+ |--------|------|-------|
183
+ | A | `app.example.com` | `<server-ip>` |
184
+ | A | `api.example.com` | `<server-ip>` |
185
+
186
+ If you have optional services enabled, add records for their subdomains too (e.g., `grafana.example.com`, `n8n.example.com`).
187
+
188
+ SSL certificates are handled automatically by Traefik via Let's Encrypt — no manual certificate management required.
189
+
190
+ ## Backup & Restore
191
+
192
+ Create and manage database backups with the CLI:
193
+
194
+ ```bash
195
+ # Interactive — prompts for env and action
196
+ npx vibecarbon backup
197
+
198
+ # Create a backup for a specific env
199
+ npx vibecarbon backup prod
200
+
201
+ # List existing backups
202
+ npx vibecarbon backup prod -l
203
+
204
+ # Restore from a backup (interactive picker)
205
+ npx vibecarbon restore prod
206
+ ```
207
+
208
+ Backups include the full PostgreSQL database (schema, data, and auth tables).
209
+
210
+ ## Monitoring
211
+
212
+ Add the observability stack for metrics, dashboards, and log aggregation:
213
+
214
+ ```bash
215
+ npx vibecarbon add observability
216
+ ```
217
+
218
+ This enables:
219
+ - **Prometheus** — Metrics collection from all services
220
+ - **Grafana** — Pre-built dashboards for API performance, database metrics, and container health
221
+ - **Loki** — Centralized log aggregation with Grafana integration
222
+
223
+ Access Grafana at `https://grafana.your-domain.com` (requires `super_admin` role in production).
224
+
225
+ ## SSL Certificates
226
+
227
+ Traefik automatically obtains and renews SSL certificates via Let's Encrypt. No manual certificate management required.
@@ -0,0 +1,238 @@
1
+ ---
2
+ title: "Development"
3
+ description: "Day-to-day development workflow, commands, and how to add pages, routes, and content."
4
+ order: 3
5
+ ---
6
+
7
+ ## CLI Commands
8
+
9
+ If you installed Vibecarbon globally, you can manage your dev environment with these commands:
10
+
11
+ | Command | Purpose |
12
+ |---------|---------|
13
+ | `npx vibecarbon up` | Full cold start — Docker, migrations, and dev servers |
14
+ | `npx vibecarbon down` | Stop all Docker services |
15
+ | `npx vibecarbon reset` | Remove containers, volumes, and built images (run `npx vibecarbon up` to restart) |
16
+
17
+ These are wrappers around the `pnpm` scripts listed below — use whichever you prefer.
18
+
19
+ ## Dev Commands
20
+
21
+ | Command | Purpose |
22
+ |---------|---------|
23
+ | `pnpm dev:start` | Full cold start — Docker, migrations, and dev servers |
24
+ | `pnpm dev` | Start API + Vite (assumes Docker is already running) |
25
+ | `pnpm dev:reset` | Remove containers, volumes, and built images (run `pnpm dev:start` to restart) |
26
+ | `pnpm docker:up` | Start Supabase and infrastructure services |
27
+ | `pnpm docker:down` | Stop all Docker services |
28
+ | `pnpm db:migrate` | Run SQL migrations from `supabase/migrations/` |
29
+ | `pnpm build` | Build client (Vite) and server (esbuild) for production |
30
+ | `pnpm lint` | Biome linting and formatting check |
31
+ | `pnpm lint:fix` | Auto-fix lint and formatting issues |
32
+ | `pnpm typecheck` | TypeScript type checking |
33
+ | `pnpm test` | Run vitest tests |
34
+ | `pnpm start` | Run production server (`node dist/server/index.js`) |
35
+ | `pnpm stripe:listen` | Forward Stripe webhooks to local API |
36
+ | `pnpm docker:logs` | Tail logs from all Docker containers |
37
+
38
+ ## How It Works
39
+
40
+ `pnpm dev:start` runs three phases in sequence:
41
+
42
+ 1. **Docker startup** — Starts PostgreSQL, Kong, GoTrue, PostgREST, Realtime, Storage, Studio, and Traefik. Blocks until all services are healthy.
43
+ 2. **Migrations** — Executes all SQL files in `supabase/migrations/` to set up the schema, RLS policies, and initial admin user.
44
+ 3. **Dev servers** — Spawns two processes in parallel:
45
+ - **Hono API** on port 3000 via `tsx watch` (auto-restarts on file changes)
46
+ - **Vite** on port 5173 with full HMR (instant browser updates)
47
+
48
+ Vite proxies all `/api/*` requests to the Hono server, so the client can call `fetch('/api/v1/...')` without worrying about ports or CORS.
49
+
50
+ ## Development URLs
51
+
52
+ Traefik routes `*.localhost` subdomains to each service:
53
+
54
+ | Service | URL |
55
+ |---------|-----|
56
+ | App | http://app.localhost |
57
+ | Supabase Studio | http://studio.localhost |
58
+ | Traefik Dashboard | http://traefik.localhost |
59
+
60
+ Optional services (n8n, Metabase, Grafana) get their own subdomains when enabled — see [Optional Services](/docs/optional-services).
61
+
62
+ ## Hot Reloading
63
+
64
+ **Client changes** (React components, CSS, MDX) update instantly in the browser via Vite HMR. Component state is preserved.
65
+
66
+ **Server changes** (API routes, middleware) trigger a full process restart via `tsx watch`. The API is briefly unavailable during restart.
67
+
68
+ **Database changes** require running `pnpm db:migrate` manually — migrations are not watched.
69
+
70
+ ## Debugging
71
+
72
+ **Container logs** — Run `pnpm docker:logs` to tail logs from all Docker services. Useful for debugging Supabase Auth errors, PostgREST issues, or Kong routing problems.
73
+
74
+ **Supabase Studio** — Open [http://studio.localhost](http://studio.localhost) to browse your database, inspect tables, view RLS policies, and manage auth users directly.
75
+
76
+ **React DevTools** — Vite's dev server supports React DevTools out of the box. Install the browser extension for component inspection and state debugging.
77
+
78
+ ## Adding a Page
79
+
80
+ 1. Create a component in `src/client/pages/`:
81
+
82
+ ```tsx
83
+ export default function MyPage() {
84
+ return <h1>My Page</h1>;
85
+ }
86
+ ```
87
+
88
+ 2. Add a route in `src/client/App.tsx`:
89
+
90
+ ```tsx
91
+ <Route
92
+ path="/my-page"
93
+ element={
94
+ <ProtectedRoute>
95
+ <MyPage />
96
+ </ProtectedRoute>
97
+ }
98
+ />
99
+ ```
100
+
101
+ Wrap with `<ProtectedRoute>` to require authentication, or omit it for public pages.
102
+
103
+ ## Adding an API Route
104
+
105
+ 1. Create a route file in `src/server/routes/v1/`:
106
+
107
+ ```typescript
108
+ import { Hono } from 'hono';
109
+ import { z } from 'zod';
110
+ import type { HonoVariables } from '../../types';
111
+
112
+ const items = new Hono<{ Variables: HonoVariables }>();
113
+
114
+ const createSchema = z.object({
115
+ name: z.string().min(1).max(100),
116
+ });
117
+
118
+ items.get('/', async (c) => {
119
+ const user = c.get('user');
120
+ if (!user) return c.json({ error: 'Unauthorized' }, 401);
121
+
122
+ const supabase = c.get('supabase');
123
+ const { data, error } = await supabase.from('items').select('*');
124
+ if (error) return c.json({ error: 'Failed to fetch items' }, 500);
125
+ return c.json(data);
126
+ });
127
+
128
+ items.post('/', async (c) => {
129
+ const user = c.get('user');
130
+ if (!user) return c.json({ error: 'Unauthorized' }, 401);
131
+
132
+ const body = await c.req.json();
133
+ const result = createSchema.safeParse(body);
134
+ if (!result.success) {
135
+ return c.json({ error: result.error.issues.map((e) => e.message).join(', ') }, 400);
136
+ }
137
+
138
+ const supabase = c.get('supabase');
139
+ const { data, error } = await supabase
140
+ .from('items')
141
+ .insert(result.data)
142
+ .select()
143
+ .single();
144
+ if (error) return c.json({ error: 'Failed to create item' }, 500);
145
+ return c.json({ item: data }, 201);
146
+ });
147
+
148
+ export { items };
149
+ ```
150
+
151
+ 2. Mount in `src/server/index.ts`:
152
+
153
+ ```typescript
154
+ import { items } from './routes/v1/items';
155
+ app.route('/api/v1/items', items);
156
+ ```
157
+
158
+ The Vite proxy forwards `/api/*` to the Hono server automatically.
159
+
160
+ ## Adding MDX Content
161
+
162
+ MDX files in `content/` are auto-discovered at build time. Drop a file in the right directory and it appears on the site.
163
+
164
+ **Blog post** — `content/blog/my-post.mdx`:
165
+
166
+ ```markdown
167
+ ---
168
+ title: "My Post"
169
+ description: "A short summary."
170
+ date: "2025-01-15"
171
+ author: "Your Name"
172
+ ---
173
+
174
+ Post content with **markdown** and JSX.
175
+ ```
176
+
177
+ **Documentation page** — `content/docs/my-page.mdx`:
178
+
179
+ ```markdown
180
+ ---
181
+ title: "My Page"
182
+ description: "What this page covers."
183
+ order: 7
184
+ ---
185
+
186
+ Page content here.
187
+ ```
188
+
189
+ **Changelog entry** — `content/changelog/v1-1-0.mdx`:
190
+
191
+ ```markdown
192
+ ---
193
+ title: "v1.1.0"
194
+ description: "What changed."
195
+ date: "2025-01-15"
196
+ version: "1.1.0"
197
+ ---
198
+
199
+ ## Features
200
+ - New feature
201
+ ```
202
+
203
+ The `order` field controls sidebar position in docs. Blog and changelog entries sort by `date` (newest first).
204
+
205
+ ## Running Multiple Projects
206
+
207
+ To run two Vibecarbon projects simultaneously, set a port offset in `.env.local`:
208
+
209
+ ```bash
210
+ DEV_PORT_OFFSET=100
211
+ ```
212
+
213
+ This shifts all ports by 100 (Vite → 5273, API → 3100, Kong → 8100, etc.). You can also override individual ports:
214
+
215
+ ```bash
216
+ DEV_VITE_PORT=5273
217
+ DEV_API_PORT=3100
218
+ DEV_KONG_PORT=8100
219
+ ```
220
+
221
+ ## Resetting the Environment
222
+
223
+ If your database gets into a bad state or you want a clean slate:
224
+
225
+ ```bash
226
+ pnpm dev:reset # Remove containers, volumes, and built images
227
+ pnpm dev:start # Cold start: Docker + migrations + dev servers
228
+ ```
229
+
230
+ `dev:reset` removes all Docker containers, volumes (including database data), and locally-built images. It does **not** restart services — run `pnpm dev:start` afterward to start fresh.
231
+
232
+ To stop services without losing data:
233
+
234
+ ```bash
235
+ pnpm docker:down # Stop services, data preserved in volumes
236
+ pnpm docker:up # Restart services with existing data
237
+ pnpm dev # Start dev servers
238
+ ```