docs(adr): ADR-0010: Server-Side Reference Implementation Scripts
@aRustyDev ci sta già lavorando.
Dal 5/1/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
ADR-0010: Server-Side Reference Implementation Scripts
Status
Accepted
Context
mdbook-htmx generates static files (HTML, JSON manifests, search indexes) but requires server-side logic to:
- Serve appropriate content based on
HX-Requestheader - Implement search endpoints
- Handle authentication/authorization
- Manage scope switching
Users need guidance on implementing these server-side behaviors. The question: should the backend generate reference implementation scripts?
Decision Drivers
- Developer Experience - Reduce time-to-working-deployment
- HTMX Philosophy - Server-side code is expected and encouraged
- Portability - Scripts should work across runtimes (Workers, Node, Deno)
- Maintainability - Reference code needs ongoing updates
- Flexibility - Users may have different server frameworks
Decision
Generate TypeScript reference implementation scripts in book/htmx/scripts/.
These scripts are:
- Reference implementations, not required
- TypeScript for type safety and self-documentation
- Runtime-agnostic (work with Workers, Node, Deno, Bun)
- Framework-agnostic (use Web APIs, adapt to Hono/Express/etc.)
HTMX Alignment
This decision is fully aligned with HTMX philosophy:
| Principle | How Scripts Align |
|---|---|
| Server returns HTML | Scripts render HTML responses |
| Minimal client-side JS | Zero client-side code in scripts |
| Server is source of truth | Scripts manage state, auth, scope |
| Progressive enhancement | Scripts serve full pages and fragments |
HTMX's "minimal JS" applies to the client. Server-side code in any language is expected.
Output Structure
book/htmx/scripts/
├── types.ts # Shared type definitions
├── manifest-loader.ts # Load and cache manifests
├── search.ts # Search endpoint handler
├── authn.ts # Authentication middleware
├── authz.ts # Authorization middleware
├── scope.ts # Scope switching logic
├── htmx-utils.ts # HX-Request detection, OOB helpers
├── meili-proxy.ts # Meilisearch proxy (if external search enabled)
└── README.md # Usage documentation
Deployment Patterns
These scripts support multiple deployment architectures:
In-Memory Search (Simple Sites)
Worker bundles search index directly:
import searchIndex from "./search-index.json";
// Use Fuse.js/MiniSearch with bundled index
External Search via Cloudflare Tunnel (Recommended for Production)
Worker acts as policy enforcement proxy to self-hosted Meilisearch:
Worker → Cloudflare Tunnel → Private Meilisearch
Key security properties:
- Meilisearch never internet-facing
- Worker validates auth before searching
- Query inputs sanitized (length limits, filter whitelists)
- API keys server-side only (never sent to browser)
- Results authorization-filtered at runtime
See examples/meilisearch-cf-tunnel.md for complete implementation.
Script Contents
types.ts
// Generated from manifest schema
export interface Page {
path: string;
title: string;
file: string;
fragment: string;
auth: {
access: 'public' | 'authenticated' | 'roles';
roles?: string[];
fallback?: string;
};
scopes: string[];
}
export interface Manifest {
version: string;
generated: string;
scopes: {
available: string[];
default: string;
};
pages: Page[];
navigation: NavigationItem[];
}
export interface User {
id: string;
roles: string[];
preferences?: {
scope?: string;
};
}
htmx-utils.ts
export function isHtmxRequest(request: Request): boolean {
return request.headers.get('HX-Request') === 'true';
}
export function oobSwap(id: string, content: string): string {
return `<div id="${id}" hx-swap-oob="true">${content}</div>`;
}
export function htmxRedirect(url: string): Response {
return new Response(null, {
status: 200,
headers: { 'HX-Redirect': url }
});
}
authz.ts
import type { Page, User } from './types';
export function isAuthorized(user: User | null, page: Page): boolean {
switch (page.auth.access) {
case 'public':
return true;
case 'authenticated':
return user !== null;
case 'roles':
return page.auth.roles?.some(role => user?.roles?.includes(role)) ?? false;
default:
return false;
}
}
Configuration
[output.htmx.scripts]
enabled = true # Generate reference scripts
language = "typescript" # typescript | javascript
runtime = "workers" # workers | node | deno | bun
framework = "hono" # hono | express | none
Consequences
Positive
- Faster time-to-deployment
- Types document the manifest schema
- Consistent patterns across deployments
- Testable reference implementations
Negative
- Maintenance burden (scripts need updates)
- May not fit all server architectures
- Users might copy without understanding
Mitigation
- Clear "reference implementation" labeling
- Extensive inline documentation
- Integration tests in mdbook-htmx repo
- Version scripts with manifest schema
Alternatives Considered
No Scripts (Documentation Only)
Provide patterns in docs, no generated code.
Rejected because:
- Higher barrier to entry
- Documentation drifts from actual implementation
- Users reinvent the wheel
Generate Full Server Application
Generate complete deployable server.
Rejected because:
- Too opinionated
- Hard to customize
- Framework lock-in
References
- Lingua principale
- Rust
- Stelle
- 0
- Fork
- 1
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di aRustyDev/mdbook-htmx
-
feat(ci): Implement cross-repo-validate compliance for docs syncForse di nuovo libera @aRustyDev l’ha presa 274 giorni fa e non c’è nessuna pull request aperta. Apertaci enhancement
aRustyDev/mdbook-htmx#58 · 1 commento · 1 assegnatario ·
-
docs(htmx): Explain how HTMX worksForse di nuovo libera @aRustyDev l’ha presa 277 giorni fa e non c’è nessuna pull request aperta. Aperta
aRustyDev/mdbook-htmx#48 · 3 commenti · 1 assegnatario ·
-
docs(mdbook-htmx): Parent Issue for documentationForse di nuovo libera @aRustyDev l’ha presa 277 giorni fa e non c’è nessuna pull request aperta. Apertadocumentation
aRustyDev/mdbook-htmx#47 · 1 assegnatario ·
-
docs(examples): Secure Self-Hosted Meilisearch via CloudflareForse di nuovo libera @aRustyDev l’ha presa 277 giorni fa e non c’è nessuna pull request aperta. Apertadocumentation
aRustyDev/mdbook-htmx#46 · 1 assegnatario ·
-
docs(examples): Kubernetes with MeilisearchForse di nuovo libera @aRustyDev l’ha presa 277 giorni fa e non c’è nessuna pull request aperta. Apertadocumentation
aRustyDev/mdbook-htmx#45 · 1 assegnatario ·
Tutte le issue di aRustyDev/mdbook-htmx
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
chroma-core/chroma#7879 ·
I maintainer di solito rispondono entro 1 giorno
-
priority middle
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 72/100
KATO-Hiro/AtCoderClans#12838 ·
I maintainer di solito rispondono entro 1 giorno
-
clap_complete env (PowerShell): values after a space don't complete in Windows PowerShell 5.1Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
I maintainer di solito rispondono entro 1 giorno