feat!: delete the mirror fringe; rename adapters' /dev-spa to /single; plugins default-export their factory - #238
Merged
Merged
Conversation
✅ Deploy Preview for devfra ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
…m @devframes/hub/constants
Deletes three drift-prone hand-copy clusters:
- plugins/{a11y,assets,data-inspector,inspect,messages,og}/src/vite.ts
— each an 8-25 line rename over devframeVite(def, options) from
@devframes/vite/dev-spa, and the sole reason those plugins depended
on @devframes/vite. Consumers now call devframeVite() directly
against the plugin's default export; @devframes/vite moves to
devDependencies where it's still needed for the plugin's own SPA
dev config. plugin-code-server's codeServerVite and
plugin-terminals's terminalsVite are unaffected — they compose a
bridge + static plugin and build their devframe from options, which
is real behaviour beyond delegation, not a mirror.
- DEVFRAMES_HUB_BASE hand-copied across packages/{vite,nuxt,next}'s
hub-client wrappers (each commented "mirrors @devframes/hub's").
Now defined once in the client-safe packages/hub/src/constants.ts
and imported everywhere; packages/hub/src/node/initiate.ts
re-exports it for existing importers of that entry.
- normalizeBase reimplemented ×4 with two different mechanisms (ufo
vs hand-rolled). One canonical normalizeHubBase (ufo-based, hub
already depends on ufo) now lives next to the constant and is used
by @devframes/hub itself and all three framework adapters.
Also deletes packages/hub-ui/src/client/state/renderers.ts, a
30-line shim that only delegated to createDockRenderersContext; its
one call site now calls that directly.
Breaking: the six plugins' /vite export subpath is gone. Migration
documented in docs/guide/migration-0.9.md.
Created with the help of an agent.
…Vite The migration note and each affected plugin's docs page now lead with createPluginFromDevframe (@vitejs/devtools-kit/node) for a Vite DevTools host, with devframeVite (@devframes/vite/dev-spa) as the DevTools-free fallback — matching the existing framework/hub docs' stance that Vite DevTools is the recommended integration path for a Vite app. Created with the help of an agent.
antfubot
force-pushed
the
plan-040-mirror-fringe
branch
from
August 16, 2026 23:20
23e4fb1 to
65a0347
Compare
… their factory as default
Two related breaking changes to the framework adapter/plugin surface:
- @devframes/{vite,nuxt,next} rename their single-devframe subpath
from .../dev-spa to .../single (and .../dev-spa/client to
.../single/client on next) — 'single' names the scope precisely
(author/dev-serve ONE devframe), matching the sibling '/hub' scope's
naming style. Source files, package.json exports, tsdown entries,
alias.ts/tsconfig.base.json path maps, and every doc/example
reference are updated in lockstep; AGENTS.md's framework-adapter
section documents the new name.
- Every built-in plugin (a11y, assets, code-server, data-inspector,
git, inspect, messages, og, terminals) now exports its
create<X>Devframe factory as the default export, not a pre-built
DevframeDefinition instance constructed eagerly at module load.
const xDevframe = createXDevframe(); export default xDevframe
becomes export default createXDevframe — importing the module no
longer pays for an instance nobody may want, and every consumer
(examples, storybook, the hub-ui playground, each plugin's own
cli.ts/spa vite.config.ts/tests) now calls the factory explicitly.
Documented as a new AGENTS.md convention so new plugins follow it
from the start.
tsnapi API snapshots regenerated deliberately (TSNAPI_ALLOW_BREAKING=1)
for both changes; knip.jsonc ignores the intentional named+default
duplicate export the second change introduces on every plugin's
src/index.ts.
Created with the help of an agent.
antfubot
added a commit
that referenced
this pull request
Aug 17, 2026
Resolve dependency conflicts in plugins/inspect and plugins/messages package.json: keep main's #238 layout (which moved @devframes/vite to devDependencies) and drop the now-unused nostics dependency, since these plugins reach nostics through devframe/utils/nostics.
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.
Intent
Deletes three drift-prone hand-copy clusters described in plan 040 ("delete the mirror fringe"), then follows up with two reviewer-requested API-shape improvements on the surface it touches. Each is an intentional breaking change during the 0.9 beta window; there is no deprecation cycle.
A. Six per-plugin
vite.tswrappers deletedplugins/{a11y,assets,data-inspector,inspect,messages,og}/src/vite.tswere each an 8–25 line rename overdevframeVite(def, options)from@devframes/vite/single, and the sole reason those six plugins depended on@devframes/vite. Deleted, along with their/viteexport subpath,tsdown.config.tsentry, and the now-stale@devframes/vitedependenciesentry (moved todevDependencies, since each plugin's ownsrc/spa/vite.config.tsstill usesdevframeVitedirectly to dogfood the plugin duringpnpm dev/build). Every internalvite.config.tsthat imported the wrapper now callsdevframeVite(pluginDevframe, options)directly.Docs (migration guide + each affected plugin's page) lead with the recommended path for a Vite app —
createPluginFromDevframefrom@vitejs/devtools-kit/node, mounting into Vite DevTools — withdevframeVitedocumented as the DevTools-free fallback, matching the stance the framework/hub docs already take elsewhere in this repo.plugin-code-server'scodeServerViteandplugin-terminals'sterminalsViteare intentionally left alone (a STOP condition in the plan) — inventory found they aren't pure delegation: each composesdevframeViteBridge+devframeVitePlugintogether (two plugins where the other six use exactly one) and builds its devframe from the passed options viacreateCodeServerDevframe/createTerminalsDevframe, rather than importing a static default export. That's real behavior, not a mirror.B.
DEVFRAMES_HUB_BASEhand-copied ×4Previously defined in
packages/hub/src/node/initiate.tsand hand-copied (each commented "mirrors@devframes/hub's") intopackages/vite/src/hub-client.ts,packages/nuxt/src/hub.ts,packages/nuxt/src/hub-client.ts, andpackages/next/src/hub-client.tsx. Now defined once in the client-safepackages/hub/src/constants.ts(already a published@devframes/hub/constantssubpath, and confirmed to stay client-safe — it only adds a plain string constant and a pure string-manipulation helper backed byufo, a package hub already depends on).node/initiate.tsre-exports it for existing importers of that entry (no user-facing break there).C.
normalizeBasereimplemented ×4Two different mechanisms were in play (
ufoinhub/node/initiate.tsandnext/src/hub.ts; hand-rolled string concatenation invite/src/hub.tsandnuxt/src/hub.ts). Consolidated into onenormalizeHubBase(ufo-based, since@devframes/hubalready depends onufo) exported next to the constant, and every call site —@devframes/hubitself plus all three framework adapters — now imports it instead of keeping a local copy.Also deleted
packages/hub-ui/src/client/state/renderers.ts, a 30-line shim that only delegated tocreateDockRenderersContext; its one call site (state/context.ts) now calls that directly.D. Framework adapters'
/dev-spasubpath renamed to/single@devframes/{vite,nuxt,next}rename their single-devframe subpath from.../dev-spato.../single(and.../dev-spa/client→.../single/clienton next).singlenames the scope precisely — author / dev-serve one devframe — matching the sibling/hubscope's naming style, wheredev-sparead like an implementation detail. Source files,package.jsonexports,tsdown.config.tsentries, thealias.ts/tsconfig.base.jsonpath maps, the Nuxtmodule.jsonname, and every doc/example reference move in lockstep; AGENTS.md's framework-adapter section documents the new name.E. Plugin default export is now the factory, not a pre-built instance
Every built-in plugin used to eagerly construct one
DevframeDefinitionat module load (const xDevframe = createXDevframe(); export default xDevframe) and export that instance — so importing the package paid for an instance whether or not the consumer wanted the zero-config shape, and a host needing its own options discarded a second one. The default export is now thecreate<X>Devframefactory itself (export default createXDevframe); every consumer (examples, storybook, the hub-ui playground, each plugin's owncli.ts/spa/vite.config.ts/ tests, the Next dynamic-import hosts) calls it explicitly. Documented as a new AGENTS.md convention so new plugins follow it from the start.Breaking changes
/viteexport subpath (a11yVitePlugin, …,ogVitePlugin) is gone.@devframes/{vite,nuxt,next}/dev-spa→.../single(andnext's/dev-spa/client→/single/client).DevframeDefinitionto a() => DevframeDefinitionfactory.All three are documented in
docs/guide/migration-0.9.md(dedicated sections + overview-table rows).Verification
pnpm lint && pnpm knip && pnpm test && pnpm typecheck && pnpm build— all green. tsnapi API snapshots that changed (the hubconstants/initiateentries; the three adapters' renamedsingleentries; every plugin'sindexdefault-export shape) were regenerated deliberately withTSNAPI_ALLOW_BREAKING=1.knip.jsoncignores the intentional named+defaultduplicateson each plugin'ssrc/index.ts.examples/hub-viteend-to-end (vite, exercisingviteDevframeHub→initHub→normalizeHubBase/DEVFRAMES_HUB_BASE, and every built-in plugin's factory default export): all nine plugin docks — including the untouchedcode-server/terminalswrappers — mounted and served200at/__devframes/<id>/, and/__devframes/__index.jsonlisted every frame.Created with the help of an agent.