aRustyDev / aRustyDev/mdbook-htmx
docs(examples): GitHub Pages Deployment
- Dominant language
- Rust
- Stars
- 0
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
# GitHub Pages Deployment
Deploy mdbook-htmx to GitHub Pages for free static hosting.
## Overview
GitHub Pages is ideal for:
- Open source documentation
- Public API references
- Project documentation
Limitations:
- Static only (no server-side search/auth)
- 1GB repository size limit
- 100GB bandwidth/month
## Quick Start
### GitHub Actions Workflow
```yaml
# .github/workflows/deploy-pages.yml
name: Deploy to GitHub Pages
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-action@stable
- name: Install mdbook and plugins
run: |
cargo install mdbook
cargo install mdbook-htmx
- name: Build documentation
run: mdbook build
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: './book'
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
```
## Repository Setup
### Enable GitHub Pages
1. Go to **Settings** → **Pages**
2. Source: **GitHub Actions**
3. (Optional) Add custom domain
### book.toml Configuration
```toml
[book]
title = "My Documentation"
authors = ["Your Name"]
language = "en"
src = "src"
[output.htmx]
# GitHub Pages URL format
base_url = "https://username.github.io/repo-name"
# Client-side search (no server available)
[output.htmx.search]
mode = "client"
enabled = true
# Asset hashing for cache busting
asset_hashing = true
# Prerender all pages
prerender = true
# No authentication (public)
[output.htmx.authn]
enabled = false
```
## Custom Domain
### Configure DNS
Add a CNAME record:
```
docs.example.com → username.github.io
```
### Add CNAME file
Create `book/CNAME` (or add to build):
```
docs.example.com
```
### Update workflow
```yaml
- name: Build documentation
run: mdbook build
- name: Add CNAME
run: echo "docs.example.com" > book/CNAME
```
### book.toml for custom domain
```toml
[output.htmx]
base_url = "https://docs.example.com"
```
## Multi-Version Documentation
### Version branches
```
main → /
v1.x → /v1/
v2.x → /v2/
```
### Workflow for versioned docs
```yaml
name: Deploy Versioned Docs
on:
push:
branches:
- main
- 'v[0-9]+.x'
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Determine version
id: version
run: |
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
echo "version=latest" >> $GITHUB_OUTPUT
echo "path=." >> $GITHUB_OUTPUT
else
VERSION=$(echo "${{ github.ref }}" | sed 's/refs\/heads\/v//')
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "path=v${VERSION%.*}" >> $GITHUB_OUTPUT
fi
- name: Install mdbook
run: cargo install mdbook mdbook-htmx
- name: Build
run: mdbook build
env:
MDBOOK_OUTPUT__HTMX__BASE_URL: "https://docs.example.com/${{ steps.version.outputs.path }}"
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: './book'
name: docs-${{ steps.version.outputs.version }}
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: combined
- name: Combine versions
run: |
mkdir -p public
# Latest goes to root
if [ -d "combined/docs-latest" ]; then
cp -r combined/docs-latest/* public/
fi
# Versions go to subdirectories
for dir in combined/docs-v*/; do
version=$(basename "$dir" | sed 's/docs-//')
mkdir -p "public/$version"
cp -r "$dir"/* "public/$version/"
done
- name: Deploy
uses: actions/deploy-pages@v4
with:
artifact_name: combined-docs
```
## Version Switcher
Add version dropdown to documentation:
### Version config
```toml
# book.toml
[output.htmx.versions]
enabled = true
current = "v2.0"
available = [
{ version = "v2.0", url = "/", label = "2.0 (latest)" },
{ version = "v1.0", url = "/v1/", label = "1.0" },
]
```
### Version dropdown template
```html
{% for v in config.htmx.versions.available %}
{{ v.label }}
{% endfor %}
```
## Client-Side Search
Since GitHub Pages is static, use client-side search:
### lunr.js Integration
```html
document.addEventListener('DOMContentLoaded', async () => {
// Load search index generated by mdbook-htmx
const response = await fetch('/search-index.json');
const data = await response.json();
// Build lunr index
const idx = lunr(function() {
this.ref('path');
this.field('title', { boost: 10 });
this.field('content');
this.field('headings', { boost: 5 });
data.pages.forEach(page => {
this.add(page);
});
});
// Search handler
window.doSearch = (query) => {
const results = idx.search(query);
return results.map(r => data.pages.find(p => p.path === r.ref));
};
});
```
## SEO Optimization
### robots.txt
Create `book/robots.txt`:
```
User-agent: *
Allow: /
Sitemap: https://docs.example.com/sitemap.xml
```
### sitemap.xml
Generate sitemap in build:
```yaml
- name: Generate sitemap
run: |
echo '' > book/sitemap.xml
echo '' >> book/sitemap.xml
find book -name "*.html" | while read file; do
url=$(echo "$file" | sed 's|book/|https://docs.example.com/|')
echo " $url" >> book/sitemap.xml
done
echo '' >> book/sitemap.xml
```
## Performance Optimization
### Cache headers
GitHub Pages sets cache headers automatically:
- HTML: `Cache-Control: max-age=600` (10 minutes)
- Assets: `Cache-Control: max-age=31536000` (1 year)
### Asset optimization
```yaml
- name: Optimize assets
run: |
# Minify CSS
npx postcss book/assets/css/*.css --replace
# Optimize images
npx imagemin book/assets/images/* --out-dir=book/assets/images
# Compress with Brotli (served by GitHub)
find book -type f \( -name "*.html" -o -name "*.css" -o -name "*.js" \) \
-exec brotli -k {} \;
```
## Monitoring
### Google Analytics
```html
{% if config.htmx.analytics.google_id %}
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ config.htmx.analytics.google_id }}');
{% endif %}
```
### Plausible (privacy-friendly)
```html
```
## Troubleshooting
### Build failures
```bash
# Check workflow logs
gh run view --log
# Test locally
mdbook build
```
### 404 errors
1. Check base_url in book.toml
2. Verify all links are relative
3. Add .nojekyll file: `touch book/.nojekyll`
### Slow deploys
- Reduce artifact size
- Use sparse checkout for large repos
- Cache cargo dependencies
```yaml
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
```
## Cost
GitHub Pages is **free** for public repositories.
For private repos:
- GitHub Pro: $4/month
- GitHub Team: $4/user/month
## Next Steps
- Add [Cloudflare CDN](./cf-pages-static.md) for better performance
- Set up [authentication](./cf-workers-d1.md) for private docs
- Deploy to [Kubernetes](./k8s-deployment.md) for more control
Contributor guide
Assessment
This issue has not been assessed yet.