Skip to content

feat(next): @devframes/next — Next.js host integration (experimental package) - #140

Merged
antfu merged 5 commits into
mainfrom
advisor/027-devframes-next-spike
Jul 28, 2026
Merged

feat(next): @devframes/next — Next.js host integration (experimental package)#140
antfu merged 5 commits into
mainfrom
advisor/027-devframes-next-spike

Conversation

@antfubot

@antfubot antfubot commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Why

Both Next examples hand-rolled static serving that duplicates devframe's own serveStaticHandler, and @devframes/nuxt had no Next counterpart — a bridge parity gap. This spike (plan 027) closes it: a thin Next host-integration package, proven by refactoring the hub example onto it.

Nuxt stays tiny because it reuses viteDevBridge; Next is webpack/Turbopack and can't, so it needs its own route-handler primitive. That primitive is the deliverable.

What

  • packages/next (private spike):
    • createDevframeNextHost({ resolveOrigin, getStorageDir }) → { host, fetch, setConnectionMeta } — a DevframeHost whose mountStatic/mountConnectionMeta calls accumulate into one WHATWG-fetch handler that reuses devframe's serveStaticHandler (via h3 v2 app.mount + app.fetch). Connection-meta is answered before the static handler so SPA fallback can't swallow the discovery fetch; meta returns 503 until setConnectionMeta publishes the live WS port.
    • withDevframe(nextConfig) — applies the host-mode setting Next requires (skipTrailingSlashRedirect).
  • examples/minimal-next-devframe-hub refactored onto the bridge: the 109-line catch-all route, both hand-rolled registries, and the by-hand DevframeHost are gone (~200 lines removed); both routes collapse to return hub.fetch(request).
  • turbo.json: added the @devframes/next#build task (this repo uses explicit per-package build tasks) and wired it into the example's dependsOn so a clean CI builds the bridge first.
  • Written proposal + open questions in plans/notes/devframes-next-proposal.md; plans/README.md row marked DONE.

Scope note

Runtime pinned to Node (the static handler streams from disk). The single-plugin createDevframeNextHandler(definition) wrapper and a client RpcProvider are deferred to the promotion follow-up — documented in the proposal. This ships as a private spike, not a published package.

Verification

next build (Next 16) · full Turbo build 20/20 · typecheck 21/21 incl. coverage guard · lint · example tests 4/4 · API snapshots 194 · runtime smoke against real plugins/git/dist/client (dir→index, SPA fallback, HEAD, 404, meta precedence, 503→200).


This PR was created with the help of an agent.

Docs & plan cleanup

  • docs/helpers/next.md documents the bridge (sidebar + helpers index + example cross-links), flagged experimental since the package is an unpublished spike.
  • Removed the completed plans/027-*.md spec file (the plans/README.md DONE row remains the record, pointing at the proposal notes) — matching the repo convention of keeping only open plans.

Promotion to a published (experimental) package

Follow-up commit 9bbb582 implements the proposal's open questions and ships it for real:

  • Publish shape — dropped private; publishConfig.tag: experimental (installs via @devframes/next@experimental, never latest). next + react are optional peers; exports are . (Node) + ./client (browser). tsnapi API snapshots generated under tests/__snapshots__/tsnapi/@devframes/next/.
  • createDevframeNextHandler(def, options) — single-plugin host wrapper: serves the SPA + starts a bridge-mode side-car RPC/WS server (mirrors viteDevBridge), returning { fetch, ready, close }. Covered by a test that boots a real side-car.
  • @devframes/next/client — React RpcProvider + useRpc (the $rpc counterpart), 'use client' preserved through the browser build.
  • 404 parity — host fetch normalizes a miss to a bare 404.
  • Cleanup — removed the design-system transpilePackages: ['@antfu/design'] example from the docs/config docstring; docs now cover both host modes + the client; proposal notes updated to the promoted state.

Gates: full build 20/20, typecheck 21/21, tests (API snapshots 198 + handler 2 + example 4), lint, and docs build all green.


Refinements (commit 66a78c2)

  • No npm dist-tag. Dropped publishConfig; the package is flagged experimental in its description + docs only (matching every other package — no @experimental tag).
  • Client surface evolved. RpcProvider now renders children eagerly and exposes live connection state: useRpc() returns the client or null, useRpcStatus() returns { status, error } (subscribed to the client's connection:status / connection:error events).
  • Adopted in examples/next-runtime-snapshot. Its hand-rolled connect provider is now a thin adapter over @devframes/next/client (host/handler adapter stays N/A there — devframe owns the server via createCac). Turbo build edge wired; client API snapshot regenerated.

Serve mounted devframe SPAs and connection meta from a Next.js App
Router route via a single WHATWG-fetch handler that reuses devframe's
serveStaticHandler, closing the Nuxt/Next bridge parity gap.

Refactors the minimal-next-devframe-hub example onto the bridge,
removing ~200 lines of hand-rolled static serving and registries.

Implements plan 027 (spike); proposal in plans/notes/devframes-next-proposal.md.
@netlify

netlify Bot commented Jul 28, 2026

Copy link
Copy Markdown

Deploy Preview for devfra ready!

Name Link
🔨 Latest commit 42b112f
🔍 Latest deploy log https://app.netlify.com/projects/devfra/deploys/6a68558667e993000893a72a
😎 Deploy Preview https://deploy-preview-140--devfra.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

antfubot added 2 commits July 28, 2026 05:51
Add docs/helpers/next.md (sidebar + helpers index + example cross-links),
flagged experimental. Remove the plan-027 spec file now that it's DONE — the
plans/README.md row remains the record, pointing at the proposal notes.
- Publish shape: drop private, publishConfig experimental tag, react/next
  optional peers, add ./client export; generate tsnapi API snapshots.
- Add createDevframeNextHandler: single-plugin host wrapper that serves the
  SPA and starts a bridge-mode side-car RPC/WS server (mirrors viteDevBridge).
- Add @devframes/next/client: React RpcProvider + useRpc surface.
- Normalize the host fetch miss to a bare 404 (static-server parity).
- Register source aliases + a vitest project; cover the handler with a test.
- Docs: document both host modes + the client surface; drop the design-system
  transpilePackages example. Update the proposal notes to the promoted state.
@antfubot antfubot changed the title feat(next): @devframes/next host-integration spike (plan 027) feat(next): @devframes/next — Next.js host integration (experimental package) Jul 28, 2026
antfubot added 2 commits July 28, 2026 06:55
- Drop the experimental npm dist-tag (publishConfig); the package stays flagged
  experimental in its description and docs only, matching the other packages.
- RpcProvider now renders children eagerly and exposes live connection state:
  useRpc() returns the client or null, useRpcStatus() returns { status, error }
  (subscribed to the client's connection:status / connection:error events).
- Apply @devframes/next/client to examples/next-runtime-snapshot: its connect
  provider is now a thin adapter over the package (the host/handler adapter
  stays N/A there since devframe owns the server via createCac). Wire the turbo
  build edge and regenerate the client API snapshot.
The spike proposal is fully realized in the shipped @devframes/next package,
its tests/API snapshots, and docs/helpers/next.md; remove the stale note and
point the plans/README row at the shipped artifacts instead.
@antfu
antfu merged commit 51c8b29 into main Jul 28, 2026
12 checks passed
@antfu
antfu deleted the advisor/027-devframes-next-spike branch July 28, 2026 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants