vibecarbon 0.1.6 → 0.2.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/carbon/.env.example +3 -2
- package/carbon/DEVELOPMENT.md +18 -3
- package/carbon/PRODUCTION.md +1 -1
- package/carbon/content/docs/cli.mdx +3 -3
- package/carbon/content/docs/deployment.mdx +1 -1
- package/carbon/content/docs/development.mdx +1 -1
- package/carbon/content/docs/getting-started.mdx +0 -1
- package/carbon/docker-compose.prod.yml +11 -1
- package/carbon/scripts/dev-init.js +1 -1
- package/carbon/scripts/generate-dev-configs.sh +5 -7
- package/carbon/scripts/validate-dev-configs.sh +5 -7
- package/carbon/src/client/components/TechStackSection.tsx +0 -68
- package/carbon/src/client/index.css +0 -14
- package/carbon/src/client/locales/de.json +0 -18
- package/carbon/src/client/locales/en.json +86 -36
- package/carbon/src/client/locales/es.json +0 -18
- package/carbon/src/client/locales/fr.json +0 -18
- package/carbon/src/client/locales/pt.json +0 -18
- package/carbon/src/client/pages/Home.tsx +0 -3
- package/package.json +4 -2
- package/services/index.json +29 -0
- package/services/metabase/compose/docker-compose.override.yml +14 -0
- package/services/metabase/compose/docker-compose.prod.yml +29 -0
- package/services/metabase/compose/docker-compose.yml +68 -0
- package/services/metabase/db/init.sh +29 -0
- package/services/metabase/docs/integration.md +191 -0
- package/services/metabase/k8s/deployment.yaml +88 -0
- package/services/metabase/k8s/ingressroute.yaml +22 -0
- package/services/metabase/k8s/kustomization.yaml +9 -0
- package/services/metabase/k8s/network-policy.yaml +74 -0
- package/services/metabase/k8s/pvc.yaml +12 -0
- package/services/metabase/k8s/service.yaml +15 -0
- package/services/metabase/manifest.json +34 -0
- package/services/metabase/scripts/setup.sh +152 -0
- package/services/n8n/compose/docker-compose.override.yml +14 -0
- package/services/n8n/compose/docker-compose.prod.yml +32 -0
- package/services/n8n/compose/docker-compose.yml +99 -0
- package/services/n8n/db/init.sh +25 -0
- package/services/n8n/docs/SSO.md +124 -0
- package/services/n8n/docs/integration.md +155 -0
- package/services/n8n/hooks/hooks.js +131 -0
- package/services/n8n/k8s/deployment.yaml +116 -0
- package/services/n8n/k8s/ingressroute.yaml +24 -0
- package/services/n8n/k8s/kustomization.yaml +9 -0
- package/services/n8n/k8s/network-policy.yaml +82 -0
- package/services/n8n/k8s/pvc.yaml +14 -0
- package/services/n8n/k8s/service.yaml +14 -0
- package/services/n8n/manifest.json +36 -0
- package/services/n8n/scripts/setup.sh +42 -0
- package/{carbon/docker-compose.observability.prod.yml → services/observability/compose/docker-compose.prod.yml} +8 -0
- package/services/observability/docs/integration.md +31 -0
- package/services/observability/k8s/grafana-deployment.yaml +107 -0
- package/services/observability/k8s/grafana-provisioning-configmap.yaml +65 -0
- package/services/observability/k8s/grafana-pvc.yaml +14 -0
- package/services/observability/k8s/grafana-service.yaml +16 -0
- package/services/observability/k8s/ingressroute.yaml +22 -0
- package/services/observability/k8s/kustomization.yaml +24 -0
- package/services/observability/k8s/loki-configmap.yaml +74 -0
- package/services/observability/k8s/loki-deployment.yaml +72 -0
- package/services/observability/k8s/loki-pvc.yaml +14 -0
- package/services/observability/k8s/loki-service.yaml +16 -0
- package/services/observability/k8s/network-policy.yaml +141 -0
- package/services/observability/k8s/prometheus-configmap.yaml +80 -0
- package/services/observability/k8s/prometheus-deployment.yaml +78 -0
- package/services/observability/k8s/prometheus-pvc.yaml +14 -0
- package/services/observability/k8s/prometheus-rbac.yaml +55 -0
- package/services/observability/k8s/prometheus-service.yaml +16 -0
- package/services/observability/manifest.json +28 -0
- package/services/redis/compose/docker-compose.prod.yml +10 -0
- package/services/redis/compose/docker-compose.yml +24 -0
- package/services/redis/docs/integration.md +148 -0
- package/services/redis/k8s/deployment.yaml +70 -0
- package/services/redis/k8s/kustomization.yaml +8 -0
- package/services/redis/k8s/network-policy.yaml +20 -0
- package/services/redis/k8s/pvc.yaml +12 -0
- package/services/redis/k8s/service.yaml +15 -0
- package/services/redis/manifest.json +30 -0
- package/services/s3/compose/docker-compose.s3-ha.yml +86 -0
- package/services/s3/compose/docker-compose.s3.yml +35 -0
- package/services/s3/manifest.json +87 -0
- package/src/add.js +57 -89
- package/src/cli.js +1 -1
- package/src/create.js +3 -87
- package/src/lib/deploy/bundle.js +4 -2
- package/src/lib/deploy/compose/index.js +45 -17
- package/src/lib/deploy/orchestrator.js +13 -1
- package/src/remove.js +9 -6
- package/carbon/content/docs/optional-services.mdx +0 -160
- package/carbon/src/client/components/MetricsStrip.tsx +0 -48
- /package/{carbon/docker-compose.observability.override.yml → services/observability/compose/docker-compose.override.yml} +0 -0
- /package/{carbon/docker-compose.observability.yml → services/observability/compose/docker-compose.yml} +0 -0
- /package/{carbon → services/observability}/volumes/grafana/dashboards/logs.json +0 -0
- /package/{carbon → services/observability}/volumes/grafana/dashboards/overview.json +0 -0
- /package/{carbon → services/observability}/volumes/grafana/dashboards/postgresql.json +0 -0
- /package/{carbon → services/observability}/volumes/grafana/dashboards.dev/logs.json +0 -0
- /package/{carbon → services/observability}/volumes/grafana/dashboards.dev/overview.json +0 -0
- /package/{carbon → services/observability}/volumes/grafana/dashboards.dev/postgresql.json +0 -0
- /package/{carbon → services/observability}/volumes/grafana/provisioning/dashboards/dashboards.dev.yml +0 -0
- /package/{carbon → services/observability}/volumes/grafana/provisioning/dashboards/dashboards.yml +0 -0
- /package/{carbon → services/observability}/volumes/grafana/provisioning/datasources/datasources.yml +0 -0
- /package/{carbon → services/observability}/volumes/loki/loki-config.yml +0 -0
- /package/{carbon → services/observability}/volumes/prometheus/prometheus.yml +0 -0
- /package/{carbon → services/observability}/volumes/promtail/promtail-config.yml +0 -0
package/carbon/.env.example
CHANGED
|
@@ -93,8 +93,9 @@ POLAR_PRICE_PRO=""
|
|
|
93
93
|
# =============================================================================
|
|
94
94
|
# OBSERVABILITY (optional - enabled per-environment)
|
|
95
95
|
# =============================================================================
|
|
96
|
-
# Prometheus + Grafana + Loki stack
|
|
97
|
-
#
|
|
96
|
+
# Prometheus + Grafana + Loki stack. Install it first with `vibecarbon add
|
|
97
|
+
# observability` (it is not bundled by default), then enable with:
|
|
98
|
+
# docker compose -f docker-compose.yml -f docker-compose.observability.yml up -d
|
|
98
99
|
|
|
99
100
|
GRAFANA_ADMIN_USER="admin"
|
|
100
101
|
GRAFANA_ADMIN_PASSWORD="your-grafana-password-here"
|
package/carbon/DEVELOPMENT.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
This guide covers developing and testing the `carbon/` template directory locally.
|
|
4
4
|
|
|
5
|
+
## Running locally
|
|
6
|
+
|
|
7
|
+
From the **vibecarbon repo root**, `pnpm dev` is the one-command way to boot the template for testing:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm dev # ensures carbon/'s dev env exists, then runs `vibecarbon up` in carbon/
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`carbon/.env` and `.env.local` are gitignored, so a fresh checkout has none. `pnpm dev` runs `pnpm dev:init` for you when they're missing, then starts the stack via the working-tree CLI. Running `vibecarbon up` directly from `carbon/` also works, but you must `pnpm dev:init` first.
|
|
14
|
+
|
|
5
15
|
## Template Variable System
|
|
6
16
|
|
|
7
17
|
The CLI replaces placeholders like `{{PROJECT_NAME}}` when users run `npx vibecarbon create`. However, these placeholders cause issues when testing locally because:
|
|
@@ -111,19 +121,24 @@ cd test-app && pnpm dev:start
|
|
|
111
121
|
| Service Compose | Dev Override | Notes |
|
|
112
122
|
|-----------------|--------------|-------|
|
|
113
123
|
| `docker-compose.yml` | `docker-compose.override.yml` | Core services (db, kong, traefik) |
|
|
114
|
-
| `docker-compose.observability.yml` | `docker-compose.observability.override.yml` | Grafana: volumes + no ForwardAuth |
|
|
124
|
+
| `docker-compose.observability.yml` | `docker-compose.observability.override.yml` | Grafana: volumes + no ForwardAuth (installed via `vibecarbon add observability`) |
|
|
115
125
|
| `docker-compose.n8n.yml` | `docker-compose.n8n.override.yml` | n8n: no ForwardAuth |
|
|
116
126
|
| `docker-compose.metabase.yml` | `docker-compose.metabase.override.yml` | Metabase: no ForwardAuth |
|
|
117
127
|
|
|
128
|
+
> Optional services (observability, n8n, metabase, redis) are installed on
|
|
129
|
+
> demand with `vibecarbon add <service>`; their compose overlays and config
|
|
130
|
+
> files only appear after that.
|
|
131
|
+
|
|
118
132
|
### Volume Config Files
|
|
119
133
|
|
|
120
134
|
| Template File | Dev File | Notes |
|
|
121
135
|
|--------------|----------|-------|
|
|
122
136
|
| `volumes/db/super-admin.sql` | `volumes/db/super-admin.dev.sql` | Admin credentials |
|
|
123
|
-
| `volumes/grafana/provisioning/dashboards/dashboards.yml` | `...dashboards.dev.yml` | Folder UIDs |
|
|
124
|
-
| `volumes/grafana/dashboards/*.json` | `volumes/grafana/dashboards.dev/*.json` | Dashboard UIDs |
|
|
125
137
|
| `volumes/traefik/middlewares.yml` | `volumes/traefik/middlewares.dev.yml` | ForwardAuth uses host.docker.internal |
|
|
126
138
|
|
|
139
|
+
Observability's Grafana dev variants ship pre-made with the `observability`
|
|
140
|
+
add-on (in `volumes/grafana/`), so they are not generated by the script below.
|
|
141
|
+
|
|
127
142
|
## Automation
|
|
128
143
|
|
|
129
144
|
### Generate all dev configs from templates
|
package/carbon/PRODUCTION.md
CHANGED
|
@@ -96,7 +96,7 @@ Deno.serve((req) => {
|
|
|
96
96
|
.
|
|
97
97
|
├── docker-compose.yml # Base (local + production)
|
|
98
98
|
├── docker-compose.prod.yml # Production enhancements
|
|
99
|
-
├── docker-compose.observability.yml # Optional: Grafana, Prometheus, Loki
|
|
99
|
+
├── docker-compose.observability.yml # Optional: Grafana, Prometheus, Loki (via `vibecarbon add observability`)
|
|
100
100
|
├── docker-compose.n8n.yml # Optional: n8n workflow automation
|
|
101
101
|
├── docker-compose.metabase.yml # Optional: Metabase analytics
|
|
102
102
|
├── k8s/ # Kubernetes manifests with Kustomize overlays
|
|
@@ -164,7 +164,7 @@ npx vibecarbon add observability
|
|
|
164
164
|
npx vibecarbon add observability redis
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
-
**Available features:** `observability`, `
|
|
167
|
+
**Available features:** `observability`, `redis`.
|
|
168
168
|
|
|
169
169
|
CI/CD and external services (Stripe, OAuth, SMTP, etc.) live in
|
|
170
170
|
[`vibecarbon configure`](#configure) instead.
|
|
@@ -185,10 +185,10 @@ Remove a feature from a Vibecarbon project.
|
|
|
185
185
|
npx vibecarbon remove
|
|
186
186
|
|
|
187
187
|
# Remove a specific feature
|
|
188
|
-
npx vibecarbon remove
|
|
188
|
+
npx vibecarbon remove redis
|
|
189
189
|
|
|
190
190
|
# Remove without confirmation
|
|
191
|
-
npx vibecarbon remove
|
|
191
|
+
npx vibecarbon remove redis -force
|
|
192
192
|
```
|
|
193
193
|
|
|
194
194
|
Service data (volumes, databases) is preserved — only deployment configs
|
|
@@ -183,7 +183,7 @@ Point your domain to the server's IP address:
|
|
|
183
183
|
| A | `app.example.com` | `<server-ip>` |
|
|
184
184
|
| A | `api.example.com` | `<server-ip>` |
|
|
185
185
|
|
|
186
|
-
If you have optional services enabled, add records for their subdomains too (e.g., `grafana.example.com
|
|
186
|
+
If you have optional services enabled, add records for their subdomains too (e.g., `grafana.example.com`).
|
|
187
187
|
|
|
188
188
|
SSL certificates are handled automatically by Traefik via Let's Encrypt — no manual certificate management required.
|
|
189
189
|
|
|
@@ -57,7 +57,7 @@ Traefik routes `*.localhost` subdomains to each service:
|
|
|
57
57
|
| Supabase Studio | http://studio.localhost |
|
|
58
58
|
| Traefik Dashboard | http://traefik.localhost |
|
|
59
59
|
|
|
60
|
-
Optional services
|
|
60
|
+
Optional services like observability (Grafana) get their own subdomains when enabled — see the [CLI reference](/docs/cli#add).
|
|
61
61
|
|
|
62
62
|
## Hot Reloading
|
|
63
63
|
|
|
@@ -109,4 +109,3 @@ k8s/ # Kubernetes manifests (Kustomize)
|
|
|
109
109
|
- [Background Jobs](/docs/background-jobs) — Scheduled tasks with pg_cron
|
|
110
110
|
- [Analytics](/docs/analytics) — Privacy-friendly analytics with Plausible
|
|
111
111
|
- [Environments](/docs/environments) — Manage staging, dev, and production environments
|
|
112
|
-
- [Optional Services](/docs/optional-services) — Add n8n, Metabase, Redis, and more
|
|
@@ -187,12 +187,22 @@ services:
|
|
|
187
187
|
# (Internal services still connect directly for better performance)
|
|
188
188
|
|
|
189
189
|
# ===========================================
|
|
190
|
-
# EDGE FUNCTIONS (Production)
|
|
190
|
+
# EDGE FUNCTIONS (Production) — opt-in
|
|
191
191
|
# ===========================================
|
|
192
|
+
# Off by default: the template ships no real edge functions (only the 404
|
|
193
|
+
# stub at functions/main/index.ts), so running this container buys nothing
|
|
194
|
+
# and just adds an idle process. This `profiles:` gate keeps it from starting
|
|
195
|
+
# on a normal deploy — matching the k8s setup, where functions are likewise
|
|
196
|
+
# off until needed (deployment.functions.enabled in k8s/values/supabase.values.yaml).
|
|
197
|
+
# A project that adds a real function opts in with:
|
|
198
|
+
# docker compose --profile functions ... up
|
|
199
|
+
# The functions/ dir is already bundled to the server (see bundle.js), so
|
|
200
|
+
# enabling the profile works out of the box.
|
|
192
201
|
|
|
193
202
|
edge-functions:
|
|
194
203
|
image: supabase/edge-runtime:v1.71.2
|
|
195
204
|
container_name: ${PROJECT_NAME}-functions
|
|
205
|
+
profiles: ["functions"]
|
|
196
206
|
restart: unless-stopped
|
|
197
207
|
security_opt:
|
|
198
208
|
- no-new-privileges:true
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* node scripts/dev-init.js --force # Overwrite existing files
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { createHmac } from 'node:crypto';
|
|
13
14
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
14
15
|
|
|
15
16
|
const force = process.argv.includes('--force');
|
|
@@ -37,7 +38,6 @@ const DEV = {
|
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
function signDevJwt(role, secret) {
|
|
40
|
-
const { createHmac } = require('node:crypto');
|
|
41
41
|
const b64url = (buf) =>
|
|
42
42
|
Buffer.from(buf)
|
|
43
43
|
.toString('base64')
|
|
@@ -47,16 +47,14 @@ declare -A SUBSTITUTIONS=(
|
|
|
47
47
|
# Files that need dev variants (relative to carbon/)
|
|
48
48
|
# Format: "template_path:dev_path"
|
|
49
49
|
declare -a CONFIG_PAIRS=(
|
|
50
|
-
# Grafana dashboards
|
|
51
|
-
"volumes/grafana/provisioning/dashboards/dashboards.yml:volumes/grafana/provisioning/dashboards/dashboards.dev.yml"
|
|
52
50
|
# Database initialization (only super-admin needs dev variant — roles/services use runtime env vars)
|
|
53
51
|
"volumes/db/super-admin.sql:volumes/db/super-admin.dev.sql"
|
|
54
52
|
)
|
|
55
53
|
|
|
56
|
-
# Directories where all files need dev variants
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
)
|
|
54
|
+
# Directories where all files need dev variants.
|
|
55
|
+
# (Observability's Grafana dev variants ship pre-made with the `observability`
|
|
56
|
+
# add-on bundle — see services/observability/ — so they are not generated here.)
|
|
57
|
+
declare -a CONFIG_DIRS=()
|
|
60
58
|
|
|
61
59
|
generate_dev_file() {
|
|
62
60
|
local src="$1"
|
|
@@ -108,7 +106,7 @@ echo ""
|
|
|
108
106
|
|
|
109
107
|
# Process directories
|
|
110
108
|
echo "Config directories:"
|
|
111
|
-
for dir_pair in "${CONFIG_DIRS[@]}"; do
|
|
109
|
+
for dir_pair in ${CONFIG_DIRS[@]+"${CONFIG_DIRS[@]}"}; do
|
|
112
110
|
src_dir="${dir_pair%%:*}"
|
|
113
111
|
dest_dir="${dir_pair##*:}"
|
|
114
112
|
|
|
@@ -14,16 +14,14 @@ errors=0
|
|
|
14
14
|
|
|
15
15
|
# Known template/dev file pairs that must exist
|
|
16
16
|
declare -a REQUIRED_PAIRS=(
|
|
17
|
-
# Grafana dashboards
|
|
18
|
-
"volumes/grafana/provisioning/dashboards/dashboards.yml:volumes/grafana/provisioning/dashboards/dashboards.dev.yml"
|
|
19
17
|
# Database initialization (only super-admin needs dev variant — roles/services use runtime env vars)
|
|
20
18
|
"volumes/db/super-admin.sql:volumes/db/super-admin.dev.sql"
|
|
21
19
|
)
|
|
22
20
|
|
|
23
|
-
# Directories where each template file needs a dev counterpart
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
)
|
|
21
|
+
# Directories where each template file needs a dev counterpart.
|
|
22
|
+
# (Observability's Grafana dev variants ship with the `observability` add-on
|
|
23
|
+
# bundle in services/observability/, so they are not validated here.)
|
|
24
|
+
declare -a REQUIRED_DIR_PAIRS=()
|
|
27
25
|
|
|
28
26
|
echo "Validating dev config files..."
|
|
29
27
|
echo ""
|
|
@@ -51,7 +49,7 @@ echo ""
|
|
|
51
49
|
|
|
52
50
|
# Check directory pairs
|
|
53
51
|
echo "Required directory pairs:"
|
|
54
|
-
for dir_pair in "${REQUIRED_DIR_PAIRS[@]}"; do
|
|
52
|
+
for dir_pair in ${REQUIRED_DIR_PAIRS[@]+"${REQUIRED_DIR_PAIRS[@]}"}; do
|
|
55
53
|
template_dir="${dir_pair%%:*}"
|
|
56
54
|
dev_dir="${dir_pair##*:}"
|
|
57
55
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { motion } from 'framer-motion';
|
|
2
2
|
import type { LucideIcon } from 'lucide-react';
|
|
3
3
|
import {
|
|
4
|
-
Activity,
|
|
5
4
|
Atom,
|
|
6
|
-
BarChart3,
|
|
7
5
|
Box,
|
|
8
6
|
CreditCard,
|
|
9
7
|
Database,
|
|
@@ -14,15 +12,10 @@ import {
|
|
|
14
12
|
Layers,
|
|
15
13
|
Network,
|
|
16
14
|
Paintbrush,
|
|
17
|
-
Puzzle,
|
|
18
15
|
RefreshCw,
|
|
19
|
-
Workflow,
|
|
20
16
|
} from 'lucide-react';
|
|
21
|
-
import { useState } from 'react';
|
|
22
17
|
import { useTranslation } from 'react-i18next';
|
|
23
18
|
import vibecarbonIcon from '../assets/vibecarbon-icon.svg';
|
|
24
|
-
import { GlowTracker } from './effects/GlowTracker';
|
|
25
|
-
import { CommandBox } from './WorkflowSection';
|
|
26
19
|
|
|
27
20
|
interface TechItem {
|
|
28
21
|
name: string;
|
|
@@ -32,7 +25,6 @@ interface TechItem {
|
|
|
32
25
|
|
|
33
26
|
export function TechStackSection() {
|
|
34
27
|
const { t } = useTranslation();
|
|
35
|
-
const [hoveredAddon, setHoveredAddon] = useState<string | null>(null);
|
|
36
28
|
|
|
37
29
|
const tech: TechItem[] = [
|
|
38
30
|
{ name: 'React 19', description: t('landing.techStack.items.react'), icon: Atom },
|
|
@@ -49,21 +41,6 @@ export function TechStackSection() {
|
|
|
49
41
|
{ name: 'Kubernetes', description: t('landing.techStack.items.kubernetes'), icon: Network },
|
|
50
42
|
];
|
|
51
43
|
|
|
52
|
-
const addons: { icon: LucideIcon; name: string; description: string }[] = [
|
|
53
|
-
{
|
|
54
|
-
icon: Activity,
|
|
55
|
-
name: 'Observability',
|
|
56
|
-
description: t('landing.techStack.addOns.observability.description'),
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
icon: BarChart3,
|
|
60
|
-
name: 'Metabase',
|
|
61
|
-
description: t('landing.techStack.addOns.metabase.description'),
|
|
62
|
-
},
|
|
63
|
-
{ icon: Workflow, name: 'n8n', description: t('landing.techStack.addOns.n8n.description') },
|
|
64
|
-
{ icon: Database, name: 'Redis', description: t('landing.techStack.addOns.redis.description') },
|
|
65
|
-
];
|
|
66
|
-
|
|
67
44
|
return (
|
|
68
45
|
<section className="relative py-24 md:py-36">
|
|
69
46
|
<div className="mx-auto max-w-7xl px-6">
|
|
@@ -114,51 +91,6 @@ export function TechStackSection() {
|
|
|
114
91
|
</motion.div>
|
|
115
92
|
))}
|
|
116
93
|
</div>
|
|
117
|
-
|
|
118
|
-
{/* Optional Add-ons */}
|
|
119
|
-
<div className="mt-12 mx-auto max-w-3xl">
|
|
120
|
-
<div className="flex items-center justify-center gap-2 mb-6">
|
|
121
|
-
<Puzzle className="size-4 text-secondary-accent" />
|
|
122
|
-
<span className="text-sm font-semibold text-secondary-accent uppercase tracking-wider">
|
|
123
|
-
{t('landing.techStack.addOnsLabel')}
|
|
124
|
-
</span>
|
|
125
|
-
</div>
|
|
126
|
-
|
|
127
|
-
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
128
|
-
{addons.map((addon, index) => (
|
|
129
|
-
<motion.div
|
|
130
|
-
key={addon.name}
|
|
131
|
-
initial={{ opacity: 0, y: 16 }}
|
|
132
|
-
whileInView={{ opacity: 1, y: 0 }}
|
|
133
|
-
viewport={{ once: true, margin: '-30px' }}
|
|
134
|
-
transition={{ duration: 0.3, delay: index * 0.05 }}
|
|
135
|
-
>
|
|
136
|
-
{/* biome-ignore lint/a11y/noStaticElementInteractions: hover updates copy command text */}
|
|
137
|
-
<div
|
|
138
|
-
onMouseEnter={() => setHoveredAddon(addon.name.toLowerCase())}
|
|
139
|
-
className="group relative overflow-hidden rounded-2xl border border-secondary-accent/15 bg-gradient-to-br from-secondary-accent/5 via-transparent to-transparent p-5 hover:border-secondary-accent/30 transition-all duration-300"
|
|
140
|
-
>
|
|
141
|
-
<GlowTracker />
|
|
142
|
-
<div className="relative z-10 flex items-start gap-4">
|
|
143
|
-
<div className="flex items-center justify-center size-10 rounded-xl bg-secondary-accent/10 group-hover:bg-secondary-accent/15 transition-colors shrink-0">
|
|
144
|
-
<addon.icon className="size-5 text-secondary-accent" strokeWidth={1.5} />
|
|
145
|
-
</div>
|
|
146
|
-
<div>
|
|
147
|
-
<h3 className="font-semibold text-foreground mb-1">{addon.name}</h3>
|
|
148
|
-
<p className="text-sm text-muted-foreground leading-relaxed">
|
|
149
|
-
{addon.description}
|
|
150
|
-
</p>
|
|
151
|
-
</div>
|
|
152
|
-
</div>
|
|
153
|
-
</div>
|
|
154
|
-
</motion.div>
|
|
155
|
-
))}
|
|
156
|
-
</div>
|
|
157
|
-
|
|
158
|
-
<div className="mt-4">
|
|
159
|
-
<CommandBox command={`npx vibecarbon add ${hoveredAddon ?? '<name>'}`} />
|
|
160
|
-
</div>
|
|
161
|
-
</div>
|
|
162
94
|
</div>
|
|
163
95
|
</section>
|
|
164
96
|
);
|
|
@@ -349,20 +349,6 @@ body {
|
|
|
349
349
|
.hero-orb { animation: orb-pulse 6s ease-in-out infinite; }
|
|
350
350
|
@media (prefers-reduced-motion: reduce) { .hero-orb { animation: none; } }
|
|
351
351
|
|
|
352
|
-
/* MetricsStrip value shimmer — reuses existing shimmer keyframe */
|
|
353
|
-
.metric-value {
|
|
354
|
-
background: linear-gradient(90deg,
|
|
355
|
-
oklch(0.98 0 0) 0%,
|
|
356
|
-
oklch(0.82 0.14 192) 40%,
|
|
357
|
-
oklch(0.98 0 0) 80%
|
|
358
|
-
);
|
|
359
|
-
background-size: 200% auto;
|
|
360
|
-
-webkit-background-clip: text;
|
|
361
|
-
-webkit-text-fill-color: transparent;
|
|
362
|
-
background-clip: text;
|
|
363
|
-
animation: shimmer 4s linear infinite;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
352
|
/* Spotlight particle dots for glass containers */
|
|
367
353
|
.spotlight-particles {
|
|
368
354
|
background-image: radial-gradient(circle, oklch(1 0 0 / 0.5) 1px, transparent 1px);
|
|
@@ -277,24 +277,6 @@
|
|
|
277
277
|
"subheading": "Sichere, skalierbare, vollautomatische Architektur und SaaS-Starter-Kit — präzise für KI entwickelt.",
|
|
278
278
|
"getUpdates": "Updates erhalten"
|
|
279
279
|
},
|
|
280
|
-
"metrics": {
|
|
281
|
-
"time": {
|
|
282
|
-
"value": "< 5 Min.",
|
|
283
|
-
"label": "Von null zu Produktion"
|
|
284
|
-
},
|
|
285
|
-
"services": {
|
|
286
|
-
"value": "12 Services",
|
|
287
|
-
"label": "Automatisch bereitgestellt"
|
|
288
|
-
},
|
|
289
|
-
"config": {
|
|
290
|
-
"value": "Zero Config",
|
|
291
|
-
"label": "Sicherheit von Anfang an"
|
|
292
|
-
},
|
|
293
|
-
"commands": {
|
|
294
|
-
"value": "3 Befehle",
|
|
295
|
-
"label": "Erstellen · entwickeln · deployen"
|
|
296
|
-
}
|
|
297
|
-
},
|
|
298
280
|
"logoStrip": {
|
|
299
281
|
"label": "Optimiert für deine Tools"
|
|
300
282
|
},
|
|
@@ -277,21 +277,24 @@
|
|
|
277
277
|
"subheading": "Full-stack SaaS architecture with auth, billing, infrastructure, and deployment — built for AI-driven development.",
|
|
278
278
|
"getUpdates": "Get Updates"
|
|
279
279
|
},
|
|
280
|
-
"metrics": {
|
|
281
|
-
"time": { "value": "< 5 min", "label": "From zero to production" },
|
|
282
|
-
"services": { "value": "12 services", "label": "Provisioned automatically" },
|
|
283
|
-
"config": { "value": "Zero config", "label": "Security hardened from creation" },
|
|
284
|
-
"commands": { "value": "3 commands", "label": "Create · develop · deploy" }
|
|
285
|
-
},
|
|
286
280
|
"logoStrip": {
|
|
287
281
|
"label": "Optimized for the tools you use"
|
|
288
282
|
},
|
|
289
283
|
"workflow": {
|
|
290
284
|
"headline": "Three commands to production",
|
|
291
285
|
"subheading": "Provision, deploy, and scale from the CLI",
|
|
292
|
-
"create":
|
|
293
|
-
|
|
294
|
-
|
|
286
|
+
"create": {
|
|
287
|
+
"label": "Create",
|
|
288
|
+
"description": "Full-stack app with auth, database, API, and Kubernetes manifests — ready to go."
|
|
289
|
+
},
|
|
290
|
+
"develop": {
|
|
291
|
+
"label": "Develop",
|
|
292
|
+
"description": "Spin up your entire dev environment: database, auth, API, and hot-reloading frontend."
|
|
293
|
+
},
|
|
294
|
+
"deploy": {
|
|
295
|
+
"label": "Deploy",
|
|
296
|
+
"description": "Provision a VPS or Kubernetes cluster with SSL, HA, backups, and CI/CD in one command."
|
|
297
|
+
}
|
|
295
298
|
},
|
|
296
299
|
"techStack": {
|
|
297
300
|
"headline": "Built on tech that",
|
|
@@ -299,24 +302,32 @@
|
|
|
299
302
|
"subheading": "Every layer chosen for production reliability, not trend-chasing.",
|
|
300
303
|
"addOnsLabel": "Optional add-ons",
|
|
301
304
|
"items": {
|
|
302
|
-
"react":
|
|
305
|
+
"react": "Lightning-fast UI",
|
|
303
306
|
"typescript": "End-to-end type safety",
|
|
304
|
-
"hono":
|
|
305
|
-
"supabase":
|
|
306
|
-
"tailwind":
|
|
307
|
-
"shadcn":
|
|
308
|
-
"tanstack":
|
|
309
|
-
"stripe":
|
|
310
|
-
"mdx":
|
|
311
|
-
"i18next":
|
|
312
|
-
"docker":
|
|
307
|
+
"hono": "13KB server framework",
|
|
308
|
+
"supabase": "Auth, DB & realtime",
|
|
309
|
+
"tailwind": "Utility-first styling",
|
|
310
|
+
"shadcn": "50+ ready components",
|
|
311
|
+
"tanstack": "Smart data fetching",
|
|
312
|
+
"stripe": "Payments & billing",
|
|
313
|
+
"mdx": "Blog, docs & changelog",
|
|
314
|
+
"i18next": "Multi-language support",
|
|
315
|
+
"docker": "Containerized deploys",
|
|
313
316
|
"kubernetes": "Production orchestration"
|
|
314
317
|
},
|
|
315
318
|
"addOns": {
|
|
316
|
-
"observability": {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
"
|
|
319
|
+
"observability": {
|
|
320
|
+
"description": "Grafana, Prometheus & Loki — metrics, logs, and dashboards pre-configured."
|
|
321
|
+
},
|
|
322
|
+
"metabase": {
|
|
323
|
+
"description": "Self-hosted business intelligence with direct access to your database."
|
|
324
|
+
},
|
|
325
|
+
"n8n": {
|
|
326
|
+
"description": "Visual workflow automation for background jobs, webhooks, and integrations."
|
|
327
|
+
},
|
|
328
|
+
"redis": {
|
|
329
|
+
"description": "In-memory caching and queues for high-throughput workloads."
|
|
330
|
+
}
|
|
320
331
|
}
|
|
321
332
|
},
|
|
322
333
|
"architecture": {
|
|
@@ -328,12 +339,36 @@
|
|
|
328
339
|
"headline": "Scalable &",
|
|
329
340
|
"headlineHighlight": "Secure.",
|
|
330
341
|
"subheading": "Ship fast — without going down in flames.",
|
|
331
|
-
"hacked":
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
"
|
|
342
|
+
"hacked": {
|
|
343
|
+
"risk": "Getting hacked",
|
|
344
|
+
"protection": "Security hardened",
|
|
345
|
+
"how": "Traefik proxy, firewall rules, CSP headers, rate limiting"
|
|
346
|
+
},
|
|
347
|
+
"exposed": {
|
|
348
|
+
"risk": "Database exposed",
|
|
349
|
+
"protection": "Database isolation",
|
|
350
|
+
"how": "Network-isolated database, row-level security, scoped credentials"
|
|
351
|
+
},
|
|
352
|
+
"traffic": {
|
|
353
|
+
"risk": "Can't handle traffic",
|
|
354
|
+
"protection": "Auto-scaling",
|
|
355
|
+
"how": "Kubernetes autoscaling across pods and VPS nodes"
|
|
356
|
+
},
|
|
357
|
+
"redundancy": {
|
|
358
|
+
"risk": "Zero redundancy",
|
|
359
|
+
"protection": "High availability",
|
|
360
|
+
"how": "Multi-region with health monitoring & one-command failover"
|
|
361
|
+
},
|
|
362
|
+
"visibility": {
|
|
363
|
+
"risk": "No visibility",
|
|
364
|
+
"protection": "Full observability",
|
|
365
|
+
"how": "Native Grafana & Prometheus, configured per environment"
|
|
366
|
+
},
|
|
367
|
+
"dataLoss": {
|
|
368
|
+
"risk": "Data loss",
|
|
369
|
+
"protection": "Automated backups",
|
|
370
|
+
"how": "Scheduled S3 backups with one-command restore"
|
|
371
|
+
}
|
|
337
372
|
},
|
|
338
373
|
"aiIntegration": {
|
|
339
374
|
"headline1": "Works with",
|
|
@@ -342,10 +377,22 @@
|
|
|
342
377
|
"subheading": "Every project includes CLAUDE.md, Cursor rules, and security guardrails for AI agents. Code generated by AI follows your architecture and security policies from the first prompt.",
|
|
343
378
|
"footer1": "Use any AI to build — Vibecarbon handles the",
|
|
344
379
|
"footer2": "infrastructure and security",
|
|
345
|
-
"docs":
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
380
|
+
"docs": {
|
|
381
|
+
"title": "AI-native documentation",
|
|
382
|
+
"description": "CLAUDE.md, AGENTS.md, .windsurfrules, Copilot instructions, and Cursor rules ship with every project — your AI assistant gets full codebase context from the first prompt."
|
|
383
|
+
},
|
|
384
|
+
"guardrails": {
|
|
385
|
+
"title": "Built-in security guardrails",
|
|
386
|
+
"description": "AGENTS.md encodes mandatory MUST/NEVER rules for RLS, auth checks, client selection, and infrastructure hardening — so AI-generated code follows your security policies by default."
|
|
387
|
+
},
|
|
388
|
+
"architecture": {
|
|
389
|
+
"title": "Clean architecture",
|
|
390
|
+
"description": "Clear separation of client, server, and shared code with typed interfaces. AI agents can navigate, understand, and extend your app without hallucinating structure."
|
|
391
|
+
},
|
|
392
|
+
"patterns": {
|
|
393
|
+
"title": "Predictable patterns",
|
|
394
|
+
"description": "Every route validates with Zod, every query uses the right Supabase client, every table has RLS. AI agents replicate the same correct patterns every time."
|
|
395
|
+
}
|
|
349
396
|
},
|
|
350
397
|
"pricing": {
|
|
351
398
|
"headline1": "From",
|
|
@@ -354,7 +401,10 @@
|
|
|
354
401
|
"headlineScale": "scale.",
|
|
355
402
|
"subheading": "Same carbon, different form. One payment, lifetime access.",
|
|
356
403
|
"popular": "Most Popular",
|
|
357
|
-
"units": {
|
|
404
|
+
"units": {
|
|
405
|
+
"forever": "forever",
|
|
406
|
+
"oneTime": "one-time payment"
|
|
407
|
+
},
|
|
358
408
|
"graphite": {
|
|
359
409
|
"tagline": "Sketch and design locally",
|
|
360
410
|
"cta": "Start Sketching",
|
|
@@ -446,7 +496,7 @@
|
|
|
446
496
|
"cta": {
|
|
447
497
|
"badge": "Secure by design",
|
|
448
498
|
"headline": "Ship something you own.",
|
|
449
|
-
"subheading": "Production-grade
|
|
499
|
+
"subheading": "Production-grade, automated everything."
|
|
450
500
|
},
|
|
451
501
|
"footer": {
|
|
452
502
|
"userDocs": "User Docs",
|
|
@@ -458,4 +508,4 @@
|
|
|
458
508
|
"terms": "Terms"
|
|
459
509
|
}
|
|
460
510
|
}
|
|
461
|
-
}
|
|
511
|
+
}
|
|
@@ -277,24 +277,6 @@
|
|
|
277
277
|
"subheading": "Arquitectura segura, escalable y totalmente automatizada, y kit de inicio SaaS meticulosamente diseñado para IA.",
|
|
278
278
|
"getUpdates": "Recibir actualizaciones"
|
|
279
279
|
},
|
|
280
|
-
"metrics": {
|
|
281
|
-
"time": {
|
|
282
|
-
"value": "< 5 min",
|
|
283
|
-
"label": "De cero a producción"
|
|
284
|
-
},
|
|
285
|
-
"services": {
|
|
286
|
-
"value": "12 servicios",
|
|
287
|
-
"label": "Aprovisionados automáticamente"
|
|
288
|
-
},
|
|
289
|
-
"config": {
|
|
290
|
-
"value": "Cero config",
|
|
291
|
-
"label": "Seguridad desde el primer momento"
|
|
292
|
-
},
|
|
293
|
-
"commands": {
|
|
294
|
-
"value": "3 comandos",
|
|
295
|
-
"label": "Crear · desarrollar · desplegar"
|
|
296
|
-
}
|
|
297
|
-
},
|
|
298
280
|
"logoStrip": {
|
|
299
281
|
"label": "Optimizado para las herramientas que usas"
|
|
300
282
|
},
|
|
@@ -277,24 +277,6 @@
|
|
|
277
277
|
"subheading": "Architecture sécurisée, évolutive et entièrement automatisée, et kit de démarrage SaaS méticuleusement conçu pour l'IA.",
|
|
278
278
|
"getUpdates": "Recevoir les mises à jour"
|
|
279
279
|
},
|
|
280
|
-
"metrics": {
|
|
281
|
-
"time": {
|
|
282
|
-
"value": "< 5 min",
|
|
283
|
-
"label": "De zéro à la production"
|
|
284
|
-
},
|
|
285
|
-
"services": {
|
|
286
|
-
"value": "12 services",
|
|
287
|
-
"label": "Provisionnés automatiquement"
|
|
288
|
-
},
|
|
289
|
-
"config": {
|
|
290
|
-
"value": "Zéro config",
|
|
291
|
-
"label": "Sécurité dès le départ"
|
|
292
|
-
},
|
|
293
|
-
"commands": {
|
|
294
|
-
"value": "3 commandes",
|
|
295
|
-
"label": "Créer · développer · déployer"
|
|
296
|
-
}
|
|
297
|
-
},
|
|
298
280
|
"logoStrip": {
|
|
299
281
|
"label": "Optimisé pour les outils que tu utilises"
|
|
300
282
|
},
|
|
@@ -277,24 +277,6 @@
|
|
|
277
277
|
"subheading": "Arquitetura segura, escalável e totalmente automatizada, e SaaS Starter Kit meticulosamente desenvolvido para IA.",
|
|
278
278
|
"getUpdates": "Receber atualizações"
|
|
279
279
|
},
|
|
280
|
-
"metrics": {
|
|
281
|
-
"time": {
|
|
282
|
-
"value": "< 5 min",
|
|
283
|
-
"label": "Do zero à produção"
|
|
284
|
-
},
|
|
285
|
-
"services": {
|
|
286
|
-
"value": "12 serviços",
|
|
287
|
-
"label": "Aprovisionados automaticamente"
|
|
288
|
-
},
|
|
289
|
-
"config": {
|
|
290
|
-
"value": "Zero config",
|
|
291
|
-
"label": "Segurança pronta a usar"
|
|
292
|
-
},
|
|
293
|
-
"commands": {
|
|
294
|
-
"value": "3 comandos",
|
|
295
|
-
"label": "Criar · desenvolver · publicar"
|
|
296
|
-
}
|
|
297
|
-
},
|
|
298
280
|
"logoStrip": {
|
|
299
281
|
"label": "Otimizado para as ferramentas que usas"
|
|
300
282
|
},
|
|
@@ -21,7 +21,6 @@ import { VGlowEffect } from '../components/effects/VGlowEffect';
|
|
|
21
21
|
import { FAQSection } from '../components/FAQSection';
|
|
22
22
|
import Hero from '../components/Hero';
|
|
23
23
|
import { LogoStrip } from '../components/LogoStrip';
|
|
24
|
-
import { MetricsStrip } from '../components/MetricsStrip';
|
|
25
24
|
import { NewsletterSignup } from '../components/NewsletterSignup';
|
|
26
25
|
import { PricingSection } from '../components/PricingSection';
|
|
27
26
|
import { SEO } from '../components/SEO';
|
|
@@ -153,8 +152,6 @@ export default function VibecarbonHome() {
|
|
|
153
152
|
<WorkflowSection />
|
|
154
153
|
</ScrollSection>
|
|
155
154
|
|
|
156
|
-
<MetricsStrip />
|
|
157
|
-
|
|
158
155
|
<ScrollSection id="comparison">
|
|
159
156
|
<ComparisonSection />
|
|
160
157
|
</ScrollSection>
|