aRustyDev / aRustyDev/mdbook-htmx

docs(mdbook-htmx): book.json / manifest.json

Open
#34 0 comments 0 reactions 1 assignee Claimed by @aRustyDev View on GitHub
documentation
Dominant language
Rust
Stars
0
Forks
1
PR merge metrics
No merged PRs in 30d

Description

# Manifest Reference

This document provides a complete reference for the `manifest.json` file generated by mdbook-htmx.

## Overview

The manifest is a JSON file that describes all pages, their metadata, navigation structure, and authorization requirements. It serves as the contract between the build-time generator and runtime server.

```json
{
"$schema": "https://schemas.arusty.dev/mdbook-htmx/manifest.schema.json",
"version": "1.0.0",
"generated": "2026-01-04T12:00:00Z",
"book": { ... },
"pages": [ ... ],
"navigation": { ... }
}
```

---

## Schema Reference

Manifests are validated against the JSON Schema at:
```
https://schemas.arusty.dev/mdbook-htmx/manifest.schema.json
```

---

## Top-Level Fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `$schema` | string | No | JSON Schema URL for validation |
| `version` | string | Yes | Manifest schema version (semver) |
| `generated` | string | Yes | ISO 8601 build timestamp |
| `book` | object | Yes | Book-level metadata |
| `pages` | array | Yes | Array of page entries |
| `navigation` | object | Yes | Navigation structure |
| `authn` | object | No | Authentication configuration |
| `scopes` | object | No | Scope configuration |

---

## Version Field

The version field uses semantic versioning:

```json
{
"version": "1.0.0"
}
```

| Version Part | When to Increment |
|--------------|-------------------|
| Major | Breaking changes to manifest structure |
| Minor | New optional fields added |
| Patch | Bug fixes, documentation updates |

Server implementations should:
1. Parse the major version
2. Reject manifests with unsupported major versions
3. Ignore unknown fields for forward compatibility

---

## Book Metadata (`book`)

| Field | Type | Description |
|-------|------|-------------|
| `title` | string | Book title |
| `description` | string | Book description |
| `authors` | string[] | Author names |
| `language` | string | Language code (e.g., "en") |
| `baseUrl` | string | Base URL for the documentation |

### Example

```json
{
"book": {
"title": "My Documentation",
"description": "Complete reference for My Project",
"authors": ["John Doe", "Jane Smith"],
"language": "en",
"baseUrl": "/docs"
}
}
```

---

## Pages Array (`pages`)

Each page entry contains:

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `id` | string | Yes | Unique page identifier |
| `path` | string | Yes | URL path |
| `title` | string | Yes | Page title |
| `file` | string | Yes | Path to full HTML file |
| `fragment` | string | No | Path to fragment (content only) |
| `section` | string | No | Parent section name |
| `auth` | object | No | Authorization requirements |
| `htmx` | object | No | HTMX behavior configuration |
| `search` | object | No | Search index metadata |
| `scopes` | string[] | No | Audience scopes |
| `lastModified` | string | No | ISO 8601 last modified date |

### Page Example

```json
{
"pages": [
{
"id": "getting-started",
"path": "/docs/getting-started",
"title": "Getting Started",
"file": "pages/getting-started.html",
"fragment": "fragments/getting-started.html",
"section": "Introduction",
"auth": {
"access": "public"
},
"htmx": {
"preload": true,
"cache": 3600
},
"search": {
"indexed": true,
"weight": 2.0
},
"scopes": ["all", "developers"],
"lastModified": "2026-01-04T10:30:00Z"
}
]
}
```

### Page Auth Object

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `access` | enum | `"public"` | Access level |
| `roles` | string[] | `[]` | Required roles |
| `fallback` | string | `/auth/access-denied` | Unauthorized redirect |

### Page HTMX Object

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `lazy` | boolean | `false` | Lazy load content |
| `preload` | boolean | `false` | Preload on hover |
| `cache` | integer | `0` | Cache-Control max-age |
| `swap` | string | `"innerHTML"` | Swap strategy |

### Page Search Object

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `indexed` | boolean | `true` | Include in search |
| `weight` | number | `1.0` | Ranking weight |
| `keywords` | string[] | `[]` | Additional keywords |
| `excerpt` | string | (auto) | Search result excerpt |

---

## Navigation (`navigation`)

| Field | Type | Description |
|-------|------|-------------|
| `chapters` | array | Hierarchical chapter structure |
| `flat` | array | Flat list of all pages |

### Chapters Structure

```json
{
"navigation": {
"chapters": [
{
"title": "Introduction",
"path": "/docs",
"children": [
{
"title": "Getting Started",
"path": "/docs/getting-started",
"children": []
},
{
"title": "Installation",
"path": "/docs/installation",
"children": []
}
]
}
]
}
}
```

### Flat List

```json
{
"navigation": {
"flat": [
{ "path": "/docs", "title": "Introduction" },
{ "path": "/docs/getting-started", "title": "Getting Started" },
{ "path": "/docs/installation", "title": "Installation" }
]
}
}
```

---

## Authentication Configuration (`authn`)

Optional authentication metadata for server reference.

| Field | Type | Description |
|-------|------|-------------|
| `enabled` | boolean | Whether auth is enabled |
| `signinPage` | string | Path to sign-in page |
| `signinPartial` | string | Path to sign-in partial |
| `signoutPage` | string | Path to sign-out page |
| `provider` | string | Auth provider hint |

### Example

```json
{
"authn": {
"enabled": true,
"signinPage": "/auth/signin",
"signinPartial": "partials/signin.html",
"signoutPage": "/auth/signout",
"provider": "jwt"
}
}
```

---

## Scope Configuration (`scopes`)

| Field | Type | Description |
|-------|------|-------------|
| `enabled` | boolean | Whether scopes are enabled |
| `available` | string[] | List of available scopes |
| `default` | string | Default scope |
| `globalScopes` | string[] | Scopes in main index |

### Example

```json
{
"scopes": {
"enabled": true,
"available": ["all", "developers", "managers", "sre"],
"default": "all",
"globalScopes": ["all"]
}
}
```

---

## Scope-Filtered Manifests

When scopes are enabled, mdbook-htmx generates filtered manifests:

```
manifest.json # Full manifest (all pages)
manifest.developers.json # Only pages with 'developers' scope
manifest.managers.json # Only pages with 'managers' scope
manifest.sre.json # Only pages with 'sre' scope
```

Each filtered manifest:
- Contains only pages matching the scope
- Has `scope` field set to the filter scope
- Includes filtered navigation structure

---

## Complete Example

```json
{
"$schema": "https://schemas.arusty.dev/mdbook-htmx/manifest.schema.json",
"version": "1.0.0",
"generated": "2026-01-04T12:00:00Z",
"book": {
"title": "Platform Documentation",
"description": "Complete platform reference",
"authors": ["Platform Team"],
"language": "en",
"baseUrl": "/docs"
},
"pages": [
{
"id": "index",
"path": "/docs",
"title": "Introduction",
"file": "pages/index.html",
"fragment": "fragments/index.html",
"auth": { "access": "public" },
"scopes": ["all"]
},
{
"id": "api-reference",
"path": "/docs/api",
"title": "API Reference",
"file": "pages/api.html",
"fragment": "fragments/api.html",
"section": "Developer Guide",
"auth": {
"access": "roles",
"roles": ["developer", "admin"]
},
"scopes": ["developers"]
}
],
"navigation": {
"chapters": [
{
"title": "Introduction",
"path": "/docs",
"children": []
},
{
"title": "Developer Guide",
"path": "/docs/dev",
"children": [
{
"title": "API Reference",
"path": "/docs/api",
"children": []
}
]
}
],
"flat": [
{ "path": "/docs", "title": "Introduction" },
{ "path": "/docs/api", "title": "API Reference" }
]
},
"authn": {
"enabled": true,
"signinPage": "/auth/signin",
"provider": "jwt"
},
"scopes": {
"enabled": true,
"available": ["all", "developers", "managers"],
"default": "all"
}
}
```

---

## Server Usage

### Loading the Manifest

```typescript
import manifest from './manifest.json';

// Type-safe access
interface Manifest {
version: string;
pages: Page[];
navigation: Navigation;
}

const m: Manifest = manifest;
```

### Finding a Page

```typescript
function findPage(path: string): Page | undefined {
return manifest.pages.find(p => p.path === path);
}
```

### Checking Authorization

```typescript
function canAccess(page: Page, user: User): boolean {
if (page.auth.access === 'public') return true;
if (page.auth.access === 'authenticated') return !!user;
if (page.auth.access === 'roles') {
return page.auth.roles.some(role => user.hasRole(role));
}
return false;
}
```

### Version Checking

```typescript
function isCompatible(manifest: Manifest): boolean {
const [major] = manifest.version.split('.');
return parseInt(major) === 1; // Server supports v1.x.x
}
```

---

## Related Documentation

- [ADR-0015: Manifest Schema Versioning](../adr/0015-manifest-schema-versioning.md)
- [ADR-0003: Authorization Metadata via Manifest](../adr/0003-authorization-via-manifest.md)
- [JSON Schema: manifest.schema.json](../schemas/manifest.schema.json)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.