Skip to content

A Fedify project · built by the Fedify team

Fediverse bots,
as standalone servers.

BotKit is a TypeScript framework for standalone ActivityPub bots. No Mastodon account and no 500‑character limit: your bot runs as a complete fediverse server, and it fits in a single file.

deno add jsr:@fedify/botkit
The BotKit dinosaur, held on its model-kit runner

No. 01 · some assembly required


A complete bot in one file

Create the bot, answer events, and publish. This is the whole thing, with no accounts to register and no platform to ask permission from.

weatherbot.ts
import { createBot, MemoryKvStore, text } from "@fedify/botkit";

const bot = createBot<void>({
  username: "weatherbot",
  name: "Seoul Weather Bot",
  summary: text`I post daily weather updates for Seoul!`,
  kv: new MemoryKvStore(),
});

// Reply when someone mentions the bot
bot.onMention = async (session, message) => {
  await message.reply(text`It's 18°C with clear skies in Seoul.`);
};

// Publish on a schedule
setInterval(async () => {
  const session = bot.getSession("https://weather.example.com");
  await session.publish(text`Good morning! Today: 22°C, clear skies ☀️`);
}, 1000 * 60 * 60 * 24);
  • createBot() gives the bot an identity and storage. That is the entire setup.
  • onMention and its siblings are just async functions you assign.
  • text`…` builds safe, formatted content: mentions, hashtags, and links included.

Standalone

Its own server, not an account

Each BotKit bot is a complete ActivityPub server, with its own actor, inbox, and outbox. There's no Mastodon or Misskey account to create or maintain, message length is yours to define, and you keep direct control over the database and message queue. It still federates with Mastodon, Misskey, and the rest of the fediverse.

More on standalone bots →
Bot · spec sheet
Actor@weatherbot@example.com
Serverstandalone ActivityPub
Post lengthyours to define
StorageRepository, your backend
FederatesMastodon · Misskey · …

Messages

Rich messages, safely composed

Write posts with the text`…` template. It escapes HTML for you and understands mentions, hashtags, links, and custom emoji. Attach images, open polls, collect emoji reactions, and allow quote posts with consent (FEP‑044f). Choose each post's visibility, then edit or delete it later.

Read about messages →
post.ts
await session.publish(
  text`New chart is up! ${hashtag("BotKit")}`,
  {
    attachments: [new Image({ url, mediaType: "image/png" })],
    visibility: "public",
  },
);

Events

Answer what happens

Assign an async function to respond to activity: mentions, replies, follows and unfollows, quotes, poll votes, and emoji reactions. Every handler receives a session, so it can publish, reply, or react in return.

See all events →
handlers.ts
bot.onFollow = async (session, follower) => {
  await session.publish(text`Thanks for the follow, ${follower}!`, {
    visibility: "direct",
  });
};

bot.onReact = async (session, reaction) => {
  await reaction.message.reply(text`Glad you liked it!`);
};

Instance

Many bots, one server

Need more than one bot? createInstance() owns the shared infrastructure (the key‑value store, queue, repository, and HTTP handling), and each bot on it keeps its own actor, handle, and event handlers. Declare static bots up front, or resolve a whole family of bots from a database on demand.

Read about instances →
instance.ts
const instance = createInstance<void>({ kv: new MemoryKvStore() });

const greetBot = instance.createBot("greet", {
  username: "greetbot",
  name: "Greeting Bot",
});

const echoBot = instance.createBot("echo", {
  username: "echobot",
  name: "Echo Bot",
});

export default instance;

Web

A web presence, out of the box

BotKit serves each bot's own pages: a profile, individual posts, the follower list, hashtag pages, and an Atom feed. They render in the bot's accent color, adapt to light and dark, and you can restyle them with the color, theme, and css options. Nothing extra to deploy.

More on web pages →
Greeting Bot
@greetbot@example.com

I greet everyone who follows me. 👋

128 followers342 posts

Also in the box

Everything else that comes with the framework.

Type‑safe API

Written in TypeScript end to end: autocomplete, compile‑time checks, and typed builders for every message you send.

Follower policy

Approve every follower automatically, or review each follow request yourself before accepting.

Deno and Node.js

Runs on both with minimal dependencies. A whole bot fits in a single TypeScript file.


Built on Fedify

BotKit is the sister project of Fedify, built by the same team. Fedify does the hard part of federation: the ActivityPub protocol, compatibility with Mastodon, Misskey, and the rest of the fediverse, signed message delivery, and retries. BotKit adds the bot on top: events, sessions, messages, and storage.

Learn about Fedify →

Store it and ship it anywhere

BotKit keeps storage behind its own Repository interface, so switching backends never touches your bot code.

Storage

KvRepository adapts any Fedify KvStore (Redis, PostgreSQL, Deno KV, or in‑memory); SqliteRepository, RedisRepository, and PostgresRepository store to those backends directly.


Build your first bot

Install the package and follow the guide, and you'll have a bot on the fediverse in minutes.

deno add jsr:@fedify/botkit