npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cosveti-sync

v0.0.8

Published

A convex component for syncing tiptap in a svelte project

Readme

cosveti-sync

Real-time collaborative editing for TipTap in Svelte with Convex synchronization.

Translated to svelte from React version

Features

  • Real-time synchronization for TipTap editors across multiple clients
  • Convex-powered backend for reliable data synchronization
  • Optimistic updates for smooth user experience
  • Client-side caching with localStorage fallback
  • Configurable sync options and error handling
  • Easy integration with SvelteKit projects
  • Support for pausing/resuming synchronization
  • Prosemirror collab protocol implementation

Installation

Install the package using your preferred package manager:

# npm
npm install cosveti-sync

# yarn
yarn add cosveti-sync

# pnpm
pnpm add cosveti-sync

# bun
bun install cosveti-sync

This package has the following peer dependencies that you'll also need to install:

  • @tiptap/pm (v3.18.0+)
  • @tiptap/core (v3.18.0+)
  • convex (v1.10.0+)
  • svelte (v5.0.0+)

Basic Setup

1. Convex Config

First, set up the backend API in your Convex project. Create a file like convex/convex.config.ts:

import { defineApp } from 'convex/server';

import tiptapSync from 'cosveti-sync/convex.config.js';

const app = defineApp();

app.use(tiptapSync);

export default app;

2. Convex Backend Configuration

First, set up the backend API in your Convex project. Create a file like convex/tiptapSync.ts:

import { TiptapSyncClient } from 'cosveti-sync';
import { components } from './_generated/api.js';

const tiptapSync = new TiptapSyncClient(components.tiptapSync);

export const { getSnapshot, submitSnapshot, latestVersion, getSteps, submitSteps } =
	tiptapSync.syncApi();

API Documentation

useTiptapSync()

The main hook for enabling real-time synchronization.

Parameters

  • convex: Convex client instance
  • syncApi: The sync API object from your Convex backend
  • id: Unique identifier for the document
  • opts (optional): Options object with the following properties:
    • onSyncError: Callback function for handling synchronization errors
    • snapshotDebounceMs: Debounce time for snapshot submissions (default: 1000ms)
    • debug: Enable debug logging (default: false)

Returns

  • isSyncEnabled: Svelte store for controlling sync enable/disable state
  • isLoading: Svelte store indicating if the initial content is loading
  • initialContent: Svelte store with the initial document content
  • extension: TipTap extension to add to your editor
  • create: Function to create a new document with initial content

Configuration Options

Sync Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | onSyncError | (error: Error) => void | undefined | Callback for handling synchronization errors | | snapshotDebounceMs | number | 1000 | Debounce time in milliseconds for submitting snapshots | | debug | boolean | false | Enable debug logging to console |

Backend API Options

When creating the sync API in Convex, you can configure:

  • checkRead: Function to check read permissions
  • checkWrite: Function to check write permissions
  • onSnapshot: Callback when new snapshots are available
  • pruneSnapshots: Whether to prune old snapshots (default: true)

Example Usage in Svelte

Here's a complete example showing how to integrate the library:

<script lang="ts">
	import { useTiptapSync } from 'cosveti-sync/tiptap';
	import { api } from '$convex/_generated/api.js';
	import type { ConvexClient } from 'convex/browser';
	import { useConvexClient } from 'convex-svelte';
	import Editor from './Editor.svelte';

	// This is if you have used convex-svelte pakage in +layout.svelte to setup the client
	const convex: ConvexClient = useConvexClient();

	const { isSyncEnabled, extension, isLoading, initialContent, create } = $derived(
		useTiptapSync(convex, api.tiptapSyncSvelte, 'test-doc-id')
	);

	let editor = $state<Editor>();
</script>

{#if $isLoading}
	Loading...
{:else if !$initialContent}
	<button
		onclick={() => {
			create({ type: 'doc', content: [] });
		}}
		>Create doc
	</button>
{:else if $extension != undefined}
	<div class="py-4 text-center text-xl font-bold">
		Shadcn Example
		<button
			onclick={() => {
				isSyncEnabled.update((n) => !n);
				console.log($isSyncEnabled);
			}}
		>
			{#if $isSyncEnabled}Pause Sync{:else}Resume Sync{/if}
		</button>
		<div class="z-50 mt-12 size-full w-screen rounded-md border border-dashed bg-background">
			<Editor
				class="h-120 max-h-screen overflow-y-scroll pr-2 pl-6"
				additionalExtensions={$extension}
				content={$initialContent}
				bind:editor
			/>
		</div>
	</div>
{/if}

License

Apache-2.0