A House Divided A House DividedDocumentation
Changelog
Game Design/Platform

Wiki System

Last updated 2026-08-21
Source files

Overview#

The wiki is a community knowledge base embedded in the game. It serves two distinct purposes:

  1. Game guides and reference articles - authored by players or admins, covering mechanics, strategy, elections, and congress. These are stored as markdown documents in the wikiPages MongoDB collection.
  2. Auto-generated entity pages - dynamically assembled from live game data at request time, covering politicians (player characters and NPPs), parties, congressional seats, and leadership roles. These do not have entries in wikiPages; they are rendered from DB queries and flavor-text templates.

The wiki is accessible at /wiki/[slug]. All published pages are browsable via /wiki, and search is available site-wide via the navbar.


Page Types#

Manual Pages (stored in wikiPages)#

These are markdown pages that live in the database.

Dynamic Entity Pages (not stored in wikiPages)#

These are served from dedicated app routes that query game data directly:

Route pattern Description
/wiki/party/[id] Party profile: seat counts, member count, economic/social position, flavor text
/wiki/seat/[slug] Office seat: current holder(s) for governor, US Senate class, or House delegation
/wiki/leadership/[role] Congressional leadership role: Speaker, Majority/Minority Leaders and Whips
/character/[id] Canonical public player profile with election history and game-facing context
/politicians/npp/[id] Canonical public NPP profile with election history

Seat slugs follow the pattern {state-lowercase}-{governor|senate-class-1|senate-class-2|senate-class-3|house} (e.g. fl-senate-class-1, ca-governor).


Edit Workflow#

Player-submitted pages go through a review cycle. Admin-created pages bypass review and publish immediately.

(player creates)         (admin reviews)         (admin rejects)
    draft  ──────────>  pending_review  ──────>  draft
                              │
                              └──────────────>  published
                                               (admin approves)
published  ──────────>  archived
           (admin deletes)

Drafts and pending pages return 404 to users who are neither the page author nor an admin.

The editHistory array on each page records every state transition with the acting user's ObjectId, a timestamp, action name (created | edited | approved | rejected | archived), and an optional note (used to store the rejection reason).


Auto-generation#

Politician Election History#

When an election resolves (during turn processing), updatePoliticianPagesAfterElection() in runs for every non-NPP candidate. It writes or updates a document in the politicianOverrides collection with an electionHistory array entry per resolved election. Player characters only - NPPs are skipped.

Each history entry records: electionId, electionType, state, year, result (won/lost), raw vote count, vote percentage, party name, office label, and completion timestamp.

This data is then displayed on the canonical /character/[id] public profile page.

Flavor Text Generation#

For entity pages that have no user-authored content, the system generates templated flavor text at render time:

When page content is loaded via loadWikiContent() in , [[Page Title]] syntax is transformed into markdown links using a title-to-slug map built from all published wikiPages. Broken links render as italic markdown text (_Page Title_).


User Permissions#

Action Who can do it
Read published pages Anyone (unauthenticated or authenticated)
Read draft/pending pages Author or admin
Create a page Any authenticated player (POST /api/wiki)
Edit own page Author (PATCH /api/wiki/[slug]); published edits go to pending_review
Edit any field (incl. status) Admin (PATCH /api/admin/wiki/[slug])
Delete (archive) a page Admin only (DELETE /api/admin/wiki/[slug])
Approve a page Admin only
Reject a page Admin only
Create page bypassing review Admin only (POST /api/admin/wiki)

The canEdit flag returned by GET /api/wiki/[slug] is true for the page's author or any admin. Authors can edit their own pages via PATCH /api/wiki/[slug]; edits to a published page send it back to pending_review for re-approval. Admins use PATCH /api/admin/wiki/[slug] instead, which can update any field including status.


Database#

wikiPages collection#

| Field | Type | Description | | -------------------- | --------------------- | ------------------------------------------------------------ | -------------- | --------- | ------------------------------------------- | --------- | | _id | ObjectId | Standard document ID | | slug | string | Unique URL identifier; lowercase alphanumeric + hyphens | | title | string | Display title | | description | string | Short summary (10-500 chars) | | content | string | Markdown body (50-100,000 chars) | | status | WikiPageStatus | draft | pending_review | published | archived | | submittedBy | ObjectId? | User who created the page | | reviewedBy | ObjectId? | Admin who approved the page | | tags | string[]? | Freeform and system tags; first tag used as primary category | | templateType | string? | References a wikiTemplates document slug | | featured | boolean? | Shown in featured section on wiki home | | difficulty | WikiPageDifficulty? | beginner | intermediate | advanced | | estimatedReadTime | number? | Minutes | | isAutoGenerated | boolean? | True for pages seeded by migration scripts | | autoGenerateConfig | AutoGenerateConfig? | { type: "party | leadership | seat | politician", entityId, widgetComponents? } | | createdAt | Date | | | updatedAt | Date | | | editHistory | EditHistoryEntry[]? | Append-only log of created | edited | approved | rejected | archived |

wikiTemplates collection#

| Field | Type | Description | | ------------- | ----------------- | ---------------------------------------------------------------------------- | -------- | ----------------------------------- | | _id | string | Template slug (used as identifier) | | name | string | Display name | | description | string | What this template is for | | icon | string | Emoji or icon string | | fields | TemplateField[] | Ordered list of form fields with id, label, placeholder, type (text | textarea | markdown), required, and order |

systemTags collection#

Curated tags with display metadata (name, description, icon, Tailwind color class, sort order). Player-created tags are plain strings on wikiPages.tags that do not have a systemTags document.

politicianOverrides collection#

Stores per-politician data that augments auto-generated profile pages. Key field: electionHistory - array of PoliticianElectionEntry objects written after each election resolution.


API Routes#

Public routes#

Method Path Description
GET /api/wiki List all wiki pages (no status filter - returns all)
POST /api/wiki Submit a new page; requires auth; status set to pending_review
GET /api/wiki/[slug] Fetch a single page by slug; enforces status visibility rules
GET /api/wiki/search Full-text search over published pages; params: q, tags (comma-separated), limit
GET /api/wiki/tags Returns system tags (with per-tag page counts) and player-defined tags
GET /api/wiki/templates Returns all wikiTemplates documents
GET /api/wiki/templates/[id] Returns a single template by slug
GET /api/wiki/elections Completed election summaries, grouped by year+type and state+type; supports ?year=&type= and ?state=&type= filters
GET /api/wiki/elections/[id] Full detail for a single completed election: primary results + general results from vote tallies
GET /api/wiki/live-stats Current Congress seat counts by party and active/upcoming election counts; cached 2 min

Admin routes (require admin auth)#

Method Path Description
POST /api/admin/wiki Create a page; published immediately (bypasses review)
PATCH /api/admin/wiki/[slug] Update any field on an existing page including status
DELETE /api/admin/wiki/[slug] Soft-delete: sets status to archived
GET /api/admin/wiki/review-queue List all pending_review pages sorted by creation date
POST /api/admin/wiki/review/[slug]/approve Approve a pending page; optionally apply edits to content, title, description, or tags
POST /api/admin/wiki/review/[slug]/reject Reject a pending page (returns it to draft); requires a reason string

Custom Markdown Components#

Wiki page content supports embedded interactive components via fenced code blocks with a custom language identifier. The registry lives in .

Language identifier Component Description
flowchart-turn TurnProcessingFlowchart Visual diagram of turn processing phases
favorability-decay FavorabilityDecayDiagram Favorability decay curve visualization
senate-classes SenateClassesDiagram Senate class rotation diagram
congress-snapshot CongressSnapshot Live widget showing current House/Senate seat counts
vote-share-calculator VoteShareCalculator Interactive calculator for vote share math

Search Index#

getWikiSearchItems() in src/lib/wiki/searchIndex.ts builds a unified search index used by the navbar search. It merges:

Results are returned as WikiSearchItem objects with a slug, title, description, href, and optional searchText (heading extracts + content snippets).


Redirects#

maps legacy or shorthand slugs to their canonical paths:

Slug Redirects to
democrat /wiki/party/1?country=us
democrats /wiki/party/1?country=us
republican /wiki/party/2?country=us
republicans /wiki/party/2?country=us
election-history /wiki/elections
Country aliases The matching country overview
Feature aliases The matching canonical wiki page

The redirect helper preserves query strings in canonical targets, which is required for country-scoped party pages. Country and feature aliases include common names such as america, britain, ussr, campaign-presence, and independence-referendums; consult WIKI_REDIRECTS for the complete current map.

Connected pages

References →
docsWiki System
← Referenced by
docsWiki System