* ♻️ refactor(ui): move DraggablePanel to the antd-free base-ui build
@lobehub/ui@5.41.0 ships a headless DraggablePanel under
`@lobehub/ui/base-ui`, rewritten on motion values so a drag never
re-renders React.
- switch all 10 import sites to `@lobehub/ui/base-ui`
- drop `stableLayout`: the new panel holds the content size while the
box animates, so the behaviour is unconditional
- drop ChatTerminal's `smoothResize` workaround and align its unmount
delay with the panel's own 250ms collapse
Claude-Session: https://claude.ai/code/session_016Yc2kk25CBo6DXmeGJo1k9
* ♻️ refactor(share): move the share portal to the antd-free DraggablePanel
The original sweep only covered `src/`, so this render site in the share app
kept importing the antd component.
Claude-Session: https://claude.ai/code/session_016Yc2kk25CBo6DXmeGJo1k9
* ⬆️ chore(deps): bump @lobehub/ui to 5.42.1
5.42.1 carries the fix that makes `collapseThreshold` work again behind
`RightPanel`'s `expandable={false}`, which this migration depends on.
Claude-Session: https://claude.ai/code/session_016Yc2kk25CBo6DXmeGJo1k9
* ⬆️ chore(deps): bump @lobehub/ui to 5.42.2
Picks up the drag-collapse clipping fix (lobehub/ui#651).
Claude-Session: https://claude.ai/code/session_012BkEgtdLyHGbfKsHAL4Z5U
* 🔧 chore: exclude the whole @lobehub scope from minimumReleaseAge
Every release of ours is one we cut ourselves, so the release-age window only
costs a version-pinned exclude entry on each bump.
Claude-Session: https://claude.ai/code/session_012BkEgtdLyHGbfKsHAL4Z5U
The antd-based wrappers are deprecated since @lobehub/ui@5.33.0. This moves every call site to the base-ui subpath.
Beyond the import path, the migration required:
- ActionIcon now renders a native <button> instead of a div: dropped the hardcoded 'nativeButton: false' in ActionDropdown's trigger props (it overrode the library's own inference, so Base UI applied role/aria-disabled to a real button), and retyped the dictation control refs to HTMLButtonElement
- Avatar is no longer antd's: replaced src/icon with avatar, dropped gap (no equivalent)
- Tag is no longer antd's: dropped bordered={false}, which antd v6 already ignored whenever variant was set — and the wrapper always set it
- prop types (ActionIconProps, AvatarProps) now come from the base-ui subpath, since the legacy ones carry antd props and a div ref
- seven files that still imported Button from @lobehub/ui or antd are migrated too, since touching them surfaced the existing no-restricted-imports error: variant=filled -> type=fill, variant=outlined + color=default -> type=default
Verified: type-check clean, 503 tests pass across ChatInput/NavPanel/User, and the migrated surfaces render with no Base UI warnings.
* ✨ feat: add product-origin artifact share page
Add /share/artifact/:id with a thin chrome around a sandboxed iframe. OSS ships a not-found stub; product metadata is loaded through the existing business-slot tRPC router.
* 🐛 fix(share): make artifact share chrome auth-agnostic
* ✨ feat(share): extract share pages into a standalone SSR micro app
`/share/t/:id` and `/share/page/:id` were client-only routes inside the main
SPA, so a shared link opened on a blank shell and link previews carried the
generic app card. They now live in `apps/share`, built the same way as
`apps/workbench`: a React Router framework-mode app that server-renders on a
Cloudflare Worker for cloud, plus a plain SPA build that Next serves for
self-hosted deployments.
What the server renders is the shell, the hero and a complete meta set — title,
description and the OG/Twitter card — resolved from the route loader through a
per-request tRPC client. The conversation and page-viewer stacks stay on the
client: `clientOnly()` gates them and, in the SSR environment, a resolver stub
cuts every `*.client` module out of the worker graph entirely. Gating the render
alone does not help, because the dynamic import still pulls the graph into the
bundle.
Keeping that worker deployable took three more cuts, each found by tracing the
module graph rather than guessing:
- `@/store/user` is stubbed for SSR — `GroupAvatar` reads the viewer profile,
and the store drags the model catalog and every provider behind it (39MB→19MB)
- `shiki` and `shiki/wasm` are stubbed for SSR — the `@lobehub/ui` barrel reads
the bundled-language catalog at module scope, registering ~400 grammars for a
highlighter the server never runs (19MB→7.6MB, 1.78MB gzip)
- SSR i18n resolves only the namespaces the shell renders; the generic loader
would register every locale x namespace pair as a worker chunk
The conversation list keeps its `headerSlot` while it shows the skeleton. It
returned early before, so mounting the list to fetch blanked a title the server
had already rendered.
`/share` is removed from the desktop and mobile routers and rewritten by the
Next middleware to `/spa-share/<locale>/…`, mirroring how `/verify` reaches
workbench. The cloud worker is published from lobehub-cloud, which builds this
same app against its business overlay, so this repo ships no deploy workflow
for it.
* 🐛 fix(share): preload the error namespace so the boundary renders translated
The root ErrorBoundary reaches for the `error` namespace, which SSR did not
bundle, so a failed share page rendered `error.title error.desc error.retry`
verbatim. Fetching it on demand does not fix that case: a chunk-load failure is
exactly when the client can never load the dictionary to correct itself.
* 🐛 fix(share): drop the dev template fetch that served the main SPA
The handler asked the main Vite server for `/index.share.html`, which does not
exist at the repo root. Vite answers that with the HTML fallback — 200, main SPA
shell — so `/share/*` in `bun run dev` silently booted an app that no longer has
those routes. Share is developed against its own Vite server, so the branch goes
rather than the file being added.
`spaDevShells.test.ts` guards both directions: every remaining dev template must
exist at the root and point at its own app entry, and share must not reintroduce
one.
* 📝 docs(skill): record the cloud-overlay split in split-micro-app
Share is the second micro app and the first whose rendering code lives in the
lobehub-cloud business overlay, so the skill needed the ownership rules that
decides which repo builds and deploys, and the Vite 8 tsconfig-nearest-importer
landmine that makes an overlay build ship the open-source fallback with a green
build.
Also folds in what the extraction turned up: the full Docker chain, the dev shell
that answers 200 with the wrong app, shiki and @lobehub/ui bundle cuts, the error
namespace, hydration and virtualized-prefill rules, the asset prefix convention,
and the prod promote gate.