Skip to contentAsheeUIAsheeUI

AsheeUI 3.0.0

The contract release: core keeps the rules, the renderers keep the pixels, the umbrella becomes the intersection, and the two reference applications prove it.

Field Value
Version 3.0.0
Packages asheeui 3.0.0, @asheeui/core 3.0.0, @asheeui/web 2.8.0, @asheeui/native 2.8.0, @asheeui/puck 2.3.1, @asheeui/cli 1.0.1
Previous release the 2.7 line (@asheeui/web and @asheeui/native 2.7.0, core 2.5.0)
Breaking changes for an existing application Yes. This is the major where core stops rendering and the umbrella stops being export * over the renderers.

AsheeUI 3.0 is the release where the contract stopped being an engine. @asheeui/core keeps the tokens, the rules, the types and the configuration cascade — the part that is true on both platforms. Every pixel decision moved to the renderer that compiles it. The umbrella stopped re-exporting both renderers and became the list of names that are actually portable.

The result is a smaller core, two renderers that own their implementations, and one import a shared screen can use without learning which platform it is on.

What changed

Core is the contract, not the engine

  • Both class dictionaries left core: the web's constants moved to @asheeui/web, the platform's to @asheeui/native. @asheeui/core now declares no dependencies and contains no class string.
  • Core keeps the tokens, the typography role table, the palette model, the cascade, the shared rules (isFieldInvalid, resolveFieldStatusColor, UnderlineRadius, selectTheme, the breakpoint resolver) and the configuration types.
  • The compatibility matrix moved to @asheeui/core/dev. It is data for tooling — the parity guard, the umbrella guard, the CLI, this documentation — not something a component renders.
  • pnpm check:core-charter is the ratchet: no class string, no dependency, no renderer import, and every export has a reader. It is a blocking CI step.

The umbrella is the intersection

asheeui publishes 182 names (90 from core, 92 from the branch renderer) plus AsheeConfig. A name is on it only when both renderers publish it under the same name and contract.

  • The list is declared once, as PORTABLE_API in @asheeui/core, and both umbrella entries are generated from it. The branches cannot drift.
  • Renderer-only names stay with their renderer: Breadcrumb, ResizableScreen, SkipLink and the keyboard family on the web; RowList and TabBar on a device.
  • The umbrella owns three subpaths: asheeui/styles (the web stylesheet), asheeui/tailwind-preset (the native preset) and asheeui/section-kit (the composition vocabulary).
  • The renderers are optional peers; an application installs the one it builds for.

The native contract is complete

Every component the matrix promises for native is implemented and tested with the platform's own tooling. The native parity guard reads what the package publishes, not what its file names suggest, and fails when the matrix, the exports and the queue disagree. The queue is empty.

The provider names align with the web renderer: AsheeUIProvider is the current name, and AsheeNativeProvider is an alias that warns once per process.

Puck is one document, two renderers

@asheeui/puck keeps one set of block specs and two renderings. The editor is a web concern; a device bundle imports the native renderer and never @puckeditor/core. The editor is an optional peer of the web half alone. See Puck.

Two reference applications

The repository ships a fitness tracker as one shared kit and two applications: TanStack Start on the web with a top Navbar, Expo on a device with a header and a bottom TabBar, and a Puck studio on both. It is the layout the monorepo blueprint describes, with seven screens.

Breaking changes

Change What to do
Class dictionaries and cn are no longer published by @asheeui/core Import the renderer's own utility, or stay on the portable surface
The compatibility matrix moved Change @asheeui/core to @asheeui/core/dev
ExternalColorVariant is no longer a root export Type a palette as ExternalColorConfig; the variant is its internal shape
The umbrella is no longer export * A name only one renderer has must be imported from that renderer
asheeui/styles and asheeui/tailwind-preset are the umbrella paths The renderer paths still work; the umbrella path is the default
RowList and TabBar are native-only Keep them in the native shell, not in a shared screen
The native provider names changed AsheeUIProvider, AsheeUIProviderProps, AsheeConfigContext, useAsheeConfig; the old names warn and are removed in the next major

The detailed paths are Migrating the umbrella and Migrating the core layer. The target layout is the monorepo blueprint.

What was deliberately not done

Not done Why
Per-component subpaths The umbrella is one entry and three subpaths; a page imports the name, not a door per component
A native Puck editor Composing is a web authoring concern; the device renders the document
One Tailwind version for both The web is Tailwind 4 and NativeWind is Tailwind 3; the umbrella spans both rather than pretending they are one compiler
Sharing renderer source Sharing source would give one platform the other's behaviour, which is what the contract split exists to avoid

The release set

Package Version What it contains
asheeui 3.0.0 The portable surface, generated from PORTABLE_API
@asheeui/core 3.0.0 Tokens, rules, types, cascade; no classes, no dependencies
@asheeui/web 2.8.0 The DOM renderer and its dictionaries
@asheeui/native 2.8.0 The React Native renderer and its dictionaries
@asheeui/puck 2.3.1 The shared block specs and the two renderings
@asheeui/cli 1.0.1 asheeui list and asheeui check against the published matrix

The packages version independently. The current release keeps the table and the short form; the migration hub records every breaking change.