Piral packages
Piral ships as a small stack of layered packages. They share one runtime and one API; the difference is how much opinion comes pre-wired. Pick the outermost layer you need, and move inward as your app matures.
piral; graduate to piral-core for the long run.piral — the opinionated starting point
piral is the fastest way to a working app shell. It re-exports everything from piral-core and piral-base and bundles a curated set of standard plugins and sensible defaults, so the common capabilities are already wired up.
Out of the box you get createInstance, the root rendering component, ExtensionSlot, the standard plugin components and APIs (menu, notifications, modals, dashboard, …), and the hooks (useGlobalState, useAction, useExtensions, usePilet). It's opinionated about what's included but leaves rendering and layout entirely to you. See createInstance for the full options.
piral-core — the choice for the long run
piral-core is the same runtime and the same API surface, but unopinionated about which plugins are included. You install and register exactly the capabilities you use — nothing more.
That explicitness is exactly what you want as an application matures:
- Smaller, intentional footprint — no plugins you don't use.
- No surprises on upgrade — behavior is whatever you registered, not whatever the meta-package decided to bundle.
- Clear dependency graph — each capability traces to a package you chose.
For these reasons, piral-core is the recommended target for mid- to long-term and production applications. piral is the great on-ramp; piral-core is where serious apps tend to settle.
Migrating from piral to piral-core
The migration is mechanical and low-risk, because the runtime and API are identical — you're just making the implicit explicit.
1. Swap the dependency. Remove piral; add piral-core plus the plugin packages you actually use, and make sure React and React Router are direct dependencies.
2. Update imports. Pull the runtime from piral-core, and each plugin factory from its own package (with piral these came along for free).
3. Register the plugins explicitly. Anything piral set up for you now goes into the plugins array.
4. Verify the Pilet API. Every method your pilets call must come from a plugin you registered. If a pilet uses api.showNotification but you didn't add piral-notifications, add it. This audit is the point of the move: each capability becomes intentional.
The result behaves identically to your piral app — just leaner and fully under your control.
Start on piral to move fast and prove the idea. Plan to graduate to piral-core once the app and team mature and you want a tighter, explicit footprint. Because the API is the same, the switch is a dependency-and-imports change, not a rewrite.
piral-base — the low-level loader
piral-base is the foundation both other packages build on: it fetches, evaluates, and manages the lifecycle of pilets, with no dependency on React or any UI framework. You'd use it directly only when building a completely custom, non-React runtime. For anything React-based, you'll be on piral-core (or piral), which already include it.
Converter packages
Framework converters (piral-vue, piral-svelte, piral-ng, …) are a special case worth calling out. They're published as plugin packages, but a converter should not be installed as a plugin in the app shell — that would make every pilet depend on the shell having the right converter.
Instead, each converter also ships a standalone convert submodule that a pilet imports and uses directly:
Used this way, the converter carries its own logic inside the pilet and emits a plain HTML component the core already knows how to render — so the shell stays framework-agnostic and the pilet stays portable. Reach for the /convert submodule in pilets and avoid the plugin form for converters. See Creating a converter and Multi-framework pilets.
Shared API surface
Whichever layer you choose, the building blocks are the same — these all come from piral and piral-core alike: