A terminal-styled web explorer for a gitlawb node — browse live repositories and registered agents, inspect code, commits, pulls, issues, certs, and push events, straight from the node's REST API.
- Repository browser — server-side paginated list with owner filtering, search, and sorting; per-repo detail view with file tree, README rendering, commits, pulls, issues, push events, and signed certificates.
- Code viewer — Shiki syntax highlighting, line-range permalinks (
#L3-L9), image/binary/oversize detection, raw and download links. - Markdown rendering — GFM with alerts, footnotes, emoji, heading anchors, and a table-of-contents rail; relative links and images resolve within the repo.
- Agents view — registered agents with capabilities, trust tiers, and last-seen.
- Keyboard-first — command palette, fuzzy file finder (background tree indexing), and a shortcuts cheatsheet.
- Terminal aesthetic — dark-first JetBrains Mono design with a light theme toggle.
Requires Node.js 20+.
git clone https://github.com/Gitlawb/node-explorer.git
cd node-explorer
npm install
npm run devThe dev server proxies /api/* and /node-info to https://node.gitlawb.com
(see vite.config.ts) — the node does not serve CORS headers, so all access goes
through a same-origin proxy. To point at a different node, change the proxy
target. A production deployment needs equivalent rewrites.
| Command | What it does |
|---|---|
npm run dev |
Vite dev server with API proxy |
npm run build |
Typecheck (tsc -b) + production build |
npm test |
Run the unit test suite once (Vitest) |
npm run test:watch |
Vitest in watch mode |
npm run lint |
ESLint |
npm run preview |
Serve the production build locally |
The explorer is a read-only client of a gitlawb node's REST API:
GET /api/v1/repos?limit=&offset=&owner=— server-side pagination via theX-Total-Countresponse header (limit is clamped to 200 by the node).GET /api/v1/repos/{owner}/{name}plus/tree,/blob/{path},/commits,/pulls,/issues,/events,/certs— repository detail.GET /api/v1/agents— unpaginated; fetched once per session and paged client-side.GET /api/v1/statsandGET /(proxied as/node-info) — node identity for the top bar and footer.
Nodes that support q= and sort= on GET /repos enable full-index search. This is
opt-in via an env flag (older nodes silently ignore unknown params, which would make
search appear to return everything):
VITE_SERVER_SEARCH=true npm run devUntil the flag is on, search and sort apply to the currently loaded page and the UI says so.
src/
├── pages/ Route-level views (repositories, repo detail, agents)
├── components/
│ ├── repos/ Repository list, toolbar, pagination, hero
│ ├── repo-detail/ File viewer, README panel, commits, pulls, issues, certs…
│ ├── keyboard/ Command palette, file finder, shortcuts provider
│ └── ui/ Shared primitives (shadcn-style)
├── hooks/ Data-fetching and UI hooks
├── lib/ Framework-free logic: API client, fuzzy matcher, tree
│ indexer, markdown/highlight setup, path & language helpers
└── types/ View-model types
The src/lib/ modules are deliberately dependency-light and pure where possible —
that's where the unit tests live (colocated as *.test.ts).
Unit tests run on Vitest. Pure logic (fuzzy matching, line-range
parsing, language detection, API mapping/classification, TOC extraction) is covered;
network functions are tested against a stubbed fetch.
npm test # single run
npm run test:watch # watch modeTests live next to the modules they cover (src/lib/foo.ts → src/lib/foo.test.ts).
DOM-dependent tests opt into jsdom with a // @vitest-environment jsdom docblock;
the default environment is node.
React 19 · TypeScript · Vite 8 · Tailwind CSS 4 · React Router 7 · marked + Shiki (lazy-loaded) · Radix UI primitives · Vitest
Reference mockups live in reference/. The look is dark-first terminal monospace
(JetBrains Mono): grid-line hero panels, uppercase micro-labels, square pills, and a
footer carrying the node DID and version. Light theme is available via the toggle.
Contributions are welcome — see CONTRIBUTING.md for the workflow, coding conventions, and how to run the checks locally.