#!/usr/bin/env node /** * Production startup wrapper for `next start` when `output: "standalone"` * is set in next.config.ts. Loads .env from a known absolute location, * then exec's the standalone server with the loaded env. * * Why this exists: * 1. `next start` against a standalone build is unsupported by Next.js — * it prints "next start does not work with output: standalone * configuration. Use `node .next/standalone/server.js` instead" — and * silently disables the image optimizer (every `/_next/image?url=...` * returned "url parameter is not allowed"), which is why all the * WP-imported brand imagery never rendered. See commit 129c9d2. * * 2. bash's `set -a; . ./.env` truncates DATABASE_URL at the `&` in * `&channel_binding=require`, so the server boots with empty DB env * and the public storefront falls back to dark gradient backgrounds. * A small Node loader sidesteps the bash word-splitting. * * 3. The standalone server reads `.next/static/` relative to itself, so * the deploy workflow must `cp -r .next/static .next/standalone/.next/static` * after every sync. * * Usage: * PORT=3100 HOSTNAME=0.0.0.0 \ * NODE_BIN=/home/tyler/.cache/act/tool_cache/node/22.22.3/x64/bin/node \ * node /home/tyler/route-commerce/scripts/start-standalone.cjs * * pm2 typically overrides interpreter with its own node and sets `cwd` * arbitrarily, so we resolve the project root from the script's own path * instead of `process.cwd()`. */ const fs = require("fs"); const path = require("path"); const APP_DIR = path.resolve(__dirname, ".."); const ENV_PATH = process.env.ENV_FILE || path.join(APP_DIR, ".env"); const STANDALONE = path.join(APP_DIR, ".next", "standalone", "server.js"); if (!fs.existsSync(STANDALONE)) { console.error(`[start-standalone] Missing standalone server at ${STANDALONE}`); process.exit(1); } if (fs.existsSync(ENV_PATH)) { for (const line of fs.readFileSync(ENV_PATH, "utf8").split("\n")) { const m = line.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/); if (m && !process.env[m[1]]) process.env[m[1]] = m[2]; } console.log(`[start-standalone] loaded env from ${ENV_PATH}`); } else { console.warn(`[start-standalone] no .env at ${ENV_PATH}; relying on existing env`); } // Hand off to the standalone server. Re-exec keeps the process title at // `next-server` (next-start.sh sets it) and matches `node .next/standalone/server.js`. const { spawn } = require("child_process"); const child = spawn(process.execPath, [STANDALONE], { stdio: "inherit", env: process.env }); child.on("exit", (code) => process.exit(code ?? 0)); for (const sig of ["SIGINT", "SIGTERM"]) { process.on(sig, () => child.kill(sig)); }