Can You Make a Discord Bot With Next.js? Full Build Guide
Yes, you can build a Discord bot with Next.js — no always-on server required. This guide covers Discord's Interactions Endpoint, a full slash-command build with App Router route handlers, Vite vs Next.js for bot dashboards, and how to host it for free on Vercel.

Yes, you can build a Discord bot with Next.js — no always-on server required. This guide covers Discord's Interactions Endpoint, a full slash-command build with App Router route handlers, Vite vs Next.js for bot dashboards, and how to host it for free on Vercel.
Can You Make a Discord Bot With Next.js? Yes — Here's the Full Build Guide
If you've spent any time in a Next.js Discord server or scrolling through dev Twitter, you've probably seen the question pop up on repeat: can you make a Discord bot with Next.js?
The short answer is yes — and not in a hacky, duct-tape kind of way. Discord's modern Interactions Endpoint model was practically built for frameworks like Next.js. Instead of running a bot that stays connected to Discord 24/7, you expose a single HTTPS endpoint, Discord sends your bot an event whenever a user runs a slash command, and your Next.js route handler responds. No dedicated server, no while(true) loop, no always-on Node process required.
Quick answer: Yes, you can build a fully functional Discord bot with Next.js using API routes (or App Router route handlers) to receive interactions, verify Discord's signature, and respond to slash commands — all deployable for free on Vercel.
In this guide, we'll walk through why this works, how Discord's two bot architectures differ, and then build a real, working slash-command bot step by step using the Next.js App Router. We'll also cover the inevitable Vite vs Next.js question for anyone building a bot dashboard, whether you can build custom Discord bots for free, and where no-code tools like Bot Designer For Discord fit into the picture if you'd rather skip the code entirely.
Why Next.js Works for Discord Bots
Traditionally, Discord bots were built with discord.js, running as a persistent Node.js process that opens a WebSocket connection (the "Gateway") to Discord and listens for every event happening across every server the bot is in. That model needs a server that's always on — a VPS, a Docker container, a Railway or Render instance humming away in the background.
Discord changed the game when it introduced slash commands and the Interactions Endpoint. Instead of maintaining a live connection, your bot registers a single HTTPS URL with Discord. When someone runs /ping in a server, Discord sends a POST request to that URL, waits up to three seconds, and expects a JSON response back. That's it. No socket, no daemon, no server that needs to stay online around the clock.
This request/response pattern maps almost perfectly onto how Next.js already works:
API Routes (
pages/api/*) or Route Handlers (app/api/*/route.ts) already accept incomingPOSTrequests and return JSON.Serverless and Edge Functions on Vercel spin up on demand, execute in milliseconds, and shut down — which is exactly the lifecycle an interaction needs.
You get the rest of a full web framework for free: an admin dashboard, OAuth2 login for your bot's users, a marketing landing page, and your bot's backend, all living in one codebase.
If you're already comfortable with the framework — check the official Next.js docs if you need a refresher on route handlers — building a bot on top of it feels far more natural than spinning up a separate discord.js project just to handle a handful of commands.
Gateway Bots vs Interactions Endpoint Bots
Before you start coding, it's worth understanding the two architectures side by side, because the one you pick determines whether Next.js is even the right tool for the job.
Gateway Bot (discord.js) | Interactions Endpoint Bot (Next.js) | |
|---|---|---|
Connection type | Persistent WebSocket | Stateless HTTPS webhook |
Hosting requirement | Always-on server/process | Serverless — runs only on demand |
Can read every message in a channel | Yes (with intents) | No — only interaction payloads |
Ideal for | Moderation bots, message-based triggers, live presence tracking | Slash commands, buttons, modals, select menus |
Cost at small scale | Needs a paid always-on host | Free tier on Vercel is usually enough |
Cold starts | None | Possible, but usually well under Discord's 3-second limit |
The important nuance here: a Next.js bot is fantastic for slash-command and component-based interactions, but it is not a drop-in replacement for a bot that needs to passively read every message in a channel (like a keyword-triggered auto-moderator) or maintain a live "online" presence indicator. For that kind of always-listening behavior, you'd still reach for discord.js running on a persistent process. Plenty of production bots actually run both: a lightweight Next.js interactions endpoint for commands, and if needed a small discord.js worker for anything that requires the Gateway.
For the vast majority of hobby bots, community bots, and even many commercial bots (ticketing systems, giveaway bots, verification bots, economy bots), the interactions-only approach is more than enough.
What You'll Need Before Starting
Node.js 18+ installed locally
A free Discord Developer Portal account
A free Vercel account for deployment
Basic familiarity with TypeScript (recommended but not required)
Step 1: Create Your Discord Application
Head to the Discord Developer Portal and click New Application.
Give it a name — this becomes your bot's display name.
Under Bot, click Add Bot, then copy the Bot Token somewhere safe. Never commit this to git.
Under General Information, copy your Application ID and Public Key. You'll need both shortly.
Under OAuth2 → URL Generator, check the
botandapplications.commandsscopes, give it permissions likeSend Messages, and use the generated URL to invite the bot to a test server.
Keep this tab open — you'll come back to set the Interactions Endpoint URL once your Next.js app is deployed.
Step 2: Scaffold the Next.js Project
npx create-next-app@latest discord-bot-nextjs --typescript --app
cd discord-bot-nextjs
npm install discord-interactions
The discord-interactions package is the official-adjacent helper library for verifying request signatures and working with interaction types and response types — it saves you from hand-rolling the cryptography yourself.
If you'd rather start from a pre-styled dashboard instead of Next.js's default boilerplate, a template like the NovaForge Next.js SaaS starter gives you a landing page, auth-ready layout, and pricing section already wired up — handy if your bot is going to ship with a public-facing dashboard rather than just a bare API route.
Add your secrets to .env.local:
DISCORD_TOKEN=your_bot_token
DISCORD_PUBLIC_KEY=your_public_key
DISCORD_APPLICATION_ID=your_application_id
Step 3: Verify Discord's Request Signature
Every request Discord sends to your endpoint is signed. If you skip verification, Discord will reject your endpoint outright, and worse, anyone could spoof requests to your bot. This is the one step people most often botch when they first ask "can you make a Discord bot with Next.js" and try it themselves.
Create src/lib/verify-discord-request.ts:
import { verifyKey } from "discord-interactions";
export async function verifyDiscordRequest(request: Request) {
const signature = request.headers.get("x-signature-ed25519");
const timestamp = request.headers.get("x-signature-timestamp");
const body = await request.text();
const isValidRequest =
signature &&
timestamp &&
verifyKey(body, signature, timestamp, process.env.DISCORD_PUBLIC_KEY!);
if (!isValidRequest) {
return { isValid: false, body: null };
}
return { isValid: true, body: JSON.parse(body) };
}
Step 4: Build the Interactions Route Handler
Create src/app/api/interactions/route.ts:
import {
InteractionType,
InteractionResponseType,
} from "discord-interactions";
import { verifyDiscordRequest } from "@/lib/verify-discord-request";
export async function POST(request: Request) {
const { isValid, body } = await verifyDiscordRequest(request);
if (!isValid) {
return new Response("Bad request signature", { status: 401 });
}
const interaction = body;
// Discord sends a PING to verify your endpoint is alive
if (interaction.type === InteractionType.PING) {
return Response.json({ type: InteractionResponseType.PONG });
}
if (interaction.type === InteractionType.APPLICATION_COMMAND) {
const { name } = interaction.data;
if (name === "ping") {
return Response.json({
type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
data: { content: "🏓 Pong! Your bot is running on Next.js." },
});
}
}
return new Response("Unknown command", { status: 400 });
}
That's the entire runtime logic for a working slash command. PING handles Discord's endpoint verification handshake, and APPLICATION_COMMAND handles the actual /ping interaction.
Step 5: Register Your Slash Commands
Slash commands need to be registered with Discord's REST API separately — this is a one-time (or on-change) script, not something your route handler does on every request.
Create scripts/register-commands.ts:
const commands = [
{
name: "ping",
description: "Check if the bot is alive",
type: 1,
},
];
const url = `https://discord.com/api/v10/applications/${process.env.DISCORD_APPLICATION_ID}/commands`;
fetch(url, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bot ${process.env.DISCORD_TOKEN}`,
},
body: JSON.stringify(commands),
}).then(async (res) => {
console.log(res.status);
console.log(await res.json());
});
Run it with npx tsx scripts/register-commands.ts (or ts-node). Using PUT overwrites all global commands with this list — great for keeping things in sync as your bot grows.
Step 6: Test Locally With a Tunnel
Discord can't send requests to localhost, so you'll need a tunnel like ngrok during development:
npm run dev
ngrok http 3000
Take the https:// URL ngrok gives you, append /api/interactions, and paste it into Interactions Endpoint URL on your Discord application's General Information page. Discord will immediately send a PING — if your verification and PONG response are correct, you'll see a green checkmark.
Step 7: Deploy to Vercel
npm install -g vercel
vercel
Add your three environment variables (DISCORD_TOKEN, DISCORD_PUBLIC_KEY, DISCORD_APPLICATION_ID) in the Vercel dashboard, then swap your Interactions Endpoint URL from the ngrok tunnel to your production Vercel URL, e.g. https://your-bot.vercel.app/api/interactions.
From here, your bot is live, globally distributed, and — on Vercel's free Hobby tier — costs nothing to run for light-to-moderate traffic.
Handling Slower Commands: Deferred Responses and Buttons
The /ping example above responds instantly, but real bots usually need to hit a database, call an external API, or generate something that takes longer than Discord's three-second window allows. Discord's fix for this is the deferred response — you acknowledge the interaction immediately, then edit your response once the real work finishes.
if (name === "weather") {
// Acknowledge immediately so Discord doesn't time out
const deferResponse = Response.json({
type: InteractionResponseType.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE,
});
// Do the slow work after responding, then edit the original message
fetchWeatherData().then(async (weather) => {
await fetch(
`https://discord.com/api/v10/webhooks/${process.env.DISCORD_APPLICATION_ID}/${interaction.token}/messages/@original`,
{
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ content: `It's ${weather.temp}°F outside.` }),
}
);
});
return deferResponse;
}
The same interactions endpoint also handles buttons, select menus, and modals — Discord just sends a different interaction.type (MESSAGE_COMPONENT or MODAL_SUBMIT) with a custom_id you defined when you first sent the component. This means a Next.js bot isn't limited to plain slash commands; you can build multi-step flows, confirmation dialogs, and interactive forms entirely through the same route handler, which is exactly how tools like ticketing bots and role-selection bots work under the hood.
This is also where a lot of teams appreciate having the rest of Next.js sitting right there — if your button handler needs to write to a database, you can reuse the same Prisma client, the same environment variables, and the same deployment pipeline as your dashboard, instead of duplicating that setup in a separate bot service.
Vite vs Next.js: Which One Should Power Your Bot Dashboard?
Once your interactions endpoint is working, most bot creators want a dashboard — a place for server admins to configure welcome messages, toggle moderation features, or view analytics. This is where the Vite vs Next.js question actually becomes relevant to a Discord bot project, rather than an abstract framework debate.
Choose Next.js if your dashboard needs to live in the same project as your interactions endpoint, needs server-rendered pages for SEO (like a public bot listing page), or you want OAuth2 login, API routes, and UI all in one deployable app. This is the simpler setup for most bot projects, since your route handlers and your dashboard pages share the same server runtime.
Choose Vite (typically paired with React Router or a plain SPA) if your dashboard is entirely behind Discord OAuth login, has zero public/SEO-facing pages, and you want the fastest possible dev server and smallest client bundle. In that case, you'd run your Vite dashboard as a separate app and keep your interactions endpoint as a small standalone Next.js or Node service.
In practice, most bot creators land on Next.js for the whole project simply because it avoids maintaining two separate codebases — one for the bot's API, one for the dashboard SPA. If you're still weighing the two frameworks for a broader project (not just a bot), this breakdown of React vs Next.js and when to choose each goes deeper into the rendering and tooling tradeoffs, and this comparison of starting from a Next.js template vs building from scratch is worth a read if you're deciding how much boilerplate to write yourself for the dashboard side.
If your bot dashboard needs charts for server activity or command usage, a component like this analytics dashboard graph or a full HUD-style dashboard layout can save you the layout work entirely.
Can You Make Discord Bots for Free?
Yes — and the Next.js approach is arguably the cheapest way to run a bot long-term:
Hosting: Vercel's free tier comfortably runs an interactions-only bot for small-to-mid-sized communities, since your function only executes when a command is used — you're not paying for idle uptime like you would with a traditional always-on discord.js host.
Discord's own APIs: Creating an application, registering commands, and receiving interactions costs nothing on Discord's side, regardless of how you build the bot.
No-code alternatives: If you'd rather skip the code entirely, tools like Bot Designer For Discord let you build custom Discord bots for free from a phone or browser using a simplified scripting language, with hosting handled for you. It's a reasonable starting point if you're not ready to write TypeScript yet, though — like most no-code tools — it trades flexibility for simplicity once your bot's logic gets complex (things like variable limits and execution-time caps tend to show up on the free tier).
The tradeoff is straightforward: no-code builders get you a working bot in minutes with zero setup, while the Next.js route means a bit more upfront work in exchange for full control, your own dashboard, and no platform lock-in.
Limitations You Should Know About
Building a Discord bot with Next.js is genuinely solid for command-based bots, but be upfront with yourself about the edges:
No passive message reading. You can't build a bot that scans every message for banned words unless you also run a Gateway connection (via discord.js) somewhere.
Three-second response window. Discord expects a response within 3 seconds. For anything slower (like generating an image or querying a slow API), you'll need to send an initial "deferred" response and follow up asynchronously.
No persistent bot presence/status. A Gateway-based bot can show as "Online" with a custom status; an interactions-only bot technically doesn't maintain a live connection, so it may show as offline even while fully functional.
Cold starts on serverless. Rare, but possible on the free tier — usually still well within Discord's timeout, but worth monitoring if your bot grows.
If any of these matter for your use case, look into hybrid setups where Next.js handles commands and a small always-on worker (Railway, Fly.io, a cheap VPS) handles Gateway-dependent features.
FAQ
Can you make a Discord bot with Next.js without writing a separate backend? Yes — Next.js route handlers are your backend. You don't need Express, Fastify, or a separate API server.
Do I need discord.js at all? Not for slash-command-only bots. The discord-interactions package covers verification and response typing. You'd only add discord.js if you need Gateway events (message content, presence, etc.).
Is Vite better than Next.js for a Discord bot? Not for the bot's backend — Vite has no server runtime, so it can't receive Discord's webhook requests on its own. Vite is only relevant if you're building a separate, purely client-side dashboard that talks to your Next.js (or other) API.
Can you make Discord bots for free with Next.js? Yes. Discord's API is free to use regardless of framework, and Vercel's free tier is generally sufficient for small and mid-sized bots built on the interactions model.
What's the difference between this and using Bot Designer For Discord? Bot Designer For Discord and similar no-code tools are faster to start with and require no programming knowledge, but they run on their own scripting language and hosting, which limits customization at scale. Building on Next.js gives you full control of the codebase, your own hosting, and the ability to extend the bot with any npm package.
Can a Next.js Discord bot also send messages proactively, not just reply to commands? Yes, but it needs your bot token rather than the interaction token. Any route handler, cron job, or server action in your Next.js app can call Discord's REST API directly (POST /channels/{channel.id}/messages with an Authorization: Bot <token> header) to post a message outside of a slash command — useful for scheduled announcements, webhook-triggered alerts, or moderation logs.
Wrapping Up
So — can you make a Discord bot with Next.js? Absolutely, and for slash-command-driven bots, it's arguably one of the more elegant ways to do it: no always-on server, a free deployment path, and your bot's dashboard living in the same codebase as its backend. Verify the signature, handle the PING, respond to APPLICATION_COMMAND, and you've got a production-ready bot.
If you're building out the dashboard side next, a ready-made login form component or responsive navbar can save you a few hours of layout work, and this guide to React authentication patterns is a solid next stop once you're adding Discord OAuth login for server admins. If you're also curious how testing fits into a Next.js bot project, this rundown on testing in Next.js is worth bookmarking before you ship to production. And if you're migrating an older JavaScript bot dashboard to TypeScript, the JSX to TSX converter tool can speed that up considerably.
Happy building — and if your /ping command replies with "Pong! Your bot is running on Next.js," you're officially past the hardest part.
Frequently asked questions
What does "Can You Make a Discord Bot With Next.js? Full Build Guide" cover?
Yes, you can build a Discord bot with Next.js — no always-on server required. This guide covers Discord's Interactions Endpoint, a full slash-command build with App Router route handlers, Vite vs Next.js for bot dashboards, and how to host it for free on Vercel.
Which TemplatesCenter resources relate to Web Development?
Browse our Web Development templates and React components to apply these techniques in your own projects.
Is the code in this Web Development guide ready to use?
Yes — the examples are written to be adapted directly into Next.js, React, and Tailwind CSS projects.