Skip to main content

Configuration

evjs is zero-config by default. Optionally create ev.config.ts in the project root to override defaults. The defineConfig helper provides full type-safety.

import { defineConfig } from "@evjs/cli";
export default defineConfig({ /* ... */ });

Defaults

All fields are optional. These are the built-in defaults:

SettingDefault
entry./src/main.tsx
html./index.html
dev.port3000
server.runtime"node"
server.dev.port3001
server.endpoint/api/fn

Full Reference

import { defineConfig } from "@evjs/cli";

export default defineConfig({
// ── Entry & HTML ──
entry: "./src/main.tsx",
html: "./index.html",

// ── Client dev server ──
dev: {
port: 3000,
https: false,
},

// ── Server (optional) ──
// Set to `false` for CSR-only apps (flat dist/ output, no server bundle)
// server: false,
server: {
entry: "./src/server.ts", // Explicit server entry (optional)
runtime: "node", // "node" | "bun" | "deno run --allow-net"
endpoint: "/api/fn", // Server function RPC endpoint

dev: {
port: 3001,
https: false,
},
},
});

Client Options

entry

Path to the client entry point. Must export the createApp() call.

html

Path to the HTML template. Must contain a mount element (e.g. <div id="app">).

dev

OptionTypeDefaultDescription
portnumber3000Webpack Dev Server port
httpsboolean | { key: string; cert: string }falseEnable HTTPS. Pass true for auto-certs or an object with explicit key/cert.

Server Options

The server field accepts an object for fullstack apps, or false to disable the server entirely (CSR-only mode).

// CSR-only: flat dist/ output, no server bundle
export default defineConfig({ server: false });

When server: false:

  • Build output goes to dist/ instead of dist/client/ + dist/server/
  • Any "use server" module causes a build error
  • No API proxy is configured in dev mode

server.entry

Explicit server entry file. If provided, overrides the auto-generated entry. Use this when you need to mount custom route handlers.

server.runtime

The runtime command used to start the server:

ValueBehavior
"node" (default)Uses --watch for auto-restart in dev
"bun"Passes args as-is
"deno run --allow-net"Split on whitespace, extra args forwarded
warning

The ECMA adapter (@evjs/server/ecma) only exports a { fetch } handler — it does not start a listening server. For ev dev, always use "node" as the runtime. Use ECMA adapters only for production targets like Deno or Bun.

server.endpoint

OptionTypeDefaultDescription
endpointstring/api/fnPath for server function RPC calls

server.dev

OptionTypeDefaultDescription
portnumber3001API server port in dev mode
https{ key: string; cert: string } | falsefalseEnable HTTPS for the API server. Must provide explicit key/cert.

Plugins

Plugins use a setup() function that receives the resolved config and returns lifecycle hooks:

setup(ctx)

Initialize the plugin and return lifecycle hooks. The context provides mode ("development" | "production") and the fully resolved config.

{
name: "my-plugin",
setup(ctx) {
return {
buildStart() { /* before compilation */ },
bundler(config) { /* modify bundler config */ },
buildEnd(result) { /* after compilation, receives manifests */ },
};
},
}

Lifecycle Hooks

HookSignatureWhen
buildStart() => voidBefore compilation begins
bundler(config: unknown, ctx: EvBundlerCtx) => voidDuring bundler config creation
buildEnd(result: EvBuildResult) => voidAfter compilation (every recompile in dev)

Type-Safe Bundler Config

Use the webpack() helper from @evjs/bundler-webpack for full type safety:

import { webpack } from "@evjs/bundler-webpack";

{
name: "mdx-support",
setup() {
return {
bundler: webpack((config) => {
config.module?.rules?.push({
test: /\.mdx$/,
use: ["mdx-loader"],
});
}),
};
},
}

Context types:

  • EvPluginContext: { mode: "development" | "production", config: ResolvedEvConfig }
  • EvBundlerCtx: { mode: "development" | "production", config: ResolvedEvConfig }
  • EvBuildResult: { clientManifest: ClientManifest, serverManifest?: ServerManifest, isRebuild: boolean }

Bundler Options

The bundler field selects the compilation engine.

OptionTypeDefaultDescription
name"webpack""webpack"The active bundler adapter. Future: "utoopack" (planned)

Built-in Support: CSS & Tailwind

evjs includes built-in PostCSS/Tailwind support. If a postcss.config.js file is detected in the project root, the internal Webpack adapter automatically enables postcss-loader. No plugin or custom hook is required for standard Tailwind setups.

Complete Example

This example demonstrates a production-ready setup with custom loaders and build analytics.

import { defineConfig } from "@evjs/cli";
import { webpack } from "@evjs/bundler-webpack";

export default defineConfig({
entry: "./src/entry-client.tsx",
server: {
entry: "./src/entry-server.ts",
endpoint: "/api/rpc",
dev: { port: 4001 },
},

dev: { port: 4000 },

plugins: [
{
name: "mdx-support",
setup() {
return {
bundler: webpack((config) => {
config.module?.rules?.push({
test: /\.mdx$/,
use: ["mdx-loader"],
});
}),
};
},
},
{
name: "build-timer",
setup(ctx) {
const t0 = Date.now();
return {
buildStart() {
console.log(`Building (${ctx.mode})...`);
},
buildEnd(result) {
console.log(`Done in ${Date.now() - t0}ms`);
console.log(`Assets: ${result.clientManifest.assets.js.length} JS`);
},
};
},
},
],
});