---
id: page-wiki-engine
slug: wiki-engine
title: Wiki engine
summary: Static wiki engine designed for AI-collaborative knowledge bases. Compiles markdown sources into themed HTML, clean markdown twins, talk pages, and machine-readable corpus files; defines a per-page edit contract with sign-off-tracked provenance.
doc_id: project-wiki-engine
section: project
tags: [project, engine, architecture, build, ssg]
canonical_url: /wiki-engine.html
md_url: /wiki-engine.md
llms_section_url: /llms-full.txt
last_updated: 2026-04-21
version: 6
access: public
source_type: authored
alternate_formats:
  html: /wiki-engine.html
  mcp_handle: 1context://wiki-engine
---

The **1Context wiki engine** is a static wiki engine for
AI-collaborative knowledge bases. It compiles markdown source files
into the surfaces a wiki needs — themed HTML, machine-readable
corpus files, sibling discussion pages, and an auto-generated
provenance log — from a single authoring step. It is part of the
broader 1Context system and was extracted from a
[BookStack](https://www.bookstackapp.com/) theme module into a
standalone engine in April 2026.

The engine belongs to the static-build category of wiki software,
alongside [Quartz](https://quartz.jzhao.xyz),
[Foam](https://foambubble.github.io/foam/),
[MkDocs](https://www.mkdocs.org/), and
[Obsidian Publish](https://obsidian.md/publish). What distinguishes
it from those peers is that AI agents are treated as first-class
readers and authors rather than incidental ones. Every page is
fetchable as both themed HTML and clean markdown. Machine-readable
corpus files following the [llms.txt convention](https://llmstxt.org/)
are emitted automatically. Every page may carry a sibling
discussion file in an
[LKML-flavored Wikipedia-talk format](/talk-conventions). Every
modification is governed by an explicit sign-off contract, and the
resulting provenance is recorded by the engine in a per-page
history file rather than in author-maintained frontmatter.

The engine is at version 0.3.0 (pre-1.0; breaking changes expected)
as of April 2026. It powers the 1Context wiki itself, including
this article: the page describing the engine is rendered by the
engine that is the article's subject — a self-bootstrap pattern
common to language compilers and one that converts any drift between
documented behavior and actual behavior into a build-time bug
rather than a documentation lag.

::: infobox
### Fast facts

- **Category:** Static wiki engine
- **Closest peers:** Quartz, Foam, MkDocs, Obsidian Publish
- **Source format:** Markdown with YAML frontmatter
- **Outputs:** themed HTML, markdown twin, talk surface, history log, `llms.txt`, `llms-full.txt`, `docs-index.json`
- **Storage:** adapter-based (default: filesystem; planned: Puter DB, BookStack, Git)
- **Version:** 0.3.0 (April 2026)
- **License:** TBD
- **Repository:** `wiki-engine/` in [hapticasensorics/bookstack-opcontext-module](https://github.com/hapticasensorics/bookstack-opcontext-module)
:::

## History

### Origins as a BookStack module

The engine began life as a theme module for
[BookStack](https://www.bookstackapp.com/), a self-hosted PHP wiki,
in the early months of 2026. The module added 1Context-specific
surfaces — clean markdown twins, agent-discovery files, themed page
chrome — to a stock BookStack installation, on the working
assumption that BookStack itself would supply storage, editing, and
authentication for the long term.

That assumption shifted as the module grew. By April 2026, the
load-bearing work consisted of the rendering pipeline, the theme,
the talk-page parser, and the agent-surface generator — none of
which depended meaningfully on BookStack's PHP backend. The
remaining BookStack-specific code (`functions.php`, `views/`,
`bookstack-module.json`) was a smaller surface than the engine
itself, and BookStack's role was reframed: rather than the
foundation, it became one possible storage backend among several,
accessible through a planned `BookStackAdapter` (see
§ Storage adapters).

### Extraction and bootstrap

In April 2026 the engine code was migrated into a dedicated
`wiki-engine/` directory at the repository root, the BookStack
module artifacts were removed, and the engine was renamed to
reflect its new standalone scope. Three numbered releases punctuated
the transition:

| Version | Date | Notable change |
| --- | --- | --- |
| 0.1.0 | April 2026 | Initial scope-marker release; engine code still in `css/`, `preview/js/`, `tools/`. |
| 0.2.0 | April 2026 | Engine code migrated to `wiki-engine/`; theme, JS, and tooling relocated under one root. |
| 0.2.1 | April 2026 | Markdown-to-HTML renderer scaffold landed (`renderPage()`, frontmatter validator, TOC builder, page template). |
| 0.3.0 | April 2026 | "Bootstrap" milestone: this article was rendered through the engine for the first time, replacing a hand-authored HTML version. |

The 0.3.0 release is structurally important. From v0.3.0 onward,
any drift between the engine's design statements (in this article)
and its actual behavior is, by construction, a real bug rather than
a documentation lag — a property the project shares with
self-hosting language compilers such as those described in
[bootstrapping (compilers)](https://en.wikipedia.org/wiki/Bootstrapping_(compilers)).
The deployed page's HTML carries
`<meta name="generator" content="1Context wiki-engine">`, making
the bootstrap externally verifiable.

Versions are tracked in the engine's
[CHANGELOG.md](https://github.com/hapticasensorics/bookstack-opcontext-module/blob/main/wiki-engine/CHANGELOG.md);
pre-1.0 releases are expected to make breaking changes.

## Design

### Static-first

The engine compiles the wiki at build time and deploys the result
to a static host (currently
[Cloudflare Pages](https://pages.cloudflare.com/)). This places it
in the static-build category of wiki software, alongside
[Hugo](https://gohugo.io), Quartz, Foam, and MkDocs.

The static-first decision was made not for ideological reasons but
because it makes the load-bearing engine work — rendering,
talk-page parsing, agent-surface generation, discovery-file
emission — shippable without first solving the harder problems
characteristic of runtime-editable wikis like
[MediaWiki](https://en.wikipedia.org/wiki/MediaWiki),
[Confluence](https://en.wikipedia.org/wiki/Confluence_(software)),
and [Notion](https://en.wikipedia.org/wiki/Notion_(productivity_software)):
authentication, conflict resolution, real-time push, and continuous
server operations. Git provides collaboration history, audit,
rollback, and offline editing as an effect of source-of-truth being
plain files in version control. A planned runtime-editable layer is
described in § Future development; it is intended to layer on top
of the static system rather than replace it.

### Engine and content separation

The codebase observes a Hugo-style separation between the engine
and the content of any particular wiki built on top of it. Material
that two different 1Context-style wikis would share belongs in the
engine; material specific to a particular wiki belongs in the
content directory. The boundary is documented in the engine's
[SCOPE.md](https://github.com/hapticasensorics/bookstack-opcontext-module/blob/main/wiki-engine/SCOPE.md)
and is enforced by directory layout rather than by code.

| Engine (`wiki-engine/`) | Content (`preview/public/`, eventually `content/`) |
| --- | --- |
| Renderer (markdown → HTML) | Page sources (`.md` with frontmatter) |
| Theme (CSS) and chrome (interactive JS) | Talk pages (`.talk.md`) |
| HTML page templates | Static assets (images, embedded media) |
| Build tools (discovery generator, link-graph validator, audience-tier filter, deploy scripts) | Site-specific configuration (deployment URLs, branding overrides, audience policy) |
| Storage adapters | Page prose itself |
| Schemas (frontmatter, talk-page format, manifest) | |

The boundary scales: the engine grows when capabilities are added
that all wikis would want; the content directory grows when a
particular wiki adds pages, talk discussions, or assets.

### Storage adapters

The renderer reads page content through a small `Adapter` interface
and does not assume markdown-on-disk indefinitely. Adapters return
content in a normalized shape (`{ slug, frontmatter, body }`); the
renderer is unaware of the underlying storage mechanism.

The default adapter, `StaticMarkdownAdapter`, reads `.md` files
from a local directory. Several other adapters are planned but not
yet implemented:

- **`PuterDBAdapter`** — backed by [Puter](https://puter.com)'s
  key-value store, allowing a 1Context wiki to operate without
  checked-in markdown files, with the database as source of truth.
- **`BookStackAdapter`** — backed by a BookStack instance's REST
  API, restoring the original BookStack-module use case as one
  option among several rather than as a hard dependency.
- **`GitAdapter`** — backed by a remote git repository's working
  tree, useful for read-only mirrors of a remote source.
- **`MemoryAdapter`** — used for testing; holds adapter state in
  process memory.

The adapter pattern is a textbook
[adapter design pattern](https://en.wikipedia.org/wiki/Adapter_pattern)
application: the renderer programs against the abstract interface,
and the choice of concrete adapter is a deployment-time decision
rather than a code-time decision.

## Authoring model

A page in a 1Context wiki is a single markdown file with YAML
frontmatter, addressed by a kebab-case slug. The engine compiles
each authored source into multiple surfaces (see § Output surfaces)
and extends standard CommonMark with a small vocabulary of
structured directives (see § Directives) for patterns that bare
markdown does not express well. Provenance and history are not
written by the author; they are maintained by the engine itself
under the rules of an explicit edit contract (see § Edit contract).

### Page source

Each page lives at `content/pages/{slug}.md` (currently
`preview/public/{slug}.md`). The file consists of YAML frontmatter
delimited by `---` followed by a markdown body. The page template
emits the H1 and subtitle from the `title` and `summary`
frontmatter fields, so the body of an authored page begins directly
with the lead paragraph rather than with a top-level heading.

A minimal page is small:

```yaml
---
title: Hello world
slug: hello-world
section: project
access: public
summary: My first 1Context page.
last_updated: 2026-04-21
---

Lead paragraph here. The body starts directly, not at an H1.

## A section heading

Some content. The TOC entry, the slug anchor, the copy-as-markdown
button, and this section's appearance in the wiki-wide corpus all
happen without further authoring.
```

### Frontmatter

Every page-level setting that varies across pages is expressible in
frontmatter, so an authoring agent does not need to leave the
source file to change how the page behaves. Reader-side preferences
(theme, font size, layout) live in the customizer and persist in
`localStorage`; frontmatter only sets per-page *defaults* that the
customizer respects when a reader has expressed no preference of
their own.

The validator at
[`wiki-engine/src/renderer/frontmatter.mjs`](https://github.com/hapticasensorics/bookstack-opcontext-module/blob/main/wiki-engine/src/renderer/frontmatter.mjs)
enforces the schema. Typos in known enum fields fail the build with
a clear message; unknown fields pass through silently for
forward-compatibility with future engine versions and per-site
plugins.

The schema is grouped by purpose. Identity fields are required;
everything else is optional with sensible defaults.

#### Identity

| Field | Type | Notes |
| --- | --- | --- |
| `title` | string | Rendered as `<h1>` and `<title>`. |
| `slug` | string | Kebab-case, ≤60 chars, alphanumeric start. |
| `section` | enum | `project` · `reference` · `ops` · `api` · `product` |
| `access` | enum | `public` · `shared` · `private` |

#### Access control

| Field | Type | Notes |
| --- | --- | --- |
| `shared_with` | string list | Required when `access: shared`. |
| `requires_auth` | boolean | Override; default derived from `access`. |

#### Display defaults

These values express a *recommended* presentation that the reader's
customizer respects when no per-reader preference has been set. The
engine never overrides a reader who has expressed an explicit
choice in localStorage.

| Field | Type | Default | Values |
| --- | --- | --- | --- |
| `theme_default` | enum | `auto` | `light` · `dark` · `auto` |
| `article_width` | enum | `m` | `s` · `m` · `l` |
| `font_size` | enum | `m` | `s` · `m` · `l` |
| `border_radius` | enum | `rounded` | `rounded` · `square` |
| `links_style` | enum | `underline` | `underline` · `color` |
| `cover_image` | enum | `show` | `show` · `hide` |
| `article_style` | enum | `full` | `full` · `pics` · `text` |

#### Structural toggles

The engine assumes every chrome feature should appear on every page;
toggles let a particular page suppress one selectively.

| Field | Type | Default | Effect when `false` |
| --- | --- | --- | --- |
| `toc_enabled` | boolean | `true` | Hides the TOC sidebar. |
| `talk_enabled` | boolean | `true` | Hides the Talk button. |
| `agent_view_enabled` | boolean | `true` | Hides the Agent toggle. |
| `copy_buttons_enabled` | boolean | `true` | Hides the per-section copy buttons. |
| `footer_enabled` | boolean | `true` | Suppresses the site footer. |
| `search_indexed` | boolean | `true` | Excludes the page from site search. |
| `noindex` | boolean | `false` | Emits `<meta robots="noindex,nofollow">`. |

#### Lifecycle

Status, supersession, and deprecation are first-class so the
reader sees an inline banner without an author having to
hand-author one. The engine emits the banner automatically when
`status` differs from `published` or when `deprecation_notice` is
set.

| Field | Type | Notes |
| --- | --- | --- |
| `last_updated` | ISO date | Last meaningful authoring change. |
| `version` | integer | Bumped on substantive revisions. |
| `status` | enum | `draft` · `published` · `archived` · `superseded` (default `published`). |
| `superseded_by` | slug | Required when `status: superseded`. |
| `expires_at` | ISO date | Optional auto-archive trigger. |
| `deprecation_notice` | string | Overrides the auto-generated banner copy. |

#### Discoverability

| Field | Type | Notes |
| --- | --- | --- |
| `summary` | string | Page subtitle and OpenGraph description. |
| `tags` | string list | Free-form taxonomy. |
| `keywords` | string list | Emitted as `<meta name="keywords">`. |
| `language` | IETF tag | Emitted as `<html lang="…">` (default `en`). |

#### Content metadata

| Field | Type | Notes |
| --- | --- | --- |
| `canonical_url` | string | |
| `md_url` | string | Overrides the default `/{slug}.md`. |
| `alternate_formats` | object | Extra format pointers (e.g. `mcp_handle`). |
| `related` | string list | Programmatic relations beyond `:::see-also`. |
| `parent` | slug | Parent page for breadcrumb-style lineage. |
| `source_type` | enum | `authored` · `imported` |

### Directives

The engine extends standard [CommonMark](https://commonmark.org/)
with a small vocabulary of block-level directives, all using
[Pandoc fenced-div](https://pandoc.org/MANUAL.html#extension-fenced_divs)
syntax: an opening line `:::name args`, body content, and a closing
`:::` on its own line.

| Directive | Purpose |
| --- | --- |
| `:::infobox` | Wraps a fast-facts sidebar in `<aside class="infobox">`. Body is full markdown. |
| `:::main-article slug` | Emits a Wikipedia-style hatnote pointing at a canonical sub-article. The slug becomes the link target; the human-readable title is derived from the slug. The block has no body. |
| `:::see-also` | Wraps a related-pages list at the bottom of an article in an H2-plus-list block. |
| `:::audience tier` | Wraps a section for the planned audience-tier build pipeline. Tier is `internal`, `public`, or `both`. |

The vocabulary is deliberately small. Adding a directive is treated
as a wiki-policy change rather than an unannounced code change: a
`[PROPOSAL]` topic on the engine's
[talk page](/talk.html?page=wiki-engine) precedes implementation,
so the surface area stays small enough for an authoring agent to
keep in working memory.

### Edit contract

Provenance is the engine's responsibility, not the authoring
agent's. Frontmatter does not contain author, model identifier, or
revision-history fields; those would couple the source file to a
particular edit, requiring agents to remember to update them and
allowing them to lie if they did not. Instead the engine maintains
a per-page sibling file at `pages/{slug}.history.md`, append-only,
that records every edit and every render: who made the change, when,
what changed, and why.

The trail is enforced by a contract on the edit, not on the source
file. Every edit must be **signed off** by the editing agent. A
sign-off carries an identity (agent name plus model version, or
human email), an ISO-8601 UTC timestamp, and a one-line edit
message describing the change.

In static-build mode (the configuration shipped today) sign-off is
derived from git commit metadata plus a `Signed-off-by:` trailer
following the
[Linux kernel convention](https://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin).
The render pipeline reads `git log` for each touched source file
and appends a `[HISTORY]` topic to that page's history file. Commits
without a sign-off trailer fail the pre-commit hook.

In runtime mode (planned, see § Future development) the write API
requires a `sign_off` field on every modification request, and
unsigned writes are rejected at the edge before any state changes.

History files are reachable two ways: as raw markdown at
`/{slug}.history.md` for agents and external systems, and themed
via the existing talk-page renderer at
`/talk.html?page={slug}&track=history`. The same parser and UI
conventions apply; provenance is structurally just another talk
discussion that the engine authors automatically.

## Output surfaces

For every authored markdown source the engine emits the following
per-page surfaces:

| Surface | URL | Notes |
| --- | --- | --- |
| Themed HTML | `/{slug}` | Human-readable Reader view. |
| Markdown twin | `/{slug}.md` | Agent fetch target; frontmatter preserved. |
| Talk surface | `/{slug}.talk.md`, `/talk.html?page={slug}` | Present when a `.talk.md` sibling file exists. |
| History surface | `/{slug}.history.md`, `/talk.html?page={slug}&track=history` | Auto-maintained per the edit contract. |
| Index entry | inside `/docs-index.json` | Page metadata as structured fields. |
| Corpus entry | inside `/llms-full.txt` | Body folded into the wiki-wide corpus with [llms.txt-style](https://llmstxt.org/) separators. |

For the wiki as a whole the engine emits three corpus-wide files:

| File | Purpose |
| --- | --- |
| `/llms.txt` | Curated index following the [llms.txt convention](https://llmstxt.org/), suitable as a single-fetch overview for a language model. |
| `/llms-full.txt` | Concatenated authored content, formatted for machine consumption. |
| `/docs-index.json` | Array of every page's frontmatter, suitable as a search or routing index. |

### Engine-managed surfaces

In addition to the per-page and corpus outputs, the engine emits a
number of derived surfaces automatically. These do not require
authoring; they are functions of the markdown body, the
frontmatter, or the page set as a whole:

- The H1 and subtitle, derived from `title` and `summary`.
- A table-of-contents nav from H2/H3 headings, with stable slug
  anchors.
- Header chrome (brand mark, search input, tier badge derived from
  `access`).
- Reader / Agent / Talk view toggles in the header.
- Per-section "copy as markdown" buttons next to each H2 and H3.
- A mobile-hardened layout (off-canvas TOC drawer,
  scroll-direction-reveal header, safe-area insets, touch-action
  containment).
- A theme system (light, dark, or system-auto) with a no-flash
  bootstrap script.
- A status banner when `status` differs from `published` or
  `deprecation_notice` is set.
- A footer banner identifying the wiki as "1Context by Haptica".
- A favicon.
- A `<link rel="alternate" type="text/markdown">` element pointing
  at the markdown twin.
- OpenGraph and `<meta name="keywords">` tags derived from
  frontmatter.
- The `<html lang="…">` attribute from `language`.
- `data-*` attributes carrying the page's display defaults so the
  customizer respects page-level recommendations.
- An append to `.history.md` on every render or edit.

## Future development

The engine is currently a pure static-build system: source files
become HTML at compile time, the deployed wiki is a CDN-served
bundle, and edits propagate through git. A runtime-editable layer
is planned, designed to layer onto the static path rather than
replace it.

The wider wiki-software ecosystem distinguishes between two
coherent design points:

| Design point | Examples | Edit path |
| --- | --- | --- |
| Static-build | Hugo, Quartz, Foam, MkDocs, this engine today | Source files become HTML at build time; edits go through version control. |
| Runtime-editable | MediaWiki, Confluence, Notion, Obsidian Publish | Source lives in a database; the server renders on demand; edits go through HTTP APIs and propagate live. |

The engine occupies the static-build position today and is designed
so the runtime layer can land incrementally rather than as a fork.
The planned runtime additions are:

- A small **write API** through which authenticated users can post
  to talk pages or edit articles from a browser, with the server
  appending to the underlying source file and triggering a rebuild.
- A **change-notification stream**
  ([Server-Sent Events](https://en.wikipedia.org/wiki/Server-sent_events)
  or [WebSocket](https://en.wikipedia.org/wiki/WebSocket)) so
  connected clients see updates without polling.
- A **sync agent**, separable from the engine core, that mirrors a
  remote adapter into a user's local file tree in a Dropbox-like
  fashion, supporting users who prefer a local editor.
- Real-time **multi-cursor editing**, layered over the write API as
  either a
  [conflict-free replicated data type](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type)
  or operational-transformation system, if demand warrants the
  additional complexity.

The `Adapter` interface is the seam that makes layered evolution
possible. `StaticMarkdownAdapter` operates against the filesystem;
a future `PuterDBAdapter` would operate against Puter's KV store; a
hypothetical `HybridAdapter` could read from disk while writing
through the API. Because the renderer is adapter-agnostic, the
static path continues to function as runtime capabilities light up
incrementally.

The order in which the runtime pieces land — and the choice of
backend they target — are open coordination questions tracked on
the [talk page](/talk.html?page=wiki-engine).

## Status

The engine is at version 0.3.0 (April 2026). Work is tracked
publicly on the engine's
[talk page](/talk.html?page=wiki-engine), where each roadmap item
carries a `[TODO]` topic that contributors claim, discuss, and
resolve via `[DECIDED]` replies, following the
1Context [talk-page conventions](/talk-conventions).

Headline roadmap items, ordered by their internal P-numbers:

| ID | Item | State |
| --- | --- | --- |
| P1 | Markdown → HTML renderer pipeline | Renderer scaffold landed in v0.2.1; build wiring pending. |
| P2 | Engine code migrated into `wiki-engine/` | Complete in v0.2.0. |
| P3 | Storage-adapter interface | Not started. |
| P4 | Content folder split | Not started. |
| P5 | Audience-tier pipeline (build-time filter, link-graph CI) | Not started. |
| P6 | Command-line interface (`wiki-engine init/build/dev/deploy`) | Not started. |
| P7 | Engine repo extraction (publish as standalone npm package) | Not started. |

Additional design proposals not yet given P-numbers, all documented
on the talk page: auto-generated `.history.md` plus sign-off
enforcement (declared in v0.3.0 spec, implementation pending),
link-integrity validation, asset handling, authoring error UX, and
discoverability and search.

::: see-also
- [1Context project](/1context-project) — parent overview of the system the engine is part of
- [Agent UX (AX)](/agent-ux) — agent-surface design philosophy the engine implements
- [Talk page conventions](/talk-conventions) — discussion-page format and editorial rules
:::

## References

- [SCOPE.md](https://github.com/hapticasensorics/bookstack-opcontext-module/blob/main/wiki-engine/SCOPE.md) — engine vs content boundary
- [ROADMAP.md](https://github.com/hapticasensorics/bookstack-opcontext-module/blob/main/wiki-engine/ROADMAP.md) — numbered priorities
- [CHANGELOG.md](https://github.com/hapticasensorics/bookstack-opcontext-module/blob/main/wiki-engine/CHANGELOG.md) — release history
- [docs/architecture.md](https://github.com/hapticasensorics/bookstack-opcontext-module/blob/main/wiki-engine/docs/architecture.md) — layered model and key types
