Skip to content

Configuration

Create a pareto.config.ts in your project root to customize Pareto’s behavior.

pareto.config.ts
import type { ParetoConfig } from '@paretojs/core'
const config: ParetoConfig = {
// options
}
export default config
interface ParetoConfig {
appDir?: string
outDir?: string
wkWebViewFlushHint?: boolean
}

The directory containing your route files. Defaults to app.

The output directory for production builds. Defaults to .pareto.

Inject a hidden element with 200+ zero-width characters into the HTML shell to force iOS WKWebView to begin rendering before the stream completes. WebKit delays first paint until visible text exceeds 200 characters, which can cause a white flash for minimal-text pages loaded inside native iOS apps. Has no visual effect and is ignored by screen readers. Only relevant for WKWebView — Safari and Chrome browsers are not affected. Defaults to false.

Pareto uses Vite natively. To customize Vite, create a standard vite.config.ts in your project root — Pareto loads and merges it automatically in both dev and build modes.

vite.config.ts
import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'
export default defineConfig({
plugins: [tsconfigPaths()],
resolve: {
alias: { '@': '/src' },
},
ssr: {
noExternal: ['some-esm-only-pkg'],
external: ['heavy-library'],
},
})

To apply config conditionally for client vs server builds, use Vite’s native isSsrBuild flag:

export default defineConfig(({ isSsrBuild, command }) => ({
plugins: [
// Client-only plugin
!isSsrBuild && clientOnlyPlugin(),
].filter(Boolean),
}))

Use cases:

  • Adding Vite plugins (Tailwind, SVG imports, tsconfig-paths, etc.)
  • Configuring SSR externals for Node.js-only packages
  • Adding path aliases (resolve.alias)
  • Modifying the dev server proxy settings

See the Vite config reference for all available options.

Pareto uses Vite’s built-in environment variable handling. Variables prefixed with VITE_ are exposed to client-side code:

.env
VITE_API_URL=https://api.example.com # Available on client and server
DATABASE_URL=postgres://localhost/mydb # Server only

Access them in your code:

// Client and server
const apiUrl = import.meta.env.VITE_API_URL
// Server only (loaders, resource routes)
const dbUrl = process.env.DATABASE_URL

Vite supports .env, .env.local, .env.development, and .env.production files. See the Vite env docs for the full loading order.

Terminal window
pareto dev # Start dev server with HMR
pareto build # Build for production
pareto start # Start production server
Terminal window
pareto dev --port 8080 # Custom port (default: 3000)
pareto dev --host 0.0.0.0 # Expose to network
Terminal window
pareto build # Build for production
Terminal window
pareto start # Start production server (default port: 3000)
pareto start --port 8080 # Custom port

The default port is 3000. You can change it in three ways, listed by priority (highest first):

  1. CLI flag: pareto dev --port 8080
  2. Environment variable: PORT=8080 pareto dev
  3. Default: 3000

For production deployments, build first, then start:

Terminal window
npm run build # Runs pareto build
npm run start # Runs pareto start

The build step outputs (inside the configured outDir, default .pareto):

  • .pareto/client/ — Static assets (JS, CSS, images) for CDN deployment
  • .pareto/server/ — Server bundle for the Node.js runtime

A minimal production Dockerfile:

FROM node:20-alpine
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile --prod
COPY .pareto/ .pareto/
EXPOSE 3000
CMD ["npx", "pareto", "start"]