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.
- package/LICENSE +663 -0
- package/README.md +188 -0
- package/carbon/.claude/hooks/task-completed-gate.sh +19 -0
- package/carbon/.claude/hooks/teammate-idle-gate.sh +29 -0
- package/carbon/.claude/settings.json +29 -0
- package/carbon/.cursor/rules/vibecarbon.mdc +6 -0
- package/carbon/.dockerignore +57 -0
- package/carbon/.env.example +219 -0
- package/carbon/.github/copilot-instructions.md +3 -0
- package/carbon/.github/workflows/deploy.yml +346 -0
- package/carbon/.github/workflows/vibecarbon-build.yml +81 -0
- package/carbon/.windsurfrules +74 -0
- package/carbon/AGENTS.md +422 -0
- package/carbon/CLAUDE.md +3 -0
- package/carbon/DEVELOPMENT.md +187 -0
- package/carbon/Dockerfile +98 -0
- package/carbon/LICENSE +21 -0
- package/carbon/PRODUCTION.md +364 -0
- package/carbon/README.md +193 -0
- package/carbon/TESTING.md +138 -0
- package/carbon/backup/Dockerfile +75 -0
- package/carbon/backup/backup.sh +95 -0
- package/carbon/backup/compose-backup.sh +140 -0
- package/carbon/biome.json +83 -0
- package/carbon/cloud-init/docker-ce-setup.yaml +55 -0
- package/carbon/cloud-init/k3s/master-init.sh +215 -0
- package/carbon/cloud-init/k3s/supabase-init.sh +167 -0
- package/carbon/cloud-init/k3s/worker-init.sh +147 -0
- package/carbon/components.json +24 -0
- package/carbon/content/blog/authentication-guide.mdx +34 -0
- package/carbon/content/blog/getting-started.mdx +41 -0
- package/carbon/content/changelog/v0-1-0.mdx +40 -0
- package/carbon/content/docs/analytics.mdx +90 -0
- package/carbon/content/docs/authentication.mdx +231 -0
- package/carbon/content/docs/background-jobs.mdx +116 -0
- package/carbon/content/docs/cli.mdx +630 -0
- package/carbon/content/docs/database.mdx +236 -0
- package/carbon/content/docs/deployment.mdx +227 -0
- package/carbon/content/docs/development.mdx +238 -0
- package/carbon/content/docs/environments.mdx +84 -0
- package/carbon/content/docs/getting-started.mdx +112 -0
- package/carbon/content/docs/legal/privacy-policy.mdx +89 -0
- package/carbon/content/docs/legal/terms-of-service.mdx +99 -0
- package/carbon/content/docs/optional-services.mdx +160 -0
- package/carbon/db/Dockerfile +23 -0
- package/carbon/docker-compose.dev-init.yml +5 -0
- package/carbon/docker-compose.metabase.override.yml +14 -0
- package/carbon/docker-compose.metabase.prod.yml +28 -0
- package/carbon/docker-compose.metabase.yml +84 -0
- package/carbon/docker-compose.n8n.override.yml +14 -0
- package/carbon/docker-compose.n8n.prod.yml +31 -0
- package/carbon/docker-compose.n8n.yml +97 -0
- package/carbon/docker-compose.observability.override.yml +18 -0
- package/carbon/docker-compose.observability.prod.yml +28 -0
- package/carbon/docker-compose.observability.yml +125 -0
- package/carbon/docker-compose.override.yml +28 -0
- package/carbon/docker-compose.prod.yml +294 -0
- package/carbon/docker-compose.yml +508 -0
- package/carbon/docker-entrypoint.sh +12 -0
- package/carbon/ha/activate-standby.sh +52 -0
- package/carbon/ha/primary-init.sql +36 -0
- package/carbon/ha/standby-init.sh +74 -0
- package/carbon/k8s/LICENSE +99 -0
- package/carbon/k8s/README.md +272 -0
- package/carbon/k8s/base/app/deployment.yaml +130 -0
- package/carbon/k8s/base/app/hpa.yaml +44 -0
- package/carbon/k8s/base/app/kustomization.yaml +10 -0
- package/carbon/k8s/base/app/network-policy.yaml +124 -0
- package/carbon/k8s/base/app/pdb.yaml +14 -0
- package/carbon/k8s/base/app/rbac.yaml +36 -0
- package/carbon/k8s/base/app/service.yaml +16 -0
- package/carbon/k8s/base/backup/cronjob.yaml +120 -0
- package/carbon/k8s/base/backup/kustomization.yaml +7 -0
- package/carbon/k8s/base/backup/network-policy.yaml +31 -0
- package/carbon/k8s/base/backup/rbac.yaml +7 -0
- package/carbon/k8s/base/cluster-autoscaler/deployment.yaml +103 -0
- package/carbon/k8s/base/cluster-autoscaler/kustomization.yaml +17 -0
- package/carbon/k8s/base/cluster-autoscaler/rbac.yaml +109 -0
- package/carbon/k8s/base/config/configmap.yaml +48 -0
- package/carbon/k8s/base/config/kustomization.yaml +8 -0
- package/carbon/k8s/base/hetzner-ccm/kustomization.yaml +9 -0
- package/carbon/k8s/base/hetzner-csi/kustomization.yaml +9 -0
- package/carbon/k8s/base/kustomization.yaml +43 -0
- package/carbon/k8s/base/namespace.yaml +7 -0
- package/carbon/k8s/base/network-policies.yaml +95 -0
- package/carbon/k8s/base/registry/kustomization.yaml +5 -0
- package/carbon/k8s/base/registry/local-registry.yaml +193 -0
- package/carbon/k8s/base/traefik/certificate.yaml +21 -0
- package/carbon/k8s/base/traefik/configmap.yaml +13 -0
- package/carbon/k8s/base/traefik/deployment.yaml +165 -0
- package/carbon/k8s/base/traefik/ingressroute.yaml +141 -0
- package/carbon/k8s/base/traefik/kustomization.yaml +11 -0
- package/carbon/k8s/base/traefik/middleware.yaml +109 -0
- package/carbon/k8s/base/traefik/network-policy.yaml +92 -0
- package/carbon/k8s/base/traefik/service.yaml +38 -0
- package/carbon/k8s/flux/README.md +49 -0
- package/carbon/k8s/flux/clusters/primary/vibecarbon.yaml +128 -0
- package/carbon/k8s/flux/clusters/standby/vibecarbon.yaml +83 -0
- package/carbon/k8s/gitops/cert-manager-webhook-hetzner/helm-release.yaml +38 -0
- package/carbon/k8s/gitops/cert-manager-webhook-hetzner/helm-repository.yaml +16 -0
- package/carbon/k8s/gitops/cert-manager-webhook-hetzner/kustomization.yaml +10 -0
- package/carbon/k8s/gitops/supabase/helm-release.yaml +66 -0
- package/carbon/k8s/gitops/supabase/helm-repository.yaml +18 -0
- package/carbon/k8s/gitops/supabase/kustomization.yaml +33 -0
- package/carbon/k8s/infra/cert-manager-resources/cluster-issuers-cloudflare.yaml +51 -0
- package/carbon/k8s/infra/cert-manager-resources/cluster-issuers-hetzner.yaml +59 -0
- package/carbon/k8s/infra/cert-manager-resources/cluster-issuers-manual.yaml +43 -0
- package/carbon/k8s/infra/cert-manager-resources/kustomization.yaml +15 -0
- package/carbon/k8s/infra/kustomization.yaml +21 -0
- package/carbon/k8s/infra/traefik-crds/kustomization.yaml +10 -0
- package/carbon/k8s/overlays/local/configmap.yaml +23 -0
- package/carbon/k8s/overlays/local/ingressroute-studio.yaml +104 -0
- package/carbon/k8s/overlays/local/kustomization.yaml +215 -0
- package/carbon/k8s/overlays/local/namespace.yaml +8 -0
- package/carbon/k8s/overlays/local/secrets.yaml +32 -0
- package/carbon/k8s/overlays/production/kustomization.yaml +34 -0
- package/carbon/k8s/test-local.sh +318 -0
- package/carbon/k8s/values/supabase.values.yaml +133 -0
- package/carbon/package.json +154 -0
- package/carbon/runtime.Dockerfile +17 -0
- package/carbon/scripts/_dev-jwt.mjs +45 -0
- package/carbon/scripts/check-rls.ts +53 -0
- package/carbon/scripts/dev-init.js +191 -0
- package/carbon/scripts/dev.js +191 -0
- package/carbon/scripts/docker-down.js +63 -0
- package/carbon/scripts/docker-logs.js +59 -0
- package/carbon/scripts/docker-up.js +222 -0
- package/carbon/scripts/generate-dev-configs.sh +131 -0
- package/carbon/scripts/generate-rss.ts +116 -0
- package/carbon/scripts/generate-sitemap.ts +102 -0
- package/carbon/scripts/k8s-apply.js +71 -0
- package/carbon/scripts/k8s-delete.js +75 -0
- package/carbon/scripts/lib/manifest.js +176 -0
- package/carbon/scripts/secret-scan.mjs +278 -0
- package/carbon/scripts/validate-dev-configs.sh +101 -0
- package/carbon/src/client/App.tsx +202 -0
- package/carbon/src/client/assets/hyperformant-dark.svg +29 -0
- package/carbon/src/client/assets/hyperformant-light.svg +29 -0
- package/carbon/src/client/assets/logos/aider.svg +1 -0
- package/carbon/src/client/assets/logos/antigravity.svg +1 -0
- package/carbon/src/client/assets/logos/bolt.svg +1 -0
- package/carbon/src/client/assets/logos/claude-code.svg +1 -0
- package/carbon/src/client/assets/logos/copilot.svg +1 -0
- package/carbon/src/client/assets/logos/cursor.svg +1 -0
- package/carbon/src/client/assets/logos/gemini-cli.svg +1 -0
- package/carbon/src/client/assets/logos/lovable.svg +1 -0
- package/carbon/src/client/assets/logos/openai-codex.svg +1 -0
- package/carbon/src/client/assets/logos/v0.svg +1 -0
- package/carbon/src/client/assets/logos/windsurf.svg +1 -0
- package/carbon/src/client/assets/vibecarbon-icon.svg +19 -0
- package/carbon/src/client/assets/vibecarbon-logo-dark.svg +29 -0
- package/carbon/src/client/assets/vibecarbon-logo-light.svg +29 -0
- package/carbon/src/client/components/AIIntegrationSection.tsx +120 -0
- package/carbon/src/client/components/AppSidebar.tsx +760 -0
- package/carbon/src/client/components/ArchitectureSection.tsx +46 -0
- package/carbon/src/client/components/CTAFooter.tsx +59 -0
- package/carbon/src/client/components/ComparisonSection.tsx +132 -0
- package/carbon/src/client/components/ContentPanel.tsx +66 -0
- package/carbon/src/client/components/ContentSkeleton.tsx +21 -0
- package/carbon/src/client/components/ErrorBoundary.tsx +46 -0
- package/carbon/src/client/components/FAQSection.tsx +76 -0
- package/carbon/src/client/components/FileUpload.tsx +210 -0
- package/carbon/src/client/components/HeaderActions.tsx +17 -0
- package/carbon/src/client/components/Hero.tsx +608 -0
- package/carbon/src/client/components/ImpersonationBanner.tsx +31 -0
- package/carbon/src/client/components/LanguageSwitcher.tsx +67 -0
- package/carbon/src/client/components/Logo.tsx +87 -0
- package/carbon/src/client/components/LogoStrip.tsx +76 -0
- package/carbon/src/client/components/MetricsStrip.tsx +48 -0
- package/carbon/src/client/components/Nav.tsx +195 -0
- package/carbon/src/client/components/NewsletterSignup.tsx +147 -0
- package/carbon/src/client/components/NotificationDrawer.tsx +171 -0
- package/carbon/src/client/components/PageHeader.tsx +24 -0
- package/carbon/src/client/components/PlanGate.tsx +36 -0
- package/carbon/src/client/components/PricingSection.tsx +371 -0
- package/carbon/src/client/components/SEO.tsx +34 -0
- package/carbon/src/client/components/SmoothScroll.tsx +45 -0
- package/carbon/src/client/components/TechStackSection.tsx +165 -0
- package/carbon/src/client/components/WorkflowSection.tsx +604 -0
- package/carbon/src/client/components/admin/DockerLogs.tsx +276 -0
- package/carbon/src/client/components/admin/PerformanceMetrics.tsx +230 -0
- package/carbon/src/client/components/admin/ServiceCard.tsx +45 -0
- package/carbon/src/client/components/admin/ServicesStatus.tsx +296 -0
- package/carbon/src/client/components/architecture/ArchitectureDiagram.tsx +413 -0
- package/carbon/src/client/components/auth/AuthProvider.tsx +466 -0
- package/carbon/src/client/components/effects/FilmGrainOverlay.tsx +35 -0
- package/carbon/src/client/components/effects/FresnelEdge.tsx +49 -0
- package/carbon/src/client/components/effects/GlowTracker.tsx +46 -0
- package/carbon/src/client/components/effects/SparkBurst.tsx +145 -0
- package/carbon/src/client/components/effects/VGlowEffect.tsx +83 -0
- package/carbon/src/client/components/effects/index.ts +2 -0
- package/carbon/src/client/components/layouts/SidebarLayout.tsx +20 -0
- package/carbon/src/client/components/scroll/ScrollSection.tsx +76 -0
- package/carbon/src/client/components/scroll/ScrollytellingProvider.tsx +81 -0
- package/carbon/src/client/components/scroll/index.ts +2 -0
- package/carbon/src/client/components/ui/accordion.tsx +71 -0
- package/carbon/src/client/components/ui/alert-dialog.tsx +162 -0
- package/carbon/src/client/components/ui/alert.tsx +73 -0
- package/carbon/src/client/components/ui/aspect-ratio.tsx +22 -0
- package/carbon/src/client/components/ui/avatar.tsx +91 -0
- package/carbon/src/client/components/ui/badge.tsx +50 -0
- package/carbon/src/client/components/ui/breadcrumb.tsx +100 -0
- package/carbon/src/client/components/ui/button-group.tsx +78 -0
- package/carbon/src/client/components/ui/button.tsx +120 -0
- package/carbon/src/client/components/ui/calendar.tsx +182 -0
- package/carbon/src/client/components/ui/card.tsx +85 -0
- package/carbon/src/client/components/ui/carousel.tsx +227 -0
- package/carbon/src/client/components/ui/chart.tsx +357 -0
- package/carbon/src/client/components/ui/checkbox.tsx +27 -0
- package/carbon/src/client/components/ui/collapsible.tsx +15 -0
- package/carbon/src/client/components/ui/command.tsx +178 -0
- package/carbon/src/client/components/ui/context-menu.tsx +233 -0
- package/carbon/src/client/components/ui/dialog.tsx +132 -0
- package/carbon/src/client/components/ui/drawer.tsx +118 -0
- package/carbon/src/client/components/ui/dropdown-menu.tsx +242 -0
- package/carbon/src/client/components/ui/empty.tsx +94 -0
- package/carbon/src/client/components/ui/field.tsx +226 -0
- package/carbon/src/client/components/ui/hover-card.tsx +44 -0
- package/carbon/src/client/components/ui/input-group.tsx +146 -0
- package/carbon/src/client/components/ui/input-otp.tsx +83 -0
- package/carbon/src/client/components/ui/input.tsx +20 -0
- package/carbon/src/client/components/ui/item.tsx +188 -0
- package/carbon/src/client/components/ui/kbd.tsx +26 -0
- package/carbon/src/client/components/ui/label.tsx +21 -0
- package/carbon/src/client/components/ui/menubar.tsx +250 -0
- package/carbon/src/client/components/ui/navigation-menu.tsx +155 -0
- package/carbon/src/client/components/ui/pagination.tsx +102 -0
- package/carbon/src/client/components/ui/popover.tsx +75 -0
- package/carbon/src/client/components/ui/progress.tsx +66 -0
- package/carbon/src/client/components/ui/radio-group.tsx +36 -0
- package/carbon/src/client/components/ui/resizable.tsx +46 -0
- package/carbon/src/client/components/ui/scroll-area.tsx +48 -0
- package/carbon/src/client/components/ui/select.tsx +186 -0
- package/carbon/src/client/components/ui/separator.tsx +21 -0
- package/carbon/src/client/components/ui/sheet.tsx +124 -0
- package/carbon/src/client/components/ui/sidebar.tsx +702 -0
- package/carbon/src/client/components/ui/skeleton.tsx +13 -0
- package/carbon/src/client/components/ui/slider.tsx +57 -0
- package/carbon/src/client/components/ui/sonner.tsx +45 -0
- package/carbon/src/client/components/ui/spinner.tsx +15 -0
- package/carbon/src/client/components/ui/switch.tsx +30 -0
- package/carbon/src/client/components/ui/table.tsx +89 -0
- package/carbon/src/client/components/ui/tabs.tsx +73 -0
- package/carbon/src/client/components/ui/textarea.tsx +18 -0
- package/carbon/src/client/components/ui/toggle-group.tsx +87 -0
- package/carbon/src/client/components/ui/toggle.tsx +44 -0
- package/carbon/src/client/components/ui/tooltip.tsx +56 -0
- package/carbon/src/client/hooks/api/index.ts +14 -0
- package/carbon/src/client/hooks/api/useAuthSettings.ts +80 -0
- package/carbon/src/client/hooks/api/useSubscription.ts +87 -0
- package/carbon/src/client/hooks/use-mobile.ts +21 -0
- package/carbon/src/client/hooks/useMousePosition.ts +91 -0
- package/carbon/src/client/hooks/useNotifications.tsx +124 -0
- package/carbon/src/client/hooks/useOrganizationMembers.ts +127 -0
- package/carbon/src/client/hooks/useOrganizations.tsx +230 -0
- package/carbon/src/client/hooks/usePackageManager.ts +69 -0
- package/carbon/src/client/hooks/useReducedMotion.ts +20 -0
- package/carbon/src/client/hooks/useRunningServices.ts +114 -0
- package/carbon/src/client/hooks/useScrollProgress.ts +56 -0
- package/carbon/src/client/index.css +467 -0
- package/carbon/src/client/index.html +56 -0
- package/carbon/src/client/lib/admin-services.ts +151 -0
- package/carbon/src/client/lib/api.ts +32 -0
- package/carbon/src/client/lib/blog.ts +35 -0
- package/carbon/src/client/lib/changelog.ts +33 -0
- package/carbon/src/client/lib/docs-search.ts +101 -0
- package/carbon/src/client/lib/docs.ts +37 -0
- package/carbon/src/client/lib/i18n.ts +32 -0
- package/carbon/src/client/lib/supabase.ts +72 -0
- package/carbon/src/client/lib/tailwind-colors.ts +357 -0
- package/carbon/src/client/lib/theme.ts +117 -0
- package/carbon/src/client/lib/utils.ts +22 -0
- package/carbon/src/client/locales/de.json +529 -0
- package/carbon/src/client/locales/en.json +461 -0
- package/carbon/src/client/locales/es.json +529 -0
- package/carbon/src/client/locales/fr.json +529 -0
- package/carbon/src/client/locales/pt.json +529 -0
- package/carbon/src/client/main.tsx +56 -0
- package/carbon/src/client/mdx.d.ts +13 -0
- package/carbon/src/client/pages/ApiDocs.tsx +76 -0
- package/carbon/src/client/pages/AuthCallback.tsx +34 -0
- package/carbon/src/client/pages/Blog.tsx +167 -0
- package/carbon/src/client/pages/Changelog.tsx +171 -0
- package/carbon/src/client/pages/Charts.tsx +388 -0
- package/carbon/src/client/pages/Checkout.tsx +227 -0
- package/carbon/src/client/pages/Contact.tsx +174 -0
- package/carbon/src/client/pages/Dashboard.tsx +368 -0
- package/carbon/src/client/pages/Docs.tsx +372 -0
- package/carbon/src/client/pages/ForgotPassword.tsx +111 -0
- package/carbon/src/client/pages/Home.tsx +187 -0
- package/carbon/src/client/pages/Legal.tsx +100 -0
- package/carbon/src/client/pages/Login.tsx +408 -0
- package/carbon/src/client/pages/MFAVerify.tsx +156 -0
- package/carbon/src/client/pages/NotFound.tsx +21 -0
- package/carbon/src/client/pages/Onboarding.tsx +246 -0
- package/carbon/src/client/pages/ResetPassword.tsx +200 -0
- package/carbon/src/client/pages/UIComponents.tsx +390 -0
- package/carbon/src/client/pages/admin/ContactSubmissions.tsx +220 -0
- package/carbon/src/client/pages/admin/Dashboard.tsx +24 -0
- package/carbon/src/client/pages/admin/Infrastructure.tsx +257 -0
- package/carbon/src/client/pages/admin/Jobs.tsx +225 -0
- package/carbon/src/client/pages/admin/Logs.tsx +18 -0
- package/carbon/src/client/pages/admin/Newsletter.tsx +300 -0
- package/carbon/src/client/pages/admin/Notifications.tsx +603 -0
- package/carbon/src/client/pages/admin/Organizations.tsx +306 -0
- package/carbon/src/client/pages/admin/Settings.tsx +314 -0
- package/carbon/src/client/pages/admin/Theme.tsx +465 -0
- package/carbon/src/client/pages/admin/Users.tsx +365 -0
- package/carbon/src/client/pages/api-docs.css +156 -0
- package/carbon/src/client/pages/organizations/Details.tsx +200 -0
- package/carbon/src/client/pages/organizations/Members.tsx +402 -0
- package/carbon/src/client/pages/settings/Billing.tsx +473 -0
- package/carbon/src/client/pages/settings/Profile.tsx +160 -0
- package/carbon/src/client/pages/settings/Security.tsx +341 -0
- package/carbon/src/client/public/favicon.svg +19 -0
- package/carbon/src/client/public/robots.txt +8 -0
- package/carbon/src/server/billing/index.ts +104 -0
- package/carbon/src/server/billing/provider.ts +81 -0
- package/carbon/src/server/billing/providers/paddle.ts +314 -0
- package/carbon/src/server/billing/providers/polar.ts +325 -0
- package/carbon/src/server/billing/providers/stripe.ts +233 -0
- package/carbon/src/server/emails/templates.ts +116 -0
- package/carbon/src/server/index.ts +554 -0
- package/carbon/src/server/lib/auth.ts +6 -0
- package/carbon/src/server/lib/email.ts +64 -0
- package/carbon/src/server/lib/env.ts +112 -0
- package/carbon/src/server/lib/errors.ts +21 -0
- package/carbon/src/server/lib/logger.ts +17 -0
- package/carbon/src/server/lib/rate-limiter.ts +288 -0
- package/carbon/src/server/lib/request.ts +34 -0
- package/carbon/src/server/lib/stripe.ts +42 -0
- package/carbon/src/server/lib/supabase.ts +65 -0
- package/carbon/src/server/middleware/requirePlan.ts +80 -0
- package/carbon/src/server/routes/_internal/services-status.ts +958 -0
- package/carbon/src/server/routes/_internal/verify-role.ts +185 -0
- package/carbon/src/server/routes/health.ts +48 -0
- package/carbon/src/server/routes/v1/admin/contact.ts +128 -0
- package/carbon/src/server/routes/v1/admin/jobs.ts +171 -0
- package/carbon/src/server/routes/v1/admin/newsletter.ts +237 -0
- package/carbon/src/server/routes/v1/auth.ts +390 -0
- package/carbon/src/server/routes/v1/billing.ts +718 -0
- package/carbon/src/server/routes/v1/contact.ts +93 -0
- package/carbon/src/server/routes/v1/index.ts +1333 -0
- package/carbon/src/server/routes/v1/newsletter.ts +181 -0
- package/carbon/src/server/routes/v1/performance.ts +157 -0
- package/carbon/src/server/routes/v1/stats.ts +170 -0
- package/carbon/src/server/routes/v1/theme.ts +106 -0
- package/carbon/src/server/routes/webhooks/billing.ts +376 -0
- package/carbon/src/server/routes/webhooks/stripe.ts +276 -0
- package/carbon/src/server/types.ts +11 -0
- package/carbon/src/shared/pricing.ts +155 -0
- package/carbon/src/shared/types.ts +338 -0
- package/carbon/supabase/migrations/00001_init.sql +717 -0
- package/carbon/supabase/migrations/00002_theme_settings.sql +13 -0
- package/carbon/supabase/migrations/00003_pg_cron.sql +121 -0
- package/carbon/supabase/migrations/00004_contact_newsletter.sql +81 -0
- package/carbon/supabase/migrations/00005_localization_languages.sql +22 -0
- package/carbon/supabase/seed.sql +16 -0
- package/carbon/tests/_helpers/app.ts +45 -0
- package/carbon/tests/_helpers/env.ts +37 -0
- package/carbon/tests/_helpers/factories.ts +69 -0
- package/carbon/tests/_helpers/jwt.ts +23 -0
- package/carbon/tests/_helpers/setup-integration.ts +20 -0
- package/carbon/tests/_helpers/setup-rtl.ts +12 -0
- package/carbon/tests/component/ErrorBoundary.test.tsx +53 -0
- package/carbon/tests/component/use-auth-settings.test.tsx +119 -0
- package/carbon/tests/integration/server/routes/contact.test.ts +162 -0
- package/carbon/tests/integration/server/routes/health.test.ts +61 -0
- package/carbon/tests/structural/i18n-parity.test.ts +42 -0
- package/carbon/tests/unit/client/utils.test.ts +49 -0
- package/carbon/tests/unit/shared/pricing.test.ts +93 -0
- package/carbon/tsconfig.json +27 -0
- package/carbon/tsconfig.server.json +27 -0
- package/carbon/tsconfig.test.json +9 -0
- package/carbon/vite.config.ts +110 -0
- package/carbon/vitest.config.ts +74 -0
- package/carbon/volumes/db/jwt.sql +57 -0
- package/carbon/volumes/db/metabase-init.sh +29 -0
- package/carbon/volumes/db/n8n-init.sh +25 -0
- package/carbon/volumes/db/realtime.sql +33 -0
- package/carbon/volumes/db/roles.sql +93 -0
- package/carbon/volumes/db/set-passwords.sh +12 -0
- package/carbon/volumes/db/super-admin.dev.sql +113 -0
- package/carbon/volumes/db/super-admin.generated.sql +113 -0
- package/carbon/volumes/db/super-admin.sql +114 -0
- package/carbon/volumes/grafana/dashboards/logs.json +179 -0
- package/carbon/volumes/grafana/dashboards/overview.json +523 -0
- package/carbon/volumes/grafana/dashboards/postgresql.json +337 -0
- package/carbon/volumes/grafana/dashboards.dev/logs.json +179 -0
- package/carbon/volumes/grafana/dashboards.dev/overview.json +156 -0
- package/carbon/volumes/grafana/dashboards.dev/postgresql.json +337 -0
- package/carbon/volumes/grafana/provisioning/dashboards/dashboards.dev.yml +16 -0
- package/carbon/volumes/grafana/provisioning/dashboards/dashboards.yml +16 -0
- package/carbon/volumes/grafana/provisioning/datasources/datasources.yml +43 -0
- package/carbon/volumes/kong/docker-entrypoint.sh +9 -0
- package/carbon/volumes/kong/kong.yml +208 -0
- package/carbon/volumes/loki/loki-config.yml +58 -0
- package/carbon/volumes/n8n/hooks.js +131 -0
- package/carbon/volumes/n8n/scripts/setup.sh +66 -0
- package/carbon/volumes/prometheus/prometheus.yml +43 -0
- package/carbon/volumes/promtail/promtail-config.yml +64 -0
- package/carbon/volumes/traefik/middlewares.dev.yml +83 -0
- package/carbon/volumes/traefik/middlewares.yml +95 -0
- package/carbon/volumes/traefik/vite-dev.yml +20 -0
- package/package.json +95 -0
- package/src/access.js +354 -0
- package/src/activate.js +187 -0
- package/src/add.js +718 -0
- package/src/backup.js +786 -0
- package/src/cli.js +350 -0
- package/src/configure.js +967 -0
- package/src/console.js +155 -0
- package/src/create.js +1499 -0
- package/src/deploy.js +311 -0
- package/src/destroy.js +2033 -0
- package/src/diagnose.js +735 -0
- package/src/down.js +80 -0
- package/src/failover.js +1032 -0
- package/src/lib/backup-s3.js +179 -0
- package/src/lib/build.js +33 -0
- package/src/lib/checksum.js +28 -0
- package/src/lib/ci-setup.js +666 -0
- package/src/lib/cli/help.js +129 -0
- package/src/lib/cli/parse-flags.js +160 -0
- package/src/lib/cli/select-action.js +65 -0
- package/src/lib/cli/select-environment.js +108 -0
- package/src/lib/cli/tty-guard.js +75 -0
- package/src/lib/cloudflare.js +447 -0
- package/src/lib/colors.js +52 -0
- package/src/lib/command.js +361 -0
- package/src/lib/config.js +359 -0
- package/src/lib/cost.js +103 -0
- package/src/lib/deploy/bundle.js +231 -0
- package/src/lib/deploy/compose/acme-verify.js +121 -0
- package/src/lib/deploy/compose/build-args.js +78 -0
- package/src/lib/deploy/compose/ha.js +1874 -0
- package/src/lib/deploy/compose/index.js +1294 -0
- package/src/lib/deploy/compose/reconcile.js +74 -0
- package/src/lib/deploy/github.js +382 -0
- package/src/lib/deploy/image.js +191 -0
- package/src/lib/deploy/index.js +119 -0
- package/src/lib/deploy/k8s/LICENSE +99 -0
- package/src/lib/deploy/k8s/gitops-deploy.js +298 -0
- package/src/lib/deploy/k8s/ha/index.js +1000 -0
- package/src/lib/deploy/k8s/index.js +62 -0
- package/src/lib/deploy/k8s/k3s.js +2515 -0
- package/src/lib/deploy/orchestrator.js +1401 -0
- package/src/lib/deploy/prompts.js +545 -0
- package/src/lib/deploy/remote-build.js +130 -0
- package/src/lib/deploy/state.js +120 -0
- package/src/lib/deploy/utils.js +328 -0
- package/src/lib/deploy-logger.js +93 -0
- package/src/lib/dns-propagation.js +48 -0
- package/src/lib/environment.js +58 -0
- package/src/lib/fetch-retry.js +103 -0
- package/src/lib/github-environments.js +335 -0
- package/src/lib/hetzner-dns.js +377 -0
- package/src/lib/hetzner-guided-setup.js +275 -0
- package/src/lib/host-keys.js +37 -0
- package/src/lib/iac/cloud-init.js +52 -0
- package/src/lib/iac/index.js +325 -0
- package/src/lib/iac/programs/hetzner-compose.js +130 -0
- package/src/lib/iac/programs/hetzner-k8s.js +320 -0
- package/src/lib/kubectl.js +81 -0
- package/src/lib/licensing/index.js +259 -0
- package/src/lib/licensing/tiers.js +181 -0
- package/src/lib/licensing/validator.js +171 -0
- package/src/lib/merge-package-json.js +90 -0
- package/src/lib/operator-ip.js +381 -0
- package/src/lib/package-manager.js +111 -0
- package/src/lib/perf.js +71 -0
- package/src/lib/project-guard.js +39 -0
- package/src/lib/project.js +334 -0
- package/src/lib/providers/base.js +276 -0
- package/src/lib/providers/hetzner-s3.js +656 -0
- package/src/lib/providers/hetzner.js +755 -0
- package/src/lib/providers/index.js +164 -0
- package/src/lib/s3.js +510 -0
- package/src/lib/secret-scan.js +583 -0
- package/src/lib/secrets.js +63 -0
- package/src/lib/server-types.js +195 -0
- package/src/lib/shell.js +91 -0
- package/src/lib/ssh.js +241 -0
- package/src/lib/tracker.js +242 -0
- package/src/lib/upgrade-policy.js +170 -0
- package/src/lib/validators.js +105 -0
- package/src/lib/version.js +5 -0
- package/src/remove.js +292 -0
- package/src/reset.js +97 -0
- package/src/restore.js +871 -0
- package/src/scale.js +1734 -0
- package/src/shell.js +222 -0
- package/src/status.js +981 -0
- package/src/up.js +264 -0
- package/src/upgrade.js +721 -0
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
import { motion, useInView } from 'framer-motion';
|
|
2
|
+
import {
|
|
3
|
+
Activity,
|
|
4
|
+
Check,
|
|
5
|
+
Cloud,
|
|
6
|
+
Copy,
|
|
7
|
+
Database,
|
|
8
|
+
FileCode,
|
|
9
|
+
Folder,
|
|
10
|
+
FolderOpen,
|
|
11
|
+
Globe,
|
|
12
|
+
Layers,
|
|
13
|
+
Server,
|
|
14
|
+
Terminal,
|
|
15
|
+
Zap,
|
|
16
|
+
} from 'lucide-react';
|
|
17
|
+
import { useRef, useState } from 'react';
|
|
18
|
+
import { useTranslation } from 'react-i18next';
|
|
19
|
+
import vibecarbonIcon from '../assets/vibecarbon-icon.svg';
|
|
20
|
+
|
|
21
|
+
// Clean command box with prominent copy button
|
|
22
|
+
export function CommandBox({
|
|
23
|
+
command,
|
|
24
|
+
description,
|
|
25
|
+
delay = 0,
|
|
26
|
+
}: {
|
|
27
|
+
command: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
delay?: number;
|
|
30
|
+
}) {
|
|
31
|
+
const [copied, setCopied] = useState(false);
|
|
32
|
+
|
|
33
|
+
const handleCopy = async () => {
|
|
34
|
+
await navigator.clipboard.writeText(command);
|
|
35
|
+
setCopied(true);
|
|
36
|
+
setTimeout(() => setCopied(false), 2000);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<motion.div
|
|
41
|
+
initial={{ opacity: 0, y: 20 }}
|
|
42
|
+
whileInView={{ opacity: 1, y: 0 }}
|
|
43
|
+
viewport={{ once: true }}
|
|
44
|
+
transition={{ duration: 0.5, delay }}
|
|
45
|
+
className="group"
|
|
46
|
+
>
|
|
47
|
+
{description && <p className="text-sm text-muted-foreground mb-2 ml-1">{description}</p>}
|
|
48
|
+
<div className="relative flex items-center bg-muted/80 dark:bg-black/40 border border-border dark:border-white/10 rounded-xl overflow-hidden hover:border-primary/30 transition-colors">
|
|
49
|
+
<div className="flex-1 flex items-center gap-3 px-5 py-4 font-mono text-sm md:text-base">
|
|
50
|
+
<span className="text-primary font-bold">$</span>
|
|
51
|
+
<span className="text-foreground">{command}</span>
|
|
52
|
+
</div>
|
|
53
|
+
<button
|
|
54
|
+
type="button"
|
|
55
|
+
onClick={handleCopy}
|
|
56
|
+
className="flex items-center gap-2 px-5 self-stretch bg-black/[0.03] hover:bg-black/[0.06] dark:bg-white/5 dark:hover:bg-white/10 border-l border-border dark:border-white/10 transition-all cursor-pointer"
|
|
57
|
+
aria-label="Copy command"
|
|
58
|
+
>
|
|
59
|
+
{copied ? (
|
|
60
|
+
<>
|
|
61
|
+
<Check className="w-4 h-4 text-primary" />
|
|
62
|
+
<span className="text-xs text-primary font-medium hidden sm:inline">Copied!</span>
|
|
63
|
+
</>
|
|
64
|
+
) : (
|
|
65
|
+
<>
|
|
66
|
+
<Copy className="w-4 h-4 text-muted-foreground group-hover:text-foreground transition-colors" />
|
|
67
|
+
<span className="text-xs text-muted-foreground group-hover:text-foreground font-medium hidden sm:inline transition-colors">
|
|
68
|
+
Copy
|
|
69
|
+
</span>
|
|
70
|
+
</>
|
|
71
|
+
)}
|
|
72
|
+
</button>
|
|
73
|
+
</div>
|
|
74
|
+
</motion.div>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Step number indicator
|
|
79
|
+
function StepNumber({ number, color }: { number: number; color: 'teal' | 'magenta' }) {
|
|
80
|
+
return (
|
|
81
|
+
<div
|
|
82
|
+
className={`flex items-center justify-center w-12 h-12 rounded-2xl text-2xl font-black ${
|
|
83
|
+
color === 'teal'
|
|
84
|
+
? 'bg-primary/20 text-primary border border-primary/30'
|
|
85
|
+
: 'bg-secondary-accent/20 text-secondary-accent border border-secondary-accent/30'
|
|
86
|
+
}`}
|
|
87
|
+
style={{
|
|
88
|
+
boxShadow:
|
|
89
|
+
color === 'teal'
|
|
90
|
+
? '0 0 20px oklch(0.82 0.14 192 / 0.25)'
|
|
91
|
+
: '0 0 20px oklch(0.65 0.26 350 / 0.25)',
|
|
92
|
+
}}
|
|
93
|
+
>
|
|
94
|
+
{number}
|
|
95
|
+
</div>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Create Visual: Project scaffolding animation
|
|
100
|
+
function CreateVisual() {
|
|
101
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
102
|
+
const isInView = useInView(ref, { once: true, margin: '-50px' });
|
|
103
|
+
|
|
104
|
+
const structure = [
|
|
105
|
+
{ name: 'my-app/', icon: FolderOpen, level: 0, delay: 0.2 },
|
|
106
|
+
{ name: 'src/', icon: FolderOpen, level: 1, delay: 0.3 },
|
|
107
|
+
{ name: 'client/', icon: Folder, level: 2, delay: 0.4 },
|
|
108
|
+
{ name: 'server/', icon: Folder, level: 2, delay: 0.5 },
|
|
109
|
+
{ name: 'shared/', icon: Folder, level: 2, delay: 0.6 },
|
|
110
|
+
{ name: 'supabase/', icon: FolderOpen, level: 1, delay: 0.7 },
|
|
111
|
+
{ name: 'migrations/', icon: Folder, level: 2, delay: 0.8 },
|
|
112
|
+
{ name: 'k8s/', icon: FolderOpen, level: 1, delay: 0.9 },
|
|
113
|
+
{ name: 'docker-compose.yml', icon: Layers, level: 1, delay: 1.0 },
|
|
114
|
+
{ name: 'package.json', icon: FileCode, level: 1, delay: 1.1 },
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<div ref={ref} className="relative">
|
|
119
|
+
{/* Behind-card glow */}
|
|
120
|
+
<div className="absolute -inset-[40px] -z-10 pointer-events-none">
|
|
121
|
+
<div
|
|
122
|
+
className="absolute inset-0"
|
|
123
|
+
style={{
|
|
124
|
+
background:
|
|
125
|
+
'radial-gradient(ellipse 70% 60% at 50% 60%, rgb(0, 180, 200) 0%, rgb(0, 100, 140) 25%, rgba(0, 130, 160, 0) 65%)',
|
|
126
|
+
filter: 'blur(50px)',
|
|
127
|
+
opacity: 0.4,
|
|
128
|
+
}}
|
|
129
|
+
/>
|
|
130
|
+
<div
|
|
131
|
+
className="absolute inset-[20%]"
|
|
132
|
+
style={{
|
|
133
|
+
background:
|
|
134
|
+
'radial-gradient(ellipse 80% 70% at 50% 55%, rgb(100, 255, 240) 0%, rgba(0, 200, 210, 0) 60%)',
|
|
135
|
+
filter: 'blur(30px)',
|
|
136
|
+
opacity: 0.2,
|
|
137
|
+
}}
|
|
138
|
+
/>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<div className="relative bg-muted dark:bg-black/60 backdrop-blur-xl border border-border dark:border-white/10 rounded-2xl overflow-hidden">
|
|
142
|
+
{/* Glowing top edge */}
|
|
143
|
+
<div className="absolute inset-x-0 -top-px h-px bg-gradient-to-r from-transparent via-primary/80 to-transparent" />
|
|
144
|
+
{/* Spotlight from above */}
|
|
145
|
+
<div
|
|
146
|
+
className="absolute inset-x-0 top-0 h-[250px] pointer-events-none"
|
|
147
|
+
style={{
|
|
148
|
+
background:
|
|
149
|
+
'radial-gradient(ellipse 80% 60% at 50% 0%, oklch(0.82 0.14 192 / 0.25) 0%, transparent 100%)',
|
|
150
|
+
}}
|
|
151
|
+
/>
|
|
152
|
+
{/* Particle dots */}
|
|
153
|
+
<div className="spotlight-particles absolute inset-0 pointer-events-none opacity-50" />
|
|
154
|
+
|
|
155
|
+
{/* Terminal header */}
|
|
156
|
+
<div className="relative flex items-center gap-2 px-4 py-3 border-b border-border dark:border-white/10 bg-black/[0.03] dark:bg-white/5">
|
|
157
|
+
<div className="flex gap-1.5">
|
|
158
|
+
<div className="w-3 h-3 rounded-full bg-red-500/70" />
|
|
159
|
+
<div className="w-3 h-3 rounded-full bg-yellow-500/70" />
|
|
160
|
+
<div className="w-3 h-3 rounded-full bg-green-500/70" />
|
|
161
|
+
</div>
|
|
162
|
+
<span className="text-xs text-muted-foreground ml-2 font-mono">Terminal</span>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
<div className="relative p-5">
|
|
166
|
+
{/* Command */}
|
|
167
|
+
<motion.div
|
|
168
|
+
initial={{ opacity: 0 }}
|
|
169
|
+
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
|
170
|
+
transition={{ duration: 0.3, delay: 0.1 }}
|
|
171
|
+
className="font-mono text-sm mb-4 flex items-center gap-2"
|
|
172
|
+
>
|
|
173
|
+
<span className="text-primary">$</span>
|
|
174
|
+
<span className="text-foreground">npx vibecarbon create</span>
|
|
175
|
+
</motion.div>
|
|
176
|
+
|
|
177
|
+
{/* File structure */}
|
|
178
|
+
<div className="space-y-0.5 font-mono text-sm">
|
|
179
|
+
{structure.map((item) => (
|
|
180
|
+
<motion.div
|
|
181
|
+
key={item.name}
|
|
182
|
+
initial={{ opacity: 0, x: -20 }}
|
|
183
|
+
animate={isInView ? { opacity: 1, x: 0 } : { opacity: 0, x: -20 }}
|
|
184
|
+
transition={{ duration: 0.3, delay: item.delay }}
|
|
185
|
+
className="flex items-center gap-2"
|
|
186
|
+
style={{ paddingLeft: `${item.level * 20}px` }}
|
|
187
|
+
>
|
|
188
|
+
<item.icon
|
|
189
|
+
className={`w-4 h-4 flex-shrink-0 ${
|
|
190
|
+
item.name.endsWith('/') ? 'text-primary' : 'text-secondary-accent'
|
|
191
|
+
}`}
|
|
192
|
+
/>
|
|
193
|
+
<span className="text-foreground/80">{item.name}</span>
|
|
194
|
+
</motion.div>
|
|
195
|
+
))}
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
{/* Success */}
|
|
199
|
+
<motion.div
|
|
200
|
+
initial={{ opacity: 0, y: 10 }}
|
|
201
|
+
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 10 }}
|
|
202
|
+
transition={{ duration: 0.4, delay: 1.3 }}
|
|
203
|
+
className="mt-4 pt-4 border-t border-border dark:border-white/10 flex items-center gap-2"
|
|
204
|
+
>
|
|
205
|
+
<div className="w-2 h-2 rounded-full bg-green-500 animate-pulse" />
|
|
206
|
+
<span className="text-green-600 dark:text-green-400 text-sm font-medium">
|
|
207
|
+
Project created successfully
|
|
208
|
+
</span>
|
|
209
|
+
</motion.div>
|
|
210
|
+
</div>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Build Visual: Dev environment running
|
|
217
|
+
function BuildVisual() {
|
|
218
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
219
|
+
const isInView = useInView(ref, { once: true, margin: '-50px' });
|
|
220
|
+
|
|
221
|
+
const services = [
|
|
222
|
+
{ name: 'Vite', port: '5173', status: 'ready', icon: Zap, color: 'text-secondary-accent' },
|
|
223
|
+
{ name: 'API', port: '3000', status: 'ready', icon: Server, color: 'text-primary' },
|
|
224
|
+
{ name: 'Supabase', port: '8000', status: 'ready', icon: Database, color: 'text-green-400' },
|
|
225
|
+
{ name: 'Studio', port: '3001', status: 'ready', icon: Globe, color: 'text-blue-400' },
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
return (
|
|
229
|
+
<div ref={ref} className="relative">
|
|
230
|
+
{/* Behind-card glow */}
|
|
231
|
+
<div className="absolute -inset-[40px] -z-10 pointer-events-none">
|
|
232
|
+
<div
|
|
233
|
+
className="absolute inset-0"
|
|
234
|
+
style={{
|
|
235
|
+
background:
|
|
236
|
+
'radial-gradient(ellipse 70% 60% at 50% 60%, rgb(200, 60, 180) 0%, rgb(140, 30, 120) 25%, rgba(160, 40, 140, 0) 65%)',
|
|
237
|
+
filter: 'blur(50px)',
|
|
238
|
+
opacity: 0.35,
|
|
239
|
+
}}
|
|
240
|
+
/>
|
|
241
|
+
<div
|
|
242
|
+
className="absolute inset-[20%]"
|
|
243
|
+
style={{
|
|
244
|
+
background:
|
|
245
|
+
'radial-gradient(ellipse 80% 70% at 50% 55%, rgb(255, 140, 220) 0%, rgba(200, 60, 180, 0) 60%)',
|
|
246
|
+
filter: 'blur(30px)',
|
|
247
|
+
opacity: 0.15,
|
|
248
|
+
}}
|
|
249
|
+
/>
|
|
250
|
+
</div>
|
|
251
|
+
|
|
252
|
+
<div className="relative bg-muted dark:bg-black/60 backdrop-blur-xl border border-border dark:border-white/10 rounded-2xl overflow-hidden">
|
|
253
|
+
{/* Glowing top edge */}
|
|
254
|
+
<div className="absolute inset-x-0 -top-px h-px bg-gradient-to-r from-transparent via-secondary-accent/80 to-transparent" />
|
|
255
|
+
{/* Spotlight from above */}
|
|
256
|
+
<div
|
|
257
|
+
className="absolute inset-x-0 top-0 h-[250px] pointer-events-none"
|
|
258
|
+
style={{
|
|
259
|
+
background:
|
|
260
|
+
'radial-gradient(ellipse 80% 60% at 50% 0%, oklch(0.65 0.26 350 / 0.25) 0%, transparent 100%)',
|
|
261
|
+
}}
|
|
262
|
+
/>
|
|
263
|
+
{/* Particle dots */}
|
|
264
|
+
<div className="spotlight-particles absolute inset-0 pointer-events-none opacity-50" />
|
|
265
|
+
|
|
266
|
+
{/* Header */}
|
|
267
|
+
<div className="relative flex items-center justify-between px-4 py-3 border-b border-border dark:border-white/10 bg-black/[0.03] dark:bg-white/5">
|
|
268
|
+
<div className="flex items-center gap-2">
|
|
269
|
+
<Terminal className="w-4 h-4 text-secondary-accent" />
|
|
270
|
+
<span className="text-xs text-muted-foreground font-mono">Development Server</span>
|
|
271
|
+
</div>
|
|
272
|
+
<div className="flex items-center gap-2">
|
|
273
|
+
<Activity className="w-3 h-3 text-green-600 dark:text-green-400 animate-pulse" />
|
|
274
|
+
<span className="text-xs text-green-600 dark:text-green-400">Running</span>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
|
|
278
|
+
<div className="relative p-5 space-y-3">
|
|
279
|
+
{services.map((service, index) => (
|
|
280
|
+
<motion.div
|
|
281
|
+
key={service.name}
|
|
282
|
+
initial={{ opacity: 0, x: -20 }}
|
|
283
|
+
animate={isInView ? { opacity: 1, x: 0 } : { opacity: 0, x: -20 }}
|
|
284
|
+
transition={{ duration: 0.4, delay: 0.2 + index * 0.15 }}
|
|
285
|
+
className="flex items-center justify-between p-3 bg-black/[0.03] dark:bg-white/5 rounded-xl border border-border/50 dark:border-white/5"
|
|
286
|
+
>
|
|
287
|
+
<div className="flex items-center gap-3">
|
|
288
|
+
<service.icon className={`w-5 h-5 ${service.color}`} />
|
|
289
|
+
<span className="text-foreground font-medium">{service.name}</span>
|
|
290
|
+
</div>
|
|
291
|
+
<div className="flex items-center gap-3">
|
|
292
|
+
<span className="text-muted-foreground font-mono text-sm">:{service.port}</span>
|
|
293
|
+
<div className="flex items-center gap-1.5">
|
|
294
|
+
<div className="w-2 h-2 rounded-full bg-green-500" />
|
|
295
|
+
<span className="text-xs text-green-600 dark:text-green-400">
|
|
296
|
+
{service.status}
|
|
297
|
+
</span>
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
</motion.div>
|
|
301
|
+
))}
|
|
302
|
+
|
|
303
|
+
{/* Hot reload indicator */}
|
|
304
|
+
<motion.div
|
|
305
|
+
initial={{ opacity: 0 }}
|
|
306
|
+
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
|
307
|
+
transition={{ duration: 0.4, delay: 0.9 }}
|
|
308
|
+
className="pt-3 border-t border-border dark:border-white/10 flex items-center justify-center gap-2 text-sm text-muted-foreground"
|
|
309
|
+
>
|
|
310
|
+
<Zap className="w-4 h-4 text-secondary-accent" />
|
|
311
|
+
<span>
|
|
312
|
+
Hot reload active at <span className="text-primary font-mono">localhost:5173</span>
|
|
313
|
+
</span>
|
|
314
|
+
</motion.div>
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Deploy Visual: Production infrastructure
|
|
322
|
+
function DeployVisual() {
|
|
323
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
324
|
+
const isInView = useInView(ref, { once: true, margin: '-50px' });
|
|
325
|
+
|
|
326
|
+
return (
|
|
327
|
+
<div ref={ref} className="relative">
|
|
328
|
+
{/* Behind-card glow */}
|
|
329
|
+
<div className="absolute -inset-[40px] -z-10 pointer-events-none">
|
|
330
|
+
<div
|
|
331
|
+
className="absolute inset-0"
|
|
332
|
+
style={{
|
|
333
|
+
background:
|
|
334
|
+
'radial-gradient(ellipse 70% 60% at 50% 60%, rgb(0, 180, 200) 0%, rgb(0, 100, 140) 25%, rgba(0, 130, 160, 0) 65%)',
|
|
335
|
+
filter: 'blur(50px)',
|
|
336
|
+
opacity: 0.4,
|
|
337
|
+
}}
|
|
338
|
+
/>
|
|
339
|
+
<div
|
|
340
|
+
className="absolute inset-[20%]"
|
|
341
|
+
style={{
|
|
342
|
+
background:
|
|
343
|
+
'radial-gradient(ellipse 80% 70% at 50% 55%, rgb(100, 255, 240) 0%, rgba(0, 200, 210, 0) 60%)',
|
|
344
|
+
filter: 'blur(30px)',
|
|
345
|
+
opacity: 0.2,
|
|
346
|
+
}}
|
|
347
|
+
/>
|
|
348
|
+
</div>
|
|
349
|
+
|
|
350
|
+
<div className="relative bg-muted dark:bg-black/60 backdrop-blur-xl border border-border dark:border-white/10 rounded-2xl overflow-hidden">
|
|
351
|
+
{/* Glowing top edge */}
|
|
352
|
+
<div className="absolute inset-x-0 -top-px h-px bg-gradient-to-r from-transparent via-primary/80 to-transparent" />
|
|
353
|
+
{/* Spotlight from above */}
|
|
354
|
+
<div
|
|
355
|
+
className="absolute inset-x-0 top-0 h-[250px] pointer-events-none"
|
|
356
|
+
style={{
|
|
357
|
+
background:
|
|
358
|
+
'radial-gradient(ellipse 80% 60% at 50% 0%, oklch(0.82 0.14 192 / 0.25) 0%, transparent 100%)',
|
|
359
|
+
}}
|
|
360
|
+
/>
|
|
361
|
+
{/* Particle dots */}
|
|
362
|
+
<div className="spotlight-particles absolute inset-0 pointer-events-none opacity-50" />
|
|
363
|
+
|
|
364
|
+
{/* Header */}
|
|
365
|
+
<div className="relative flex items-center justify-between px-4 py-3 border-b border-border dark:border-white/10 bg-black/[0.03] dark:bg-white/5">
|
|
366
|
+
<div className="flex items-center gap-2">
|
|
367
|
+
<Cloud className="w-4 h-4 text-primary" />
|
|
368
|
+
<span className="text-xs text-muted-foreground font-mono">
|
|
369
|
+
Production Infrastructure
|
|
370
|
+
</span>
|
|
371
|
+
</div>
|
|
372
|
+
<span className="text-xs text-primary font-medium">Kubernetes</span>
|
|
373
|
+
</div>
|
|
374
|
+
|
|
375
|
+
<div className="relative p-5">
|
|
376
|
+
{/* Infrastructure diagram */}
|
|
377
|
+
<div className="flex flex-col items-center gap-3">
|
|
378
|
+
{/* Load Balancer */}
|
|
379
|
+
<motion.div
|
|
380
|
+
initial={{ opacity: 0, y: -20 }}
|
|
381
|
+
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: -20 }}
|
|
382
|
+
transition={{ duration: 0.4, delay: 0.2 }}
|
|
383
|
+
className="w-full max-w-xs p-3 bg-gradient-to-r from-primary/20 to-primary/10 border border-primary/30 rounded-xl flex items-center justify-between"
|
|
384
|
+
>
|
|
385
|
+
<div className="flex items-center gap-2">
|
|
386
|
+
<Globe className="w-5 h-5 text-primary" />
|
|
387
|
+
<span className="font-medium text-sm">Load Balancer</span>
|
|
388
|
+
</div>
|
|
389
|
+
<div className="flex items-center gap-1.5">
|
|
390
|
+
<div className="w-2 h-2 rounded-full bg-green-500" />
|
|
391
|
+
<span className="text-xs text-foreground/70">Healthy</span>
|
|
392
|
+
</div>
|
|
393
|
+
</motion.div>
|
|
394
|
+
|
|
395
|
+
{/* Connection line */}
|
|
396
|
+
<motion.div
|
|
397
|
+
initial={{ scaleY: 0 }}
|
|
398
|
+
animate={isInView ? { scaleY: 1 } : { scaleY: 0 }}
|
|
399
|
+
transition={{ duration: 0.2, delay: 0.4 }}
|
|
400
|
+
className="w-px h-4 bg-gradient-to-b from-primary/50 to-secondary-accent/50 origin-top"
|
|
401
|
+
/>
|
|
402
|
+
|
|
403
|
+
{/* App Pods */}
|
|
404
|
+
<motion.div
|
|
405
|
+
initial={{ opacity: 0, scale: 0.9 }}
|
|
406
|
+
animate={isInView ? { opacity: 1, scale: 1 } : { opacity: 0, scale: 0.9 }}
|
|
407
|
+
transition={{ duration: 0.4, delay: 0.5 }}
|
|
408
|
+
className="flex flex-wrap justify-center gap-2"
|
|
409
|
+
>
|
|
410
|
+
{[1, 2, 3].map((i) => (
|
|
411
|
+
<div
|
|
412
|
+
key={i}
|
|
413
|
+
className="p-2.5 bg-black/[0.03] dark:bg-white/5 border border-border/50 dark:border-white/10 rounded-lg flex items-center gap-2"
|
|
414
|
+
>
|
|
415
|
+
<Server className="w-4 h-4 text-secondary-accent" />
|
|
416
|
+
<span className="text-xs font-mono">pod-{i}</span>
|
|
417
|
+
<div className="w-1.5 h-1.5 rounded-full bg-green-500" />
|
|
418
|
+
</div>
|
|
419
|
+
))}
|
|
420
|
+
</motion.div>
|
|
421
|
+
|
|
422
|
+
{/* Connection line */}
|
|
423
|
+
<motion.div
|
|
424
|
+
initial={{ scaleY: 0 }}
|
|
425
|
+
animate={isInView ? { scaleY: 1 } : { scaleY: 0 }}
|
|
426
|
+
transition={{ duration: 0.2, delay: 0.7 }}
|
|
427
|
+
className="w-px h-4 bg-gradient-to-b from-secondary-accent/50 to-primary/50 origin-top"
|
|
428
|
+
/>
|
|
429
|
+
|
|
430
|
+
{/* Database */}
|
|
431
|
+
<motion.div
|
|
432
|
+
initial={{ opacity: 0, y: 20 }}
|
|
433
|
+
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
|
434
|
+
transition={{ duration: 0.4, delay: 0.8 }}
|
|
435
|
+
className="w-full max-w-xs p-3 bg-gradient-to-r from-secondary-accent/20 to-secondary-accent/10 border border-secondary-accent/30 rounded-xl flex items-center justify-between"
|
|
436
|
+
>
|
|
437
|
+
<div className="flex items-center gap-2">
|
|
438
|
+
<Database className="w-5 h-5 text-secondary-accent" />
|
|
439
|
+
<span className="font-medium text-sm">PostgreSQL HA</span>
|
|
440
|
+
</div>
|
|
441
|
+
<div className="flex items-center gap-1.5">
|
|
442
|
+
<div className="w-2 h-2 rounded-full bg-green-500" />
|
|
443
|
+
<span className="text-xs text-foreground/70">Primary</span>
|
|
444
|
+
</div>
|
|
445
|
+
</motion.div>
|
|
446
|
+
</div>
|
|
447
|
+
|
|
448
|
+
{/* Status bar */}
|
|
449
|
+
<motion.div
|
|
450
|
+
initial={{ opacity: 0 }}
|
|
451
|
+
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
|
452
|
+
transition={{ duration: 0.4, delay: 1.0 }}
|
|
453
|
+
className="mt-4 pt-4 border-t border-border dark:border-white/10 flex items-center justify-between text-xs"
|
|
454
|
+
>
|
|
455
|
+
<div className="flex items-center gap-4">
|
|
456
|
+
<span className="text-muted-foreground">
|
|
457
|
+
Autoscaling: <span className="text-primary">Active</span>
|
|
458
|
+
</span>
|
|
459
|
+
<span className="text-muted-foreground">
|
|
460
|
+
High availability: <span className="text-primary">Ready</span>
|
|
461
|
+
</span>
|
|
462
|
+
</div>
|
|
463
|
+
<span className="text-foreground/70 flex items-center gap-1.5">
|
|
464
|
+
<span className="w-1.5 h-1.5 rounded-full bg-green-500 animate-pulse" />
|
|
465
|
+
All systems operational
|
|
466
|
+
</span>
|
|
467
|
+
</motion.div>
|
|
468
|
+
</div>
|
|
469
|
+
</div>
|
|
470
|
+
</div>
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Workflow step component
|
|
475
|
+
function WorkflowStep({
|
|
476
|
+
step,
|
|
477
|
+
title,
|
|
478
|
+
subtitle,
|
|
479
|
+
command,
|
|
480
|
+
visual,
|
|
481
|
+
color,
|
|
482
|
+
reverse = false,
|
|
483
|
+
}: {
|
|
484
|
+
step: number;
|
|
485
|
+
title: string;
|
|
486
|
+
subtitle: string;
|
|
487
|
+
command: string;
|
|
488
|
+
visual: React.ReactNode;
|
|
489
|
+
color: 'teal' | 'magenta';
|
|
490
|
+
reverse?: boolean;
|
|
491
|
+
}) {
|
|
492
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
493
|
+
const isInView = useInView(ref, { once: true, margin: '-100px' });
|
|
494
|
+
|
|
495
|
+
return (
|
|
496
|
+
<div
|
|
497
|
+
ref={ref}
|
|
498
|
+
className={`flex flex-col ${reverse ? 'lg:flex-row-reverse' : 'lg:flex-row'} gap-12 lg:gap-20 items-center lg:items-start`}
|
|
499
|
+
>
|
|
500
|
+
{/* Text content */}
|
|
501
|
+
<div className="w-full lg:w-1/2 space-y-6">
|
|
502
|
+
<motion.div
|
|
503
|
+
initial={{ opacity: 0, y: 20 }}
|
|
504
|
+
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
|
505
|
+
transition={{ duration: 0.5 }}
|
|
506
|
+
className="flex items-center gap-4"
|
|
507
|
+
>
|
|
508
|
+
<StepNumber number={step} color={color} />
|
|
509
|
+
<div>
|
|
510
|
+
<h2
|
|
511
|
+
className={`text-4xl md:text-6xl font-black tracking-tight ${
|
|
512
|
+
color === 'teal' ? 'text-primary' : 'text-secondary-accent'
|
|
513
|
+
}`}
|
|
514
|
+
>
|
|
515
|
+
{title}
|
|
516
|
+
</h2>
|
|
517
|
+
</div>
|
|
518
|
+
</motion.div>
|
|
519
|
+
|
|
520
|
+
<motion.p
|
|
521
|
+
initial={{ opacity: 0 }}
|
|
522
|
+
animate={isInView ? { opacity: 1 } : { opacity: 0 }}
|
|
523
|
+
transition={{ duration: 0.5, delay: 0.1 }}
|
|
524
|
+
className="text-lg text-muted-foreground max-w-md"
|
|
525
|
+
>
|
|
526
|
+
{subtitle}
|
|
527
|
+
</motion.p>
|
|
528
|
+
|
|
529
|
+
<CommandBox command={command} delay={0.2} />
|
|
530
|
+
</div>
|
|
531
|
+
|
|
532
|
+
{/* Visual */}
|
|
533
|
+
<div className="w-full lg:w-1/2">{visual}</div>
|
|
534
|
+
</div>
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
export function WorkflowSection() {
|
|
539
|
+
const { t } = useTranslation();
|
|
540
|
+
return (
|
|
541
|
+
<section className="relative py-24 md:py-36 overflow-hidden">
|
|
542
|
+
<div className="mx-auto max-w-7xl px-6">
|
|
543
|
+
{/* Section header */}
|
|
544
|
+
<motion.div
|
|
545
|
+
initial={{ opacity: 0, y: 20 }}
|
|
546
|
+
whileInView={{ opacity: 1, y: 0 }}
|
|
547
|
+
viewport={{ once: true }}
|
|
548
|
+
transition={{ duration: 0.5 }}
|
|
549
|
+
className="text-center mb-10"
|
|
550
|
+
>
|
|
551
|
+
<motion.div
|
|
552
|
+
className="flex justify-center mb-6"
|
|
553
|
+
animate={{ y: [0, -6, 0] }}
|
|
554
|
+
transition={{ duration: 3, repeat: Infinity, ease: 'easeInOut' }}
|
|
555
|
+
>
|
|
556
|
+
<img
|
|
557
|
+
src={vibecarbonIcon}
|
|
558
|
+
alt=""
|
|
559
|
+
width={56}
|
|
560
|
+
height={56}
|
|
561
|
+
className="drop-shadow-[0_0_12px_oklch(0.82_0.14_192/0.6)]"
|
|
562
|
+
/>
|
|
563
|
+
</motion.div>
|
|
564
|
+
<h2 className="text-3xl md:text-4xl font-black tracking-tight mb-4">
|
|
565
|
+
{t('landing.workflow.headline')}
|
|
566
|
+
</h2>
|
|
567
|
+
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
|
|
568
|
+
{t('landing.workflow.subheading')}
|
|
569
|
+
</p>
|
|
570
|
+
</motion.div>
|
|
571
|
+
|
|
572
|
+
{/* Steps */}
|
|
573
|
+
<div className="space-y-14">
|
|
574
|
+
<WorkflowStep
|
|
575
|
+
step={1}
|
|
576
|
+
title={t('landing.workflow.create.label')}
|
|
577
|
+
subtitle={t('landing.workflow.create.description')}
|
|
578
|
+
command="npx vibecarbon create"
|
|
579
|
+
visual={<CreateVisual />}
|
|
580
|
+
color="teal"
|
|
581
|
+
/>
|
|
582
|
+
|
|
583
|
+
<WorkflowStep
|
|
584
|
+
step={2}
|
|
585
|
+
title={t('landing.workflow.develop.label')}
|
|
586
|
+
subtitle={t('landing.workflow.develop.description')}
|
|
587
|
+
command="npx vibecarbon up"
|
|
588
|
+
visual={<BuildVisual />}
|
|
589
|
+
color="magenta"
|
|
590
|
+
/>
|
|
591
|
+
|
|
592
|
+
<WorkflowStep
|
|
593
|
+
step={3}
|
|
594
|
+
title={t('landing.workflow.deploy.label')}
|
|
595
|
+
subtitle={t('landing.workflow.deploy.description')}
|
|
596
|
+
command="npx vibecarbon deploy"
|
|
597
|
+
visual={<DeployVisual />}
|
|
598
|
+
color="teal"
|
|
599
|
+
/>
|
|
600
|
+
</div>
|
|
601
|
+
</div>
|
|
602
|
+
</section>
|
|
603
|
+
);
|
|
604
|
+
}
|