A privacy-first, anonymous forum for AO3 readers to discuss fanfics, built on a
Flarum 2.0 scaffold (forked from
flarum/flarum) plus a custom first-party extension,
ao3/companion.
| AO3-reader need | How it's covered |
|---|---|
| Fandom tags | flarum/tags primary tags — one space per fandom (Harry Potter, Marvel, Anime & Manga, K-Pop & RPF, Books & Lit, Other Fandoms seeded) |
| Pairing/ship tags | Secondary tags (Drarry, Wolfstar, Stucky, Reylo, Rare Pairs, Gen) plus trope tags (Fluff, Angst, Hurt/Comfort, AU, Slow Burn, Fix-It, Canon Divergence, Long Fic). Fetch from AO3 maps the work's canonical relationships onto these ship tags and adds them automatically |
| Spoiler labels | Per-thread "Spoilers through …" scope shown as a badge; [spoiler]…[/spoiler] and [spoiler=Chapter 12]…[/spoiler] collapsed blocks; ||inline|| blacked-out spoiler text |
| Fic recommendation threads | Fic Rec thread type with fic title + AO3 link metadata card and a dedicated sidebar filter; Fetch from AO3 auto-fills the title, archive warnings, and ship tags from a pasted work link |
| Chapter discussion threads | Chapter Discussion thread type with chapter number + spoiler scope on the thread header, plus an optional readalong schedule — a checkpoint timeline (chapter · date) that highlights which chapter the group is reading now |
| "Looking for a fic" posts | Looking for a Fic thread type with its own badge and sidebar filter; the OP (or a mod) can Mark as found, which adds a green Found badge and makes the thread searchable via is:found |
| Content warning filters | Threads carry AO3-style archive warnings (admin-editable vocabulary); each reader picks warnings to filter in Settings → matching threads are blurred in lists, and direct links are blocked by a full-page interstitial until the reader opts in |
| Private / semi-private fandom spaces | Restricted tags with scoped permissions — the seeded Members Lounge is invisible to guests, visible/postable for members and mods |
| Long comments and quote replies | flarum/mentions quote-reply and post mentions; SQLite/MySQL TEXT posts, full Markdown + BBCode |
- No IP retention — the extension nulls poster IP addresses before every post is saved (on by default, admin-toggleable). Mods' "view post IPs" permission is removed.
- Anonymous display names —
flarum/nicknamesis enabled; emails are never exposed via the API and the display name never has to be a real name. - Reader-side content control — spoiler and content-warning filters are personal preferences, visible and writable only by the account that owns them.
- GDPR tooling —
flarum/gdprgives every user self-service data export and erasure requests. - Online status hidden by default — every new account starts with
discloseOnlineoff (opt-in, not opt-out), the mod "view last seen" permission is removed, and the AO3 metadata lookup runs server-side so AO3 never sees reader IPs. - Local-first storage — SQLite by default; no third-party services required to run.
Lives in extensions/ao3-companion and provides:
- Discussion fields:
ao3Type(rec/chapter/lff/general),ao3FicTitle,ao3FicUrl(http/https only),ao3Chapter,ao3SpoilerScope,ao3ContentWarnings(validated against the admin vocabulary). - User fields:
ao3HiddenWarnings,ao3HideSpoilers(self-only visibility). - Composer UI: thread-type select, fic metadata inputs, content-warning checklist.
- Discussion list: type/spoiler/CW badges, CSS blur + click-to-reveal for filtered threads.
- Discussion page: fic metadata card with "Open on AO3" link.
- Server-side
filter[ao3Type]/filter[ao3Solved]for the discussion list, wired to sidebar navigation and to thetype:rec/type:chapter/type:lffandis:foundsearch gambits. - "Edit AO3 details" modal in the discussion controls — the thread starter can always correct their own metadata and content warnings, with no edit-window cutoff.
- Spoiler BBCode + inline spoiler formatter.
GET /api/ao3/work/{id}: server-side AO3 work metadata lookup (title, rating, archive warnings, fandoms, ships, chapter count). Registered users only, and SSRF-safe — the URL is constructed from a numeric work id against a fixed host. Fetched relationships are mapped to forum ship tags via a configurable alias map.- Readalong scheduler: a
Schedule readalongcontrol on chapter threads opens a modal to add checkpoint rows (chapter · label · date); the discussion sidebar renders them as a timeline that marks each checkpoint done / reading-now / upcoming against today's date. - Weekly "still looking" digest: opt-in per user,
php flarum ao3:lff-digest(scheduled weekly) emails subscribers the open Looking for a Fic threads.--dry-runprints the digest instead of sending. Needs mail configured; verified end-to-end via thelogdriver. - Admin settings: warning vocabulary (one per line), IP anonymization toggle, "require a thread type" toggle.
Requirements: PHP ≥ 8.2 (with pdo_sqlite), Composer, Node 18+ (only to rebuild extension JS).
composer install
# install with SQLite (interactive; or use `php flarum install -f <config.json>`)
php flarum install
php flarum extension:enable ao3-companion
php flarum extension:enable flarum-nicknames
php flarum extension:enable flarum-gdpr
php flarum extension:enable flarum-messages
# serve
php -S localhost:8000 -t publicTo rebuild the extension frontend after changing extensions/ao3-companion/js/src:
cd extensions/ao3-companion/js
npm install
npm run build
cd ../../..
php flarum assets:publish && php flarum cache:clearA seed for the fandom/ship tag taxonomy and the Members Lounge permissions is in
docs/seed-tags.sql.
Scaffold: flarum/flarum (MIT). All Flarum bundled extensions are first-party MIT-licensed packages.