Back to Blog
Tutorial

How to Deploy a Nuxt Application in 1 Minute

Daniel Brooks5 min read
How to Deploy a Nuxt Application in 1 Minute

Nuxt is the full-stack framework for Vue.js. It supports server-side rendering, static generation, and hybrid rendering out of the box. Built on the Nitro server engine, Nuxt provides file-based routing, auto-imports, and a powerful server directory for building APIs — all with zero configuration. Deploying a Nuxt application to production typically involves configuring servers, build presets, and SSL certificates.

With Out Plane, you can deploy your Nuxt application in under a minute. This guide shows you exactly how.

What You'll Need

Before starting, make sure you have:

  • Node.js 20+ installed on your machine
  • npm (comes with Node.js)
  • A GitHub account
  • A Nuxt application in a GitHub repository

Don't have Node.js installed? Download it from nodejs.org:

  • Windows: Download the LTS installer from nodejs.org
  • macOS: Use brew install node or download from nodejs.org
  • Linux: Run curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - && sudo apt install -y nodejs (Ubuntu/Debian)

Once Node.js is installed, create a new Nuxt project:

bash
npx nuxi@latest init my-nuxt-app
cd my-nuxt-app

If you don't have a Nuxt app yet, use our example below.

Quick Start: Sample Nuxt Application

Here's a minimal Nuxt application you can use. Create a new project with the Nuxt CLI:

bash
npx nuxi@latest init my-nuxt-app
cd my-nuxt-app
npm install

The CLI generates a project with the essential configuration. Update the following files for a production-ready application.

Replace pages/index.vue with a simple page that fetches data from an API route:

vue
<script setup lang="ts">
const { data } = await useFetch('/api/health')
</script>

<template>
  <main style="padding: 2rem; font-family: system-ui">
    <h1>Hello from Nuxt!</h1>
    <p>Deployed on Out Plane</p>
    <p v-if="data">Server status: {{ data.status }}</p>
  </main>
</template>

Create a Nitro API route at server/api/health.ts:

typescript
export default defineEventHandler(() => {
  return {
    status: 'healthy',
    timestamp: new Date().toISOString(),
  }
})

Nitro auto-registers files in the server/api/ directory as API endpoints. No router configuration needed.

Update nuxt.config.ts — no special configuration is needed for Node.js deployment since Nitro defaults to the node-server preset:

typescript
export default defineNuxtConfig({
  compatibilityDate: '2025-01-01',
  devtools: { enabled: false },
})

Create a Dockerfile in the project root:

dockerfile
# Build stage
FROM node:20-alpine AS builder

WORKDIR /app

COPY package.json package-lock.json* ./
RUN npm ci

COPY . .
RUN npm run build

# Production stage
FROM node:20-alpine

WORKDIR /app

ENV NODE_ENV=production

COPY --from=builder /app/.output ./.output

EXPOSE 3000

ENV NITRO_PORT=3000
ENV NITRO_HOST=0.0.0.0

CMD ["node", ".output/server/index.mjs"]

The Nitro server engine compiles your entire application into a self-contained .output directory. The production image only needs this directory to run — no node_modules required.

Push this code to a GitHub repository, and you're ready to deploy.

Deploy in 3 Steps

Step 1: Connect Your Repository

  1. Go to console.outplane.com
  2. Sign in with your GitHub account
  3. Select your Nuxt repository from the list

Out Plane automatically detects your application and configures the build process.

Step 2: Configure Your Application

Configure the following settings in the create application form:

Build Method

Select how Out Plane should build your application:

  • Dockerfile (Recommended): Uses the multi-stage Dockerfile above for optimal image size. The Nitro output is self-contained, producing very small production images.
  • Buildpacks: Automatically detects Node.js and runs npm run build. Works for simpler Nuxt applications.

For production Nuxt applications, Dockerfile is the recommended approach because it leverages Nitro's self-contained output for minimal image sizes.

Basic Settings

  • Port: Set to 3000
  • Branch: Select main or your preferred branch
  • Region: Choose the region closest to your users

Environment Variables (Optional)

If your application uses environment-specific configuration, add them here. Nuxt uses the NUXT_ prefix for runtime configuration:

  • Runtime config: Variables prefixed with NUXT_ override values in runtimeConfig at runtime
  • Public runtime config: Variables prefixed with NUXT_PUBLIC_ are exposed to the client

Add variables using the Add button or Raw Edit for bulk entry:

text
DATABASE_URL=postgres://user:password@host/database
NUXT_API_SECRET=your-api-secret
NUXT_PUBLIC_APP_URL=https://your-app.outplane.app

Step 3: Deploy

Click Deploy Application and watch the build process:

  1. Queued → Waiting for resources
  2. Building → Installing dependencies, running nuxt build
  3. Deploying → Starting your Nuxt application
  4. Ready → Your app is live

Once the status shows Ready, your application is live. You can find your application URL at the top of the deployment page. Click the URL to open your Nuxt app in a new tab. SSL is automatically configured.

Production Best Practices

Runtime Config vs App Config

Nuxt provides two ways to configure your application. Use runtime config for values that change between environments, and app config for values set at build time:

typescript
// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    // Server-only (overridden by NUXT_API_SECRET env var)
    apiSecret: '',
    // Public (overridden by NUXT_PUBLIC_API_BASE env var)
    public: {
      apiBase: '/api',
    },
  },
})

Access runtime config in your application:

vue
<script setup lang="ts">
const config = useRuntimeConfig()
// Client: config.public.apiBase
// Server: config.apiSecret
</script>

Nitro Presets

Nitro defaults to the node-server preset, which is ideal for container deployments. If you need a different output format, set the preset in nuxt.config.ts:

typescript
export default defineNuxtConfig({
  nitro: {
    preset: 'node-server', // Default, best for Docker
  },
})

Do not change this preset unless you have a specific reason. The node-server preset works best with Out Plane.

Auto-Imports and Composables

Nuxt auto-imports Vue composables, utility functions, and your own composables from the composables/ directory. This means you don't need explicit import statements:

vue
<script setup lang="ts">
// useState, useFetch, useRuntimeConfig are auto-imported
const count = useState('counter', () => 0)
const { data } = await useFetch('/api/items')
const config = useRuntimeConfig()
</script>

Custom composables in composables/ are also auto-imported:

typescript
// composables/useApi.ts
export const useApi = () => {
  const config = useRuntimeConfig()

  const fetch = async (path: string) => {
    return await $fetch(`${config.public.apiBase}${path}`)
  }

  return { fetch }
}

Server Middleware

Use Nitro server middleware for request processing that runs before your API routes:

typescript
// server/middleware/log.ts
export default defineEventHandler((event) => {
  console.log(`${event.method} ${getRequestURL(event)}`)
})

Middleware files in server/middleware/ run automatically on every request. Use them for logging, authentication, or request transformation.

Connecting a Database

Most Nuxt applications need a database. Out Plane provides managed PostgreSQL:

  1. Go to Databases in the sidebar
  2. Click Create Database
  3. Select PostgreSQL version and region
  4. Copy the connection URL

Add the connection URL as an environment variable:

text
DATABASE_URL=postgres://user:password@host:5432/database

Use it in your Nuxt application with Drizzle ORM in the server/ directory:

bash
npm install drizzle-orm postgres
npm install -D drizzle-kit

Define your schema:

typescript
// server/database/schema.ts
import { pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core'

export const items = pgTable('items', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
  createdAt: timestamp('created_at').defaultNow(),
})

Create a database utility:

typescript
// server/utils/db.ts
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'

const client = postgres(process.env.DATABASE_URL!)

export const db = drizzle(client)

Create an API route that fetches from the database:

typescript
// server/api/items.ts
import { db } from '../utils/db'
import { items } from '../database/schema'

export default defineEventHandler(async () => {
  const allItems = await db.select().from(items).limit(50)
  return allItems
})

Files in server/utils/ are auto-imported in your server routes, so db is available without explicit imports.

Custom Domain Setup

Replace the default .outplane.app URL with your own domain:

  1. Navigate to Domains
  2. Click Map Domain
  3. Enter your domain (e.g., app.yourdomain.com)
  4. Add the DNS records shown to your domain registrar

Update your NUXT_PUBLIC_APP_URL environment variable to reflect the new domain. SSL certificates are automatically provisioned once DNS propagates.

Monitoring Your Application

After deployment, monitor your Nuxt application:

  • Logs: View real-time application logs including server-side rendering logs and Nitro request logs
  • Metrics: Track CPU, memory, and network usage
  • HTTP Logs: Analyze incoming requests, response times, and status codes

Access these from the sidebar in your application dashboard.

Troubleshooting

Nitro Preset Issues

Verify the correct preset is configured. For Docker deployments on Out Plane, use the default node-server preset. If you previously set a different preset (like vercel or netlify), remove it or change it to node-server:

typescript
export default defineNuxtConfig({
  nitro: {
    preset: 'node-server',
  },
})

Runtime Config Not Available

Use the NUXT_ prefix for environment variables. Nuxt maps environment variables to runtime config using the NUXT_ prefix. For nested values, use double underscores:

text
# Maps to runtimeConfig.apiSecret
NUXT_API_SECRET=your-secret

# Maps to runtimeConfig.public.apiBase
NUXT_PUBLIC_API_BASE=https://api.example.com

# Maps to runtimeConfig.database.host
NUXT_DATABASE_HOST=localhost

If runtime config values are still empty, verify that you defined them in nuxt.config.ts first. Environment variables only override existing keys.

Build Errors

Run npm run build locally before deploying. Common build failures include missing dependencies, TypeScript errors, and invalid imports. Check your application logs for specific error messages.

If the build fails with memory errors, set NODE_OPTIONS in your environment:

text
NODE_OPTIONS=--max-old-space-size=4096

Hydration Mismatches

Ensure server and client render the same content. Hydration errors occur when the HTML rendered on the server doesn't match what the client expects. Common causes:

  • Using Date.now() or random values without useState
  • Accessing window or document during SSR
  • Conditional rendering based on client-only state

Use the <ClientOnly> component for client-specific content:

vue
<template>
  <ClientOnly>
    <BrowserOnlyComponent />
  </ClientOnly>
</template>

API Route 404s

Verify the file path matches the expected URL. Nitro maps files in server/api/ to URLs automatically:

  • server/api/health.ts/api/health
  • server/api/items/index.ts/api/items
  • server/api/items/[id].ts/api/items/:id

Make sure the file is in the correct directory and uses the right naming convention. Restart the dev server after adding new API routes.

Next Steps

Your Nuxt application is now deployed and running in production. Here's what to explore next:

  • Scale your application: Adjust instance types and auto-scaling settings for higher traffic
  • Set up CI/CD: Enable automatic deployments on every git push
  • Add monitoring: Integrate with external monitoring tools via Out Plane's metrics export
  • Configure caching: Add Redis for session storage and Nitro route caching

Summary

Deploying a Nuxt application to Out Plane takes three steps:

  1. Connect your GitHub repository
  2. Configure port (3000), environment variables with NUXT_ prefix, and build method
  3. Deploy and get your live URL with automatic HTTPS

No server configuration, no manual SSL setup, no infrastructure management. Full support for server-side rendering, Nitro API routes, and hybrid rendering.

Ready to deploy your Nuxt application? Get started with Out Plane and receive $20 in free credit.


Tags

nuxt
vuejs
deployment
tutorial
javascript
typescript

Start deploying in minutes

Connect your GitHub repository and deploy your first application today. $20 free credit. No credit card required.