Building Discord Bots with Quill
Quill makes it easy to build Discord bots with clean, readable syntax. With built-in slash command declarations, embed builders, and automatic environment loading, you can have a bot running in minutes.
Prerequisites
Before you start, make sure you have the following:
-
Node.js (version 16.11 or later) — download from nodejs.org. You can check your version by running
node --versionin your terminal. - Quill installed — see the Getting Started guide.
-
A Discord bot token — you get this from the Discord Developer Portal. Follow these steps:
- Go to the Discord Developer Portal and click New Application.
- Give your application a name and click Create.
- In the left sidebar, click Bot.
- Click Reset Token (or Add Bot if it is a new application) and copy the token. Keep it secret.
- Under Privileged Gateway Intents, enable Message Content Intent if you want your bot to read message text.
- Go to OAuth2 → URL Generator, select the bot and applications.commands scopes, choose the permissions your bot needs, and use the generated URL to invite the bot to your server.
.env file and add it to your .gitignore. Quill automatically loads .env files for you.
Quick Start
The fastest way to get a Discord bot running is with the built-in scaffolding command:
quill discord my-bot
cd my-bot
This creates a new project with the following structure:
my-bot/
bot.quill -- Your bot code
package.json -- Node.js dependencies (discord.js)
.env -- Your bot token goes here
.gitignore -- Keeps .env out of version control
Step 1: Open .env and paste your bot token:
DISCORD_TOKEN=your-bot-token-here
Step 2: Install dependencies:
npm install
Step 3: Build and run your bot:
quill build bot.quill
node bot.js
Your bot should come online in your Discord server. Slash commands are registered automatically — try typing /ping in a channel.
Full Bot Example
Here is a complete bot using Quill's built-in command syntax. Slash commands are declared inline, registered automatically when the bot starts, and dispatched with no boilerplate:
use "discord.js" as Discord
bot is Discord.bot(env("DISCORD_TOKEN"))
command "ping" described "Check if bot is alive":
reply "Pong!"
command "help" described "Learn about this bot":
reply embed "My Bot":
color green
description "A Discord bot built with Quill"
field "Ping" "Check if the bot is alive"
field "Hello" "Get a greeting"
command "hello" with user described "Greet someone":
reply "Hello, {user}!"
That is the entire bot. No event handler boilerplate, no manual command registration, no separate deploy-commands script. Quill handles all of it.
Discord.bot(token)creates a client with common intents and auto-logs in.commandblocks are collected and registered as slash commands when the bot connects.replyinside a command compiles tointeraction.reply().embedblocks compile to Discord'sEmbedBuilderchain.env("KEY")reads fromprocess.env, and.envfiles are loaded automatically.
Slash Commands
The command keyword is the easiest way to add slash commands to your bot.
Basic command
command "ping" described "Check if bot is alive":
reply "Pong!"
Command with parameters
Use with to declare required string parameters. Users will see these as autocomplete options in Discord.
command "greet" with user described "Greet someone":
reply "Hello, {user}!"
Command with embeds
Use embed blocks to build rich embeds inside commands:
command "info" described "Show server info":
reply embed "Server Info":
color blue
description "Information about this server"
field "Members" "100+"
footer "Powered by Quill"
Embed color names
Quill supports these built-in color names for embeds:
red -- #FF0000
green -- #1EB969
blue -- #3498DB
yellow -- #F1C40F
purple -- #9B59B6
orange -- #E67E22
white -- #FFFFFF
black -- #000000
Bot Setup
Discord.bot(token)
The simplest way to create a Discord client. It pre-configures common intents (Guilds, GuildMessages, MessageContent) and auto-logs in:
bot is Discord.bot(env("DISCORD_TOKEN"))
env("KEY")
Read environment variables. Quill automatically loads your .env file when environment variables are used:
token is env("DISCORD_TOKEN")
prefix is env("BOT_PREFIX")
Manual client setup (advanced)
If you need to configure specific intents or want full control, you can create the Discord client manually:
use "discord.js" as Discord
intents is [
Discord.GatewayIntentBits.Guilds,
Discord.GatewayIntentBits.GuildMessages,
Discord.GatewayIntentBits.MessageContent,
Discord.GatewayIntentBits.GuildMembers
]
options is {intents: intents}
bot is new Discord.Client(options)
-- Register your event handlers here...
bot.login(env("DISCORD_TOKEN"))
With manual setup, you can also use the on keyword for event handlers and handle slash commands manually:
Event Handling
For advanced use cases, you can register event handlers manually with the on keyword:
bot on "ready" with:
say "Logged in as {bot.user.tag}"
bot on "messageCreate" with msg:
if msg.author.bot:
give back nothing
if msg.content is "!ping":
msg.reply("Pong!")
bot on "guildMemberAdd" with member:
channel is member.guild.systemChannel
if channel:
channel.send("Welcome, {member.user.username}!")
Deployment
Once your bot is working locally, you will want to run it on a server so it stays online. Here are some tips for deploying your Quill Discord bot.
Build for production
Compile your Quill code to JavaScript:
quill build bot.quill
This produces a bot.js file that runs on any system with Node.js installed.
Use environment variables
Never hardcode your bot token. Use a .env file locally and set environment variables on your production server. Quill loads .env automatically:
-- In your bot code
bot is Discord.bot(env("DISCORD_TOKEN"))
Keep the bot running
Use a process manager like pm2 to keep your bot alive and restart it if it crashes:
# Install pm2 globally
npm install -g pm2
# Start your bot
pm2 start bot.js --name my-bot
# View logs
pm2 logs my-bot
# Restart after updates
quill build bot.quill
pm2 restart my-bot
Hosting options
Discord bots need a persistent process (not serverless). Good options include:
- A VPS (DigitalOcean, Linode, Vultr) — full control, starts around $5/month
- Railway — simple deployment from Git, free tier available
- Fly.io — deploy with a Dockerfile, generous free tier
- A Raspberry Pi — run it at home for free
Using Docker
You can use Quill's built-in deployment command to generate a Dockerfile:
quill deploy
Or write your own minimal Dockerfile:
FROM node:20-slim
WORKDIR /app
COPY package.json .
RUN npm install --production
COPY bot.js .
CMD ["node", "bot.js"]
Build and run:
docker build -t my-bot .
docker run -d --env-file .env my-bot
Real-World Example: Quill Community Bot
This is the bot running in the Quill Discord server. It uses Quill's built-in command syntax for slash commands with rich embeds. The full source is on GitHub.
-- Quill Discord Bot
use "discord.js" as Discord
bot is Discord.bot(env("DISCORD_TOKEN"))
command "ping" described "Check if the bot is alive":
reply "Pong!"
command "help" described "Learn about Quill":
reply embed "Quill, Code that reads like English":
color green
description "A beginner-friendly language that compiles to JavaScript"
field "Getting Started" "npm install -g @tradebuddyhq/quill"
field "Playground" "quill.tradebuddy.dev/playground"
field "Docs" "quill.tradebuddy.dev/docs"
footer "Quill by Trade Buddy"
command "hello" with user described "Greet someone":
reply "Hello, {user}!"
Next Steps
- Explore the discord.js documentation for the full Discord API.
- Check out the Examples page for more Quill programs.
- Join the Quill Discord community to share your bot and get help.