@meldkit/svelte
v0.1.2
Published
Svelte bindings for the MeldKit SDK
Readme
@meldkit/svelte
Svelte bindings for the MeldKit SDK: end-to-end encrypted real-time collaboration, as runes.
npm install @meldkit/svelte yjsSvelte 5. Everything the SDK exposes is $state, so there are no stores, no
subscriptions and no $ prefixes — the fields are the API.
Connect
<script>
import { MeldKitProvider } from '@meldkit/svelte';
</script>
<MeldKitProvider roomKey={KEY} room="doc-1" auth="/api/meldkit-auth">
<Board />
</MeldKitProvider>auth points at your own endpoint. It is POSTed { room } and answers
{ token }, minted server-side with your project's secret key — a secret key
can't be in a browser. The provider fetches a token before it connects, and
again before every reconnect, so a session outlives the short-lived token it
started with.
The connection belongs to the provider: it closes when the component unmounts.
Props are read reactively, so a room that changes reconnects — and only if
what the transport is built from actually changed.
Read and write
<script>
import { getMeldKit, syncedList } from '@meldkit/svelte';
const meldkit = getMeldKit();
const todos = syncedList('todos');
</script>
{#each todos.entries as [id, todo] (id)}
<label>
<input
type="checkbox"
checked={todo.done}
onchange={() => todos.update(id, { done: !todo.done })}
/>
{todo.text}
</label>
{/each}| Helper | What it gives you |
| ------------------ | ------------------------------------------------------------- |
| getMeldKit() | the room: status, error, readOnly, doc, client |
| syncedMap(name) | a shared record — entries, get, set, update, remove |
| syncedList(name) | the same, ordered, plus push, insert, move |
| sharedText(name) | a shared text field — see below |
| others() | everyone else's presence, each with clientId folded in |
| myPresence() | your own presence, and a merging setter |
They read the connection from Svelte's context, so — like getContext itself —
they belong at the top of a component's <script>, not inside a handler or an
effect. entries is reactive: put it straight in the markup.
update(id, patch) merges per field, so two people editing different fields
of the same item both win. set(id, value) replaces the whole entry. Use
syncedList whenever order is visible — an ordered CRDT is what stops two
concurrent inserts from landing in different orders on different screens.
Presence
<script>
const me = myPresence();
</script>
<svelte:window onpointermove={(e) => me.update({ pointer: { x: e.x, y: e.y } })} />update merges; awareness itself only replaces wholesale, which is the helper
every app was writing by hand. Set initialPresence on the provider and it is
published on connect and after every reconnect — awareness state is ephemeral,
so a client that announces itself once vanishes from everyone else's screen
after the first dropped connection and never comes back.
Shared text
<script>
const body = sharedText('body');
</script>
<textarea use:body.bind></textarea>That is the whole binding: no value, no oninput, no bind:value. Don't add
one either — two owners of a single value is exactly the fight that loses
keystrokes.
Two people typing in the same paragraph merge character by character, each local
edit goes back as the smallest change that explains it, and a remote edit moves
your caret with the text instead of dropping it at the end. body.text is the
current value, reactive, for anything that needs to render it.
Typing your shapes once
Augment one interface and every helper is typed:
// meldkit.config.ts — imported once, anywhere in your app
declare module '@meldkit/svelte' {
interface MeldKitTypes {
Presence: Presence;
Collections: { todos: Todo };
}
}Then myPresence() is your presence and syncedList('todos') is a list of
Todo, with the collection name checked against the map — a typo is a compile
error instead of an empty list. Entirely optional; explicit type arguments keep
working either way.
Ready-made UI
@meldkit/svelte-ui has the presence bar, the connection indicator, remote
carets and live cursors, against the same presence shape.
Errors
meldkit.error is a MeldKitError with a code. Two worth handling:
key-error— the socket is healthy and the document is unreadable. This is a wrong room key, and it is the one failure a status dot alone will not tell you about.config— your token endpoint answered 501, which is what it should do before it has a secret key. A first-run problem, not an auth failure;<SetupNotice />renders the four steps out of it.
