Back to Blog
Tutorial

How to Deploy a SvelteKit Application in 1 Minute

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

SvelteKit is the full-stack framework for Svelte, combining server-side rendering, static generation, and API routes into a single cohesive toolkit. It compiles your components at build time, producing minimal JavaScript that runs faster than virtual-DOM-based frameworks.

With Out Plane, you can deploy your SvelteKit application in under a minute — directly from your GitHub repository. No infrastructure management, no manual configuration. This guide shows you exactly how.

What You'll Need

Before starting, make sure you have:

  • Node.js 20+ installed on your machine
  • npm (included with Node.js)
  • A GitHub account
  • A SvelteKit 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 SvelteKit project:

bash
npx sv create my-sveltekit-app
cd my-sveltekit-app
npm install

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

Quick Start: Sample SvelteKit Application

Here's a minimal SvelteKit application you can use. Create a new project with the skeleton template:

bash
npx sv create my-sveltekit-app

Select the SvelteKit minimal (skeleton) project when prompted. Then install dependencies:

bash
cd my-sveltekit-app
npm install

Install the Node.js adapter for production server-side rendering:

bash
npm install @sveltejs/adapter-node

Update svelte.config.js to use the Node adapter instead of the default auto adapter:

javascript
import adapter from "@sveltejs/adapter-node";

/** @type {import('@sveltejs/kit').Config} */
const config = {
  kit: {
    adapter: adapter(),
  },
};

export default config;

Replace src/routes/+page.svelte with a simple page:

svelte
<main>
  <h1>Hello from SvelteKit!</h1>
  <p>Deployed on Out Plane</p>
</main>

<style>
  main {
    padding: 2rem;
    font-family: system-ui;
  }
</style>

Add a health check API route at src/routes/api/health/+server.ts:

typescript
import { json } from "@sveltejs/kit";

export function GET() {
  return json({ status: "healthy" });
}

Create a Dockerfile in the project root:

dockerfile
FROM node:20-alpine AS base

# Install dependencies
FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci

# Build the application
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

# Production image
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 sveltekit

COPY --from=builder --chown=sveltekit:nodejs /app/build ./build
COPY --from=builder /app/package.json ./

USER sveltekit

EXPOSE 3000
ENV PORT=3000
ENV HOST=0.0.0.0

CMD ["node", "build/index.js"]

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 SvelteKit repository from the list

Out Plane automatically detects your SvelteKit 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 for SvelteKit): Uses the multi-stage Dockerfile above for optimal image size and full SSR support.
  • Buildpacks: Automatically detects Node.js and runs npm run build. Works for simpler SvelteKit applications.

For production SvelteKit applications with server-side rendering, Dockerfile with adapter-node is the recommended approach.

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. SvelteKit uses two types of environment variables:

  • Private (server-only): Accessed via $env/static/private or $env/dynamic/private
  • Public (client-exposed): Prefixed with PUBLIC_ and accessed via $env/static/public or $env/dynamic/public

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

text
DATABASE_URL=postgres://user:password@host/database
API_SECRET=your-api-secret
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 vite build
  3. Deploying → Starting your SvelteKit 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 SvelteKit app in a new tab. SSL is automatically configured.

Production Best Practices

adapter-node vs adapter-static

SvelteKit supports multiple adapters for different deployment targets:

  • adapter-node: Runs a Node.js server with full SSR, API routes, and form actions. Use this for dynamic applications.
  • adapter-static: Pre-renders all pages at build time. Use this for purely static sites with no server-side logic.

For Out Plane deployments, adapter-node is recommended because it supports the full range of SvelteKit features including server-side rendering and API endpoints.

Environment Variables

SvelteKit provides four modules for accessing environment variables:

typescript
// Static (inlined at build time, tree-shakeable)
import { DATABASE_URL } from "$env/static/private";
import { PUBLIC_APP_URL } from "$env/static/public";

// Dynamic (read at runtime, not tree-shakeable)
import { env } from "$env/dynamic/private";
import { env as publicEnv } from "$env/dynamic/public";

Use $env/static/* for values that don't change between deployments. Use $env/dynamic/* for values that may differ per environment without rebuilding.

Form Actions

SvelteKit's form actions run entirely on the server, making them ideal for handling form submissions without client-side JavaScript:

typescript
// src/routes/contact/+page.server.ts
import type { Actions } from "./$types";

export const actions = {
  default: async ({ request }) => {
    const data = await request.formData();
    const email = data.get("email");

    // Process the form submission server-side
    return { success: true };
  },
} satisfies Actions;

Form actions work automatically with adapter-node on Out Plane.

Hooks

SvelteKit hooks let you intercept and modify requests at the server level. Use src/hooks.server.ts for authentication, logging, and request transformation:

typescript
// src/hooks.server.ts
import type { Handle } from "@sveltejs/kit";

export const handle: Handle = async ({ event, resolve }) => {
  const start = Date.now();
  const response = await resolve(event);
  const duration = Date.now() - start;

  console.log(`${event.request.method} ${event.url.pathname} - ${duration}ms`);
  return response;
};

Connecting a Database

Most SvelteKit 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/database

Use it in your SvelteKit application with Drizzle ORM or Prisma:

typescript
// src/lib/server/db.ts (Drizzle example)
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import { env } from "$env/dynamic/private";

const client = postgres(env.DATABASE_URL!);
export const db = drizzle(client);
typescript
// src/lib/server/db.ts (Prisma example)
import { PrismaClient } from "@prisma/client";

const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClient | undefined;
};

export const prisma = globalForPrisma.prisma ?? new PrismaClient();

if (process.env.NODE_ENV !== "production") {
  globalForPrisma.prisma = prisma;
}

Place database modules in src/lib/server/ to ensure they are never imported in client-side code.

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 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 SvelteKit application:

  • Logs: View real-time application logs including server-side rendering 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

Application Won't Start

Check the port configuration. Make sure you set the port to 3000 in the application settings. If using a Dockerfile, ensure EXPOSE 3000 and ENV PORT=3000 are set correctly.

Adapter Issues

Verify you are using adapter-node. The default adapter-auto does not produce a standalone Node.js server. Install @sveltejs/adapter-node and update svelte.config.js:

bash
npm install @sveltejs/adapter-node
javascript
import adapter from "@sveltejs/adapter-node";

Environment Variables Not Available

Check the module import path. Private variables must be accessed from $env/static/private or $env/dynamic/private. Public variables must be prefixed with PUBLIC_ and accessed from $env/static/public or $env/dynamic/public. Importing private env modules in client-side code will cause a build error.

Build Errors

Verify your dependencies are installed. Run npm install locally and commit your package-lock.json. Missing lock files can cause inconsistent builds.

Hydration Mismatches

Ensure server and client render the same content. Hydration errors occur when the server-rendered HTML doesn't match what the client expects. Common causes include using Date.now() or Math.random() directly in components, or accessing browser-only APIs without guards:

svelte
<script>
  import { browser } from "$app/environment";

  let width = 0;

  if (browser) {
    width = window.innerWidth;
  }
</script>

Use $app/environment to check whether code is running in the browser before accessing browser APIs.

Next Steps

Your SvelteKit 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 API response caching

Summary

Deploying a SvelteKit application to Out Plane takes three steps:

  1. Connect your GitHub repository
  2. Configure port (3000), environment variables, 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, API routes, form actions, and static generation.

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


Tags

sveltekit
svelte
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.