Automation & CI
Run fandom.js inside cron jobs, GitHub Actions, and ad-hoc maintenance scripts.
Scheduled maintenance
import { Client } from "fandom.js";
import cron from "node-cron";
const client = new Client({ host: process.env.FANDOM_HOST! });
async function bootstrap() {
await client.login(process.env.FANDOM_USER, process.env.FANDOM_PASS);
cron.schedule("*/30 * * * *", async () => {
const recent = await client.revisions.fetchRecent(25);
for (const rev of recent) {
if (rev.comment?.includes("typo")) continue;
console.log(`[lint] ${rev.title} edited by ${rev.user}`);
}
});
}
bootstrap();The example above polls recent changes every 30 minutes and logs notable edits. Because polling already happens
inside EventManager, you can also rely on client.events instead of a cron schedule when building bots that
react instantly.
Content linting
const missingCategories: string[] = [];
const pages = ["Main_Page", "Policies", "Template:Infobox"];
async function lintPolicies() {
for (const title of pages) {
const page = await client.pages.fetch(title);
if (!page.categories.some((c) => c.includes("Policies"))) {
missingCategories.push(title);
}
}
if (missingCategories.length > 0) {
console.warn("[lint] add Category:Policies to", missingCategories);
process.exitCode = 1;
}
}
lintPolicies();Running this script in CI prevents accidental category regressions.
Exporting data
import { createWriteStream } from "node:fs";
const stream = createWriteStream("exports/pages.ndjson");
async function exportMembers() {
const members = await client.categories.fetchMembers(
"Category:Characters",
500,
);
for (const page of members) {
stream.write(
JSON.stringify({ title: page.title, extract: page.extract ?? "" }) + "\n",
);
}
stream.close();
}
exportMembers();Because Page objects keep the client reference, you can immediately call await page.fetchHistory() later in
the pipeline without re-instantiating anything.
GitHub Actions template
name: fandom
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
- run: pnpm install --frozen-lockfile
- run: pnpm test
env:
FANDOM_HOST: https://sonic.fandom.compnpm test runs the full Vitest suite plus the type checker, so you catch regressions before publishing.
Incident response checklist
- Use
client.revisions.fetchRecentto capture the raw changes tied to an outage. - Replay edits by calling
await page.revertTo(revid)for each affected page. - Block offenders quickly with
await client.users.fetch(user).then((u) => u.block('1 day', 'cleanup')).
How is this guide?