diff --git a/.github/scripts/build-pages.py b/.github/scripts/build-pages.py
new file mode 100644
index 0000000..743eb9b
--- /dev/null
+++ b/.github/scripts/build-pages.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python3
+"""Build the docs Markdown files into a static GitHub Pages site.
+
+This intentionally avoids themed site generators and template files. Each Markdown
+file is converted to a minimal standalone HTML page, and relative .md links are
+rewritten to the generated .html filenames.
+"""
+
+from __future__ import annotations
+
+import html
+import re
+import shutil
+from pathlib import Path, PurePosixPath
+from urllib.parse import urlsplit, urlunsplit
+
+import markdown
+
+ROOT = Path(__file__).resolve().parents[2]
+DOCS_DIR = ROOT / "docs"
+SITE_DIR = ROOT / "site"
+
+MARKDOWN_EXTENSIONS = ["fenced_code", "tables", "toc"]
+HREF_RE = re.compile(r'href="([^"]+)"')
+
+
+def output_path(source: Path) -> Path:
+ if source.name == "README.md":
+ return SITE_DIR / "index.html"
+ return SITE_DIR / f"{source.stem}.html"
+
+
+def page_title(text: str, fallback: str) -> str:
+ for line in text.splitlines():
+ if line.startswith("# "):
+ return line[2:].strip()
+ return fallback
+
+
+def rewrite_markdown_links(rendered: str) -> str:
+ def replace(match: re.Match[str]) -> str:
+ href = html.unescape(match.group(1))
+ parts = urlsplit(href)
+ if parts.scheme or parts.netloc or not parts.path.endswith(".md"):
+ return match.group(0)
+
+ url_path = PurePosixPath(parts.path)
+ if url_path.name == "README.md":
+ new_path = str(url_path.with_name("index.html"))
+ else:
+ new_path = parts.path[:-3] + ".html"
+
+ new_href = urlunsplit(("", "", new_path, parts.query, parts.fragment))
+ return f'href="{html.escape(new_href, quote=True)}"'
+
+ return HREF_RE.sub(replace, rendered)
+
+
+def render_page(source: Path) -> str:
+ text = source.read_text(encoding="utf-8")
+ title = page_title(text, "Cassady docs")
+ body = markdown.markdown(
+ text,
+ extensions=MARKDOWN_EXTENSIONS,
+ output_format="html5",
+ )
+ body = rewrite_markdown_links(body)
+
+ return "\n".join(
+ [
+ "",
+ '',
+ "
",
+ ' ',
+ ' ',
+ f" {html.escape(title)}",
+ "",
+ "",
+ body,
+ "",
+ "",
+ "",
+ ]
+ )
+
+
+def copy_static_assets() -> None:
+ for item in DOCS_DIR.iterdir():
+ if item.suffix == ".md":
+ continue
+ destination = SITE_DIR / item.name
+ if item.is_dir():
+ shutil.copytree(item, destination)
+ elif item.is_file():
+ shutil.copy2(item, destination)
+
+
+def main() -> None:
+ if SITE_DIR.exists():
+ shutil.rmtree(SITE_DIR)
+ SITE_DIR.mkdir(parents=True)
+
+ for source in sorted(DOCS_DIR.glob("*.md")):
+ output_path(source).write_text(render_page(source), encoding="utf-8")
+
+ copy_static_assets()
+ (SITE_DIR / ".nojekyll").write_text("", encoding="utf-8")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index c44362b..8eef3c2 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -1,4 +1,4 @@
-name: Publish MkDocs site
+name: Publish Markdown site
on:
push:
@@ -6,12 +6,12 @@ on:
- main
paths:
- 'docs/**'
- - 'docs/mkdocs.yml'
+ - '.github/scripts/build-pages.py'
- '.github/workflows/pages.yml'
pull_request:
paths:
- 'docs/**'
- - 'docs/mkdocs.yml'
+ - '.github/scripts/build-pages.py'
- '.github/workflows/pages.yml'
workflow_dispatch:
@@ -26,7 +26,7 @@ concurrency:
jobs:
build:
- name: Build MkDocs site
+ name: Build Markdown site
runs-on: ubuntu-latest
steps:
- name: Check out repository
@@ -37,11 +37,11 @@ jobs:
with:
python-version: '3.x'
- - name: Install MkDocs
- run: python -m pip install mkdocs-material
+ - name: Install Markdown converter
+ run: python -m pip install Markdown
- name: Build site
- run: python -m mkdocs build --strict -f docs/mkdocs.yml
+ run: python .github/scripts/build-pages.py
- name: Configure Pages
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
deleted file mode 100644
index 04c3af9..0000000
--- a/docs/mkdocs.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-site_name: Cassady
-site_url: "https://owenqwenstarsky.github.io/cassady/"
-site_description: "Cassady ('cass') is a terminal coding agent written in Rust."
-site_author: Owen Qwen
-docs_dir: .
-site_dir: ../site
-repo_url: https://github.com/owenqwenstarsky/cassady
-repo_name: owenqwenstarsky/cassady
-nav:
- - Home: README.md
- - Getting Started:
- - Workflows: workflows.md
- - Platform Notes: platforms.md
- - Setup and Configuration:
- - Configuration: configuration.md
- - Providers and Models: providers.md
- - Usage Reference:
- - Commands: commands.md
- - Access Modes and Tool Safety: access-modes.md
- - Glossary: glossary.md
- - Experimental:
- - Rust API: embedding.md
- - Help:
- - Troubleshooting: troubleshooting.md
-extra:
- version: 0.2.9
- social:
- - icon: fontawesome/brands/github
- link: https://github.com/owenqwenstarsky/cassady
-theme:
- name: material
- favicon: img/favicon.ico
- features:
- - navigation.sections
- - navigation.expand
- - navigation.top
- - toc.follow