feat(ui): a React workspace UI over the hflow-server API - #87
Draft
kstonekuan wants to merge 2 commits into
Draft
Conversation
kstonekuan
marked this pull request as ready for review
August 22, 2026 04:03
kstonekuan
marked this pull request as draft
August 22, 2026 06:39
kstonekuan
force-pushed
the
workspace-ui
branch
from
August 22, 2026 19:05
a8398fd to
f6cf147
Compare
kstonekuan
force-pushed
the
workspace-api
branch
from
August 22, 2026 19:26
030baff to
63cb9db
Compare
kstonekuan
force-pushed
the
workspace-ui
branch
from
August 22, 2026 19:28
f6cf147 to
6251509
Compare
kstonekuan
force-pushed
the
workspace-api
branch
2 times, most recently
from
August 23, 2026 01:02
9d12213 to
91326e9
Compare
The first client of the JSON API: episodes as a faceted table over the wide catalog view, an episode dossier with its measurement timeline and media, a curation studio with SQL previews and pinned manifests, a runs monitor with the live DAG, and a pipeline page that draws each stage's registered steps inside the process_batch node that runs them. Strictly a client. Every screen is a rendering of a documented endpoint, no computation happens here that the server could not do, and nothing is reachable that `curl` could not reach -- so this app can be replaced, or joined by another, without touching the server. Offline like the server: no CDN, no telemetry, no runtime downloads. Built assets are copied into hflow_server/static/ at package time, which the CI job here verifies actually happens. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…PI schema `api.ts` declared 64 interfaces mirroring the server's contract by hand, and they had drifted with nothing to catch it: - `WorkspaceConfig` still read `hflow_ui_version`, a field the server no longer sends -- the version line in the rail rendered undefined. - `WorkspaceCapabilities` never learned about `curation`, so the client could not gate on the capability the server publishes for it. - Of the contract's 10 `Literal` unions, most arrived as bare `string`: the server says `kind: StepKind`, the copy said `kind: string`. `pnpm gen:api` now generates `src/apiSchema.ts` from the server's own /api/openapi.json, and the payload types are aliases of it. One owner, and regenerating is a diff instead of an audit. CI regenerates and fails on a dirty tree, so the two cannot drift again. Aliasing them surfaced 50 type errors, every one a place the client assumed a field the server declares nullable. They are fixed here, not silenced: - Timeline intervals carry `start_s`/`end_s` only when the server could derive the episode's start. Unplaceable intervals are separated out and COUNTED in the legend rather than plotted at zero. - Interval rows type every bound nullable, so the relative-seconds table renders an em dash instead of computing against `Math.min()` of nothing. - A task instance or run with no id belongs to no node and cannot be keyed or deep-linked; those are skipped at the grouping boundary, with the reason. - `formatTimestamp`, `shortFingerprint`, `StatusChip` and `VersionChip` take the null the server can send and render the same em dash as every other absent value. One narrowing remains by necessity: `PipelineResponse.manifest` is declared `dict[str, Any]` server-side because hflow.manifest owns that shape and it is forwarded verbatim, so the generated type is an open object and the local `PipelineManifest` fills the hole. Typing it server-side would delete that. Also fixes .gitignore, which still pointed at the pre-rename asset path and so let three built files be committed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
kstonekuan
force-pushed
the
workspace-ui
branch
from
August 23, 2026 01:11
6251509 to
a4817a8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The first client of the workspace API.
episodesview. Every filter compiles to DuckDB SQL server-side; the page renders JSON.process_batchnode that runs them. They have no dependency edges on each other, so the graph nests them rather than inventing a chain, and says so.Strictly a client: no computation here that the server could not do, and nothing reachable that
curlcould not reach.Offline like the server — no CDN, no telemetry, no runtime downloads. Built assets are copied into
hflow_server/static/at package time, which the CI job here verifies actually happens.React 19, Vite 8, react-router 7, TanStack Query and Table, Radix, CodeMirror 6, lucide.
pnpm checkandpnpm buildclean.Known follow-up
ui/src/api.tshand-writes 64 interfaces mirroring the server's contract, and they have already drifted — the server declareskind: StepKind, the copy sayskind: string, and most of the contract's 10Literalunions arrive as barestring. These should be generated from/api/openapi.jsoninstead. That is the change that makes a second UI cheap, so it matters more than it looks.🤖 Generated with Claude Code