Skip to main content

Agent's Guide to Wiki

Agent Guide: Updating BookStack Wiki Pages

This guide outlines how AI agents can directly query, read, edit, and update pages in the self-hosted BookStack Wiki (https://wiki.drheck.dev/).


1. Golden Rules for Agents

🚨 MANDATORY RULE: READ LIVE CONTENT FIRST BEFORE EDITING

NEVER generate or overwrite page content from memory or scratch without first reading the current live page and its latest revisions. Humans frequently make live edits in the BookStack browser interface between agent turns. Overwriting a page without reading its latest markdown and page_revisions destroys user contributions, custom links, code blocks, and embedded images.

Every page update MUST follow this sequence:

  1. Fetch live markdown to a file via /home/luke/bin/read-bookstack-page <page_id> <output_file>.
  2. Query attached images from the images table.
  3. Incorporate existing content, user edits, and image tags into the updated document.
  4. Deploy changes with /home/luke/bin/update-bookstack-page <page_id> <file_path>.
  5. Pull down the live rendered page and verify HTML and KaTeX formula output via /home/luke/bin/verify-bookstack-page <page_id_or_slug>.

🚨 MANDATORY RULE: PULL DOWN & VERIFY THE RENDERED PAGE & FORMULAS AFTER EVERY EDIT

Mathematical formulas ($$...$$ and $...$), signal chains (\longrightarrow), matrices, and TeX output are desired and encouraged across the wiki—but once an edit is made, you MUST pull down the live rendered page and check the output.

Never assume a formula rendered properly just because the Markdown source looks right or LENGTH(html) is non-zero in MariaDB. BookStack's server-side CommonMark parser transforms backslash-punctuation sequences before client-side KaTeX runs, and unquoted shell expansions can corrupt either the page source or the global app-custom-head KaTeX loader.

After every wiki edit, you MUST:

  1. Run /home/luke/bin/verify-bookstack-page <page_id_or_slug> (also executed automatically by update-bookstack-page and create-bookstack-page), which pulls down the live rendered page over HTTPS (https://wiki.drheck.dev/books/<book>/page/<slug>) and validates:
    • Every inline <script> and the global app-custom-head KaTeX auto-render loader in <head> (vm.Script syntax check + intact $$ and $ delimiter verification).
    • Every $$...$$ display formula and $...$ inline formula in the rendered .page-content DOM using real KaTeX 0.16.11 (katex.renderToString with throwOnError: true, strict: 'error').
    • Zero unrendered TeX macros (\text{...}, \longrightarrow, \frac{...}, \begin{...}), stray $$ delimiters, CommonMark-stripped matrix row breaks (\\), CommonMark-stripped percent signs (\%), or accidental $ prose collisions.
  2. Inspect the live rendered HTML of the edited section via curl -skL https://wiki.drheck.dev/books/<book_slug>/page/<page_slug> to confirm clean rendering.

🚨 ABSTRACT DATABASE-INTERNAL IDS FROM USER-FACING TEXT

Never include internal database IDs or object identifiers in user-facing page bodies, changelogs, or documentation summaries. Database IDs are internal implementation details strictly for CLI helper execution (read-bookstack-page <id>, update-bookstack-page <id>). Humans navigate the wiki by title and URL slug. Always use human-readable titles, book names, and standard markdown hyperlinks (e.g. [Setup Detail](https://wiki.drheck.dev/books/setup-detail)), never raw numeric IDs.

🚨 DUAL STORAGE RULE (markdown vs html)

BookStack stores page source in the entity_page_data table:

  • markdown: Source text loaded by BookStack when a page is opened in the browser editor.
  • html: Rendered HTML displayed to public visitors on the website.

Never update html alone! Updating html alone causes the editor to load the outdated markdown column and wipe out HTML changes upon saving. Agents must update the markdown source via the official helper scripts.


2. Environment & Database Access

  • Service Host: ul (ul.drheck.dev)
  • Docker Container (Database): bookstack_db (MariaDB)
  • Docker Container (Web/App): bookstack (runs PHP-FPM as user abc)
  • Env File: /data/docker/bookstack/.env
  • Database Name: bookstackapp

Note on Execution Context: The helper utilities interact directly with local Docker containers on ul (executing artisan as container user abc with HOME=/config so root-owned cache/log files are never created). If the agent is running on another workstation, execute helper commands over SSH to ul using single-quoted outer SSH blocks or heredocs (ssh ul << 'EOF') so $ and $$ in LaTeX formulas are never expanded by the local shell.


Official CLI utilities in /home/luke/bin/ on host ul eliminate shell quoting bugs, SQL newline escaping artifacts, and cache desync:

Step 1: Find Page ID or Book ID by Slug or Keyword

/home/luke/bin/find-bookstack-page <search_term>

Output:

id	name			slug			type
31	System Change log	system-change-log	page

Step 2: Export Live Markdown to a File (MANDATORY)

Export the live markdown directly to a clean file using the base64-safe reader:

/home/luke/bin/read-bookstack-page <page_id> /tmp/page_<page_id>.md

(Do NOT use raw mariadb -e "SELECT markdown..." queries, as the MariaDB CLI client escapes newlines into literal \n strings).

Step 3: Check Attached Images & Revisions

Check image attachments:

sudo docker exec bookstack_db mariadb \
  -ubookstack -p"$(grep DB_PASSWORD /data/docker/bookstack/.env | cut -d= -f2)" \
  bookstackapp -e "SELECT id, name, url FROM images WHERE uploaded_to=<page_id>;"

Step 4: Edit Content Locally in the File

Modify /tmp/page_<page_id>.md, ensuring that all existing user edits, links, and image references (![alt](url)) are preserved.

Step 5: Update Existing Page or Create New Page

To update an existing page:

/home/luke/bin/update-bookstack-page <page_id> /tmp/page_<page_id>.md

To create a new page in a book:

/home/luke/bin/create-bookstack-page <book_id> "<page_title>" <file_path>

These helpers Base64-encode content, invoke BookStack's native PHP PageContent models inside Docker as user abc (artisan tinker), compile both markdown and html columns, update revision tracking, clear the application and view caches, and automatically run /home/luke/bin/verify-bookstack-page against the live rendered URL.

Remember to clean up your temporary file afterwards (rm -f /tmp/page_<page_id>.md).


4. Mandatory Rendered-Page & Formula Verification

After every page update or creation, verify the live rendered output over HTTPS using /home/luke/bin/verify-bookstack-page:

/home/luke/bin/verify-bookstack-page <page_id_or_slug_or_url>

Example Output:

Verified live rendered page: https://wiki.drheck.dev/books/system-setup/page/subocr-service
  Title: subocr service | Math blocks verified: 2 display ($$...$$), 7 inline ($...$)
  STATUS: PASS (0 script errors, 0 KaTeX errors, 0 unrendered TeX blocks)

Also inspect the rendered HTML of any modified formulas or sections directly from the live web server:

curl -skL https://wiki.drheck.dev/books/<book_slug>/page/<page_slug> | grep -C 3 "<search_term>"

Why Database Length Checks Are Insufficient: Checking only SELECT LENGTH(markdown), LENGTH(html) FROM entity_page_data does not detect CommonMark backslash stripping (such as \\ turned into \ or \% turned into a TeX comment %), Markdown <em> tags splitting a formula across DOM text nodes, or JavaScript syntax errors in app-custom-head. Always verify the live rendered page.


5. Advanced Features & Typography Standards for Agents

BookStack on ul is enhanced with rich typographical, mathematical, and layout capabilities. Agents are encouraged to leverage these features:

5.1 KaTeX TeX Mathematical Engine (Globally Enabled)

A client-side KaTeX (0.16.11) rendering engine is active across all wiki pages, paired with server-side KaTeX verification in /home/luke/bin/verify-bookstack-page.

  • Display Equations (Block Math): Enclose in $$ ... $$ on their own lines with blank lines before and after:
    $$\text{FREQ} = \frac{433,920,000}{24,000,000} \times 2^{16} = 1,184,883 = \mathbf{0x121473}$$
    
  • Inline Math: Enclose in single $ ... $ directly within sentences: $T_e = 291.27\text{ }\mu\text{s}$
  • Signal Chains & Architecture Pipelines: Use \longrightarrow with \text{...} for hardware, DSP, and ML pipelines:
    $$\text{Video Frame } I(t) \longrightarrow \text{PP-OCRv5 (MIGraphX FP32)} \longrightarrow \text{Qwen2.5-32B (ROCm)} \longrightarrow \text{UniDic + JMdict/JLPT Study View}$$
    
  • Matrix & cases Row Breaks Require \\\\ (Four Backslashes) or \cr in Markdown: Because BookStack's server-side CommonMark parser unescapes \\ into a single \ before KaTeX runs, writing \\ in Markdown produces \ (a TeX space) in HTML and collapses multi-row matrices onto a single line. Always write \\\\ (four backslashes) or \cr in Markdown so the rendered HTML contains \\:
    $$\begin{pmatrix} y_1 \\\\ y_2 \end{pmatrix} = \begin{bmatrix} a_{11} & a_{12} \\\\ a_{21} & a_{22} \end{bmatrix} \begin{pmatrix} x_1 \\\\ x_2 \end{pmatrix}$$
    
  • Percent Signs Inside Math Require \\\% in Markdown: CommonMark unescapes \% into % in HTML. In TeX/KaTeX, an unescaped % is a comment character that swallows the % symbol and everything up to the closing $. Always write \\\% in Markdown (e.g. $\le 1\\%$) so the rendered HTML passes \% to KaTeX.
  • Subscript / Underscore Safety: Do not put multiple unescaped underscores on the same line in LaTeX (e.g. \text{DRATE_M}...\text{DRATE_E}), as CommonMark will interpret them as Markdown italics (<em>...</em>) and split the DOM text node so KaTeX cannot match the closing $. Use hyphens (e.g. \text{DRATE-M}) or single subscripts (x_1).
  • No Backslash-Punctuation Spacing Macros (\;, \,, \!): Never use backslash-punctuation spacing commands inside Markdown math blocks. CommonMark strips backslashes before ASCII punctuation characters prior to client-side KaTeX rendering, turning \; into a literal ; and \, into a literal ,. Always use alphabetic TeX spacing macros (\quad, \qquad, \text{ }) or rely on built-in relation spacing around \longrightarrow.
  • Wrap Shell/Nginx Variables & Multiple Currency Amounts Carefully: In prose outside code blocks, always wrap $variable names (e.g. `$host`, `$proxy_add_x_forwarded_for`) in backticks so KaTeX does not pair two $ signs in the same paragraph as an inline math expression.

5.2 Native BookStack Callout Banners

Use BookStack's native HTML callout classes for colored, professional alert callouts:

<p class="callout info"><strong>Info Note:</strong> Background context and operational instructions.</p>
<p class="callout success"><strong>Success:</strong> Empirical tests verified with zero errors.</p>
<p class="callout warning"><strong>Warning:</strong> Ensure Word Clock is 75Ω terminated on the final device.</p>
<p class="callout danger"><strong>Danger / Critical:</strong> Never run recursive find commands on host ul.</p>

5.3 Japanese Typography & Furigana (Ruby Text)

HTML5 Ruby annotations are fully supported in page bodies:

  • Whole-word Furigana: <ruby>漢字<rt>かんじ</rt></ruby>
  • Per-character Furigana: <ruby>振<rt>ふ</rt>り<rt></rt>仮<rt>が</rt>名<rt>な</rt></ruby>
  • Japanese in TeX Math: $$\text{周波数 } f = 433.92\text{ MHz}$$

5.4 Collapsible Accordions (<details>)

Use collapsible details to tuck away long raw data logs, register dumps, or secondary tables:

<details>
  <summary><strong>Click to expand technical registers</strong></summary>
  <p>Detailed register addresses and bitfield descriptions go here.</p>
</details>

5.5 High-Resolution Gallery Images with Lightbox Links

To embed images stored in the BookStack gallery with centering, scaling, and lightbox popup support:

<p align="center">
  <a href="https://wiki.drheck.dev/uploads/images/gallery/YYYY-MM/image-name.jpg" target="_blank">
    <img src="https://wiki.drheck.dev/uploads/images/gallery/YYYY-MM/image-name.jpg" alt="Description" width="65%" style="border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); display: block; margin: 0 auto;">
  </a>
  <em style="display: block; text-align: center; margin-top: 6px; font-size: 0.9em; color: #666;">Figure 1: Descriptive caption.</em>
</p>

5.6 Comprehensive Capabilities Reference

For an exhaustive cheat sheet, math examples, and live test cases, refer to: 📖 Meta: Wiki Capabilities, TeX Math & Typography Reference


6. Critical Operational Gotchas for Agents

  1. Always Pull Down & Verify the Live Rendered Page: Run /home/luke/bin/verify-bookstack-page <page_id_or_slug> after every edit to verify live HTTPS delivery, <script> syntax in app-custom-head, and strict KaTeX compilation of every $$...$$ and $...$ formula.
  2. Never Expose Internal Database IDs in Documentation: Do not write internal numeric book or page IDs in user-facing text, changelogs, or documentation summaries. Always use human-readable titles and standard hyperlinks.
  3. Never Parse SQL Output or Update app-custom-head via Double-Quoted Shell Strings: Double-quoted bash strings (ssh ul "..." or mariadb -e "...") strip single quotes and expand $$ into the bash PID, which corrupts both LaTeX formulas and the global app-custom-head KaTeX loader. Always use /home/luke/bin/read-bookstack-page, /home/luke/bin/update-bookstack-page, or hex/base64-encoded payloads.
  4. Strip Top-Level # <Page Title> Headers: BookStack renders the page title as an <h1> header automatically. Strip # <Page Title> from markdown source to prevent duplicate headers.
  5. Preserve Attached Images: Always check for image links before overwriting.
  6. Execute artisan as User abc (-u abc -e HOME=/config -w /app/www): Running artisan as root creates root-owned cache/log files in /config/www/framework/cache and /config/log/bookstack/laravel.log, causing php-fpm (abc) to return HTTP 500 errors.
  7. CommonMark Escaping Inside KaTeX: Use \\\\ (or \cr) for matrix/cases row breaks, \\\% for literal percent signs inside math, and \quad/\qquad/\text{ } instead of \;/\,/\!.