React renderers for the statewalker application shell. Each package here is
the view half of a logic package: the logic package (for example
@statewalker/shell.core) holds state, commands and slots with no React, and
the package here (@statewalker/shell.view.react) renders them. Together they
give an app a React mount, a dockview-based shell, a settings dialog, a file
explorer, viewers for images, Markdown, PDF and video, and the AI settings
tabs. All packages are published to npm under @statewalker/*.
packages/
ui.view.react React mount, <AppRoot>, core:views slot, workspace hooks, theme CSS
ui.view.shadcn shadcn/ui primitives and cn()
render.view.react <SpecRenderer>; re-exports from @json-render/react
shell.view.react dockview host, MainShell, header, the "json" dock panel, tab icons
workspace.view.react workspace label header item, switch-workspace button
settings.view.react settings dialog and settings button
explorer.view.react file-explorer panels (list, breadcrumbs, filter, drag and drop)
inline.view.react <InlineContent> and the built-in inline components
mime.view.image image/* viewer
mime.view.markdown text/markdown viewer and a reusable <Markdown> component
mime.view.pdf application/pdf viewer (browser built-in PDF viewer)
mime.view.video video/* viewer
ai-config.view.react "Remote Models" settings tab
ai-local-models.view.react "Local Models" settings tab
webapp.view.react <SiteFrame>: iframe dock panel for a web app hosted from the workspace
Most packages share one source layout:
src/
index.ts re-exports public/index.ts and the default init
fragment.ts re-exports the default init
public/ exported components, slots, catalogs, init
internal/ implementation and tests; not reachable through exports
styles.css Tailwind v4 @source globs (ui.view.react also defines the theme)
Each package exports . and ./fragment from dist/ (JS and .d.ts) and,
when it has a stylesheet, ./styles from src/styles.css.
render.view.react exports only .. webapp.view.react has no ./styles and
keeps its sources directly in src/. Packages ship both dist/ and src/.
The packages use these @statewalker packages from npm: shell.core,
workspace.core, workspace.browser, render.core, mime.core,
explorer.core, inline.core, settings.core, webapp.browser,
ai-config.core, ai-local-models.core, shared-baseclass,
shared-commands, shared-registry, shared-slots, webrun-files and (in
tests) webrun-files-mem.
- Install Node.js 24.
- Enable corepack so the pinned pnpm 10 is used:
corepack enable. - Install:
pnpm install. - Build every package:
pnpm build. - Run the tests:
pnpm test.
There is no app in this repository to start. The packages are activated by a host app; see "How a host app wires the packages" below.
A *.view.* package is the only kind of package allowed to import a UI
library (React, shadcn, the json-render React bindings). The logic packages
stay React-free, so they can be tested without a DOM and a different renderer
could replace these packages. Values that cross from logic to view are data:
a logic package names a component by a string viewKey, and the view
package registers the component under that key in the core:views slot.
Every package with a ./fragment export has a default export
init(ctx) => cleanup. It reads the Workspace from ctx, registers
components into slots, and returns a function that removes them.
host boot
create Workspace, put it into ctx
init logic fragments (shell.core, settings.core, explorer.core, ...)
init view fragments (ui.view.react, shell.view.react, settings.view.react, ...)
ui.view.react: createRoot(#app).render(<AppRoot/>)
import each package's ./styles once
ui.view.react renders whatever is registered under shell:root in
core:views; shell.view.react registers MainShell there. Neither imports
the other's components.
Packages inside this repository depend on each other with workspace:^.
Everything else comes from the pnpm catalog in pnpm-workspace.yaml
(catalog:); react and react-dom are peers (catalog:peers, >=18).
- Components render without colors or spacing. The host did not import
@statewalker/ui.view.react/styles(theme variables) or a package's./styles(Tailwind@sourceglobs), so Tailwind did not emit its classes. useAppWorkspace must be used inside <AppWorkspaceProvider>.A component that uses the workspace hooks was rendered outside<AppRoot>.No adapter registered for ...at fragment init. A view fragment ran before the logic fragment that installs the adapter it needs (for exampleSpecStore,LayoutStore,DockHost).- A dock tab shows "Spec ... is missing." or "Catalog ... is not registered." The panel was restored from the saved layout, but no fragment created its spec or registered its catalog.
- The page stays empty and nothing is logged. There is no element with
id="app";ui.view.react's init then skips the mount silently. - Nothing renders after the folder is opened. No component is registered
under
shell:root:shell.view.react's fragment was not activated. - Cleanup functions return promises. Most
initfunctions return() => Promise<void>; await them when tearing down.
| Command | What it does |
|---|---|
pnpm install |
Install dependencies |
pnpm build |
Build every package with tsdown |
pnpm test |
Run every package's vitest suite |
pnpm typecheck |
Type-check every package |
pnpm lint / pnpm lint:check |
Biome check, with or without fixes |
pnpm format / pnpm format:check |
Biome format, with or without writes |
pnpm changeset |
Add a changeset to pick a version bump and changelog text |
Packages are published to npm from CI with changesets. After CI passes on
main, a job adds a patch changeset for each package whose packed contents
differ from npm and opens a "chore: version packages" pull request; merging it
publishes. Add your own changeset with pnpm changeset to choose the bump or
the changelog text. Dependency updates come from Renovate.
MIT. See LICENSE.