Repository navigation
feat(core): declarative headers, page redirects, image escape hatches, live dev config, and a foreign-safe navigation - #97
Merged
Conversation
…, live dev config, and a foreign-safe navigation - janux.config `headers` rules (from/except, later rules override): COOP/COEP for SharedArrayBuffer pages with carve-outs for third-party iframe embeds. - `redirect()` from pages, with typed 3xx statuses. - `images: false` opt-out of the variant pre-encode; a corrupt source image is skipped with a warning instead of failing the build; `public/sw.js` survives builds (retireServiceWorker takes the app root). - Pages whose only client code is standalone foreign hosts now ship the runtime: the server render registry tracks foreign hosts, the shell gates scripts on runtimeUrl, island loaders register every def their module exports, and schema gains `json()` for payloads the app does not shape. - Declared rewrites hand HTTP handlers the resolved pathname (the request still carries the browser URL; the query survives). - `janux dev` picks up janux.config.ts edits live: Bun keys its module cache on the file path and ignores the ?mtime query, so the entry is evicted explicitly on every re-read. - Foreign interop hardening: the first React commit lands synchronously over the SSR markup (a concurrent first commit left the host empty for a frame — after a navigation the page collapsed to header+footer and Chrome's scroll anchoring dragged a restored scroll position to the bottom), and the navigation morph never diffs inside a live foreign host (React fibers keep node references: rewritten text made later renders bail out, and re-parented children made unmount throw removeChild). Needs diff-dom-streaming ≥ 0.6.11 for shouldSkipChildren; the option is ignored gracefully below that. - react-dom joins the runtime pre-bundle includes (flushSync import). - Docs: navigation (response headers), core-api (redirect), images (escape hatches), interop (the morph contract), cli-and-deployment (live config). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
…visories, update the test census - `patchedDependencies` carries brisa-build/diff-dom-streaming#26 (build + types) until 0.6.11 is on npm: the registry's 0.6.10 has neither the behavior the foreign-safe morph relies on (the interop refresh test is racy without it) nor the option in its types (typecheck and the declaration emit both tripped on TS2353). Drop the patch and refresh the lockfile once the release lands. - js-yaml 3.15.1 / 4.3.1 and nanoid 3.3.17 in the lockfile: the three High advisories osv-scan gates on, all in-range patch fixes. - Test census: 11970 → 11992 (the suite grew by the empty-host guard, the skip-children coverage and the config re-read test). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The release carrying shouldSkipChildren is on npm, so the patched 0.6.10 goes away: the option now comes from the package itself, in the build and in its types. `packages/conformance` moves to the same range so the workspace resolves one copy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Aug 11, 2026
Merged
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.
A wave of core improvements that came out of building a large content+tools app on Janux — each one is something the framework claimed or implied but didn't fully deliver, now with tests and docs.
Routing & server
headersrules injanux.config.ts— same grammar and ordering asredirects: every matching rule contributes, later rules override a header both name, andexceptcarves holes. The motivating case:Cross-Origin-Opener-Policy/Cross-Origin-Embedder-Policyeverywhere (forSharedArrayBuffer) except the pages that embed third-party iframes. Docs: navigation → "Response headers".redirect()from pages with typed 3xx statuses. Docs: core-api.url.pathnameis the rewritten one, the query survives.Build
images: falseopts out of the image variant pre-encode entirely (apps that serve theirpublic/images verbatim were paying the encode on every build); a corrupt source image is skipped with a warning instead of failing the whole build;public/sw.jssurvives builds (retireServiceWorkernow takes the app root).Interop & client runtime
foreign()hosts now ship the runtime. The server render registry tracks foreign hosts, the HTML shell gates its scripts onruntimeUrlrather than islands alone, island loaders register every def their module exports, and schema gainsjson()for pass-through payloads the app doesn't shape.flushSync) over the SSR markup. A concurrent first commit left the host empty for at least a frame; after an SPA navigation that collapsed the page to header+footer, and Chrome's scroll anchoring then dragged a freshly-restored scroll offset to the bottom of the page — "back goes to the footer". Regression test uses MutationObserver callbacks as checkpoints: the host is never observed empty.NotFoundError: removeChild. The morph now passesshouldSkipChildrenfor hosts with a live root — call-site props still flow through the synceddata-jxf-propsattribute push. This also turned a long-flaky interop test ("refreshes a preserved standalone foreign…") deterministic: the flake was this bug.react-domjoins the runtime pre-bundle includes (theflushSyncimport), keeping the mid-session re-optimize away.DX
janux devpicks upjanux.config.tsedits live. Bun keys its module cache on the file path and ignores the?mtimequery the re-import used for cache busting, so every dev session was stuck with the config it booted with. The entry is now evicted explicitly (createRequire(...).cache) on every read. Docs: cli-and-deployment.Tests
Full monorepo suite green (the only local failures are the pre-existing docs-playground e2e ones that run against a stale July
apps/docs/dist— identical onmain). New/extended:routing-rules(headers),server(declared headers, standalone-foreign runtime),app-config(config re-read mid-process),image-optimizer+service-worker+commands(escape hatches),registry(module def registration),interop/foreign(empty-host guard + the now-deterministic refresh test),deps(runtime includes census).🤖 Generated with Claude Code