Deployment

Catmint uses an adapter system to deploy your application to different platforms. Adapters transform the build output into the format required by your target environment. This guide covers the built-in adapters, the build workflow, and static deployment for frontend-only applications.

Build Workflow

The deployment process has two steps: build and start.

# Build the application
pnpm catmint build

# Start the production server
pnpm catmint start

catmint build compiles your application using Vite, producing optimized server and client bundles. The adapter then transforms these bundles into the platform-specific format. catmint start runs the built application using the configured adapter.

Adapter System

Adapters are configured in catmint.config.ts via the adapter property. Each adapter is a function that returns an object implementing the CatmintAdapter interface.

// CatmintAdapter interface
interface CatmintAdapter {
  name: string
  buildEnd?(options: {
    outputDir: string
    clientDir: string
    serverDir: string
  }): Promise<void>
  startServer?(options: {
    outputDir: string
    port: number
  }): Promise<void>
}

The buildEnd hook runs after the Vite build completes and transforms the output. The startServer hook is called by catmint start to run the production server.

Node.js Adapter

The @catmint/adapter-node package builds your application as a standalone Node.js server. This is the most flexible adapter and works anywhere Node.js runs.

pnpm add -D @catmint/adapter-node
// catmint.config.ts
import { defineConfig } from 'catmint/config'
import node from '@catmint/adapter-node'

export default defineConfig({
  mode: 'fullstack',
  adapter: node({
    port: 3000,
    host: '0.0.0.0',
  }),
})

Configuration Options

OptionDefaultDescription
port3000Port the server listens on. Can be overridden by the PORT env var.
host'0.0.0.0'Host the server binds to

Docker Deployment

The Node.js adapter works well with Docker. Here is a multi-stage Dockerfile that builds and serves the application:

# Dockerfile
FROM node:20-alpine AS base
RUN corepack enable

# Install dependencies
FROM base AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

# Build the application
FROM base AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN pnpm catmint build

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

COPY --from=deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY package.json ./

EXPOSE 3000
CMD ["pnpm", "catmint", "start"]
# Build and run
docker build -t my-catmint-app .
docker run -p 3000:3000 my-catmint-app

Vercel Adapter

The @catmint/adapter-vercel package transforms the build output into Vercel's Build Output API v3 format for seamless deployment on the Vercel platform.

pnpm add -D @catmint/adapter-vercel
// catmint.config.ts
import { defineConfig } from 'catmint/config'
import vercel from '@catmint/adapter-vercel'

export default defineConfig({
  mode: 'fullstack',
  adapter: vercel(),
})

Configuration Options

OptionDefaultDescription
runtime'nodejs20.x'Vercel serverless function runtime
regions['iad1']Deployment regions for serverless functions
splitfalseSplit routes into individual serverless functions

Deploy by connecting your Git repository to Vercel or using the CLI:

# Deploy with Vercel CLI
pnpm catmint build
npx vercel deploy --prebuilt

Cloudflare Adapter

The @catmint/adapter-cloudflare package builds your application for Cloudflare Workers, enabling edge deployment with low latency worldwide.

pnpm add -D @catmint/adapter-cloudflare
// catmint.config.ts
import { defineConfig } from 'catmint/config'
import cloudflare from '@catmint/adapter-cloudflare'

export default defineConfig({
  mode: 'fullstack',
  adapter: cloudflare(),
})

Configuration Options

OptionDefaultDescription
routesautoRoute configuration for the Workers router
compatibilityDateBuild dateCloudflare Workers compatibility date

Deploy with Wrangler:

pnpm catmint build
npx wrangler deploy

The Cloudflare Workers runtime has limitations compared to Node.js. Some Node.js APIs are not available. Ensure your database driver and dependencies are edge-compatible.

Static Deployment (Frontend Mode)

Applications using mode: 'frontend' produce a static site with no server component. No adapter is needed. The build output is a directory of HTML, CSS, and JavaScript files that can be deployed to any static hosting provider.

// catmint.config.ts
import { defineConfig } from 'catmint/config'

export default defineConfig({
  mode: 'frontend',
  // No adapter needed for static sites
})
pnpm catmint build
# Output is in dist/ -- deploy this directory

Static output can be deployed to:

  • Cloudflare Pages
  • Netlify
  • Vercel (static mode)
  • GitHub Pages
  • AWS S3 + CloudFront
  • Any web server or CDN

Environment Variables

Environment variables are handled differently depending on the platform:

PlatformConfiguration
Node.js.env files or system environment variables
VercelVercel dashboard or vercel env CLI
Cloudflarewrangler.toml or Cloudflare dashboard
Dockerdocker run -e flags or Docker Compose

Remember that env.private variables are only available on the server. Only variables accessed via env.public (prefixed with PUBLIC_) are embedded in the client bundle at build time.

Adapter Comparison

AdapterPackageRuntimeUse Case
Node.js@catmint/adapter-nodeNode.jsSelf-hosted, Docker, VMs, any Node.js environment
Vercel@catmint/adapter-vercelServerlessVercel platform with automatic scaling
Cloudflare@catmint/adapter-cloudflareEdgeGlobal edge deployment with low latency
None (static)--NoneFrontend-only apps, static hosting

Writing a Custom Adapter

You can create a custom adapter by implementing the CatmintAdapter interface. This is useful for deploying to platforms not covered by the built-in adapters.

// my-adapter.ts
import type { CatmintAdapter } from 'catmint/adapter'

export default function myAdapter(): CatmintAdapter {
  return {
    name: 'my-adapter',
    async buildEnd({ outputDir, clientDir, serverDir }) {
      // Transform the build output for your platform
      // - outputDir: the root build output directory
      // - clientDir: static client assets
      // - serverDir: server bundle
    },
    async startServer({ outputDir, port }) {
      // Start the production server
    },
  }
}
// catmint.config.ts
import { defineConfig } from 'catmint/config'
import myAdapter from './my-adapter'

export default defineConfig({
  mode: 'fullstack',
  adapter: myAdapter(),
})