comparison hg-web/README.md @ 226:3fa4bf481f42

[merge] Merge hg-web into default
author MrJuneJune <me@mrjunejune.com>
date Sun, 02 Aug 2026 14:42:01 -0700
parents 3007ef5fc0ed
children 8bb0ac8f4587
comparison
equal deleted inserted replaced
220:eb8b4230fdb9 226:3fa4bf481f42
1 # hg-web 1 # hg-web
2 2
3 A web-based Mercurial repository browser. Provides a GitHub-style interface for browsing files, viewing code with syntax highlighting, and reading markdown documentation. 3 A custom Mercurial forge and repository browser. The application keeps the
4 4 networking and HTTP stack in C with Seobeo, while the hand-drawn web interface
5 ## Features 5 is implemented in React and TypeScript.
6 6
7 - Browse repository files and directories 7 ## Wiki tree
8 - View code files with syntax highlighting (highlight.js) 8
9 - Render markdown files with WASM-based converter 9 ```text
10 - Dark/light theme support with system preference detection 10 hg-web
11 - Prefetch on hover for faster navigation 11 ├── Runtime
12 12 │ ├── hg_web_server :6970
13 ## Structure 13 │ │ ├── React application and static assets
14 14 │ │ ├── repository browsing API
15 ``` 15 │ │ ├── commit graph API
16 hg-web/ 16 │ │ └── Mercurial wire-protocol proxy
17 ├── BUILD # Bazel build configuration 17 │ └── hg serve :4444
18 ├── deploy.sh # Deployment script 18 │ ├── repository files and graph data
19 ├── main.c # C server handling API routes 19 │ └── Mercurial pull/push protocol
20 └── src/ # Frontend source files 20 ├── Backend
21 ``` 21 │ ├── main.c
22 22 │ └── ../seobeo
23 ## Building 23 │ ├── s_network.c
24 │ ├── s_web.c
25 │ ├── s_http_client.c
26 │ └── s_ssl.c
27 ├── Frontend
28 │ └── src
29 │ ├── main.tsx
30 │ ├── components
31 │ │ ├── app.tsx
32 │ │ ├── directory-browser.tsx
33 │ │ ├── graph.tsx
34 │ │ ├── header.tsx
35 │ │ ├── footer.tsx
36 │ │ ├── theme.tsx
37 │ │ └── repo-browser.tsx
38 │ ├── index.html
39 │ ├── index.css
40 │ ├── base.css
41 │ └── custom pencil, panda, and icon assets
42 ├── Build
43 │ ├── BUILD
44 │ ├── ../gui_ze/gui_ze.bzl
45 │ ├── ../markdown_converter
46 │ └── ../third_party/highlight
47 └── Operations
48 └── deploy.sh
49 ```
50
51 `repo-browser.tsx` is an older standalone browser implementation. The active
52 entry point is `main.tsx`, which renders `app.tsx`; `app.tsx` embeds
53 `directory-browser.tsx`.
54
55 ## Runtime topology
56
57 ```text
58 Browser
59 |
60 | HTTPS
61 v
62 nginx
63 |
64 | HTTP :6970
65 v
66 hg_web_server (main.c + Seobeo)
67 |
68 | HTTP :4444
69 v
70 hg serve (Zenbu Mercurial repository)
71 ```
72
73 The C server owns the public routes. It serves the application shell and
74 assets, translates browser API requests into `hg serve` requests, and streams
75 Mercurial wire-protocol traffic without routing bundle data through the normal
76 buffered HTTP response path.
77
78 ## Request flows
79
80 ### Application shell
81
82 ```text
83 GET /, /directories, or /graph
84 -> GetReactHome
85 -> hg-web/src/index.html
86 -> /page.js
87 -> src/main.tsx
88 -> components/app.tsx
89 ```
90
91 ### Repository browser
92
93 ```text
94 directory-browser.tsx
95 -> GET /api/repo/list?path=...
96 -> ApiListDirectory
97 -> GET hg-serve/file/tip/<path>?style=json
98
99 file or README selection
100 -> GET /api/repo/file?path=...
101 -> ApiGetFile
102 -> GET hg-serve/raw-file/tip/<path>
103 -> highlight.js, markdown_converter WASM, or inline static preview
104 ```
105
106 Images, SVG, video, audio, and PDF files open in the forge preview modal.
107 Unknown binary files retain a download link. The raw file API supplies explicit
108 MIME types, `nosniff`, inline disposition for supported previews, and sandboxed
109 SVG responses.
110
111 ### Commit graph
112
113 ```text
114 graph.tsx
115 -> GET /api/graph/<revision>?graphtop=...&style=json
116 -> ApiGetGraph
117 -> GET hg-serve/graph/<revision>?...
118 -> React rows + custom pencil/panda canvas
119
120 graph row selection
121 -> /changeset/<revision>
122 -> GET /api/changeset/<revision>
123 -> ApiGetChangeset
124 -> GET hg-serve/json-rev/<revision>
125 -> changeset metadata + rendered diff
126 ```
127
128 ### Mercurial clone, pull, and push
129
130 ```text
131 Mercurial client
132 -> GET or POST /repo
133 -> StreamHgWireProtocol
134 -> hg serve /?cmd=...
135 -> binary-safe streamed response
136 ```
137
138 ## Route map
139
140 | Method | Route | Owner | Purpose |
141 | --- | --- | --- | --- |
142 | `GET` | `/` | `GetReactHome` | Application shell |
143 | `GET` | `/directories` | `GetReactHome` | Legacy application-shell route |
144 | `GET` | `/directory` | `GetReactHome` | Repository browser application route |
145 | `GET` | `/graph` | `GetReactHome` | Commit graph application route |
146 | `GET` | `/changeset/:changeset_id` | `GetReactHome` | Changeset application route |
147 | `GET` | `/api/repo/list` | `ApiListDirectory` | Directory listing JSON |
148 | `GET` | `/api/repo/file` | `ApiGetFile` | Raw tracked file |
149 | `GET` | `/api/repo/readme` | `ApiGetReadme` | Directory README content |
150 | `GET` | `/api/graph/:graph_id` | `ApiGetGraph` | Mercurial graph JSON |
151 | `GET` | `/api/changeset/:changeset_id` | `ApiGetChangeset` | Changeset metadata and diff JSON |
152 | `GET`, `POST` | `/repo` | `StreamHgWireProtocol` | Mercurial wire protocol |
153
154 ## Frontend ownership
155
156 | File | Responsibility |
157 | --- | --- |
158 | `src/components/app.tsx` | Client-side routes, landing page, tabs, and history |
159 | `src/components/directory-browser.tsx` | Breadcrumbs, listings, prefetch, file modals, README rendering |
160 | `src/components/graph.tsx` | Graph fetching, pagination, canvas edges, panda nodes |
161 | `src/components/theme.tsx` | Stored light/dark preference and system-theme integration |
162 | `src/components/header.tsx` | Forge identity and theme control |
163 | `src/components/footer.tsx` | Shared footer |
164 | `src/index.css`, `src/base.css` | Custom visual language and layout |
165
166 Keep the custom assets and visual language in this package. New forge screens
167 should reuse the existing CSS variables, typography, textures, and components
168 instead of introducing a generic design system.
169
170 ## Build and local run
171
172 Build the server and deployable bundle from the repository root:
24 173
25 ```bash 174 ```bash
26 bazel build //hg-web:hg_web 175 bazel build //hg-web:hg_web_server
27 ``` 176 bazel build //hg-web:hg_web_server_bundle
28 177 bazel test //hg-web:tests
29 ## API Endpoints 178 bazel test //markdown_converter/tests:markdown_to_html_test
30 179 bazel test //seobeo/tests:all
31 The C server (`main.c`) provides: 180 ```
32 181
33 - `GET /api/repo/list?path=` - List directory contents 182 `//hg-web:tests` creates a temporary two-commit Mercurial repository and runs
34 - `GET /api/repo/file?path=` - Fetch file contents 183 the application in pinned Chromium through Playwright. It covers shell routes,
184 files and README rendering, graph and changeset navigation, browser history,
185 console and page errors, API validation, Mercurial wire protocol, Markdown
186 script escaping, static assets, and backend outages. The test invokes the
187 workspace Mercurial CLI with an isolated configuration and home directory.
188
189 Build and run the complete local stack with one Bazel command:
190
191 ```bash
192 bazel run //hg-web:dev
193 ```
194
195 This starts `hg serve` on `127.0.0.1:4444` and `hg_web_server` on port `6970`.
196 Stopping the Bazel target stops both child processes.
197
198 The bundle contains `hg_web_server` and `hg-web/src/`, including generated
199 `page.js`, markdown WASM, highlight.js, styles, and image assets.
200
201 ## Deployment contract
202
203 The expected production layout is:
204
205 ```text
206 nginx
207 -> hg_web_server.service
208 -> /opt/hg_web_server_bundle_active/hg_web_server
209 -> working directory: /opt/hg_web_server_bundle_active
210 -> hg serve service on 127.0.0.1:4444
211 ```
212
213 `deploy.sh` builds an optimized bundle into a revisioned release directory,
214 atomically repoints `/opt/hg_web_server_bundle_active`, restarts
215 `hg_web_server.service`, and checks `http://127.0.0.1:6970/`. A failed restart
216 or health check restores the previous release and restarts it. The service,
217 release root, active path, health URL, user, and group can be overridden with
218 environment variables.
219
220 ## Forge capability tree
221
222 ```text
223 Zenbu Forge
224 ├── Repository
225 │ ├── File and directory browsing available
226 │ ├── Syntax highlighting available
227 │ ├── README rendering available
228 │ ├── Commit graph available
229 │ ├── Changeset detail and diff available
230 │ ├── Branches, bookmarks, and tags planned
231 │ ├── File history and blame planned
232 │ └── Search planned
233 ├── Collaboration
234 │ ├── Authentication and authorization planned
235 │ ├── Changeset review planned
236 │ ├── Issues planned
237 │ └── Releases and artifacts planned
238 └── Automation
239 ├── Mercurial incoming/changegroup hook planned
240 ├── Durable SQLite job queue planned
241 ├── Isolated Bazel runner planned
242 ├── Live logs and job status API planned
243 ├── Forge status and log screens planned
244 ├── Artifact retention planned
245 └── Atomic deploy, health check, rollback available
246 ```
247
248 ## Automation data flow
249
250 The Actions-like subsystem should extend the existing server rather than
251 replace it:
252
253 ```text
254 hg push
255 -> Mercurial hook records repository + revision
256 -> small enqueue command writes a SQLite job
257 -> runner service claims one queued job
258 -> isolated shared checkout updates to the exact revision
259 -> Bazel build and test steps stream logs
260 -> job result and artifacts are recorded
261 -> hg-web status API exposes the result
262 -> custom React screens render runs, steps, logs, and artifacts
263 -> successful protected jobs may call atomic deployment
264 ```
265
266 Start with one runner on the same host. Keep the hook fast, never execute build
267 steps inside the Mercurial request, and make the queue durable before adding
268 parallel or remote runners.
269
270 ## Safe extension order
271
272 1. Add branches, bookmarks, tags, file history, blame, and search.
273 2. Add the hook, SQLite queue, single runner, and retained logs.
274 3. Add run/status/log pages using the existing custom UI.
275 4. Add authentication and authorization before accepting public pushes or
276 user-defined automation.
277
278 ## Invariants
279
280 - Keep public application code on Seobeo APIs.
281 - Decode and validate every path before forwarding it to Mercurial.
282 - Keep `/repo` binary-safe; bundle data can contain null bytes.
283 - Do not buffer large wire-protocol responses through the regular HTTP client.
284 - Keep backend route names synchronized with frontend fetch and navigation code.
285 - Preserve accurate status codes, content lengths, and content types.
286 - Keep secrets in service-owned environment files, not in source or job logs.