A no-build, offline-capable content wiki. Markdown is the default source format, and project extensions can render additional text formats directly in the browser. Source files remain the source of truth: there is no framework, package install, generated page index, or CDN requirement. This repository includes the runtime and a deployed authoring guide that doubles as its demo.
The engine is designed for project wikis, living design documents, and knowledge bases that should remain easy to read and edit as plain files. A reusable GitHub Action combines the engine with any content repository for publishing, while make serve provides a live local preview.
- Markdown pages rendered directly in the browser.
- Project-defined content renderers for additional text formats.
- Hash-based navigation with shareable page and section links.
- A nested, collapsible sidebar defined in Markdown, including page filtering and adjacent-page navigation.
[[Wiki links]]with optional paths and visible labels.- YAML frontmatter with document statuses:
accepted,in-progress,todo, andreference. - Visual markers for accepted decisions, open work, questions, missing evidence, images, diagrams, and examples.
- Syntax-highlighted fenced code blocks and source-file includes.
- KaTeX formulas and expandable Mermaid diagrams.
- Custom theming through
custom.cssandfavicon.svg, and optional site behavior throughcustom.js. - Vendored browser libraries, so a built wiki does not depend on external services.
There is deliberately no static-site compilation step. make build and the GitHub Action only assemble the engine and public content into a publishable directory; Markdown is still rendered at runtime.
Keep source content, project renderers, and wiki assets in your content repository. The reusable action adds the engine and assembles the publishable site; the surrounding workflow deploys it through GitHub Pages. The content repository never needs to vendor or track the runtime.
Best for: a maintained project wiki with automatic publishing on every push.
Download the Makefile into a content repository and run make build. This installs the engine locally and writes a complete static wiki to .wiki-dist/. Publish that directory with any static host, copy it to another machine, or archive it as a self-contained snapshot.
Best for: non-GitHub hosting, manual releases, and portable or offline snapshots.
Use the Makefile and make build as an installer or scaffold. The generated .wiki-dist/ can become the wiki root: the runtime lives at its top level and editable Markdown lives under .wiki-dist/content/. You can then add or edit content directly in that standalone folder and serve it with any static HTTP server.
Best for: quickly creating a self-contained wiki without adopting the GitHub Action workflow.
In all three modes, the same browser engine renders the same Markdown format. The difference is only how the engine and content are assembled and published.
The content repository root is the wiki content root—there is no engine submodule and no content/ wrapper:
_config.md
_sidebar.md
home.md
images/
custom.css # optional site override
custom.js # optional site JavaScript override
favicon.svg # optional site override
Makefile # optional local preview command
.github/workflows/pages.yml
Every Markdown page requires YAML frontmatter with a title and a status: accepted, in-progress, todo, or reference by default. _sidebar.md defines navigation; _config.md defines the wiki title, description, home page, and optional content extensions.
Put custom.js at the content repository root to run site-wide JavaScript. It is loaded after the engine module starts but before the first page renders; if absent, the engine's empty default file is used. Export a default configure function:
export default function configure({ registerStatus, setStatuses }) {
registerStatus("under-review") // add to the four defaults
// Or replace all defaults: setStatuses(["draft", "published"])
}All pages (including pages from custom renderers) must use one of the resulting statuses. Status names must be lowercase ASCII letters/numbers separated by hyphens; the engine renders them as text and as a status-NAME CSS class. Style new statuses in custom.css, for example .status-under-review { color: purple; }. The configure function may be async. Like content renderer modules, custom.js is trusted code with full browser privileges; use only scripts you control.
A content repository can render non-Markdown text formats without compiling them to Markdown first. Register trusted project-local JavaScript modules in _config.md:
extensions:
- wiki-extensions/gettext.jsAn extension module declares the file extensions it handles and returns page metadata plus rendered HTML:
export default {
extensions: [".po"],
render({ source, path, query, helpers }) {
return {
data: {
title: "Translation catalogue",
summary: path,
eyebrow: "Game text",
status: "in-progress",
},
html: `<pre>${helpers.escapeHTML(source)}</pre>`,
className: "translation-catalogue",
}
},
}Renderer modules are trusted content and run in the browser with the same privileges as the wiki. Paths must remain inside the content repository. Each renderer must declare at least one extension, and two renderers cannot claim the same extension.
Link directly to an extended file, preserving its extension:
[[Game Text/Dialogue.po|Dialogue]]Query parameters are passed to the renderer as URLSearchParams, allowing extension-specific deep links such as:
#/game-text/dialogue.po?entry=dialogue.m01.com01
The render context provides escapeHTML, escapeAttribute, pageURL, and renderMarkdown helpers. Use escapeAttribute for values interpolated inside HTML attributes. A renderer may also define afterRender({ article, path, query, helpers }) for behavior such as scrolling to an extension-specific entry. Project-specific renderer styles belong in the content repository's custom.css.
Add this workflow to the content repository as .github/workflows/pages.yml:
name: Deploy wiki
on:
push:
branches: [release]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/configure-pages@v5
- name: Build wiki
id: wiki
uses: justgook/wiki@release
- uses: actions/upload-pages-artifact@v3
with:
path: ${{ steps.wiki.outputs.path }}
- name: Deploy
id: deployment
uses: actions/deploy-pages@v4Enable GitHub Actions as the Pages source in the repository settings. For stable production use, pin the wiki action to a release tag or commit SHA instead of release.
The action accepts:
source— content directory, default.output— generated site directory, default.wiki-dist
It validates _config.md and _sidebar.md, copies public content, applies optional custom.css, custom.js, and favicon.svg, and returns the absolute generated directory as the path output. Dotfiles, .github/, Makefile, and local wiki folders are not published as content.
Copy this repository's Makefile into a content repository, then run:
make serveOn first use it downloads the engine into .wiki-engine/, then serves the current content directly at http://localhost:8080. Markdown, images, custom.css, custom.js, and favicon.svg remain live: refresh the browser to see edits without rebuilding or restarting the server. It uses Bun, Node.js, Python 3, or Python—whichever is available in that order.
To assemble the same publishable directory produced by the GitHub Action, run:
make buildThis writes .wiki-dist/ using the downloaded engine's scripts/build.sh. Engine and action-output directories should be ignored by Git:
.wiki-engine/
.wiki-dist/Useful overrides:
make serve PORT=3000
make build WIKI_OUTPUT=dist
make serve WIKI_VERSION=v1.0.0
make reinstall-engine
make cleanInside this engine repository, make serve automatically uses the existing content/ demo. In a content repository it serves the current directory; WIKI_SOURCE=path/to/content can override that detection.
For a repository like justgook/imprint-zero:
- Move everything under
content/to the repository root. - Remove the
coresubmodule,.gitmodules, and engine symlinks (app.js,index.html,style.css, andvendor). - Keep
custom.css, optionalcustom.js, andfavicon.svgat the root. - Copy this
Makefile, add the two ignored directories above, and use the publishing workflow shown above.
The deployed Wiki guide documents page metadata, navigation, [[Wiki links]], Markdown syntax, KaTeX formulas, Mermaid diagrams, and VuePress-compatible @[code](path) includes. It is built from this repository's content/ directory using the same action available to consuming repositories.
The runtime has no package install or compilation step. scripts/build.sh content .wiki-dist assembles a site. Third-party browser libraries and their licenses are kept under vendor/ so generated wikis work without CDN dependencies.