A minimal Discourse plugin that renders precomputed, site-scoped
outbound reference cards on public topic pages. It never queries the destination, computes
similarity, or matches content at render time — a validated TopicCustomField, populated by an
external job, supplies the ordered links. The plugin's only job is to present that data safely.
Two card kinds ship, each with its own custom field, its own settings, and its own origin allowlist:
| Kind | Custom field | Allow-listed origins |
|---|---|---|
wiki |
wiki_related |
wiki.objectivismonline.com, wiki.freecapitalists.org |
archive |
archive_related |
freecapitalists.org |
The repository name predates the second kind. Both are defined as data in
lib/discourse_wiki_related/kind.rb and share one presenter, so a third destination is a table
entry rather than another copy of the validation code.
In the browser, each enabled card appears as a compact reference strip below the topic title and category, before the first post. The crawler view carries the same ordered links after the posts through Discourse's server-rendered HTML hook.
Communities that run a companion MediaWiki alongside their Discourse forum want topic pages to surface relevant wiki articles. Doing that lookup live, on every page view, is unnecessary work and an unnecessary trust boundary. This plugin keeps rendering dumb and fast: a precomputation step (cron job, admin script, whatever) writes the related links to a topic custom field, and this plugin only ever displays what's already there — after validating it.
The presenter (lib/discourse_wiki_related/presenter.rb) fails closed and suppresses the card
entirely rather than rendering anything malformed:
- rows written for a different community (
site_keymismatch) - rows built for the other card. Both kinds store the same row shape, so a row states its own
kind; a row that states none is a wiki row, which is what every row written before the archive card existed is - rows written for a community that origin is not paired with, which is what stops a Liberty Archive card from ever rendering on Objectivism Online
- links pointing outside that kind's allow-listed origin (host + scheme + no userinfo/port/query)
- malformed or missing stored JSON
- private, unlisted, deleted, read-restricted, or non-public topics
- personal messages (only the default archetype is eligible)
The browser serializer and the crawler-facing HTML builder (server:topic-show-after-posts-crawler)
both call the same presenter, so logged-in users, anonymous visitors, and search-engine crawlers see
identical, identically-validated links.
Add the plugin to your Discourse container the standard way — either clone it into
containers/<container>.yml under plugins: (see the
Discourse install-plugin guide) as:
- git clone https://github.com/DavidVeksler/discourse-wiki-related.gitor, for a development checkout, clone directly into plugins/:
cd plugins
git clone https://github.com/DavidVeksler/discourse-wiki-related.gitThen rebuild/restart Discourse.
The plugin is inert after installation. Configure these site settings per Discourse site (Admin → Settings → Plugins):
| Setting | Purpose | Default |
|---|---|---|
wiki_related_enabled |
Wiki card on/off | false |
wiki_related_wiki_base_url |
Allow-listed wiki origin (https:// scheme, no path/query) |
"" |
wiki_related_heading |
Wiki card heading text | Related on the wiki |
wiki_related_max_links |
Max wiki links shown (1–3) | 3 |
archive_related_enabled |
Archive card on/off | false |
archive_related_base_url |
Allow-listed archive origin | "" |
archive_related_heading |
Archive card heading text | Free on the Liberty Archive |
archive_related_max_links |
Max archive links shown (1–3) | 3 |
The two toggles are independent: there is deliberately no plugin-level enabled_site_setting,
because one would have let the wiki card's switch silently gate the archive card. Enable a kind
last, after its base URL is set and its origin is paired with a site in
lib/discourse_wiki_related/kind.rb.
From a Discourse checkout with this repository installed at plugins/discourse-wiki-related:
bin/lint plugins/discourse-wiki-related
bin/rspec plugins/discourse-wiki-related/specSee AGENTS.md for the doc-routing table used by coding agents working in this repo.
MIT licensed.