meeko start
Starts the Node production server using meeko build output, without Vite or application sources.
meeko start imports .meeko/output/node/index.mjs, the server written by meeko build with the node adapter, and starts it: SSR, API, RPC, Socket, files from client/ and pages from prerender/, with sessions, graceful shutdown and, since 1.7, the CSP and headers from server. It does not compile anything or read app/, server/ or meeko.config.ts: it serves the build as written.
It is the same as node .meeko/output/node/index.mjs; the CLI only adds reading the project's .env and a clear message if the build is missing.
Usage#
meeko build
meeko starthttp://localhost:4173The starter declares it as "start": "meeko start .", so npm start is enough on the server.
Type#
meeko start [directorio]Options#
| Option | Type | Default | Description |
|---|---|---|---|
[directorio] |
path | . |
Project root, containing .meeko/output/node/ and .env. |
MEEKO_PORT (or PORT) |
number | the build's server.port, or 4173 |
HTTP port. PORT always works because many platforms inject it. |
MEEKO_HOST |
string | the build's server.host, or 127.0.0.1 |
Address. Use 0.0.0.0 to accept traffic from other machines (a container, for example). |
MEEKO_PUBLIC_ORIGIN |
origin | none | Public HTTPS origin behind a proxy, for HTTP and Socket Origin checks. |
MEEKO_REDIS_URL |
URL | none | Session Redis if server/runtime.ts does not declare sessions. Requires the redis package installed. |
MEEKO_SESSION_TTL, MEEKO_SESSION_SAMESITE |
string | 7d, Lax |
Lifetime and SameSite of default sessions. |
MEEKO_TRUST_PROXY |
number, true or cloudflare |
none | Trusted proxies for X-Forwarded-For (rate limiting, clientAddress). Since 1.8, cloudflare reads CF-Connecting-IP behind Cloudflare Tunnel. |
MEEKO_TRUSTED_PROXIES |
comma-separated CIDR or IP | loopback and private networks | Since 1.8, with MEEKO_TRUST_PROXY=cloudflare: networks for cloudflared and proxies, the only ones whose CF-Connecting-IP is read. |
start accepts no flags or additional arguments: meeko start . extra exits with Argumento de más para start: extra.
Result#
- On stdout, the URL to open, such as
http://localhost:4173: since1.7.1, loopback (127.0.0.1,::1) and all interfaces (0.0.0.0,::) display aslocalhost, although the server listens on the configured address. With0.0.0.0or::, linesRed: http://<IP>:4173follow with network addresses. The first line is always the local URL alone, for scripts that read it. - The process keeps running until
SIGINTorSIGTERM, which close Socket, HTTP,waitUntiltasks and the runtime, in that order. Open responses haveshutdownTimeoutmilliseconds (10,000 by default) to finish. - Responses carry assets with
ETag(andimmutablefor hashed ones), prerendered pages from their files and, since1.7,Content-Security-Policyandserver.headersheaders. They are not compressed: see the next example.
Examples#
Behind an HTTPS proxy#
MEEKO_HOST=127.0.0.1 MEEKO_PORT=3000 \
MEEKO_PUBLIC_ORIGIN=https://tienda.example.com \
MEEKO_REDIS_URL=rediss://user:[email protected]:6380 \
MEEKO_TRUST_PROXY=1 \
meeko startThe proxy (nginx, Caddy) terminates TLS and forwards to 127.0.0.1:3000. Without MEEKO_PUBLIC_ORIGIN, mutations arriving with Origin: https://tienda.example.com are rejected.
meeko start does not compress: in production, that proxy or a CDN must do it. See Build, deployment and verification.
In a container#
FROM node:24-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY .meeko/output/node ./.meeko/output/node
ENV MEEKO_HOST=0.0.0.0
CMD ["npx", "meeko", "start"]Only the build folder and production dependencies are needed, including @meekojs/meeko (and redis if you use it). Without MEEKO_HOST=0.0.0.0, the server listens on the container's 127.0.0.1 and is inaccessible from outside.
A custom host using build output#
// server.mjs
import { createNodeApp } from "./.meeko/output/node/index.mjs";
import { serveNode } from "@meekojs/meeko/node";
const app = await createNodeApp();
const server = await serveNode(app, { host: "0.0.0.0", port: 8080, handleSignals: true });
console.log(server.url);index.mjs exports start(), called by meeko start, and createNodeApp(), for those needing their own HTTP server.
Persistent sessions declared in the runtime#
// server/runtime.ts
import { createClient } from "redis";
import { defineServerRuntime, RedisSessionStore, SessionManager } from "@meekojs/meeko/server";
export default defineServerRuntime(async ({ env, production, prerendering }) => {
const redis = createClient({ url: env.REDIS_URL });
await redis.connect();
return {
sessions: new SessionManager({ store: new RedisSessionStore(redis, { prefix: "tienda:prod:session:" }), production: production && !prerendering }),
close: async () => { await redis.quit(); },
};
});With sessions in the runtime, MEEKO_REDIS_URL is no longer read: the runtime decides.
Common mistakes#
Running it without meeko build#
meeko startNo hay build de producción en C:\proyectos\tienda\.meeko\output\node\index.mjs; ejecuta meeko build.meeko/ is not versioned: on a new deployment, or after meeko clean, there is no build. Building with another adapter (--adapter bun) does not write .meeko/output/node/ either.
meeko build && meeko startProduction without persistent sessions#
The starter does not need server/runtime.ts in development because sessions live in memory. In production, meeko start refuses to start with memory:
meeko startProduction requires a persistent session store: set MEEKO_REDIS_URL (with the redis package installed), or return { sessions } with a persistent SessionStore from server/runtime.tsThe process exits with code 1 before listening.
MEEKO_REDIS_URL=redis://127.0.0.1:6379 meeko startOr declare sessions in server/runtime.ts with RedisSessionStore, SqlSessionStore or another persistent store.
Using it with the static adapter#
# server: { adapter: "static" } in meeko.config.ts
meeko build && meeko startmeeko start sirve el build de Node; el adaptador static genera archivos para un hosting estático: usa meeko preview.
meeko build && meeko previewThe path of another directory#
# from the monorepo root
meeko startstart looks for the build in ./.meeko/output/node/index.mjs under the given directory and responds with No hay build de producción en C:\monorepo\.meeko\output\node\index.mjs; ejecuta meeko build, even if the application build exists elsewhere.
meeko start apps/tiendaNotes#
- No TypeScript or Vite. The Node build does not load them at runtime; it needs Node 24 and
node_moduleswith@meekojs/meeko. To avoid depending onnode_modules, build with--adapter bunor--adapter deno. - Startup variables.
MEEKO_HOST,MEEKO_PORTandMEEKO_PUBLIC_ORIGINare read on startup, so the same build works for multiple environments.HOSTandPUBLIC_ORIGINremain supported until2.0, with a one-time warning. .env.meeko startreads the directory's.env, likedev;node .meeko/output/node/index.mjsdoes not. In production, prefer the actual environment or the platform's secret manager; the environment always takes precedence over.env.- Security. Put the server behind an HTTPS proxy and set
MEEKO_PUBLIC_ORIGIN. Pages carry the CSP fromserver.contentSecurityPolicysince1.7; before1.7, only thestaticadapter applied it. - Windows and POSIX. On Windows,
Ctrl+CsendsSIGINT, and shutdown is graceful; a service manager that kills the process is not graceful. On POSIX,SIGTERM(fromdocker stopand systemd) shuts down gracefully. - Performance. Prerendered pages are read from disk once and served from memory with their
ETagand304; hashed assets carrycache-control: public, max-age=31536000, immutable.