[Guide] Build an API Explorer (Render-Time Orchestration) - implementation notes
The API Explorer guide leans into orchestration as a constant background process: flow effects are always running, render effects document what's happening, scope config decides defaults, and the request preview is stored-derived so the builder and response panel stay coherent. It's an unusual posture, but it does make the system feel "always ready" when it's done right.
How did you structure flow effects so orchestration stayed bounded and didn't become invisible coordination? Did you store derived request previews (curl, headers, body summary), and how did you keep them correct? How did scope config influence defaults (base URL, auth, retries) without becoming a hidden global? What evidence/log lines were most useful when debugging "why did it send that request"?
Comments (16)
Back to latestThe guide works when flow effects are treated like named workflows, not like magic background threads.
If you can't describe the flow in one sentence, the flow is too big.
We made flows emit doc strings (React Tips style) and kept only the last few lines as evidence:
txt
[tips] flow=builder:sync lane=pending reason=input:change
[tips] derive=requestPreview reason=builder:sync method=GET path=/users
[tips] flow=send:request lane=ok reason=user:send requestId=req_19
If the explorer "sent something", the log tells you why and what the derived preview was at that moment.
Counterpoint: "render-time orchestration" can be read as permission to do side effects in render.
We drew a hard line: render effects can *document* and *derive*, but sending requests is always a flow effect with explicit intent and lane.
Yes. The phrasing is spicy, but the contract boundary is the important part.
If a request is sent, it should have an intent, a key, a lane, and a reason you can log.
Stored-derived request preview was essential because it stabilized the UI across panels.
If the preview is computed live in multiple places, it drifts and users stop trusting what they're sending.
Long-form: API explorers are trust products. The whole point is "the tool shows you what you are about to do".
Derived preview is the contract. If the preview is wrong, the explorer is worse than useless because it trains users to distrust the tool.
So we treat preview derive as a single call site and we log derive reasons every time.
Scope config was fine as long as it was visible and versioned. We render data-scope=prod|staging and data-auth=on|off in debug mode, and we log scope changes:
txt
[tips] scope set=staging reason=user:toggle
[tips] scope auth=tokenStore:v3 reason=scope:applyWe kept the send flow idempotent-ish by making requestId stable per preview version.
If you click send twice, it replays the same request, not a subtly different one.
Counterpoint: storing previews can mask the fact that the builder inputs are invalid or incomplete.
We included validation lanes in the preview derive and rendered them as evidence (previewLane=invalid).
Long-form counterpoint: flow effects always running can become a performance tax if you don't gate work.
We introduced gates (debounce, cooldown) and logged gate decisions so it remained explainable.
Docs tie-in: effects + APIs docs explain why naming and bounding effects matters so much here.
Related: React APIs and API Reference.
We also logged a compact "request story" so support can diagnose quickly:
txt
[tips] requestStory="GET /users -> ok (200)" scope=staging requestId=req_19Counterpoint: explorers can make it easy to leak secrets if scope config and token stores are sloppy.
We treated token store as a scoped capability and rendered evidence about which capability is active. Invisible auth is dangerous.
We required every send to reference the preview version. That prevented the classic "preview says A, request sends B" bug.
If version doesn't match, we block send and render evidence that explains why.
Long-form: this is an app where logs are part of the product, not just for developers.
If an API explorer doesn't explain itself, it's worse than a raw curl because it creates false confidence.
We also stored derived response summaries (status, timing, size) so switching panels doesn't lose context.
The response summary is part of the exploration contract.
If you implement this, start with evidence keys first: scope, preview version, send lane, request id.
Once those exist, you can safely iterate on orchestration without losing user trust.