Repository navigation
Projects plugin: GitHub repos plus hand-entered projects - #1
Conversation
…ts page Lists a GitHub user's or organization's public repos (forks and archived skipped, most-starred first) cached in the plugin store and refreshed by an hourly job, with an extra_projects textarea for entries GitHub doesn't have. Closes goblogplatform/GoBlog#648 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Needs a closer look
It introduces an entirely new network-facing plugin with security-relevant HTML output and a release workflow holding contents: write, warranting final human review despite no blocking issues found.
1 open issue
What changed in this PR
This PR adds a new goblog WebAssembly plugin, goblog-plugin-projects, that renders a Projects page (/projects, shown in the nav). It lists a GitHub user's/organization's public repositories (forks, archived, private, and exclude_repos entries dropped; most-starred first; capped by repo_limit) alongside hand-entered extra_projects. Results are cached in goblog's plugin store, refreshed by an hourly job once older than cache_hours, with synchronous page fetch only when the store is empty and a 10‑minute failure backoff. It is closely modeled on the existing, published goblog-plugin-scholar, reusing its store/cache/host-binding patterns, and all output is HTML-escaped with hrefs restricted to absolute http(s) URLs.
Changes:
- GitHub repo fetching + filtering/sorting/pagination, extra-projects parsing, safe HTML rendering, and cache-decision helpers (natively testable).
- WASM host glue (
main.go) exposingidentity/settings/pages/jobs/render_page/run_job, with a native stub (main_native.go) so logic is unit-tested off-wasm. - Project metadata, module files, docs (README/CHANGELOG), and a Release workflow that tests, builds
plugin.wasm, and uploads it on release.
| File | Description |
|---|---|
| project.go | Core types, repo/extra-projects parsing, sorting, safe HTML rendering, and cache/limit helpers. |
| project_test.go | Unit tests for parsing, sorting, escaping, and cache decisions. |
| fetch.go | Paginated GitHub repo fetch with headers, limit truncation, and status/error handling. |
| fetch_test.go | Unit tests for pagination, headers, errors, limits, and rune-safe truncation. |
| main.go | wasip1-only host bindings and plugin exports (settings, pages, jobs, render, job). |
| main_native.go | Native main() stub so go test runs off-wasm. |
| goblog-plugin.json | Plugin manifest including allowed_hosts restricted to api.github.com. |
| go.mod / go.sum | Module definition pinning extism/go-pdk v1.1.3. |
| README.md / CHANGELOG.md | Install/settings/how-it-works docs and initial changelog entry. |
| .github/workflows/release.yml | CI to test, build the wasm, and publish it on release. |
| .gitignore | Ignores build artifacts (plugin.wasm, *.test). |
Review effort: Balanced
| contents: read | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | ||
| - uses: actions/setup-go@v6 |

Closes goblogplatform/GoBlog#648.
A WebAssembly plugin modeled on goblog-plugin-scholar that adds a Projects page (
/projects, in the nav):github_user(user or org) lists public repos via/users/{user}/repos. Forks, archived repos and names inexclude_reposare skipped, repos are sorted most-starred first, andrepo_limitcaps the list. An optionalgithub_tokenraises the rate limit.allowed_hostsisapi.github.comonly.extra_projectstextarea, one per line asName | URL | Description, shown above the repos. It needs no network.cache_hours, and the page fetches by itself only when the store is empty, with a 10-minute backoff after a failure. The cache records the user, so changinggithub_userrefetches. If GitHub is down, the extra projects still render with a notice.Testing
go test ./...passes (parsing, filtering, sort, pagination and limit, headers, errors, extra_projects parsing, escaping, cache decisions).GOOS=wasip1 GOARCH=wasm go buildpasses, andgoblog validate-plugin plugin.wasmpasses.plugin/wasmhost against the live GitHub API withgithub_user=goblogplatform. It rendered the extra project first, then the repos sorted by stars, with the escaped<b>and the excluded repo hidden. With no settings it shows the "not configured" notice.After merge: tag
v1.0.0and publish a release (the workflow uploadsplugin.wasm), then submit it at goblog.live/plugins/submit.🤖 Generated with Claude Code