Public
Remixed
Discord /ping bot quickstart — interactions over HTTP
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

discord-bot

A minimal Discord bot with a /ping slash command, deployed on Val Town. Interactions arrive over HTTP — no Gateway connection, no discord.js, no always-on process.

Features

  • /ping slash command — replies "Pong!"
  • One-shot /setup endpoint registers commands and points Discord at this val (uses Discord's PATCH /applications/@me API — no manual portal config of the interactions URL)
  • Signed-request verification with native Web Crypto Ed25519 (no npm dep)
  • AGENTS.md — Claude Code can drive the entire setup end to end
  • Easily extensible: add commands by editing lib/discord.ts and the handler in interactions.ts

Setup (~2 minutes)

The fastest path: tell Claude Code "set up this discord bot" and let AGENTS.md drive. Manual path:

  1. Remix this val so you have your own copy.
  2. Create the Discord app at Discord Developer PortalNew Application. Pick a name, accept terms, create.
  3. Paste 3 secrets into your val's environment variables:
    • DISCORD_APP_ID — General Information → Application ID
    • DISCORD_PUBLIC_KEY — General Information → Public Key
    • DISCORD_BOT_TOKEN — Bot tab → Reset Token (shown once)
  4. Run setup — registers /ping and sets the interactions endpoint:
    curl -X POST <your-val-url>/setup \
      -H "Authorization: Bot <DISCORD_BOT_TOKEN>"
    
  5. Invite the bot using the URL returned by step 4 (also shown on the val's homepage).
  6. Type /ping in any channel where the bot is present → "Pong!"

The val's HTTP homepage (GET /) shows live env-var status and copy-pasteable commands — open it after remixing.

Why this exists

Discord doesn't have a Slack App Manifest equivalent — there's no URL that creates a pre-configured app from a JSON blob. But Discord's Edit Current Application API lets you set the interactions endpoint programmatically once you have the bot token, and slash commands have always been registerable via API. This template uses both so the user's only portal work is create app + copy 3 values.

Architecture

discord-bot/
├── interactions.ts       # HTTP entry: setup page + Discord webhook + /setup admin
├── AGENTS.md             # Claude Code setup script
├── README.md
└── lib/
    ├── verify.ts         # Ed25519 signature verification (Web Crypto)
    └── discord.ts        # Discord REST helpers + command definitions

Discord POSTs every interaction to /interactions. The handler verifies the ed25519 signature on (timestamp + body) using DISCORD_PUBLIC_KEY, then replies inline — slash commands return their response in the same HTTP request (no follow-up token needed for fast handlers like /ping).

Customization

  • Add a slash command → add it to PING_COMMANDS in lib/discord.ts, add a case in the APPLICATION_COMMAND handler in interactions.ts, then re-run POST /setup to register it.
  • Long-running command (>3s of work) → respond first with DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE (type 5), then PATCH the original message via /webhooks/{app}/{token}/messages/@original. Or dispatch to a second HTTP route (early-return pattern, see the Slackbot template).
  • Change scopes/permissions in buildInviteUrl() in lib/discord.ts.

Version pinning

This val uses pinned imports to avoid breaking changes:

  1. hono@4.12.0

(Discord API calls use native fetch; signature verification uses native Web Crypto. No other dependencies.)