|
1 | | -# NextBot: Serverless Discord Bot with Next.js |
| 1 | +# NextBot: Next.js Discord Bot Template that runs in the Edge Runtime |
2 | 2 |
|
3 | | -Serverless Discord bot using Discord's |
4 | | -[slash commands webhook](https://discord.com/developers/docs/interactions/slash-commands#receiving-an-interaction) and |
5 | | -[Next.js](https://nextjs.org/). |
| 3 | +NextBot is a template for building and deploying a Discord bot with Next.js. It runs 100% in the edge runtime so you get |
| 4 | +lightning-fast responses and zero cold starts. It uses Discord interactions webhooks to receive and reply to commands. |
6 | 5 |
|
7 | 6 |  |
8 | 7 |
|
9 | | -## Try it out |
| 8 | +- Runs at the edge: Lightning-fast responses, no cold start. |
| 9 | +- Free & easy to deploy: Deploy to Vercel in seconds at no cost. No need to host a server or VM to run your bot! Don't |
| 10 | + bother with Heroku, EC2, etc. |
| 11 | +- Easy to extend: Since the bot is built on Next.js, you can easily build an accompanying webapp in the same repo. |
10 | 12 |
|
11 | | -[](https://discord.gg/NmXuqGgkb3) |
| 13 | +## Try it out |
12 | 14 |
|
13 | | -Join https://discord.gg/NmXuqGgkb3 and use one of the available slash commands. |
| 15 | +Join https://discord.gg/NmXuqGgkb3 to try out a demo of NextBot. Type one of these slash commands into the general |
| 16 | +channel: |
14 | 17 |
|
15 | 18 | - `/ping` |
| 19 | +- `/invite` |
16 | 20 | - `/randompic` |
17 | 21 |
|
18 | | -Or, add NextBot to your own server: |
19 | | -https://discord.com/api/oauth2/authorize?client_id=837427503059435530&permissions=2147483648&scope=bot%20applications.commands |
20 | | - |
21 | | -You can also send slash commands through DM the bot once you're in a mutual server with the bot! |
| 22 | +Or add NextBot to your own server with this link: |
| 23 | +https://discord.com/api/oauth2/authorize?client_id=837427503059435530&permissions=2147485696&scope=bot%20applications.commands |
22 | 24 |
|
23 | | -An accompanying static web app also shows the registered commands: https://nextjs-discord-bot.vercel.app/ |
24 | | - |
25 | | -## Technologies |
26 | | - |
27 | | -- Receives slash commands through |
28 | | - [Discord's Interaction webhook](https://discord.com/developers/docs/interactions/slash-commands#receiving-an-interaction), |
29 | | - allowing for a completely serverless approach! |
30 | | -- Built on Next.js: easily build an accompanying dashboard web app in the same repo and call your API directly with SSR! |
31 | | -- Typescript <3 (thanks to https://github.com/discordjs/discord-api-types for Discord types!) |
| 25 | +You can also send slash commands through DM to the bot as long as you're in a mutual server with the it! |
32 | 26 |
|
33 | 27 | ## Development |
34 | 28 |
|
35 | | -Requires a Node.js version that can run Next.js. |
| 29 | +Node.js 18+ is required. |
36 | 30 |
|
37 | 31 | ### Setup |
38 | 32 |
|
39 | | -Follow the one-time setup as follows: |
40 | | - |
41 | | -- Clone the repo |
42 | | -- Create a Discord app and bot |
43 | | -- Copy `.env.local.example` into a new file `.env.local` and fill in the blanks with the values from your Discord app |
44 | | -- Register the slash commands. You can learn more about registering commands in the |
45 | | - [Discord API docs](https://discord.com/developers/docs/interactions/slash-commands#registering-a-command). I created |
46 | | - the commands by leveraging `createGlobalCommand` in `services/discord.ts`. I added this to`getServerSideProps` in |
47 | | - `pages/index.tsx` and ran it ONCE (i.e. refresh the page ONCE). |
48 | | - |
49 | | -```tsx |
50 | | -await createGlobalCommand({ |
51 | | - name: "randompic", |
52 | | - description: "Get a random picture", |
53 | | - options: [ |
54 | | - { |
55 | | - name: "type", |
56 | | - description: "What type of picture would you like?", |
57 | | - type: 3, |
58 | | - required: true, |
59 | | - choices: [ |
60 | | - { name: "cat", value: "cat" }, |
61 | | - { name: "dog", value: "dog" }, |
62 | | - { name: "generic", value: "picsum" }, |
63 | | - ], |
64 | | - }, |
65 | | - ], |
66 | | -}) |
67 | | - |
68 | | -await createGlobalCommand({ |
69 | | - name: "ping", |
70 | | - description: "Ping pong! I'll respond with pong.", |
71 | | -}) |
72 | | -``` |
73 | | - |
74 | | -You could also make the request via Postman, curl, etc. but I'm lazy |
| 33 | +- Clone the repo. This is a |
| 34 | + [template repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template) |
| 35 | + so you can click the green "Use this template" button on GitHub to create your own repo! |
| 36 | + - Run `yarn` to install dependencies. |
| 37 | +- [Create a new Discord application](https://discord.com/developers/applications). |
| 38 | + - In the `Bot` settings of your Discord application, enable the `Message Content` intent. |
| 39 | +- Fill out environment variables: |
| 40 | + - In the root of the repository, copy `.env.local.example` into a new file `.env.local`. Fill out the values using the |
| 41 | + real values from your Discord app. |
| 42 | +- Register some slash commands for your bot. I've included a script to register the commands included in the demo bot. |
| 43 | + - Run `yarn register-commands` to execute the script! You only need to run this once, unless you add new commands. |
| 44 | + - You can learn more about registering commands in the |
| 45 | + [Discord API docs](https://discord.com/developers/docs/interactions/application-commands#create-global-application-command) |
75 | 46 |
|
76 | 47 | ### Local Development |
77 | 48 |
|
78 | | -- Run `yarn dev` |
79 | | -- Tunnel your localhost:3000 with a tool like [ngrok](https://ngrok.com/). `ngrok http 3000` |
80 | | -- Add the `<YOUR_PUBLIC_TUNNELED_NGROK_URL>/api/interactions` as the `Interactions Endpoint URL` in your Discord app. |
81 | | -- Add the app to a server and slide in its DMs! Your registered slash commands should be available now. |
| 49 | +Once you've completed the setup steps above, you're ready to run the bot locally! |
| 50 | + |
| 51 | +Discord can only send events to a public `https` address. You'll need an HTTP tunneling service like |
| 52 | +[ngrok](https://ngrok.com/) or [Cloudflare Tunnel](https://www.cloudflare.com/products/tunnel/) when developing locally. |
| 53 | +For this guide, I'll be using ngrok. |
| 54 | + |
| 55 | +- Run `yarn dev` to start the Next.js application. |
| 56 | +- Assuming you're using ngrok, run `ngrok http 3000` to start your HTTP tunnel. |
| 57 | +- In the Discord app settings, set `Interactions Endpoint URL` to `<YOUR_PUBLIC_TUNNELED_NGROK_URL>/api/interactions`. |
| 58 | + Make sure to use the `https` URL! |
| 59 | +- Save changes in the Discord app settings. |
| 60 | + |
| 61 | +In order to verify your interactions endpoint URL, Discord will send a `PING` message to your bot, and the bot should |
| 62 | +reply with a PONG (see `src/pages/api/interactions.ts`). If this is successful, your bot is ready to go! |
| 63 | + |
| 64 | +You can now add your bot to your Discord server and try it out! Use Discord's URL generator in `OAuth2 -> URL Generator` |
| 65 | +of your Discord app's settings to generate an invite link. Make sure to select: |
| 66 | + |
| 67 | +- `bot` + `applications.commands` for scopes |
| 68 | +- `Send Messages` + `Use Slash Commands` for bot permissions |
| 69 | + |
| 70 | +After adding the bot to a server, try out one of the slash commands like `/ping` or `randompic`! |
| 71 | + |
| 72 | +- You can try modifying the response of the `/ping` command and the changes should be reflected immediately. |
| 73 | +- You're ready to add your own commands! |
| 74 | + |
| 75 | +Note: whenever you terminate/restart your ngrok tunnel, you'll need to update the `Interactions Endpoint URL` in the |
| 76 | +Discord app settings accordingly. |
| 77 | + |
| 78 | +## Deploy to Production |
| 79 | + |
| 80 | +This project is designed to be deployed on Vercel. I recommend that you create a new Discord Application for production! |
| 81 | +Here are some things you should remember to do when deploying: |
| 82 | + |
| 83 | +- Set the environment variables in Vercel accordingly. |
| 84 | +- You can still use `yarn register-commands` to register commands for your production bot, as long as you update your |
| 85 | + `.env.local` file with the correct values. |
| 86 | +- You should set `<YOUR_VERCEL_URL>/api/interactions` as the `Interactions Endpoint URL` in your prod Discord app. |
| 87 | + |
| 88 | +## How It Works |
| 89 | + |
| 90 | +Unlike traditional Discord bots which maintain a persistent connection with Discord (and thus require managing your own |
| 91 | +servers), NextBot uses Discord's |
| 92 | +[Interactions Endpoint](https://discord.com/developers/docs/interactions/slash-commands#receiving-an-interaction) to |
| 93 | +respond to interactions (such as slash commands). |
| 94 | + |
| 95 | +The Interactions Endpoint is now Discord's recommended approach to building bots. If you haven't already, I recommend |
| 96 | +you read the [Getting Started](https://discord.com/developers/docs/getting-started) and |
| 97 | +[Receiving and Responding](https://discord.com/developers/docs/interactions/receiving-and-responding) pages of Discord's |
| 98 | +documentation to learn more about Interactions, Slash Commands, and Discord bots! |
| 99 | + |
| 100 | +And be sure to check out the rest of the Discord docs to see all the awesome stuff you can do aside from basic Slash |
| 101 | +commands! |
| 102 | + |
| 103 | +### File Structure |
| 104 | + |
| 105 | +- `src/app/api/interactions/route.ts`: This is the main route handler for the Interactions Endpoint. It receives |
| 106 | + interactions from Discord and handles them accordingly. |
| 107 | +- `src/discord/verify-incoming-request.ts`: Helper functions to verify incoming requests from Discord, as outlined in https://discord.com/developers/docs/interactions/receiving-and-responding#security-and-authorization. |
| 108 | +- `src/app/page.tsx`: A basic web page. This could be your admin portal or whatever you'd like! |
| 109 | + |
| 110 | +## Why Next.js (instead of Express, serverless, or Cloudflare Workers)? |
| 111 | + |
| 112 | +NextBot leverages Next.js 13 |
| 113 | +[Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) to receive and respond to |
| 114 | +interactions. But why Next.js instead of something like Express or serverless (AWS Lambda)? |
82 | 115 |
|
83 | | -### Deploy on Vercel |
| 116 | +- Next.js is free and effortless to deploy on Vercel. Don't bother with trying to host your Express server |
| 117 | +- Compared to serverless, edge is faster (no cold start) and cheaper (Edge Runtimes have more generous free tiers and |
| 118 | + are cheaper per request) |
84 | 119 |
|
85 | | -[](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fjzxhuang%2Fnextjs-discord-bot) |
| 120 | +A better comparison would be hosting a Discord bot on Cloudflare Workers, as shown in this |
| 121 | +[official Discord tutorial](https://discord.com/developers/docs/tutorials/hosting-on-cloudflare-workers). The Next.js |
| 122 | +edge runtime is built on Cloudflare Workers! Still, I think Next.js has some notable benefits: |
86 | 123 |
|
87 | | -After deploying, add `<YOUR_VERCEL_URL>/api/interactions` as the `Interactions Endpoint URL` in your Discord app. |
| 124 | +- Next.js has the advantage of being a full web-app framework, making it easy to build an accompanying web app to go |
| 125 | + along with your Discord app! |
| 126 | +- Deploying on Vercel is not only simple, but it also scales out very effectively if you need to build a more complex |
| 127 | + app (analytics, logging, integrations, etc.) |
| 128 | + - You can use Next.js/Vercel features like [Dynamic Image Generation](NextBot is a template for building and deploying a Discord bot with Next.js. It runs 100% in the edge runtime so you get |
| 129 | +lightning-fast responses and zero cold starts). |
0 commit comments