Preview Environments for Nuxt.js: Automated Per-PR Deployments with Bunnyshell
GuideMarch 20, 202612 min read

Preview Environments for Nuxt.js: Automated Per-PR Deployments with Bunnyshell

Why Preview Environments for Nuxt.js?

Every Nuxt.js team hits the same wall: you build a feature with server routes and SSR pages, test it locally with nuxi dev, push to staging — and it breaks because staging still has someone else's middleware changes. Or your SSR pages render stale data because two feature branches share the same database. Or the reviewer asks you to "deploy it somewhere" so they can test the OAuth flow, and you waste time configuring a one-off deployment that doesn't match production.

Preview environments solve this. Every pull request gets its own isolated deployment — Nuxt.js app with Nitro server, PostgreSQL database, Redis for caching — running in Kubernetes with production-like configuration. Reviewers click a link and see the actual running app, not just the diff.

With Bunnyshell, you get:

  • Automatic deployment — A new environment spins up for every PR
  • Production parity — Same Docker images, same database engine, same SSR behavior
  • Isolation — Each PR environment is fully independent, no shared staging conflicts
  • Automatic cleanup — Environments are destroyed when the PR is merged or closed

Choose Your Approach

Bunnyshell supports three ways to set up preview environments for Nuxt.js. Pick the one that fits your workflow:

ApproachBest forComplexityCI/CD maintenance
Approach A: Bunnyshell UITeams that want the fastest setup with zero pipeline maintenanceEasiestNone — Bunnyshell manages webhooks automatically
Approach B: Docker Compose ImportTeams already using docker-compose.yml for local developmentEasyNone — import converts to Bunnyshell config automatically
Approach C: Helm ChartsTeams with existing Helm infrastructure or complex K8s needsAdvancedOptional — can use CLI or Bunnyshell UI

All three approaches end the same way: a toggle in Bunnyshell Settings that enables automatic preview environments for every PR. No GitHub Actions, no GitLab CI pipelines to maintain — Bunnyshell adds webhooks to your Git provider and listens for PR events.

Prerequisites: Prepare Your Nuxt.js App

Regardless of which approach you choose, your Nuxt.js app needs a proper Docker setup and the right configuration for running in Kubernetes.

1. Understand the Nitro Output

Nuxt 3 uses Nitro as its server engine. When you run nuxt build, Nitro produces a standalone output in .output/ that includes everything needed to run the server:

Text
1.output/
2├── server/
3│   ├── index.mjs          ← The Nitro server entry point
4│   ├── chunks/
5│   └── node_modules/      ← Only production dependencies
6├── public/
7│   ├── _nuxt/             ← Client-side bundles
8│   └── ...
9└── nitro.json

This is already a self-contained server — no need for Nginx or a separate static file server. Nitro handles both SSR and static asset serving.

2. Configure Nuxt for Docker

In your nuxt.config.ts, ensure these settings:

TypeScript
1export default defineNuxtConfig({
2  devtools: { enabled: false },
3
4  // Nitro server configuration
5  nitro: {
6    // Optional: configure server routes, plugins, etc.
7  },
8
9  // Runtime config — accessible via useRuntimeConfig()
10  runtimeConfig: {
11    // Server-only keys (NUXT_*)
12    databaseUrl: '',
13    redisUrl: '',
14    authSecret: '',
15
16    // Public keys (NUXT_PUBLIC_*)
17    public: {
18      apiBase: '/api',
19      appName: 'MyApp',
20    },
21  },
22})

Nuxt's runtime config is more Docker-friendly than Next.js. Both NUXT_* (server) and NUXT_PUBLIC_* (client) variables are resolved at runtime, not build time. This means you can change them without rebuilding the Docker image.

3. Create a Production-Ready Dockerfile

Nuxt.js with Nitro runs as a single Node.js process — no Nginx sidecar needed:

Dockerfile
1# ── Stage 1: Install dependencies ──
2FROM node:20-alpine AS deps
3RUN apk add --no-cache libc6-compat
4WORKDIR /app
5
6COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
7
8RUN \
9  if [ -f yarn.lock ]; then yarn install --frozen-lockfile; \
10  elif [ -f package-lock.json ]; then npm ci; \
11  elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm install --frozen-lockfile; \
12  else echo "No lockfile found." && exit 1; \
13  fi
14
15# ── Stage 2: Build the application ──
16FROM node:20-alpine AS builder
17WORKDIR /app
18
19COPY --from=deps /app/node_modules ./node_modules
20COPY . .
21
22# Generate Prisma client if schema exists
23RUN if [ -f prisma/schema.prisma ]; then npx prisma generate; fi
24
25RUN npm run build
26
27# ── Stage 3: Production image ──
28FROM node:20-alpine AS runner
29WORKDIR /app
30
31ENV NODE_ENV=production
32
33RUN addgroup --system --gid 1001 nuxtjs
34RUN adduser --system --uid 1001 nuxtjs
35
36# Copy the Nitro standalone output
37COPY --from=builder --chown=nuxtjs:nuxtjs /app/.output ./.output
38
39# Copy Prisma files if they exist
40COPY --from=builder /app/prisma ./prisma 2>/dev/null || true
41COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma 2>/dev/null || true
42COPY --from=builder /app/node_modules/@prisma ./node_modules/@prisma 2>/dev/null || true
43
44USER nuxtjs
45
46EXPOSE 3000
47
48# Nitro environment variables for container networking
49ENV HOST=0.0.0.0
50ENV PORT=3000
51ENV NITRO_HOST=0.0.0.0
52ENV NITRO_PORT=3000
53
54CMD ["node", ".output/server/index.mjs"]

Both HOST=0.0.0.0 and NITRO_HOST=0.0.0.0 should be set. Nitro checks NITRO_HOST first, then falls back to HOST. Without either, the server only listens on 127.0.0.1, making it unreachable from outside the container.

4. Create a Health Check Endpoint

Create server/api/health.get.ts:

TypeScript
1export default defineEventHandler(() => {
2  return { status: 'ok', timestamp: Date.now() }
3})

Nuxt server routes in the server/api/ directory are automatically available at /api/health. No additional configuration needed.

5. Environment Variables

Nuxt 3 has a clean runtime config model:

  • NUXT_PUBLIC_* — Available on both client and server, resolved at runtime
  • NUXT_* — Server-only, resolved at runtime

Update your .env.example:

.env
1# Server-only (NUXT_ prefix maps to runtimeConfig keys)
2NUXT_DATABASE_URL=postgresql://postgres:password@postgres:5432/nuxtapp
3NUXT_REDIS_URL=redis://redis:6379
4NUXT_AUTH_SECRET=
5
6# Public (available on client and server)
7NUXT_PUBLIC_API_BASE=/api
8NUXT_PUBLIC_APP_NAME=MyApp

Unlike Next.js, Nuxt's NUXT_PUBLIC_* variables are resolved at runtime, not build time. This means the same Docker image works across all preview environments — just change the environment variables. No rebuild needed.

Nuxt.js Deployment Checklist

  • Multi-stage Dockerfile with Node 20 Alpine
  • HOST=0.0.0.0 and NITRO_HOST=0.0.0.0 set for container networking
  • Health check endpoint at /api/health
  • Runtime config uses NUXT_* and NUXT_PUBLIC_* prefixes
  • NUXT_PUBLIC_* variables are runtime (no rebuild needed for URL changes)
  • Prisma client generation included in build stage
  • Nitro .output/ directory copied as standalone
  • Non-root user (nuxtjs) for security
  • Server routes (/api/*) work out of the box with Nitro

Approach A: Bunnyshell UI — Zero CI/CD Maintenance

This is the easiest approach. You connect your repo, paste a YAML config, deploy, and flip a toggle. No CI/CD pipelines to write or maintain — Bunnyshell automatically adds webhooks to your Git provider and creates/destroys preview environments when PRs are opened/closed.

Step 1: Create a Project and Environment

  1. Log into Bunnyshell
  2. Click Create project and name it (e.g., "Nuxt.js App")
  3. Inside the project, click Create environment and name it (e.g., "nuxtjs-main")

Step 2: Define the Environment Configuration

Click Configuration in your environment view and paste this bunnyshell.yaml:

YAML
1kind: Environment
2name: nuxtjs-preview
3type: primary
4
5environmentVariables:
6  NUXT_AUTH_SECRET: SECRET["your-auth-secret"]
7  DB_PASSWORD: SECRET["your-db-password"]
8
9components:
10  # ── Nuxt.js Application ──
11  - kind: Application
12    name: nuxtjs-app
13    gitRepo: 'https://github.com/your-org/your-nuxtjs-repo.git'
14    gitBranch: main
15    gitApplicationPath: /
16    dockerCompose:
17      build:
18        context: .
19        dockerfile: Dockerfile
20      environment:
21        NODE_ENV: production
22        HOST: '0.0.0.0'
23        PORT: '3000'
24        NITRO_HOST: '0.0.0.0'
25        NITRO_PORT: '3000'
26        NUXT_DATABASE_URL: 'postgresql://nuxtapp:{{ env.vars.DB_PASSWORD }}@postgres:5432/nuxtapp'
27        NUXT_REDIS_URL: 'redis://redis:6379'
28        NUXT_AUTH_SECRET: '{{ env.vars.NUXT_AUTH_SECRET }}'
29        NUXT_PUBLIC_API_BASE: '/api'
30        NUXT_PUBLIC_APP_URL: 'https://{{ components.nuxtjs-app.ingress.hosts[0] }}'
31      ports:
32        - '3000:3000'
33    dependsOn:
34      - postgres
35      - redis
36    hosts:
37      - hostname: 'app-{{ env.base_domain }}'
38        path: /
39        servicePort: 3000
40
41  # ── PostgreSQL Database ──
42  - kind: Database
43    name: postgres
44    dockerCompose:
45      image: 'postgres:16-alpine'
46      environment:
47        POSTGRES_DB: nuxtapp
48        POSTGRES_USER: nuxtapp
49        POSTGRES_PASSWORD: '{{ env.vars.DB_PASSWORD }}'
50      ports:
51        - '5432:5432'
52
53  # ── Redis (Caching / Sessions) ──
54  - kind: Service
55    name: redis
56    dockerCompose:
57      image: 'redis:7-alpine'
58      ports:
59        - '6379:6379'
60
61volumes:
62  - name: postgres-data
63    mount:
64      component: postgres
65      containerPath: /var/lib/postgresql/data
66    size: 1Gi

Key architecture notes:

  • No Nginx sidecar needed — Nitro handles both SSR and static asset serving on port 3000
  • Runtime env varsNUXT_PUBLIC_* variables are resolved at runtime, so the same image works for all preview environments without rebuilding
  • NITRO_HOST: '0.0.0.0' — Required for Nitro to accept connections from outside the container
  • Server routes included — All files in server/api/ are automatically served by Nitro

Replace your-org/your-nuxtjs-repo with your actual repository. Save the configuration.

Step 3: Deploy

Click the Deploy button, select your Kubernetes cluster, and click Deploy Environment. Bunnyshell will:

  1. Build your Nuxt.js Docker image (multi-stage, Nitro standalone output)
  2. Pull PostgreSQL and Redis images
  3. Deploy everything into an isolated Kubernetes namespace
  4. Generate HTTPS URLs automatically with DNS

Monitor the deployment in the environment detail page. When status shows Running, click Endpoints to access your live Nuxt.js app.

Step 4: Run Post-Deploy Commands

After deployment, run database setup commands:

Bash
1export BUNNYSHELL_TOKEN=your-api-token
2bns components list --environment ENV_ID --output json | jq '._embedded.item[] | {id, name}'
3
4# Run Prisma migrations
5bns exec COMPONENT_ID -c nuxtjs-app -- npx prisma migrate deploy
6
7# Or if using Drizzle
8bns exec COMPONENT_ID -c nuxtjs-app -- npx drizzle-kit push
9
10# Seed the database (if you have a seed script)
11bns exec COMPONENT_ID -c nuxtjs-app -- npx prisma db seed

Step 5: Enable Automatic Preview Environments

This is the magic step — no CI/CD configuration needed:

  1. In your environment, go to Settings
  2. Find the Ephemeral environments section
  3. Toggle "Create ephemeral environments on pull request" to ON
  4. Toggle "Destroy environment after merge or close pull request" to ON
  5. Select the Kubernetes cluster for ephemeral environments

That's it. Bunnyshell automatically adds a webhook to your Git provider (GitHub, GitLab, or Bitbucket). From now on:

  • Open a PR — Bunnyshell creates an ephemeral environment with the PR's branch
  • Push to PR — The environment redeploys with the latest changes
  • Bunnyshell posts a comment on the PR with a link to the live deployment
  • Merge or close the PR — The ephemeral environment is automatically destroyed

The primary environment must be in Running or Stopped status before ephemeral environments can be created from it.


Approach B: Docker Compose Import

Already have a docker-compose.yml for local development? Bunnyshell can import it directly and convert it to its environment format. No manual YAML writing required.

Step 1: Add a docker-compose.yml to Your Repo

If you don't already have one, create docker-compose.yml in your repo root:

YAML
1version: '3.8'
2
3services:
4  nuxtjs-app:
5    build:
6      context: .
7      dockerfile: Dockerfile
8    ports:
9      - '3000:3000'
10    environment:
11      NODE_ENV: production
12      HOST: '0.0.0.0'
13      PORT: '3000'
14      NITRO_HOST: '0.0.0.0'
15      NITRO_PORT: '3000'
16      NUXT_DATABASE_URL: 'postgresql://nuxtapp:secret@postgres:5432/nuxtapp'
17      NUXT_REDIS_URL: 'redis://redis:6379'
18      NUXT_AUTH_SECRET: 'dev-secret-change-in-production'
19      NUXT_PUBLIC_API_BASE: '/api'
20      NUXT_PUBLIC_APP_URL: 'http://localhost:3000'
21    depends_on:
22      - postgres
23      - redis
24
25  postgres:
26    image: postgres:16-alpine
27    environment:
28      POSTGRES_DB: nuxtapp
29      POSTGRES_USER: nuxtapp
30      POSTGRES_PASSWORD: secret
31    volumes:
32      - postgres-data:/var/lib/postgresql/data
33    ports:
34      - '5432:5432'
35
36  redis:
37    image: redis:7-alpine
38    ports:
39      - '6379:6379'
40
41volumes:
42  postgres-data:

Step 2: Import into Bunnyshell

  1. Create a Project and Environment in Bunnyshell (same as Approach A, Step 1)
  2. Click Define environment
  3. Select your Git account and repository
  4. Set the branch (e.g., main) and the path to docker-compose.yml (use / if it's in the root)
  5. Click Continue — Bunnyshell parses and validates your Docker Compose file

Bunnyshell automatically detects:

  • All services (nuxtjs-app, postgres, redis)
  • Exposed ports
  • Build configurations (Dockerfiles)
  • Volumes
  • Environment variables

It converts everything into a bunnyshell.yaml environment definition.

The docker-compose.yml is only read during the initial import. Subsequent changes to the file won't auto-propagate — edit the environment configuration in Bunnyshell instead.

Step 3: Adjust the Configuration

After import, go to Configuration in the environment view and update:

Replace hardcoded secrets with SECRET["..."] syntax:

YAML
1environmentVariables:
2  NUXT_AUTH_SECRET: SECRET["your-auth-secret"]
3  DB_PASSWORD: SECRET["your-db-password"]

Add dynamic URLs using Bunnyshell interpolation:

YAML
NUXT_PUBLIC_APP_URL: 'https://{{ components.nuxtjs-app.ingress.hosts[0] }}'
NUXT_DATABASE_URL: 'postgresql://nuxtapp:{{ env.vars.DB_PASSWORD }}@postgres:5432/nuxtapp'

Step 4: Deploy and Enable Preview Environments

Same as Approach A — click Deploy, then go to Settings and toggle on ephemeral environments.

Best Practices for Docker Compose with Bunnyshell

  • No Nginx sidecar needed — Nitro handles both SSR and static asset serving. Keep it as a single container
  • Remove local volumesvolumes: ['.:/app'] is for local dev (hot module replacement). Remove these in Bunnyshell — the Docker image already contains the built app
  • Use Bunnyshell interpolation for dynamic values:
YAML
1# Local docker-compose.yml
2NUXT_PUBLIC_APP_URL: http://localhost:3000
3
4# Bunnyshell environment config (after import)
5NUXT_PUBLIC_APP_URL: 'https://{{ components.nuxtjs-app.ingress.hosts[0] }}'
  • Runtime config advantage — Unlike Next.js, Nuxt's NUXT_PUBLIC_* variables are resolved at runtime. The same Docker image works across all environments — just update the environment variables in Bunnyshell

Approach C: Helm Charts

For teams with existing Helm infrastructure or complex Kubernetes requirements (custom ingress, service mesh, advanced scaling). Helm gives you full control over every Kubernetes resource.

Step 1: Create a Helm Chart

Structure your Nuxt.js Helm chart in your repo:

Text
1helm/nuxtjs/
2├── Chart.yaml
3├── values.yaml
4└── templates/
5    ├── deployment.yaml
6    ├── service.yaml
7    ├── ingress.yaml
8    ├── configmap.yaml
9    └── migration-job.yaml

A minimal values.yaml:

YAML
1replicaCount: 1
2image:
3  repository: ""
4  tag: latest
5service:
6  port: 3000
7ingress:
8  enabled: true
9  className: bns-nginx
10  host: ""
11env:
12  NODE_ENV: production
13  HOST: "0.0.0.0"
14  PORT: "3000"
15  NITRO_HOST: "0.0.0.0"
16  NITRO_PORT: "3000"
17  NUXT_DATABASE_URL: ""
18  NUXT_REDIS_URL: ""
19  NUXT_AUTH_SECRET: ""
20  NUXT_PUBLIC_API_BASE: "/api"
21  NUXT_PUBLIC_APP_URL: ""

Step 2: Define the Bunnyshell Configuration

Create a bunnyshell.yaml using Helm components:

YAML
1kind: Environment
2name: nuxtjs-helm
3type: primary
4
5environmentVariables:
6  NUXT_AUTH_SECRET: SECRET["your-auth-secret"]
7  DB_PASSWORD: SECRET["your-db-password"]
8  PG_DATABASE: nuxtapp
9  PG_USER: nuxtapp
10
11components:
12  # ── Docker Image Build ──
13  - kind: DockerImage
14    name: nuxtjs-image
15    context: /
16    dockerfile: Dockerfile
17    gitRepo: 'https://github.com/your-org/your-nuxtjs-repo.git'
18    gitBranch: main
19    gitApplicationPath: /
20
21  # ── PostgreSQL via Helm (Bitnami) ──
22  - kind: Helm
23    name: postgres
24    runnerImage: 'dtzar/helm-kubectl:3.8.2'
25    deploy:
26      - |
27        cat << EOF > pg_values.yaml
28          global:
29            storageClass: bns-network-sc
30          auth:
31            postgresPassword: {{ env.vars.DB_PASSWORD }}
32            database: {{ env.vars.PG_DATABASE }}
33            username: {{ env.vars.PG_USER }}
34            password: {{ env.vars.DB_PASSWORD }}
35        EOF
36      - 'helm repo add bitnami https://charts.bitnami.com/bitnami'
37      - 'helm upgrade --install --namespace {{ env.k8s.namespace }}
38        --post-renderer /bns/helpers/helm/bns_post_renderer
39        -f pg_values.yaml postgres bitnami/postgresql --version 13.4.4'
40      - |
41        PG_HOST="postgres-postgresql.{{ env.k8s.namespace }}.svc.cluster.local"
42    destroy:
43      - 'helm uninstall postgres --namespace {{ env.k8s.namespace }}'
44    start:
45      - 'kubectl scale --replicas=1 --namespace {{ env.k8s.namespace }}
46        statefulset/postgres-postgresql'
47    stop:
48      - 'kubectl scale --replicas=0 --namespace {{ env.k8s.namespace }}
49        statefulset/postgres-postgresql'
50    exportVariables:
51      - PG_HOST
52
53  # ── Nuxt.js App via Helm ──
54  - kind: Helm
55    name: nuxtjs-app
56    runnerImage: 'dtzar/helm-kubectl:3.8.2'
57    deploy:
58      - |
59        cat << EOF > nuxtjs_values.yaml
60          replicaCount: 1
61          image:
62            repository: {{ components.nuxtjs-image.image }}
63          service:
64            port: 3000
65          ingress:
66            enabled: true
67            className: bns-nginx
68            host: app-{{ env.base_domain }}
69          env:
70            NODE_ENV: production
71            HOST: '0.0.0.0'
72            PORT: '3000'
73            NITRO_HOST: '0.0.0.0'
74            NITRO_PORT: '3000'
75            NUXT_DATABASE_URL: 'postgresql://{{ env.vars.PG_USER }}:{{ env.vars.DB_PASSWORD }}@{{ components.postgres.exported.PG_HOST }}:5432/{{ env.vars.PG_DATABASE }}'
76            NUXT_REDIS_URL: 'redis://redis:6379'
77            NUXT_AUTH_SECRET: '{{ env.vars.NUXT_AUTH_SECRET }}'
78            NUXT_PUBLIC_API_BASE: '/api'
79            NUXT_PUBLIC_APP_URL: 'https://app-{{ env.base_domain }}'
80        EOF
81      - 'helm upgrade --install --namespace {{ env.k8s.namespace }}
82        --post-renderer /bns/helpers/helm/bns_post_renderer
83        -f nuxtjs_values.yaml nuxtjs-{{ env.unique }} ./helm/nuxtjs'
84    destroy:
85      - 'helm uninstall nuxtjs-{{ env.unique }} --namespace {{ env.k8s.namespace }}'
86    start:
87      - 'helm upgrade --namespace {{ env.k8s.namespace }}
88        --post-renderer /bns/helpers/helm/bns_post_renderer
89        --reuse-values --set replicaCount=1 nuxtjs-{{ env.unique }} ./helm/nuxtjs'
90    stop:
91      - 'helm upgrade --namespace {{ env.k8s.namespace }}
92        --post-renderer /bns/helpers/helm/bns_post_renderer
93        --reuse-values --set replicaCount=0 nuxtjs-{{ env.unique }} ./helm/nuxtjs'
94    gitRepo: 'https://github.com/your-org/your-nuxtjs-repo.git'
95    gitBranch: main
96    gitApplicationPath: /helm/nuxtjs
97
98  # ── Redis ──
99  - kind: Service
100    name: redis
101    dockerCompose:
102      image: 'redis:7-alpine'
103      ports:
104        - '6379:6379'

Always include --post-renderer /bns/helpers/helm/bns_post_renderer in your helm commands. This adds labels so Bunnyshell can track resources, show logs, and manage component lifecycle.

Step 3: Deploy and Enable Preview Environments

Same flow: paste the config in Configuration, hit Deploy, then enable ephemeral environments in Settings.


Enabling Preview Environments (All Approaches)

Regardless of which approach you used, enabling automatic preview environments is the same:

  1. Ensure your primary environment has been deployed at least once (Running or Stopped status)
  2. Go to Settings in your environment
  3. Toggle "Create ephemeral environments on pull request" to ON
  4. Toggle "Destroy environment after merge or close pull request" to ON
  5. Select the target Kubernetes cluster

What happens next:

  • Bunnyshell adds a webhook to your Git provider automatically
  • When a developer opens a PR, Bunnyshell creates an ephemeral environment cloned from the primary, using the PR's branch
  • Bunnyshell posts a comment on the PR with a direct link to the running deployment
  • When the PR is merged or closed, the ephemeral environment is automatically destroyed

No GitHub Actions. No GitLab CI pipelines. No maintenance. It just works.

Optional: CI/CD Integration via CLI

If you prefer to control preview environments from your CI/CD pipeline (e.g., for custom migration or seed scripts), you can use the Bunnyshell CLI:

Bash
1# Install
2brew install bunnyshell/tap/bunnyshell-cli
3
4# Authenticate
5export BUNNYSHELL_TOKEN=your-api-token
6
7# Create, deploy, and run migrations in one flow
8bns environments create --from-path bunnyshell.yaml --name "pr-123" --project PROJECT_ID --k8s CLUSTER_ID
9bns environments deploy --id ENV_ID --wait
10bns exec COMPONENT_ID -c nuxtjs-app -- npx prisma migrate deploy

Remote Development and Debugging

Bunnyshell makes it easy to develop and debug directly against any environment — primary or ephemeral:

Port Forwarding

Connect your local tools to the remote database:

Bash
1# Forward PostgreSQL to local port 15432
2bns port-forward 15432:5432 --component PG_COMPONENT_ID
3
4# Connect with psql, pgAdmin, or any DB tool
5psql -h 127.0.0.1 -p 15432 -U nuxtapp -d nuxtapp
6
7# Forward Redis to local port 16379
8bns port-forward 16379:6379 --component REDIS_COMPONENT_ID
9redis-cli -p 16379

Execute Commands

Bash
1# Run Prisma migrations
2bns exec COMPONENT_ID -c nuxtjs-app -- npx prisma migrate deploy
3
4# Or Drizzle migrations
5bns exec COMPONENT_ID -c nuxtjs-app -- npx drizzle-kit push
6
7# Check migration status
8bns exec COMPONENT_ID -c nuxtjs-app -- npx prisma migrate status
9
10# Seed the database
11bns exec COMPONENT_ID -c nuxtjs-app -- npx prisma db seed
12
13# Check Nitro server info
14bns exec COMPONENT_ID -c nuxtjs-app -- node -e "console.log(require('./.output/nitro.json'))"
15
16# List available server routes
17bns exec COMPONENT_ID -c nuxtjs-app -- ls -la .output/server/chunks/routes/

Live Logs

Bash
1# Stream logs in real time
2bns logs --component COMPONENT_ID -f
3
4# Last 200 lines
5bns logs --component COMPONENT_ID --tail 200
6
7# Logs from the last 5 minutes
8bns logs --component COMPONENT_ID --since 5m

Live Code Sync

For active development, sync your local code changes to the remote container in real time:

Bash
1bns remote-development up --component COMPONENT_ID
2# Edit files locally — changes sync automatically
3# When done:
4bns remote-development down

Since Nuxt's NUXT_PUBLIC_* variables are runtime, you can update them without rebuilding. For code changes to server routes and Vue components, live code sync triggers Nitro to reload automatically.


Troubleshooting

IssueSolution
502 Bad GatewayNitro server not listening. Verify NITRO_HOST=0.0.0.0 and HOST=0.0.0.0 are set — without them, Nitro only binds to 127.0.0.1. Check port 3000 is exposed and matches servicePort in hosts config.
Health check failsMissing /api/health server route. Create server/api/health.get.ts returning a JSON response.
SSR pages show wrong URLCheck NUXT_PUBLIC_APP_URL is set correctly using Bunnyshell interpolation: 'https://{{ components.nuxtjs-app.ingress.hosts[0] }}'
Prisma: "Can't reach database server"Check NUXT_DATABASE_URL uses postgres (the component name) as host, not localhost. Verify PostgreSQL is running before running migrations.
Drizzle migration failsEnsure drizzle-kit is in dependencies (not just devDependencies) or install it in the Dockerfile build stage.
Static assets return 404Nitro serves static assets from .output/public/. Verify the build completed successfully and .output/public/_nuxt/ contains the client bundles.
Server routes return 500Check Nitro logs for the actual error. Common cause: missing environment variables for database connections. Use useRuntimeConfig() and ensure all NUXT_* variables are set.
Hybrid rendering not workingRoute rules defined in nuxt.config.ts are baked at build time. Verify routeRules are correct and the build log shows the expected pre-rendered routes.
WebSocket connections failNitro supports WebSockets via defineWebSocketHandler. Ensure the Kubernetes ingress supports WebSocket upgrades — add annotations: nginx.ingress.kubernetes.io/proxy-read-timeout: "3600".
CORS errors on API routesAdd CORS headers in a Nitro server middleware: create server/middleware/cors.ts using setResponseHeaders.

What's Next?

  • Add database migrations to deploy hooks — Automate npx prisma migrate deploy or npx drizzle-kit push as a post-deploy step
  • Configure hybrid rendering — Use routeRules to pre-render marketing pages while keeping dynamic routes SSR
  • Add S3/MinIO — For file uploads and image storage (minio/minio as a Service component)
  • Add Storybook — Deploy Storybook alongside your Nuxt.js app for component review with @storybook/vue3
  • Monitor with Nitro plugins — Add request tracing and performance monitoring via Nitro server plugins

Ship faster starting today.

14-day full-feature trial. No credit card required. Pay-as-you-go from $0.007/min per environment.