Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

docs(adr): ADR-0016: Implementation Phasing Strategy

Aperta
#24 0 commenti 0 reazioni 1 assegnatario Vedi su GitHub

@aRustyDev ci sta già lavorando.

Dal 5/1/2026.

Valutazione

Questa issue non è ancora stata valutata.

Descrizione

documentation

ADR-0016: Implementation Phasing Strategy

Status

Accepted

Context

mdbook-htmx is a complex project with many features: template rendering, HTMX integration, authorization, search indexing, scope filtering, and asset handling. Implementing everything at once would be risky and make debugging difficult.

This ADR defines a phased implementation strategy that delivers value incrementally while managing complexity.

Decision Drivers

  1. Early Value - Ship usable output as soon as possible
  2. Risk Mitigation - Isolate complex features for easier debugging
  3. Testing Surface - Each phase should be independently testable
  4. Dependency Order - Features must be built in the right order
  5. User Feedback - Get feedback before building optional features

Decision

Implement in 5 phases, each with clear deliverables, tests, and release milestones.

Phase Overview
Phase Name Focus Release
1 Core Backend Basic rendering v0.1.0
2 HTMX Integration Navigation patterns v0.2.0
3 Authorization Auth metadata + manifest v0.3.0
4 Search Index generation v0.4.0
5 Polish Theming, scopes, assets v1.0.0
Deployment Methods

Three deployment methods evolve alongside the implementation:

Method Location Purpose
Docker Compose mdbook-htmx/docker/ Local dev, CI testing
Helm Chart aRustyDev/helm-charts/charts/mdbook-htmx Kubernetes
Cloudflare mdbook-htmx/workers/ + wrangler.jsonc Production edge

Each phase adds deployment features:

Phase Docker Compose Helm Chart Cloudflare
v0.1.0 NGINX static Static serve Pages static
v0.2.0 +fragment routing +Ingress rules +fragment routing
v0.3.0 +OAuth2 proxy +auth sidecar +Workers D1 auth
v0.4.0 +Meilisearch +Meilisearch +KV search index
v1.0.0 +cache, metrics +HPA, PDB +R2 assets, analytics

Phase 1: Core Backend (v0.1.0)

Goal

Produce valid HTML output from MDBook's RenderContext.

Deliverables
Component Description
Entry point Read RenderContext from stdin
Configuration Parse [output.htmx] from book.toml
Template engine Initialize Tera with default templates
Chapter rendering Render each chapter to HTML
Output structure Create pages/ and fragments/ directories
Manifest Generate basic manifest.json
Implementation Order
1. Cargo setup + dependencies
2. main.rs entry point
3. Config deserialization
4. Template loading
5. Chapter iteration
6. HTML output
7. Manifest generation
Exit Criteria
  • mdbook build produces HTML in book/htmx/
  • Pages render correctly without HTMX attributes
  • Manifest contains all pages with paths and titles
  • Default templates bundled in binary
  • Custom theme override works
Deployment (Phase 1)
Method Deliverables
Docker Compose compose.yml, nginx.conf, Dockerfile.build
Helm Chart Chart skeleton with deployment, service, configmap
Cloudflare wrangler.jsonc, basic workers/index.ts
CI test-deployments.yml, deploy-cloudflare.yml
Test Cases
#[test]
fn test_basic_render() {
    let ctx = test_render_context();
    let output = render(&ctx).unwrap();
    assert!(output.join("pages/index.html").exists());
}

#[test]
fn test_manifest_generation() {
    let ctx = test_render_context();
    render(&ctx).unwrap();
    let manifest: Manifest = serde_json::from_reader(
        File::open(ctx.destination.join("manifest.json")).unwrap()
    ).unwrap();
    assert_eq!(manifest.pages.len(), ctx.book.iter().count());
}

Phase 2: HTMX Integration (v0.2.0)

Goal

Enable SPA-like navigation with HTMX attributes.

Deliverables
Component Description
hx-boost Add to body element
hx-target Default content target
hx-swap Default swap strategy
hx-push-url URL updates
Fragments Content-only partials
OOB swaps Sidebar + breadcrumb updates
Implementation Order
1. Update layout template with HTMX body attributes
2. Fragment template (content without layout)
3. OOB partial templates
4. Sidebar active state
5. Breadcrumb generation
6. Navigation links with hx-* attributes
Exit Criteria
  • Clicking links loads content without full page reload
  • Sidebar highlights active page
  • Breadcrumbs update on navigation
  • Browser back/forward works correctly
  • Fragments served for HX-Request headers
Deployment (Phase 2)
Method Additions
Docker Compose NGINX HX-Request header detection, fragment routing
Helm Chart Ingress annotations for fragment routing
Cloudflare Worker routes fragments based on HX-Request header
Test Cases
#[test]
fn test_htmx_attributes() {
    let html = render_page(&chapter).unwrap();
    assert!(html.contains(r#"hx-boost="true""#));
    assert!(html.contains(r#"hx-target="#content""#));
}

#[test]
fn test_fragment_output() {
    let ctx = test_render_context();
    render(&ctx).unwrap();
    assert!(ctx.destination.join("fragments/chapter-1.html").exists());
    let fragment = fs::read_to_string(...).unwrap();
    assert!(!fragment.contains("<!DOCTYPE html>"));
}

Phase 3: Authorization (v0.3.0)

Goal

Extract and surface authorization metadata for server-side enforcement.

Deliverables
Component Description
Frontmatter parsing Extract auth from YAML frontmatter
Manifest auth Include auth requirements per page
Access-denied template Partial for unauthorized access
Signin template Partial for authentication prompt
Validation Build-time auth config validation
Implementation Order
1. Frontmatter extractor
2. Auth schema validation
3. Manifest auth fields
4. Access-denied partial
5. Signin partial
6. CLI validation command
Exit Criteria
  • Frontmatter auth: section parsed correctly
  • Manifest includes auth requirements per page
  • Invalid auth config fails build with clear error
  • Partials exist for access-denied and signin
  • Reference server implementation documented
Deployment (Phase 3)
Method Additions
Docker Compose compose.auth.yml overlay with OAuth2 proxy
Helm Chart OAuth2 proxy sidecar, auth secret templates
Cloudflare D1 database for sessions, auth middleware in worker

Files:

  • docker/compose.auth.yml
  • workers/auth.ts, workers/middleware.ts
  • migrations/0001_sessions.sql
Test Cases
#[test]
fn test_frontmatter_auth() {
    let (fm, _) = extract_frontmatter(r#"---
auth:
  access: roles
  roles: [admin]
---
# Content"#).unwrap();
    assert_eq!(fm.auth.access, AccessLevel::Roles);
    assert_eq!(fm.auth.roles, vec!["admin"]);
}

#[test]
fn test_manifest_includes_auth() {
    let manifest = generate_manifest(&ctx).unwrap();
    let admin_page = manifest.pages.iter()
        .find(|p| p.path == "/docs/admin").unwrap();
    assert_eq!(admin_page.auth.roles, vec!["admin"]);
}

Phase 4: Search (v0.4.0)

Goal

Generate search indexes for server-side search.

Deliverables
Component Description
Index generation Build search-index.json
Heading extraction Index up to H3 by default
Body indexing Full text content
Auth filtering Include auth info for runtime filtering
Search partial Results display template
Implementation Order
1. Document indexer
2. Heading extractor
3. Body text stripper (remove markdown)
4. JSON index writer
5. Search partial template
6. Index configuration options
Exit Criteria
  • search-index.json generated with all pages
  • Headings indexed with anchors
  • Body text stripped of markdown
  • Auth info included for filtering
  • Search partial renders results
Deployment (Phase 4)
Method Additions
Docker Compose compose.search.yml overlay with Meilisearch, indexer
Helm Chart Meilisearch StatefulSet, PVC, search init job
Cloudflare KV namespace for search index, search handler

Files:

  • docker/compose.search.yml, docker/init-meilisearch.sh
  • workers/search.ts, scripts/upload-search-index.ts
Test Cases
#[test]
fn test_search_index() {
    let index = generate_search_index(&ctx).unwrap();
    assert!(!index.documents.is_empty());

    let doc = &index.documents[0];
    assert!(!doc.body.contains("```")); // No code blocks
    assert!(doc.headings.iter().any(|h| h.level == 2));
}

#[test]
fn test_search_index_includes_auth() {
    let index = generate_search_index(&ctx).unwrap();
    let admin_doc = index.documents.iter()
        .find(|d| d.path == "/docs/admin").unwrap();
    assert_eq!(admin_doc.auth.access, "roles");
}

Phase 5: Polish (v1.0.0)

Goal

Production-ready features: theming, scopes, asset handling.

Deliverables
Component Description
Scope filtering Per-scope manifests and indexes
Asset hashing Content-based cache busting
CSS variables Theming system
Dark mode Theme switching
Minification Optional HTML/CSS minification
Implementation Order
1. Scope configuration
2. Scope-filtered manifest generation
3. Scope-filtered search indexes
4. Asset hasher
5. CSS variable system
6. Dark/light theme support
7. Minification (optional)
Exit Criteria
  • Scope-filtered manifests and indexes generated
  • Asset filenames include content hash
  • Theme switching works via CSS variables
  • Dark mode respects system preference
  • Performance benchmarks documented
Deployment (Phase 5)
Method Additions
Docker Compose compose.prod.yml with caching, metrics
Helm Chart HPA, PDB, ServiceMonitor for Prometheus
Cloudflare R2 bucket for assets, analytics, cache optimization

Files:

  • docker/compose.prod.yml, docker/nginx-cache.conf
  • workers/analytics.ts
Test Cases
#[test]
fn test_scope_filtering() {
    let ctx = test_render_context_with_scopes();
    render(&ctx).unwrap();

    let dev_manifest: Manifest = serde_json::from_reader(
        File::open(ctx.destination.join("manifest.developers.json")).unwrap()
    ).unwrap();

    assert!(dev_manifest.pages.iter().all(|p| p.scopes.contains(&"developers")));
}

#[test]
fn test_asset_hashing() {
    let ctx = test_render_context();
    render(&ctx).unwrap();

    let css_files: Vec<_> = glob("book/htmx/assets/css/*.css").unwrap().collect();
    assert!(css_files.iter().any(|f| f.contains("-")));  // Hash in filename
}

Feature Flags

Each phase's features are gated behind configuration:

[output.htmx]
# Phase 1: Always on (core rendering)

# Phase 2: HTMX attributes
boost = true  # Can disable for static output

# Phase 3: Authorization
[output.htmx.authz]
enabled = true

# Phase 4: Search
[output.htmx.search]
enabled = true

# Phase 5: Advanced features
[output.htmx.scopes]
enabled = true

[output.htmx.assets]
hash-files = true

Dependency Graph

Phase 1 (Core)
    ↓
Phase 2 (HTMX) ──────────────────┐
    ↓                            │
Phase 3 (Auth) ────┐             │
    ↓              ↓             │
Phase 4 (Search)   │             │
    ↓              │             │
Phase 5 (Polish) ←─┴─────────────┘
  • Phase 2 depends on Phase 1 (needs basic rendering)
  • Phase 3 depends on Phase 1 (needs manifest)
  • Phase 4 depends on Phase 1 + 3 (needs auth for filtering)
  • Phase 5 depends on all phases

Consequences

Positive
  • Early releases provide value
  • Each phase is testable in isolation
  • Complex features don't block simpler ones
  • User feedback informs later phases
Negative
  • Multiple releases to track
  • Some refactoring between phases
  • Users may need to upgrade incrementally
Mitigation
  • Semantic versioning with clear changelogs
  • Migration guides between versions
  • Feature flags for gradual adoption

References

Deployment Examples
Lingua principale
Rust
Stelle
0
Fork
1
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di aRustyDev/mdbook-htmx

Tutte le issue di aRustyDev/mdbook-htmx

Issue simili

Altre issue su Rust

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.