Installation
One command per component. It lands in your project as source you own, with its primitives already resolved.
Coral is not an npm package. Every component is installed as source, straight into your src/lib/components/coral/ - next to the ui/ folder shadcn keeps there - and from that moment it
is yours.
What does the installing is the shadcn-svelte CLI you already have, pointed at Coral's registry.
Requirements
A SvelteKit project already initialized with shadcn-svelte, meaning it has a components.json,
a components/ui/ folder and a utils module exporting cn, both under your lib alias - #lib on SvelteKit 3, $lib before it:
pnpm dlx shadcn-svelte@latest initThose two paths are the only things Coral reaches for outside its own folder, and both are
guaranteed by that setup - as are the icons, which come from whatever iconLibrary your components.json names.
Add a component
pnpm dlx shadcn-svelte@latest add https://coral.imlargo.dev/r/kit-select.jsonEvery component page carries its own command, for the package manager you use.
That one line does four things that the copy-the-folder install left to you:
- Installs the shadcn primitives the component imports.
kit-selectpulls inselectandbuttonfrom shadcn-svelte, in your style, and those pull in whatever they need in turn. - Installs the shared modules it depends on.
lib/optionsis theOption<T>vocabulary,lib/hidden-fieldthe input that lets a select take part in a form; you never ask for them by name. - Rewrites the imports to your aliases. Coral is written against
#lib/components/ui/*and#lib/utils.js; what lands in your project is written against whatever yourcomponents.jsonsays instead,$libincluded. - Maps the icons to your icon library. A project on
@tabler/icons-sveltegets Tabler icons, not a broken import - which is exactly the failure the copied folder used to hand you.
Where it lands
Under your components alias, beside shadcn's ui/, in the shape the repo keeps it in:
src/lib/components/
├─ ui/ ← shadcn-svelte
└─ coral/ ← Coral
├─ kit/select/select.svelte
├─ kit/select/types.ts
└─ lib/options.tsIf your components.json points components somewhere else, Coral follows it there. Components
import each other by relative path, so the folder keeps working wherever that alias points. Tests
are not published: they are written against this repo's test setup, and a copy of them in your
project would only pin you to it.
From here the folder belongs to the project. Editing it is allowed, but a change worth keeping should come back upstream, or the copies drift apart.
Import by file path
There are no barrels. One component, one folder, imported directly:
<script lang="ts">
import Select from '#lib/components/coral/kit/select/select.svelte';
</script>That makes filenames public API. Renaming one breaks every project that already installed it, so a rename is a breaking change and bumps the component's major.
Everything at once
One item pulls in every kit/* component, and through them every primitive they need:
pnpm dlx shadcn-svelte@latest add https://coral.imlargo.dev/r/coral.jsonUseful to look around in a scratch project. In a real one, add what you use.
Updating
Re-run the same command with --overwrite:
pnpm dlx shadcn-svelte@latest add https://coral.imlargo.dev/r/kit-select.json -oIt overwrites the component's files with the current version and leaves everything else alone - so if you edited the copy, that is the moment the edit disappears. Check what you changed first; that is the trade Coral makes by handing you source instead of a dependency.
Versioning
Each component carries its own version, in the file header and in coral.json,
and follows semver. The registry item repeats it under meta.version, so https://coral.imlargo.dev/r/kit-select.json tells you what the current one is without installing
anything.
There is no single Coral version to track: you installed components, and what matters is which of them are behind.
Item names
A registry item is its manifest name with the slash swapped: kit/select is published as kit-select, lib/options as lib-options. The prefix is not decoration - the CLI merges an
item's dependency tree by name, so an item called select would collide with shadcn-svelte's own select and one of the two would be dropped, files and all.
/r/index.json lists every item the registry serves.
Or copy the folder
The registry is the convenient path, not the only one. Coral is still a folder, and taking it whole still works:
npx degit imlargo/coral/src/lib/components/coral src/lib/components/coralThen install the primitives each component declares under shadcn in coral.json yourself. You
keep the tests and lose the alias and icon rewriting, which is the trade: Coral is written
against #lib, so a SvelteKit 2 project rewrites those imports to $lib by hand.