Enhance documentation structure and content across multiple guides

- Added frontmatter to various markdown files for better metadata handling.
- Updated site URLs in configuration files for consistency.
- Improved content organization and clarity in getting started, server extension, and client addon guides.
This commit is contained in:
Jacob Schmidt 2026-05-16 10:33:17 -05:00
parent 9ab4ff9fd9
commit a4d5c2fd4d
37 changed files with 325 additions and 170 deletions

View File

@ -29,7 +29,7 @@ request and response chunks through the extension transport module.
### Client Addons
Client addons live under `arma/client/addons`. They own local player UX,
keybinds, browser UI dialogs, and UI-to-SQF event handling. When a client needs`
keybinds, browser UI dialogs, and UI-to-SQF event handling. When a client needs
durable or authoritative state, it routes work to the matching server addon
instead of touching persistence directly.

View File

@ -4,7 +4,7 @@ const repoUrl =
const repoBranch = process.env.DOCS_REPO_BRANCH || 'master';
const siteUrl =
process.env.DOCS_SITE_URL ||
'https://innovativedevsolutions.github.io';
'https://innovativedevsolutions.github.io/forge';
export default defineAppConfig({
site: {

View File

@ -1,6 +1,7 @@
# Getting Started
Use this section as the main entry point for the Forge framework.
---
title: Getting Started
description: Use this section as the main entry point for the Forge framework.
---
Forge combines:

View File

@ -1,8 +1,7 @@
# Framework Architecture
Forge is organized around domain modules. A domain usually has SQF addon
entry points, Rust models, repository traits, service logic, extension command
handlers, and optional browser UI.
---
title: "Framework Architecture"
description: "Forge is organized around domain modules. A domain usually has SQF addon entry points, Rust models, repository traits, service logic, extension command handlers, and optional browser UI."
---
## Runtime Flow
@ -29,7 +28,7 @@ request and response chunks through the extension transport module.
### Client Addons
Client addons live under `arma/client/addons`. They own local player UX,
keybinds, browser UI dialogs, and UI-to-SQF event handling. When a client needs`
keybinds, browser UI dialogs, and UI-to-SQF event handling. When a client needs
durable or authoritative state, it routes work to the matching server addon
instead of touching persistence directly.

View File

@ -1,6 +1,7 @@
# Module Reference
This reference lists the main Forge modules and where each layer lives.
---
title: "Module Reference"
description: "This reference lists the main Forge modules and where each layer lives."
---
## Directory Map

View File

@ -1,6 +1,7 @@
# Development Guide
This guide covers the usual path for adding or changing a Forge module.
---
title: "Development Guide"
description: "This guide covers the usual path for adding or changing a Forge module."
---
## Local Checks

View File

@ -1,8 +1,7 @@
# SurrealDB Setup
Forge uses SurrealDB for durable storage. The Rust server extension connects to
SurrealDB on startup and applies Forge schema modules automatically, so setup
comes down to running a reachable database and matching the Forge config.
---
title: "SurrealDB Setup"
description: "Forge uses SurrealDB for durable storage. The Rust server extension connects to SurrealDB on startup and applies Forge schema modules automatically, so setup comes down to running a reachable database and matching the Forge config."
---
## Choose the Right Path
@ -94,9 +93,9 @@ or live server and you are not changing Forge source code.
Official SurrealDB resources:
- [Surrealist installation](https://surrealdb.com/docs/explore/surrealist/installation)
- [Surrealist installation](https://surrealdb.com/docs/surrealist/installation)
- [Surrealist web app](https://app.surrealdb.com)
- [Surrealist local database serving](https://surrealdb.com/docs/explore/surrealist/concepts/local-database-serving)
- [Surrealist local database serving](https://surrealdb.com/docs/surrealist/concepts/local-database-serving)
Recommended approach:

View File

@ -1,8 +1,7 @@
# Forge Server Extension
Forge Server is an arma-rs extension for Arma 3 server-side persistence and
domain services. It exposes game-facing commands and stores durable state in
SurrealDB.
---
title: "Forge Server Extension"
description: "Forge Server is an arma-rs extension for Arma 3 server-side persistence and domain services. It exposes game-facing commands and stores durable state in SurrealDB."
---
## Architecture

View File

@ -1,8 +1,7 @@
# Forge Server API Reference
The Forge server extension exposes domain-oriented commands through
`callExtension`. Persistent data is stored through the configured SurrealDB
connection and schema modules.
---
title: "Forge Server API Reference"
description: "The Forge server extension exposes domain-oriented commands through `callExtension`. Persistent data is stored through the configured SurrealDB connection and schema modules."
---
## Core Commands
@ -39,6 +38,7 @@ needed by `forge_server_addons_extension_fnc_extCall`.
- [Actor](/server-modules/actor)
- [Bank](/server-modules/bank)
- [CAD](/server-modules/cad)
- [Economy](/server-modules/economy)
- [Garage](/server-modules/garage)
- [Locker](/server-modules/locker)
- [Organization](/server-modules/organization)

View File

@ -1,7 +1,7 @@
# Forge Server Usage Examples
These examples use the domain command surface exposed by the extension.
Persistence is handled by the server through SurrealDB.
---
title: "Forge Server Usage Examples"
description: "These examples use the domain command surface exposed by the extension. Persistence is handled by the server through SurrealDB."
---
## Status Check

View File

@ -1,9 +1,7 @@
# Forge Server Common
## Overview
The common addon provides shared SQF utilities used by server-side Forge
addons. It contains lightweight helpers only; gameplay domain state belongs in
the specific domain addons or the Rust extension.
---
title: "Forge Server Common"
description: "The common addon provides shared SQF utilities used by server-side Forge addons. It contains lightweight helpers only; gameplay domain state belongs in the specific domain addons or the Rust extension."
---
## Dependencies
- `forge_server_main`

View File

@ -1,6 +1,7 @@
# Server Module Guides
These pages document the authoritative server-side workflows in Forge.
---
title: Server Module Guides
description: These pages document the authoritative server-side workflows in Forge.
---
Most modules follow the same shape:

View File

@ -1,8 +1,7 @@
# Actor Usage Guide
The actor module stores persistent player character data: identity, loadout,
position, direction, stance, contact fields, state, holster status, rank, and
organization.
---
title: "Actor Usage Guide"
description: "The actor module stores persistent player character data: identity, loadout, position, direction, stance, contact fields, state, holster status, rank, and organization."
---
## Storage Model

View File

@ -1,8 +1,7 @@
# Store Usage Guide
The store module processes checkout requests. It charges a payment source and
grants purchased items to the player locker, virtual arsenal locker, and
virtual garage unlocks.
---
title: "Store Usage Guide"
description: "The store module processes checkout requests. It charges a payment source and grants purchased items to the player locker, virtual arsenal locker, and virtual garage unlocks."
---
## Server SQF Module

View File

@ -1,8 +1,7 @@
# Task Usage Guide
The task module stores transient mission task metadata for active server or
mission lifecycle workflows. SQF still owns Arma-only runtime state such as
objects and participants.
---
title: "Task Usage Guide"
description: "The task module stores transient mission task metadata for active server or mission lifecycle workflows. SQF still owns Arma-only runtime state such as objects and participants."
---
The server addon at `arma/server/addons/task` also owns task execution:
creating BIS tasks, registering task entities, tracking participants, binding

View File

@ -1,8 +1,7 @@
# Bank Usage Guide
The bank module stores player account balances, earnings, PINs, and transaction
strings. The hot-state API also owns the active banking workflows used by the
UI: deposit, withdraw, transfer, checkout charge, and PIN validation.
---
title: "Bank Usage Guide"
description: "The bank module stores player account balances, earnings, PINs, and transaction strings. The hot-state API also owns the active banking workflows used by the UI: deposit, withdraw, transfer, checkout charge, and PIN validation."
---
## Storage Model

View File

@ -1,9 +1,7 @@
# CAD Usage Guide
The CAD module stores transient operational state for dispatch activity,
assignments, dispatch orders, support requests, group profiles, grouped views,
and hydrated UI payloads. CAD state is in-memory and follows the active server
or mission lifecycle.
---
title: "CAD Usage Guide"
description: "The CAD module stores transient operational state for dispatch activity, assignments, dispatch orders, support requests, group profiles, grouped views, and hydrated UI payloads. CAD state is in-memory and follows the active server or mission lifecycle."
---
## Data Model

View File

@ -1,9 +1,7 @@
# Economy Usage Guide
The economy server addon owns Arma-world service behavior for fuel, medical,
and repair interactions. It does not own money state. Money mutations go
through extension-backed bank and organization hot state before the world
effect is applied.
---
title: "Economy Usage Guide"
description: "The economy server addon owns Arma-world service behavior for fuel, medical, and repair interactions. It does not own money state. Money mutations go through extension-backed bank and organization hot state before the world effect is applied."
---
## Dependencies

View File

@ -1,8 +1,7 @@
# Garage Usage Guide
The garage module stores physical player vehicles. Each record keeps the
vehicle classname, generated plate UUID, fuel, overall damage, and detailed hit
point damage.
---
title: "Garage Usage Guide"
description: "The garage module stores physical player vehicles. Each record keeps the vehicle classname, generated plate UUID, fuel, overall damage, and detailed hit point damage."
---
## Storage Model

View File

@ -1,8 +1,7 @@
# Locker Usage Guide
The locker module stores physical player inventory items by classname. It is
separate from the virtual arsenal unlock module documented in
[Owned Storage Usage Guide](/server-modules/owned-storage).
---
title: "Locker Usage Guide"
description: "The locker module stores physical player inventory items by classname. It is separate from the virtual arsenal unlock module documented in [Owned Storage Usage Guide](/server-modules/owned-storage)."
---
## Storage Model

View File

@ -1,8 +1,7 @@
# Organization Usage Guide
The organization module stores organization records, members, assets, fleet
entries, and credit lines. Durable commands manage persisted records directly.
Hot-state commands support the active organization UI workflows.
---
title: "Organization Usage Guide"
description: "The organization module stores organization records, members, assets, fleet entries, and credit lines. Durable commands manage persisted records directly. Hot-state commands support the active organization UI workflows."
---
## Storage Model

View File

@ -1,8 +1,7 @@
# Owned Storage Usage Guide
Owned storage covers the `owned:locker` and `owned:garage` extension command
groups. These modules store unlock lists rather than physical item or vehicle
instances.
---
title: "Owned Storage Usage Guide"
description: "Owned storage covers the `owned:locker` and `owned:garage` extension command groups. These modules store unlock lists rather than physical item or vehicle instances."
---
Use these modules for virtual arsenal and virtual garage unlocks. Use
[Locker Usage Guide](/server-modules/locker) and

View File

@ -1,7 +1,7 @@
# Phone Usage Guide
The phone module stores contacts, messages, and emails for each UID. It is a
server-extension state module backed by SurrealDB.
---
title: "Phone Usage Guide"
description: "The phone module stores contacts, messages, and emails for each UID. It is a server-extension state module backed by SurrealDB."
---
## Storage Model

View File

@ -1,8 +1,7 @@
# Client Usage Guide
Forge Client contains the Arma client-side addons that open player interfaces,
handle browser events, cache client-visible state, and forward authoritative
requests to the server addons.
---
title: "Client Usage Guide"
description: "Forge Client contains the Arma client-side addons that open player interfaces, handle browser events, cache client-visible state, and forward authoritative requests to the server addons."
---
Use this guide as the entry point for client-side integration. Domain data,
validation, persistence, rewards, ownership, and checkout behavior remain

View File

@ -1,7 +1,7 @@
# Client Main Usage Guide
The client `main` addon provides the shared mod identity, version metadata,
CBA settings, and macro foundation used by the Forge client addons.
---
title: "Client Main Usage Guide"
description: "The client `main` addon provides the shared mod identity, version metadata, CBA settings, and macro foundation used by the Forge client addons."
---
## Purpose

View File

@ -1,8 +1,7 @@
# Client Phone Usage Guide
The client phone addon provides the in-game phone UI for contacts, SMS
messages, email, and local utility apps such as notes, calendar events, world
clocks, and alarms.
---
title: "Client Phone Usage Guide"
description: "The client phone addon provides the in-game phone UI for contacts, SMS messages, email, and local utility apps such as notes, calendar events, world clocks, and alarms."
---
## Open Phone UI
@ -26,11 +25,12 @@ Local utility app state is stored in `profileNamespace`:
- alarms
- theme/preferences
## Phone Class
## Phone Repository
`forge_client_phone_fnc_initClass` creates `GVAR(PhoneClass)`.
`forge_client_phone_fnc_initRepository` creates `GVAR(PhoneRepository)`.
The phone class currently owns local notes, events, and settings helpers.
The phone repository owns local notes, events, clocks, alarms, and settings
helpers.
Contacts, messages, and emails continue to use server-backed request/response
events.

View File

@ -1,8 +1,7 @@
# Client Store Usage Guide
The client store addon provides the storefront browser UI for catalog browsing,
category hydration, payment source display, cart handling, and checkout
requests.
---
title: "Client Store Usage Guide"
description: "The client store addon provides the storefront browser UI for catalog browsing, category hydration, payment source display, cart handling, and checkout requests."
---
## Open Store UI

View File

@ -1,7 +1,7 @@
# Client Common Usage Guide
The client `common` addon contains shared browser UI bridge declarations and
common client-side browser integration patterns.
---
title: "Client Common Usage Guide"
description: "The client `common` addon contains shared browser UI bridge declarations and common client-side browser integration patterns."
---
## Purpose

View File

@ -1,8 +1,7 @@
# Client Actor Usage Guide
The client actor addon owns the player interaction menu and client-side actor
repository. It is the main launcher for nearby player actions and other Forge
client UIs.
---
title: "Client Actor Usage Guide"
description: "The client actor addon owns the player interaction menu and client-side actor repository. It is the main launcher for nearby player actions and other Forge client UIs."
---
## Open the Actor Menu

View File

@ -1,8 +1,7 @@
# Client Bank Usage Guide
The client bank addon opens the bank and ATM browser UI, forwards banking
requests to the server bank addon, and pushes account updates back into the
browser.
---
title: "Client Bank Usage Guide"
description: "The client bank addon opens the bank and ATM browser UI, forwards banking requests to the server bank addon, and pushes account updates back into the browser."
---
## Open Bank UI

View File

@ -1,8 +1,7 @@
# Client CAD Usage Guide
The client CAD addon provides the map and dispatch UI for groups, active
tasks, task assignment, dispatch orders, support requests, and task
acknowledge/decline workflows.
---
title: "Client CAD Usage Guide"
description: "The client CAD addon provides the map and dispatch UI for groups, active tasks, task assignment, dispatch orders, support requests, and task acknowledge/decline workflows."
---
## Open CAD UI

View File

@ -1,8 +1,7 @@
# Client Garage Usage Guide
The client garage addon provides player vehicle storage UI, vehicle
store/retrieve actions, selected nearby vehicle service requests, vehicle
context building, and the virtual garage view.
---
title: "Client Garage Usage Guide"
description: "The client garage addon provides player vehicle storage UI, vehicle store/retrieve actions, selected nearby vehicle service requests, vehicle context building, and the virtual garage view."
---
## Open Garage UI

View File

@ -1,7 +1,7 @@
# Client Locker Usage Guide
The client locker addon manages personal locker display state, local locker
container behavior, and virtual arsenal unlock state.
---
title: "Client Locker Usage Guide"
description: "The client locker addon manages personal locker display state, local locker container behavior, and virtual arsenal unlock state."
---
## Repositories

View File

@ -1,7 +1,7 @@
# Client Notifications Usage Guide
The client notifications addon owns the notification HUD, notification sound,
and local notification service used by Forge client and server modules.
---
title: "Client Notifications Usage Guide"
description: "The client notifications addon owns the notification HUD, notification sound, and local notification service used by Forge client and server modules."
---
## Runtime Behavior

View File

@ -1,8 +1,7 @@
# Client Organization Usage Guide
The client organization addon provides the organization portal UI and browser
bridge for login, registration, membership, invites, credit lines, leave and
disband flows, assets, fleet, and treasury display.
---
title: "Client Organization Usage Guide"
description: "The client organization addon provides the organization portal UI and browser bridge for login, registration, membership, invites, credit lines, leave and disband flows, assets, fleet, and treasury display."
---
## Open Organization UI
@ -24,6 +23,7 @@ through `forge_client_org_fnc_handleUIEvents`.
- create/login response routing
- leave and disband requests
- credit-line assignment requests
- payroll and treasury transfer requests
- invite, accept invite, and decline invite requests
- targeted browser response events
@ -37,6 +37,8 @@ through `forge_client_org_fnc_handleUIEvents`.
| `org::disband::request` | Request disband on server. |
| `org::leave::request` | Request leave on server. |
| `org::credit::request` | Request credit-line assignment. |
| `org::payroll::request` | Request payroll payout from the organization treasury. |
| `org::transfer::request` | Request treasury transfer to a member. |
| `org::invite::request` | Request member invite. |
| `org::invite::accept` | Accept invite by org ID. |
| `org::invite::decline` | Decline invite by org ID. |
@ -83,6 +85,24 @@ Credit-line request payload:
}
```
Payroll request payload:
```json
{
"amount": 1000
}
```
Treasury transfer request payload:
```json
{
"memberUid": "76561198000000000",
"memberName": "Player Name",
"amount": 1000
}
```
Invite request payload:
```json

View File

@ -3,7 +3,10 @@ const baseURL =
(process.env.NODE_ENV === 'production' ? '/forge/' : '/');
const siteUrl =
process.env.DOCS_SITE_URL ||
'https://innovativedevsolutions.github.io';
'https://innovativedevsolutions.github.io/forge';
process.env.NUXT_SITE_URL ||= siteUrl;
process.env.NUXT_PUBLIC_SITE_URL ||= siteUrl;
export default defineNuxtConfig({
extends: ['docus'],

View File

@ -35,6 +35,10 @@ const generatedPages = [
source: 'arma/server/docs/usage-examples.md',
target: '2.server-extension/2.usage-examples.md'
},
{
source: 'arma/server/addons/common/README.md',
target: '2.server-extension/3.common.md'
},
{
source: 'docs/ACTOR_USAGE_GUIDE.md',
target: '3.server-modules/1.actor.md'
@ -323,9 +327,10 @@ icon: i-lucide-rocket
},
{
target: '1.getting-started/0.index.md',
content: `# Getting Started
Use this section as the main entry point for the Forge framework.
content: `---
title: Getting Started
description: Use this section as the main entry point for the Forge framework.
---
Forge combines:
@ -421,9 +426,10 @@ icon: i-lucide-layers-3
},
{
target: '3.server-modules/0.index.md',
content: `# Server Module Guides
These pages document the authoritative server-side workflows in Forge.
content: `---
title: Server Module Guides
description: These pages document the authoritative server-side workflows in Forge.
---
Most modules follow the same shape:
@ -555,7 +561,7 @@ for (const page of generatedPages) {
const sourceRel = toPosix(page.source);
const sourcePath = path.join(repoRoot, page.source);
const rawContent = await fs.readFile(sourcePath, 'utf8');
const content = rewriteMarkdownLinks(rawContent, sourceRel);
const content = prepareGeneratedPageContent(rewriteMarkdownLinks(rawContent, sourceRel));
await writeContentFile(page.target, content);
}
@ -591,6 +597,151 @@ function rewriteMarkdownLinks(content, sourceRel) {
});
}
function prepareGeneratedPageContent(content) {
const title = extractFirstH1(content);
const description = extractLeadParagraph(content);
const body = stripMatchingLeadParagraph(stripFirstH1(content), description).trimStart();
const frontmatter = [
'---',
title ? `title: ${yamlString(title)}` : undefined,
description ? `description: ${yamlString(description)}` : undefined,
'---'
].filter(Boolean).join('\n');
return `${frontmatter}\n\n${body}`;
}
function extractFirstH1(content) {
const match = content.match(/^#\s+(.+?)\s*#*\s*$/m);
return match ? match[1].trim() : '';
}
function extractLeadParagraph(content) {
const lines = stripFirstH1(content).split(/\r?\n/);
for (let index = 0; index < lines.length; index += 1) {
const line = lines[index].trim();
if (!line) {
continue;
}
if (!isParagraphStart(line)) {
continue;
}
const paragraph = [];
for (let paragraphIndex = index; paragraphIndex < lines.length; paragraphIndex += 1) {
const paragraphLine = lines[paragraphIndex].trim();
if (!paragraphLine) {
break;
}
paragraph.push(paragraphLine);
}
return normalizeParagraph(paragraph.join(' '));
}
return '';
}
function stripFirstH1(content) {
const lines = content.split(/\r?\n/);
const headingIndex = lines.findIndex((line) => /^#\s+.+/.test(line.trim()));
if (headingIndex === -1) {
return content;
}
lines.splice(headingIndex, 1);
while (headingIndex < lines.length && !lines[headingIndex].trim()) {
lines.splice(headingIndex, 1);
}
return lines.join('\n');
}
function stripMatchingLeadParagraph(content, description) {
if (!description) {
return content;
}
const lines = content.split(/\r?\n/);
let startIndex = 0;
while (startIndex < lines.length && !lines[startIndex].trim()) {
startIndex += 1;
}
if (startIndex < lines.length && /^##\s+overview\s*$/i.test(lines[startIndex].trim())) {
const sectionStart = startIndex;
startIndex += 1;
while (startIndex < lines.length && !lines[startIndex].trim()) {
startIndex += 1;
}
let sectionEnd = startIndex;
const sectionLines = [];
while (sectionEnd < lines.length && !/^#{2,}\s+/.test(lines[sectionEnd].trim())) {
if (lines[sectionEnd].trim()) {
sectionLines.push(lines[sectionEnd].trim());
}
sectionEnd += 1;
}
if (normalizeParagraph(sectionLines.join(' ')) === description) {
while (sectionEnd < lines.length && !lines[sectionEnd].trim()) {
sectionEnd += 1;
}
return [...lines.slice(0, sectionStart), ...lines.slice(sectionEnd)].join('\n');
}
startIndex = sectionStart;
}
if (startIndex >= lines.length || !isParagraphStart(lines[startIndex].trim())) {
return content;
}
let endIndex = startIndex;
const paragraph = [];
while (endIndex < lines.length && lines[endIndex].trim()) {
paragraph.push(lines[endIndex].trim());
endIndex += 1;
}
if (normalizeParagraph(paragraph.join(' ')) !== description) {
return content;
}
while (endIndex < lines.length && !lines[endIndex].trim()) {
endIndex += 1;
}
return [...lines.slice(0, startIndex), ...lines.slice(endIndex)].join('\n');
}
function isParagraphStart(line) {
return !(
line.startsWith('#') ||
line.startsWith('![') ||
line.startsWith('```') ||
line.startsWith(':::') ||
line.startsWith('::') ||
line.startsWith('|') ||
/^[-*+]\s+/.test(line) ||
/^\d+\.\s+/.test(line)
);
}
function normalizeParagraph(value) {
return value.replace(/\s+/g, ' ').trim();
}
function yamlString(value) {
return JSON.stringify(value);
}
function toRoute(target) {
const withoutExt = toPosix(target).replace(/\.md$/i, '');
const parts = withoutExt.split('/');