A Node.js bot hosted with us runs around the clock and starts again on its own after a crash. We'll show you how to prepare the project on your computer, what to upload and what not, how to set up startup and how to find out the Node.js version.
What you'll need
- A Discord bot at StormHost
- Your bot's code in JavaScript (Node.js), ideally tested on your computer
- The bot token from the Discord Developer Portal (guide)
- About 15 minutes
How your bot runs on our servers#
- The environment is Node.js. The bot is an ordinary Node.js application, usually built with the discord.js library.
- You manage the bot's files in the Files tab (a file manager in your browser).
- Startup is set in the Settings tab: the Startup command (the full command, read-only) and Variables (for example the name of the main file).
- The bot's output (everything from
console.logand errors) is shown in the Console tab, which also has the Start, Restart and Stop buttons. - Automatic restart: when the bot crashes, it starts again. It runs 24 hours a day, even when your computer is off.
- Memory is limited by your plan. You can see the usage below the console.
Preparing the project on your computer#
Recommended project structure:
muj-bot/
├── package.json
├── package-lock.json
├── index.js
├── deploy-commands.js
├── .env
├── .gitignore
├── commands/
│ └── utility/
│ └── ping.js
└── node_modules/package.json#
package.json describes the project: its name, which file starts it and which packages it needs. Create it in the project folder with npm init -y and add packages with npm install discord.js dotenv. Then edit the result to look roughly like this:
{
"name": "muj-bot",
"version": "1.0.0",
"private": true,
"main": "index.js",
"type": "commonjs",
"scripts": {
"start": "node index.js"
},
"engines": {
"node": ">=18"
},
"dependencies": {
"discord.js": "^14.27.0",
"dotenv": "^18.0.5"
}
}| Field | What it does | What to set |
|---|---|---|
name | The project name. Lowercase, no spaces. | Anything, for example muj-bot. |
version | Your bot's version. | 1.0.0; you can increase it as you make changes. |
private | true prevents you from accidentally publishing the project to the npm registry. | true |
main | The main file the bot starts from. | The same file you run, usually index.js. |
type | commonjs = the code uses require(), module = the code uses import. | Depends on your code. The discord.js guides use commonjs. |
scripts.start | The command for npm start on your computer. | node index.js |
engines.node | Says which Node.js version the bot needs. It doesn't change the version, it only warns. | >=18 for discord.js 14. |
dependencies | The packages the bot needs, with versions. ^14.27.0 means “14.27.0 or any newer 14.x”. | npm install <PACKAGE> fills them in; don't write them by hand. |
The package-lock.json file is created automatically and locks the exact versions of all packages. Upload it to the server together with package.json so the server installs the same versions as your computer.
JSON doesn't tolerate mistakes
In package.json, keys and strings must be in double quotes, there can't be a comma after the last item in a block, and comments aren't allowed. One mistake and the package installation fails with EJSONPARSE.
What to upload and what not#
| File or folder | Upload? | Why |
|---|---|---|
index.js, commands/, events/ and other code | Yes | The bot itself. |
package.json, package-lock.json | Yes | Packages are installed based on them. |
.env with the token | Yes, only to the server | The bot reads the token from it. Never put it on GitHub or send it to anyone (guide). |
node_modules/ | No | Thousands of files. Packages should be installed on the server. On top of that, packages with native code built on Windows wouldn't work on the server. |
.git/, logs/, test data | No | The server doesn't need them. |
Uploading in the customer area#
- In the customer area, open My services, click your bot and go to the Files tab.
- Stay in the root folder
/. This is wherepackage.jsongoes, and ideally the bot's main file too. - Click Upload and select the files from the project root (
index.js,package.json,package-lock.json,.env…). You can also drag the files into the window. - For each subfolder (for example
commands), click New folder, open it and upload its files into it. You can't upload whole folders at once.
A large project with many folders is easier to upload over SFTP; support will set up access for you (contacts). The file manager limits are listed in the file management guide.
Setting up startup#
- Go to the Settings tab.
- Expand Startup command and check which command starts the bot. The command is read-only. If it's covered by a hatched bar, streamer mode is on. Click Show details at the top.
- In the Variables section, find the variable for the main file (by its description, typically with the default value
index.js) and enter the name of your main file, for exampleindex.jsorbot.js. - Click Save.
Changes to variables take effect the next time the bot starts.
Installing packages#
The packages from package.json have to be installed on the server.
- Check whether the Startup command contains
npm install. - If it does, the packages are installed automatically every time the bot starts. The console then shows the installation output, for example
added 25 packages. That's why the first start takes longer. - If
npm installisn't in the command, or the packages still don't get installed (the bot reportsCannot find module 'discord.js'), contact us. Don't upload thenode_modulesfolder from your computer.
To add a new package, install it on your computer (npm install <PACKAGE>), upload the new package.json and package-lock.json to the server and restart the bot.
Node.js version#
You can find out which Node.js version the bot runs on from its output. Add this at the very top of the main file:
console.log('Node.js', process.version);After startup, the Console shows, for example, Node.js v22.….
process.version– the Node.js version the code is currently running on, in the formv<MAJOR>.<MINOR>.<PATCH>.
What to do with it:
| Library or feature | Required Node.js version |
|---|---|
| discord.js 14 | 18 or newer |
process.loadEnvFile() (loading .env without a package) | 20.12 or newer |
require() of packages that exist only as ES modules | 20.19 or 22.12 and newer |
Use the same major version on your computer as on the server so your code behaves the same way. LTS versions are recommended (as of October 1, 2026, Node.js 24 is the active LTS and Node.js 22 the maintenance LTS). The engines field in package.json doesn't change the version on the server. If your bot needs a different Node.js version, contact us.
First start and check#
Go to the Console tab and click Start.
Watch the output:
Outputtext Node.js v22.… Ready! Logged in as MujBot#1234The
Ready! …line is printed by the bot from the first discord.js bot guide. Your bot may print something else.On Discord, the bot has a green dot (online).
Updating the code#
- Edit and test the code on your computer.
- In the Files tab, upload the changed files. When you upload a file with the same name, you're asked whether to overwrite it; confirm.
- In the Console tab, click Restart. Node.js loads the code only at startup.
Before a bigger change, download the important files to your computer (the Download button) so you have something to go back to.
A bot with a database#
Store data that has to survive a restart (points, warnings, server settings) in a database, not in variables in memory.
In the Database tab, create a database: Database name, for example
bot, Allowed connections from%, then the Create database button. TheUsed X of Yline shows how many databases you can have.Write the details to
.envon the server:.envini DB_HOST=<DATABASE_IP> DB_PORT=3306 DB_USER=<USER> DB_PASSWORD=<PASSWORD> DB_NAME=<DATABASE_NAME><DATABASE_IP>and the port are in the Host field (the parts before and after the colon); copy the rest from the User, Password and Database name fields.On your computer, install the
mysql2library (npm install mysql2) and create the connection in your code:db.jsJavaScript const mysql = require('mysql2/promise'); const pool = mysql.createPool({ host: process.env.DB_HOST, port: Number(process.env.DB_PORT), user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, connectionLimit: 5, }); module.exports = pool;mysql.createPool({ … })– creates a set of connections that get reused. It's more resilient than a single connection, which can drop after a longer idle period.Number(– values fromprocess. env. DB_ PORT) .envare text; the port has to be a number.connectionLimit: 5– at most 5 connections at once. That's plenty for a bot.
Usage:
const db = require('./db');and thenconst [rows] = await db.query('SELECT * FROM points WHERE user_id = ?', [id]);. The question mark is a placeholder: the library inserts the value into the query safely, which protects against SQL injection.
Export your database regularly, for example with HeidiSQL (steps).
Shutting the bot down cleanly#
When you click Stop or Restart, the process gets a signal to exit. The bot can log out properly and finish its writes:
async function ukoncit(signal) {
console.log(`Received ${signal}, shutting down the bot…`);
await client.destroy();
process.exit(0);
}
process.on('SIGINT', ukoncit);
process.on('SIGTERM', ukoncit);process.on('SIGINT' | 'SIGTERM', …)– catches the request to exit (on your computer it's sent by Ctrl+C, on the server by stopping the bot).client.destroy()– disconnects the bot from Discord.process.exit(0)– exits the process with code 0 (no error).
If you use a database, close it too before process.exit (await pool.end()).
Advanced: TypeScript and other build steps#
The server runs JavaScript. Compile TypeScript code (or code with another build step) on your computer (for example npx tsc), upload the resulting .js files (typically the dist folder) to the server and in Variables set the main file to the compiled file. You don't need the .ts source files or the development packages (devDependencies) on the server.
Verification#
- The Console shows the startup output without errors and the bot isn't crashing over and over.
- The bot is online on Discord and responds to commands.
- After you click Restart, the bot is back online within a few seconds.
Troubleshooting#
Error: Cannot find module 'discord.js'#
The packages aren't installed. Check that package.json is in the root folder and has discord.js in dependencies. Then follow the “Installing packages” section.
Error: Cannot find module '/…/index.js'#
The main file doesn't match the settings: the file has a different name, is in a subfolder, or the letter case doesn't match (Index.js and index.js are two different files on the server). Fix the main file variable, or move the file to the root.
npm error code EJSONPARSE#
package.json isn't valid JSON (a missing comma or quote, an extra comma, a comment). Fix it on your computer, check it with npm install and upload it again.
The bot starts and crashes right away, over and over#
Automatic restart won't fix an error in your code. Find the first error after startup in the Console (a line with Error and a list of files below it), fix it and start the bot again. The most common messages are explained in the logs and errors guide.
An invalid token was provided. or Used disallowed intents#
There's a problem with the token or with intents in the Developer Portal. The steps are in the token and intents guide.
SyntaxError: Cannot use import statement outside a module#
The code uses import, but the project is set up for require(). Set "type": "module" in package.json, or rewrite the code to use require(). More in the logs and errors guide.
Summary
- Upload your code,
package.json,package-lock.jsonand.envto the root folder in the Files tab. Don't uploadnode_modules. maininpackage.jsonand the main file variable in the Settings tab must point to the same file.- Packages are installed on the server. Whether this happens automatically, you can tell by
npm installin the Startup command. - Find out the Node.js version with
console.. discord.js 14 needs Node.js 18 or newer.log( process. version) - Restart the bot after every code change.