> ## Documentation Index
> Fetch the complete documentation index at: https://docs.withnubo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Discord.js bot

> Run a Discord bot 24/7 on Nubo

Discord bots are long-running Node processes that don't accept HTTP traffic. They're a perfect fit for Nubo: push your code, the bot runs, redeploy from a git push.

## What you'll need

* A Discord application + bot token from the [Discord Developer Portal](https://discord.com/developers/applications).
* A repo with a `package.json` and a `start` script that boots your bot.

If you'd rather start from a working example, [`withnubo/discordjs-starter`](https://github.com/withnubo/discordjs-starter) is a ready-made repo you can fork and deploy as-is.

## Minimal bot

```bash theme={null}
mkdir my-bot && cd my-bot
npm init -y
npm install discord.js
```

`index.js`:

```js index.js theme={null}
import { Client, GatewayIntentBits } from "discord.js";

const client = new Client({
  intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
});

client.on("ready", () => {
  console.log(`Logged in as ${client.user.tag}`);
});

client.login(process.env.DISCORD_TOKEN);
```

`package.json` should have a `start` script:

```json package.json theme={null}
{
  "type": "module",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "discord.js": "^14.16.0"
  }
}
```

Test locally with your token:

```bash theme={null}
DISCORD_TOKEN=your-token-here npm start
```

If you see "Logged in as `<bot-name>`", you're ready.

## Deploy

<Steps>
  <Step title="Push to GitHub">
    Initialize git, commit, push to a private repo. Don't commit your token.
  </Step>

  <Step title="New Frame on Nubo">
    Open your Project and Space, hit **+ Frame**, connect the repo.
  </Step>

  <Step title="Set DISCORD_TOKEN">
    In the Frame's **Settings** tab, add `DISCORD_TOKEN` with your bot token. See [Environment variables](/environment-variables) for details.
  </Step>

  <Step title="Port doesn't matter (almost)">
    Discord bots don't accept HTTP, but Nubo expects a port. Set it to any valid port (`3000` is fine); ports below 1024 and a few reserved infra ports aren't allowed. The Frame's URL won't serve anything useful, which is correct.
  </Step>

  <Step title="Deploy">
    Hit deploy. Check the Logs tab for "Logged in as ...".
  </Step>
</Steps>

## Keeping the bot alive

Nubo restarts your bot if it crashes. If `client.login(...)` returns a rejected promise (bad token, network), the Node process exits, and Nubo brings it back up.

Avoid this anti-pattern:

```js theme={null}
// don't
process.on("uncaughtException", () => {});
```

Swallowing crashes hides bugs. Let the process die and let Nubo restart it.

## Sharding and gateway intents

Sharding works the same way on Nubo as anywhere else. For bots in fewer than 2,500 guilds you can ignore shards entirely.

Privileged intents (`MessageContent`, `GuildMembers`, `GuildPresences`) must be enabled in the Discord Developer Portal before your code requests them.

## Slash command registration

Register commands once at startup or via a separate script. Avoid registering on every deploy: it counts against Discord's API limits.

## How the build works

Uses the [Node.js pack](/raypacks/packs/node) of [Raypacks](/raypacks/overview). Standard Node flow: install dependencies, run your `start` script.
