From 9ecbe4aa45bbd240af58f202c342c88fd3401319 Mon Sep 17 00:00:00 2001 From: Fine_Computer_4451 <119702188+FineComputer14451@users.noreply.github.com> Date: Thu, 27 Aug 2026 11:37:49 -0700 Subject: [PATCH 1/4] feat(site): stitch pages + site.json (no npm) --- .github/workflows/deploy-website.yml | 14 ++- scripts/build-website.py | 168 +++++++++++++++++++++++++++ website/README.md | 65 ++++------- website/site.json | 23 ++++ 4 files changed, 227 insertions(+), 43 deletions(-) create mode 100644 scripts/build-website.py create mode 100644 website/site.json diff --git a/.github/workflows/deploy-website.yml b/.github/workflows/deploy-website.yml index 9c4022b..051ea6d 100644 --- a/.github/workflows/deploy-website.yml +++ b/.github/workflows/deploy-website.yml @@ -8,6 +8,12 @@ on: paths: - "website/**" - "branding/**" + - "VERSION" + - "agents/**" + - "personas/**" + - "roles/**" + - "skills/**" + - "scripts/build-website.py" - ".github/workflows/deploy-website.yml" workflow_dispatch: @@ -38,7 +44,10 @@ jobs: python3 branding/decode_assets.py fi - # Static site root = website/ (no build step) + # Stitch pages + site.json from VERSION and catalog counts (no npm) + python3 scripts/build-website.py + + # Static site root = website/ (no JS framework) cp -a website/. _site/ # Canonical brand files from branding/ — only copy what exists @@ -71,8 +80,9 @@ jobs: # Avoid Jekyll processing on Pages touch _site/.nojekyll - # Drop internal docs from public site + # Drop internal docs and stitch fragments from public site rm -f _site/README.md + rm -rf _site/_src echo echo "=== _site layout ===" diff --git a/scripts/build-website.py b/scripts/build-website.py new file mode 100644 index 0000000..11476bf --- /dev/null +++ b/scripts/build-website.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +"""Stitch GrokHunter static pages and write website/site.json. + +No npm. Safe to run on a phone (Python 3) or in GitHub Actions. +Fragments live in website/_src/. Generated HTML is committed so +`python3 -m http.server -d website` works without the stitch. +""" +from __future__ import annotations + +import json +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +WEB = ROOT / "website" +SRC = WEB / "_src" + +SKIP_AGENT_MD = {"README.md", "HANDOFF-TEMPLATES.md", "REFERENCES.md"} +PAGES = ( + { + "slug": "index", + "file": "index.html", + "body": "index.body.html", + "title": "GrokHunter {version} — AI coding lab on unrooted Android", + "description": ( + "Kali NetHunter Rootless × Grok Build 1.0.5 — AI coding lab for " + "unrooted Android. Grok 4.6, agents, personas, roles, Aider, XFCE desktop." + ), + }, + { + "slug": "install", + "file": "install.html", + "body": "install.body.html", + "title": "Install GrokHunter {version} — rootless overlay", + "description": "Install or refresh GrokHunter on unrooted Android. Overlay-only, XFCE, Grok Build.", + }, + { + "slug": "cli", + "file": "cli.html", + "body": "cli.body.html", + "title": "GrokHunter CLI — Grok TUI vs lab TUI", + "description": "grokhunter commands. Bare grokhunter opens Grok Build. grokhunter tui is the lab menu.", + }, + { + "slug": "desktop", + "file": "desktop.html", + "body": "desktop.body.html", + "title": "GrokHunter desktop — XFCE on Termux:X11", + "description": "nh-x11, grokhunter menu (XFCE submenu), binds, and phone-real X11 notes. Not the lab TUI.", + }, + { + "slug": "agents", + "file": "agents.html", + "body": "agents.body.html", + "title": "GrokHunter Coding Team — agents, personas, roles", + "description": "Coding Team loop and lab specialists for GrokHunter on unrooted Android.", + }, + { + "slug": "faq", + "file": "faq.html", + "body": "faq.body.html", + "title": "GrokHunter FAQ — rootless lab", + "description": "FAQ, architecture, and credits for the GrokHunter rootless coding lab.", + }, + { + "slug": "404", + "file": "404.html", + "body": "404.body.html", + "title": "GrokHunter — page not found", + "description": "That page is not on the GrokHunter site.", + }, +) + + +def count_catalog() -> dict[str, int]: + agents = sum( + 1 + for p in (ROOT / "agents").glob("*.md") + if p.name not in SKIP_AGENT_MD + ) + personas = sum(1 for _ in (ROOT / "personas").glob("*.toml")) + roles = sum(1 for _ in (ROOT / "roles").glob("*.toml")) + skills = sum(1 for p in (ROOT / "skills").iterdir() if p.is_dir()) + return { + "agents": agents, + "personas": personas, + "roles": roles, + "skills": skills, + } + + +def tokens(version: str, counts: dict[str, int]) -> dict[str, str]: + return { + "VERSION": version, + "MIN_GROK": "1.0.5", + "AGENTS": str(counts["agents"]), + "PERSONAS": str(counts["personas"]), + "ROLES": str(counts["roles"]), + "SKILLS": str(counts["skills"]), + } + + +def subst(text: str, table: dict[str, str]) -> str: + for key, val in table.items(): + text = text.replace("{{" + key + "}}", val) + return text + + +def stitch(page: dict, table: dict[str, str]) -> str: + head = (SRC / "head.html").read_text() + header = (SRC / "header.html").read_text() + body = (SRC / page["body"]).read_text() + footer = (SRC / "footer.html").read_text() + local = dict(table) + local["TITLE"] = page["title"].format(version=table["VERSION"]) + local["DESCRIPTION"] = page["description"] + local["PAGE"] = "" if page["file"] == "index.html" else page["file"] + local["SLUG"] = page["slug"] + html = head + header + body + footer + html = subst(html, local) + if "{{" in html: + leftover = [tok for tok in html.split("{{")[1:]] + raise SystemExit(f"unreplaced token in {page['file']}: {leftover[:3]}") + return html + + +def write_site_json(version: str, counts: dict[str, int]) -> None: + data = { + "version": version, + "min_grok": "1.0.5", + "overlay_cache": "2026.2.25", + "agents": counts["agents"], + "personas": counts["personas"], + "roles": counts["roles"], + "skills": counts["skills"], + "pages": [p["file"] for p in PAGES], + "tui": { + "bare": "Grok Build fullscreen TUI (grok-nethunter)", + "tui": "Lab operations menu (alias: lab)", + "menu": "Kali/XFCE Applications submenu", + }, + } + path = WEB / "site.json" + path.write_text(json.dumps(data, indent=2) + "\n") + print(f"wrote {path.relative_to(ROOT)}") + + +def main() -> int: + if not SRC.is_dir(): + print(f"missing {SRC}", file=sys.stderr) + return 1 + version = (ROOT / "VERSION").read_text().strip() + counts = count_catalog() + table = tokens(version, counts) + write_site_json(version, counts) + for page in PAGES: + out = WEB / page["file"] + out.write_text(stitch(page, table)) + print(f"wrote {out.relative_to(ROOT)}") + print( + f"catalog agents={counts['agents']} personas={counts['personas']} " + f"roles={counts['roles']} skills={counts['skills']}" + ) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/website/README.md b/website/README.md index 077f685..d858182 100644 --- a/website/README.md +++ b/website/README.md @@ -1,58 +1,41 @@ # GrokHunter website -Static product landing page for [GrokHunter](https://github.com/FineComputer14451/GrokHunter) **v1.0.10**. +Static product site for [GrokHunter](https://github.com/FineComputer14451/GrokHunter) **v1.0.10**. **Live:** https://finecomputer14451.github.io/GrokHunter/ -## Sections - -| Section | Content | -|---------|---------| -| Hero | Quick install + animated terminal (1.0.10 stack) | -| Stats | Version / Grok min / agents / personas / roles | -| Why | Comparison table | -| Features | 9 feature cards (Grok Build 1.0.5, Grok 4.6, agents, Aider, …) | -| Stack | skills · agents · personas · roles | -| Agents | Coding Team loop + roster table | -| Personas & roles | Full product lists | -| Install | One-liner, full, clone, overlay-only + flags | -| CLI | Full `grokhunter` command list | -| Upgrade | Paste-ready 1.0.10 upgrade path | -| Architecture | Overlay layers | -| FAQ | Rootless, auth, Aider 3.13, X11, scope | - -## Open locally +No npm. Pages are stitched from `website/_src/` by `scripts/build-website.py`. +Generated HTML is committed so a phone can open the files without running the stitch. + +## Pages + +| File | Content | +|------|---------| +| `index.html` | Hero, stats, why, features, links to the rest | +| `install.html` | Install + overlay-only + upgrade | +| `cli.html` | Command list (Grok TUI vs lab TUI vs XFCE `menu`) | +| `desktop.html` | XFCE / Termux:X11 / `nh-x11` / binds / XFCE submenu | +| `agents.html` | Stack, Coding Team, personas / roles | +| `faq.html` | Architecture, FAQ, credits | +| `404.html` | GitHub Pages fallback | +| `site.json` | Version + catalog counts + TUI wording | + +## Build ```bash +python3 scripts/build-website.py python3 -m http.server 8080 -d website -# then open http://localhost:8080 +# http://localhost:8080 ``` -Or open `index.html` directly in a browser. +`site.json` counts `agents/*.md` (minus README/HANDOFF/REFERENCES), `personas/*.toml`, `roles/*.toml`, and `skills/*/` directories. ## Deploy Workflow: [`.github/workflows/deploy-website.yml`](../.github/workflows/deploy-website.yml) -1. Pages source: **GitHub Actions** (already enabled for this repo) -2. Push `website/**` or `branding/**` to `main` **or** **Actions → Deploy website → Run workflow** +1. Pages source: **GitHub Actions** +2. Workflow runs `python3 scripts/build-website.py`, copies `website/` to `_site`, drops `_src/` and `README.md` 3. URL: https://finecomputer14451.github.io/GrokHunter/ -No Node/npm build — pure static HTML/CSS/JS. Brand tokens: `styles.css` (Grok cyan `#00E5C7` · Kali blue `#2777FF` · NetHunter red `#E31C3D` · geometric purple `#9B5DE5`). Assets: `website/assets/` (favicon, lockup, `og.jpg` 1200×630). X profile header: `branding/x-banner.jpg` (upload in X settings). - ---- - -## Geometric Branding Draft - -A new geometric low-poly wolf-fox mascot direction is under review: - -→ See [`branding/geometric-draft/`](../branding/geometric-draft/) - -- Cyan / Purple split -- Red eyes -- No crest -- Full favicon + lockup + hero/OG assets prepared - -Do not replace `website/assets/` until the draft is approved. -- Header mark is now the inline geometric SVG (cyan/purple split, red eyes). `website/assets/` raster favicon is unchanged until the draft is fully approved. -- Hero wash uses cyan left / purple right. `.chip-purple` and `.purple` are used in index.html. +Relative links only (`cli.html`, not `/GrokHunter/cli.html`) so project Pages and `file://` both work. diff --git a/website/site.json b/website/site.json new file mode 100644 index 0000000..be37575 --- /dev/null +++ b/website/site.json @@ -0,0 +1,23 @@ +{ + "version": "1.0.10", + "min_grok": "1.0.5", + "overlay_cache": "2026.2.25", + "agents": 26, + "personas": 24, + "roles": 25, + "skills": 20, + "pages": [ + "index.html", + "install.html", + "cli.html", + "desktop.html", + "agents.html", + "faq.html", + "404.html" + ], + "tui": { + "bare": "Grok Build fullscreen TUI (grok-nethunter)", + "tui": "Lab operations menu (alias: lab)", + "menu": "Kali/XFCE Applications submenu" + } +} From 4668d0ac0e8316fc9f9ee45c0cdd136f6d49411d Mon Sep 17 00:00:00 2001 From: Fine_Computer_4451 <119702188+FineComputer14451@users.noreply.github.com> Date: Thu, 27 Aug 2026 11:43:07 -0700 Subject: [PATCH 2/4] feat(site): add stitch chrome fragments + ghl alias --- config/completions/bash/grokhunter.bash | 8 +++++- config/profile.d/grokhunter.sh | 2 ++ docs/SHELL.md | 1 + website/_src/404.body.html | 17 ++++++++++++ website/_src/footer.html | 37 +++++++++++++++++++++++++ website/_src/head.html | 33 ++++++++++++++++++++++ 6 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 website/_src/404.body.html create mode 100644 website/_src/footer.html create mode 100644 website/_src/head.html diff --git a/config/completions/bash/grokhunter.bash b/config/completions/bash/grokhunter.bash index d9dba8d..444d67c 100644 --- a/config/completions/bash/grokhunter.bash +++ b/config/completions/bash/grokhunter.bash @@ -7,7 +7,7 @@ _grokhunter_completions() { cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" - local cmds="status doctor binds proot-binds setup sync boot ensure models skills agents team coding-team scout benjamin lucas harper review fix desktop overlay ship docs modeler ci aider session host mcp plugin flow storage editor hook shell github secrets toolchain menu git-identity credits ai-smoke smoke install plan help version" + local cmds="status doctor binds proot-binds setup sync boot ensure models skills agents team coding-team scout benjamin lucas harper review fix desktop overlay ship docs modeler ci aider session host mcp plugin flow storage editor hook shell github secrets toolchain tui lab menu git-identity credits ai-smoke smoke install plan help version" local model_sub="install status force --force help" local skills_sub="install status help" local agents_sub="status list help" @@ -52,6 +52,12 @@ _grokhunter_completions() { ensure) COMPREPLY=( $(compgen -W "--force" -- "${cur}") ) ;; + tui|lab) + COMPREPLY=( $(compgen -W "help --help" -- "${cur}") ) + ;; + menu|kali-menu|desktop-menu) + COMPREPLY=( $(compgen -W "install remove help" -- "${cur}") ) + ;; ai-smoke|smoke|team|coding-team|scout|benjamin|lucas|harper|review|fix|desktop|plan) # free-form prompt ;; diff --git a/config/profile.d/grokhunter.sh b/config/profile.d/grokhunter.sh index a006d06..d5d3e8f 100644 --- a/config/profile.d/grokhunter.sh +++ b/config/profile.d/grokhunter.sh @@ -51,6 +51,7 @@ if [[ -n "${ZSH_VERSION:-}" ]]; then fpath=("${GROKHUNTER_HOME}/config/completions/zsh" ${fpath[@]}) fi (( ${+aliases[ghn]} )) || alias ghn='grok-nethunter' + (( ${+aliases[ghl]} )) || alias ghl='grokhunter tui' (( ${+aliases[ghd]} )) || alias ghd='grokhunter doctor' (( ${+aliases[ghs]} )) || alias ghs='grokhunter status' (( ${+aliases[ghsu]} )) || alias ghsu='grokhunter setup' @@ -74,6 +75,7 @@ if [[ -n "${BASH_VERSION:-}" ]]; then source "${GROKHUNTER_HOME}/config/completions/bash/grokhunter.bash" fi alias ghn='grok-nethunter' 2>/dev/null || true + alias ghl='grokhunter tui' 2>/dev/null || true alias ghd='grokhunter doctor' 2>/dev/null || true alias ghs='grokhunter status' 2>/dev/null || true alias ghsu='grokhunter setup' 2>/dev/null || true diff --git a/docs/SHELL.md b/docs/SHELL.md index 502eb30..989bb2f 100644 --- a/docs/SHELL.md +++ b/docs/SHELL.md @@ -57,6 +57,7 @@ Same installer. In `~/.bashrc`: | Alias | Expands to | |-------|------------| | `ghn` | `grok-nethunter` | +| `ghl` | `grokhunter tui` | | `ghd` | `grokhunter doctor` | | `ghs` | `grokhunter status` | | `ghsu` | `grokhunter setup` | diff --git a/website/_src/404.body.html b/website/_src/404.body.html new file mode 100644 index 0000000..9cb76ce --- /dev/null +++ b/website/_src/404.body.html @@ -0,0 +1,17 @@ + + + + 404 + Page not found + + That URL is not part of the GrokHunter product site. + + + Home + Install + Desktop + CLI + + + + diff --git a/website/_src/footer.html b/website/_src/footer.html new file mode 100644 index 0000000..fd21002 --- /dev/null +++ b/website/_src/footer.html @@ -0,0 +1,37 @@ + + + +
404
+ That URL is not part of the GrokHunter product site. +