The Modern Forum Starter Kit

An open‑source, self‑hosted forum starter kit. Categories, flat threads, Slate editing, RBAC with custom roles, S3 uploads, moderation queues, and pluggable adapters. Deploy on Vercel or Docker — own your community, own your data.

$npx create-reforum@latest

Categories & Threads

Hierarchical categories with public/private visibility. Flat threads with cursor pagination, slugs for SEO, and soft-deleted states. No recursive comment trees.

Rich Text Editing

Slate-based editor with Markdown and HTML output. Content stored as portable JSON — no editor lock-in. Image uploads integrated directly into the editor.

Permissions, Not Just Roles

Fine-grained RBAC with explicit resource:action checks. Admin-configurable custom roles from a dashboard. Category visibility gated by role or group membership.

Uploads & Storage

S3-compatible presigned direct uploads for avatars and content images. Server-side hash-based filenames and path validation. Local filesystem adapter for development.

Moderation

Flag system with reasons, status workflow (pending → accepted/rejected), and admin command center. Content states: active, hidden, flagged, deleted. Never hard-delete.

Adapter-First Architecture

Pluggable storage, email, realtime, and analytics adapters. Swap providers in config — no code changes. PostgreSQL today, portable tomorrow.

Effortless setup, adapter-first

Configure your forum in one file. Swap any provider — database, storage, email — by changing an import. Everything else stays the same.

// reforum.config.ts
import { createForum } from 'reforum';
import { postgres } from 'reforum/database';
import { s3 } from 'reforum/storage';
import { resend } from 'reforum/email';

export const forum = createForum({
  database: postgres({
    url: process.env.DATABASE_URL,
  }),
  storage: s3({
    bucket: process.env.S3_BUCKET,
    region: process.env.S3_REGION,
  }),
  email: resend({
    apiKey: process.env.RESEND_KEY,
  }),
});
// Swap adapter — no code changes elsewhere
import { createForum } from 'reforum';
import { sqlite } from 'reforum/database';     // swap PG → SQLite
import { local } from 'reforum/storage';        // swap S3 → local FS
import { console as consoleAdapter } from 'reforum/email'; // noop in dev

export const forum = createForum({
  database: sqlite({ path: './data/reforum.db' }),
  storage: local({ directory: './uploads' }),
  email: consoleAdapter(),
});

Built on Next.js, portable by design

Reforum ships as a Next.js app today. The adapter-first architecture keeps your domain logic, services, and API routes framework-independent — so you can migrate when you need to.

Next.js
RemixTanStack StartHonoExpress

Deploy anywhere, customize everything

Self-host on your own infra. Reforum is adapter-first — swap storage, email, and realtime providers in config. Deploy on Vercel, Railway, Coolify, or any Docker host.

import { createForum } from 'reforum';
import { postgres } from 'reforum/database';
import { s3 } from 'reforum/storage';
import { resend } from 'reforum/email';

export const forum = createForum({
  database: postgres({ url: process.env.DATABASE_URL }),
  storage: s3({ bucket: process.env.S3_BUCKET }),
  email: resend({ apiKey: process.env.RESEND_KEY }),
});

Explore by

Every feature is built around real API calls. Categories, flat threads, RBAC, presigned uploads, flag-based moderation, and pluggable adapters — all with typed, composable methods.

import { forum } from '@/lib/forum';

// List categories the current user can see
const categories = await forum.categories.list({
  includePrivate: true,
});

// Create a private category for a team
await forum.categories.create({
  name: 'Core Team',
  slug: 'core-team',
  description: 'Internal discussions for team members',
  isPrivate: true,
  allowedRoleIds: ['role_admin', 'role_moderator'],
});

Start your community today.

Get started