← All posts

Life TODOs - Notion and Discord

I keep my to-dos in Notion, but I mainly live in Discord. The gap between "I just thought of a task" and "it's captured somewhere I'll actually see it" was exactly long enough for things to fall through. So I wired the two together: a Discord slash command that drops a to-do into a Notion database without leaving the chat.

The whole thing in one line

/todo check 2026 boston tech week

...and a new page shows up in my Notion to-do database, tagged with my Discord username and a Not started status. That's it. No app to open, no context switch.

How it works

It started as Discord's official example app — the rock-paper-scissors demo — which I forked and gutted. The bones were already useful: an Express server that verifies and receives Discord interactions at POST /interactions. I just added one command and one API call.

Discord user ──/todo──▶ Discord API ──POST /interactions──▶ Express server ──▶ Notion API

The Notion side is a few lines with the official SDK — create a page whose parent is the database, set the title from the command's task option, default the status, and stamp the Discord user into a rich-text field:

await notion.pages.create({
  parent: { database_id: databaseId },
  properties: {
    Name:   { title: [{ text: { content: title } }] },
    Status: { status: { name: 'Not started' } },
    // ...Discord User rich text
  },
});

Where it runs

Like where2hit, this lives on my Raspberry Pi — in fact it got there first and became the template everything else copied: a rootless Podman container supervised by systemd, no root, restart-on-boot. The one difference is how the outside world reaches it. A Discord bot doesn't need a website, it needs a stable interactions endpoint URL, so for now that's an ngrok tunnel rather than the Cloudflare Tunnel the web apps use.

Small project, but it's the kind that quietly earns its keep every day.