Follows @unom/ui 0.10.0 up a generation: motion 13.1 and lucide-react 1.34 in both the peer range and the dev tree, plus TypeScript 7 and biome 2.5.11. Peers moving is breaking for consumers, hence 0.3.0. `bun run check` could not run at all here: biome 2.5 refuses to start when it finds a "nested root configuration", and both scratch worktrees under .claude/worktrees/ carried their own biome.json. Neither files.includes nor vcs.useIgnoreFile suppresses that — config discovery walks the tree regardless of both. The worktrees held no uncommitted work and their branches were already in main, so they are gone; .claude/ is now ignored (via the chore/gitignore-claude branch, folded in here) so the next one cannot come back. `biome migrate` also moved the deprecated linter.rules.recommended to rules.preset and matched the schema to the CLI. Build, tsc and biome are all clean.
@unom/app-ui
Composite, app-level UI blocks shared across the unom/punktfunk apps (the
marketing site, the docs site, plugin UIs). One layer up from
@unom/ui, which is primitives only —
this package hosts larger blocks/sections that more than one app renders, so
they stay in sync instead of being hand-mirrored per repo.
Components are themed entirely through @unom/style's semantic tokens
(neutral-accent, main, brand, …). Each consumer maps those tokens to
its own surfaces (the marketing site's blue theme, the docs' Fumadocs
violet/dark chrome, the console's translucent dark chrome), so the markup is
identical while each site keeps its palette.
The 0.2.0 blocks are the plugin-composite layer: the console design language
(entry stagger, quint ease-out, brand hover-wash, translucent chrome) packaged
for plugin UIs. They compose @unom/ui ≥ 0.9.1 primitives, are generic (zero
punktfunk imports) and weightless — no sound or material providers required.
Subpath exports
@unom/app-ui/footer—<FooterView>: the punktfunk footer (link sections, socials, tagline). Presentational; data fetching stays in each app's route loader. PassresolveHrefto rebase root-relative links onto another origin (the docs do this so footer links target the marketing site).@unom/app-ui/plugin-shell—<PluginShell>: the in-iframe app frame for plugin UIs — staggered pill tab strip, Section-wrapped content column, optional standalone header + toaster.@unom/app-ui/settings—<SettingsGroup>+<SettingsRow>: a titled card of divided label/control rows with a footer slot.@unom/app-ui/stat-card—<StatCard>: one metric on translucent chrome; numeric values roll throughAnimateNumber, tones tint icon + value.@unom/app-ui/confirm-dialog—<ConfirmDialog>: confirm/cancel over@unom/ui's dialog; an asynconConfirmdrives a pending state and the dialog closes on resolve, stays open on reject.@unom/app-ui/path-list-editor—<PathListEditor<T>>: generic editable path row list (lens-styleget/set, per-row extras slot, animated add/remove).@unom/app-ui/event-feed—<EventFeed>: live mono log column withHH:MM:SSstamps and level dots; sticks to the bottom unless the user scrolled up.
import { FooterView } from "@unom/app-ui/footer";
<FooterView
sections={footer?.sections}
tagline={footer?.tagline}
socials={footer?.socials}
socialsLabel={m.footer_socials()}
/>;
Develop
bun install
bun run build # tsdown → dist/ (esm + d.ts)
bun run typecheck
bun run check # biome
bun run storybook # dev catalog on port 6012 (@unom/ui uses 6011)
dist/ is published (not committed). Releases go to the private Gitea npm
registry under the @unom scope via bun publish.