A Fedify project · built by the Fedify team
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/botkitNo. 01 · some assembly required
Create the bot, answer events, and publish. This is the whole thing, with no accounts to register and no platform to ask permission from.
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);Standalone
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 →Messages
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.
await session.publish(
text`New chart is up! ${hashtag("BotKit")}`,
{
attachments: [new Image({ url, mediaType: "image/png" })],
visibility: "public",
},
);Events
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 →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
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.
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
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 →I greet everyone who follows me. 👋
Everything else that comes with the framework.
Written in TypeScript end to end: autocomplete, compile‑time checks, and typed builders for every message you send.
Approve every follower automatically, or review each follow request yourself before accepting.
Runs on both with minimal dependencies. A whole bot fits in a single TypeScript file.
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 → BotKit keeps storage behind its own Repository interface, so switching backends never touches your bot code.
KvRepository adapts any Fedify KvStore (Redis, PostgreSQL, Deno KV, or in‑memory); SqliteRepository, RedisRepository, and PostgresRepository store to those backends directly.
Install the package and follow the guide, and you'll have a bot on the fediverse in minutes.
deno add jsr:@fedify/botkit