Intelligent content moderation at scale. Keep unwanted content off your platform without managing a team of moderators.
Features:
- Moderation Dashboard: View and manage all content moderation activity from a single place.
 - User Lifecycle: Automatically suspend users with flagged content (and handle automatic compliance when moderated content is removed).
 - Appeals Management: Handle user appeals efficiently through email notifications and a user-friendly web form.
 - Powerful Rules & Presets: Create rules to automatically moderate content based on your unique business needs.
 
Install postgres with a username postgres and password postgres:
brew install postgresql
brew services start postgresql
createdb
psql -c "CREATE USER postgres WITH LOGIN SUPERUSER PASSWORD 'postgres';"Install dependencies:
npm iCopy .env.example to .env.local.
Generate a FIELD_ENCRYPTION_KEY:
npx @47ng/cloak generate | head -1 | cut -d':' -f2 | tr -d ' *'Generate a SECRET_KEY:
openssl rand -base64 32Clerk
- Go to clerk.com and create a new app.
 - Name the app and disable all login methods except Email.
 - Under "Configure > Email, phone, username", limit authentication strategies to "Email verification link" and "Email verification code". Turn on "Personal information > Name"
 - (Optional) Under "Configure > Restrictions", turn on "Sign-up mode > Restricted"
 - Under "Configure > Organization Management", turn on "Enable organizations"
 - Under "Configure > API Keys", add 
CLERK_SECRET_KEYandNEXT_PUBLIC_CLERK_PUBLISHABLE_KEYto your.env.localfile. - Under "Organizations", create a new organization and add your email to the "Members" list.
 - Add the organization ID to your 
.env.localfile asSEED_CLERK_ORGANIZATION_ID. - (Optional, for testing) In the Clerk dashboard, disable the "Require the same device and browser" setting to ensure tests with Mailosaur work properly.
 
OpenAI
- Create an account at openai.com.
 - Create a new API key at platform.openai.com/api-keys.
 - Add the API key to your 
.env.localfile asOPENAI_API_KEY. 
Set up the database, run migrations, and add seed data:
createuser -s postgres  # Create postgres superuser if needed
createdb iffy_development
npm run dev:db:setupRun the development server:
npm run devOpen http://localhost:3000 to access the app.
To enable public sign-ups:
# .env.local
ENABLE_PUBLIC_SIGNUP=true
To enable subscriptions and billing with Stripe:
# .env.local
STRIPE_API_KEY=sk_test_...
ENABLE_BILLING=true
Email notifications (optional, via Resend)
In order to send email with Iffy, you will additionally need a Resend API key.
- Create an account at resend.com.
 - Create and verify a new domain. Add the desired from email (e.g. 
no-reply@iffy.com) to your.env.localfile asRESEND_FROM_EMAIL. - Add the desired from name (e.g. 
Iffy) to your.env.localfile asRESEND_FROM_NAME. - Create a new API key at API Keys with at least sending permissions.
 - Add the API key to your 
.env.localfile asRESEND_API_KEY. 
Email audiences (optional, via Resend)
- Create an account at resend.com.
 - Create a new audience (or use the default audience) at Audiences.
 - Add the audience ID to your 
.env.localfile asRESEND_AUDIENCE_ID. - Create a new API key at API Keys with full permissions.
 - Add the API key to your 
.env.localfile asRESEND_API_KEY. - Additionally, go to Clerk and create a new webhook at Webhooks.
 - Use the URL 
https://<your-app-url>/api/webhooks/clerkfor the webhook URL. - Subscribe to the 
user.createdevent. - Add the webhook secret to your 
.env.localfile asCLERK_WEBHOOK_SECRET. 
Natural language AI tests (optional, via Shortest)
In order to write and run natural language AI tests with Shortest, you will additionally need an Anthropic API key and a Mailosaur API key.
- Create an account at anthropic.com.
 - Create a new API key at Account Settings.
 - Add the API key to your 
.env.localfile asSHORTEST_ANTHROPIC_API_KEY. - Create an account at mailosaur.com.
 - Create a new Inbox/Server.
 - Go to API Keys and create a standard key.
 - Update the environment variables:
MAILOSAUR_API_KEY: Your API keyMAILOSAUR_SERVER_ID: Your server ID
 
To run asynchronous jobs, you will need to set up a local Inngest server. In a separate terminal, run:
npm run dev:inngestStart the development server
npm run devStart the local Inngest server (for asynchronous jobs)
npm run dev:inngestRun API (unit) tests
npm run testRun app (end-to-end) tests
npm run shortest
npm run shortest -- --no-cache # with argumentsYou may self-host Iffy Community for free. For more details, see the MIT License.
Here are the differences between the managed, hosted Iffy Cloud and the free Iffy Community version.
| Iffy Cloud | Iffy Community | |
|---|---|---|
| Infrastructure | Easy setup. We manage everything. | You set up a server and dependent services. You are responsible for installation, maintenance, upgrades, uptime, security, and service costs. | 
| Rules/Presets | 9 powerful presets: Adult content, Spam, Harassment, Non-fiat currency, Weapon components, Government services, Gambling, IPTV, and Phishing | 2 basic presets: Adult content and Spam | 

