How we pick the install tool
We pick it from your code, and the first match wins:
- The
packageManagerfield inpackage.json, such as[email protected]. - A lockfile, in this order:
pnpm-lock.yaml, thenbun.lockorbun.lockb, thenyarn.lock. - A
.yarnrc.ymlfile, which means Yarn 2 or later. engines.pnpm,engines.bunorengines.yarninpackage.json.- Otherwise npm, with
package-lock.jsonornpm-shrinkwrap.jsonwhen one is there.
This is the install command for each tool, with a lockfile, then without one:
- npm:
npm ci, ornpm install. - pnpm:
corepack pnpm install --frozen-lockfile, orcorepack pnpm install. - Yarn 1:
corepack yarn install --frozen-lockfile, orcorepack yarn install. - Yarn 2 or later:
corepack yarn install --immutable, orcorepack yarn install --no-immutable. - Bun:
bun install --frozen-lockfile, orbun install.
Corepack runs pnpm and Yarn at the version your packageManager field names. Always ship the lockfile: without it, a deployment can install library versions you never tested.
We only install again when the install command, the Node version, package.json or the lockfile changes. Otherwise the console shows dependencies are up to date (npm).
The build
When package.json has a build script, we run it after the install with the same tool, such as npm run build, on every deployment, and skip it on a plain restart. The console shows building: npm run build, then build finished. A failed build stops the deployment at stage build. For a different build command, set the build field in serverk.json.
The pre-deploy command
The pre-deploy command runs once per deployment, after the install and the build and before your bot starts. It's the place for your database migrations. We run it in your code's folder with your bot's own variables and node_modules/.bin on the path, so a command such as prisma migrate deploy works as is. A plain restart skips it, and when a deployment fails, the next start of that same deployment runs it again.
The first match wins:
- The pre-deploy command in your bot's settings.
- The
preDeployfield inserverk.json. prisma migrate deploy, when your code hasprisma/migrations/migration_lock.toml. Keepprismain the dependencies ofpackage.json.
The console shows running the pre-deploy command: prisma migrate deploy, then pre-deploy command finished. A failed command stops the deployment at stage pre-deploy, and your bot doesn't start.
A command you run from the console
The pre-deploy command runs on every deployment, so keep your migrations there. For a task you run once by hand, type its command in the console instead, such as:
npx prisma db seedto fill your database with its starting data.node scripts/backfill.jsto run one of your own scripts once.npm ls discord.jsto see which version of a library is installed.
We run it the way we run your bot: in your code's folder, as the same user your bot runs as, with your bot's variables and node_modules/.bin on the path. It works even while your bot is stopped or has crashed. Its output prints in the console, then serverk: command finished, or serverk: command failed (exit 1), where the number is the command's exit code. The next deployment puts back every file your code carries, so a lasting change, such as a new library, belongs in your code.
One command runs at a time, for 10 minutes at most, and its output stops at 256 KiB. A command can't read input, so one that asks a question ends at once: add its flag that skips the questions, such as --yes. Before your bot's first deployment, the console answers serverk: deploy the bot first.
TypeScript
- With a build:
"build": "tsc"and"start": "node dist/index.js".typescriptcan stay indevDependencies, because we install those too. Don't addNODE_ENV=productionto your variables: with it, npm skipsdevDependenciesand the build can't findtsc. - Without a build: when
index.tssits at the top of your code and no start file comes before it, we start it withnode index.ts, and Node strips the types and runs the file. If your code needs a build before it runs, add abuildscript. - With
tsxin your dependencies, astartscript such astsx src/index.tsworks, becausenode_modules/.binis on the path.
How we start your bot
The first match wins:
- The start command in your bot's settings.
- The
startfield inserverk.json. - The
worker:orbot:line of aProcfile. - The
startscript inpackage.json. - The file named in
maininpackage.json, withnode. index.js, thensrc/index.js,bot.js,src/bot.jsandindex.ts, withnode.
We run the start script's command directly, not through npm start, so a prestart script doesn't run. Put that step in build instead, or in the pre-deploy command when it runs database migrations.
Node version
Your bot runs on Node 24, the version in our runtime. We read engines.node, .nvmrc, .node-version and .tool-versions. When they ask for another version, we warn you on "Run your bot", print a line such as the code asks for Node 18, this runtime is Node 24 in the console, and run your bot on Node 24.
Bun and what else the runtime has
Bun is in the runtime too: with bun.lock we install with bun install --frozen-lockfile, and a start script such as bun run src/index.ts runs your bot with Bun. The runtime also has python3, make and g++ for libraries that build during the install, and ffmpeg for audio.
Did this guide help you?
Improve this guide
Guides are open source. Found a fix or an addition? Open a pull request on github.com/serverkgg/bot-node