{"_id":"@akrv7591/valtio-y","name":"@akrv7591/valtio-y","dist-tags":{"latest":"1.2.0-beta-1"},"versions":{"1.2.0-beta-1":{"name":"@akrv7591/valtio-y","description":"Collaborative Valtio state","version":"1.2.0-beta-1","type":"module","module":"./dist/index.js","types":"./dist/index.d.ts","author":{"name":"Alex Gogl"},"repository":{"type":"git","url":"git+https://github.com/valtiojs/valtio-y.git"},"exports":{"./package.json":"./package.json",".":{"types":"./dist/index.d.ts","workerd":{"module":"./dist/index.js","import":"./dist/index.js"},"node":{"module":"./dist/index.js","import":"./dist/index.js"},"browser":{"module":"./dist/index.js","import":"./dist/index.js"},"default":"./dist/index.js"}},"sideEffects":false,"scripts":{"build":"tsdown","dev":"tsdown --watch ./src","test":"bun vitest","bench":"bun vitest bench --config vitest.bench.config.ts","typecheck":"bun tsc -b --emitDeclarationOnly","publish":"npm publish --access public --provenance"},"keywords":["valtio","yjs","crdt"],"license":"MIT","devDependencies":{"@types/react":"^19.2.2","@types/react-dom":"^19.2.2","@vitejs/plugin-react":"catalog:","@vitest/browser":"^4.0.6","@vitest/browser-playwright":"^4.0.6","fast-check":"^4.3.0","playwright":"^1.56.1","react":"catalog:","react-dom":"catalog:","tsdown":"^0.16.1","typescript":"^5.9.3","valtio":"catalog:","vite":"catalog:","vite-tsconfig-paths":"^5.1.4","vitest":"^4.0.6","vitest-browser-react":"^2.0.2","yjs":"catalog:"},"peerDependencies":{"valtio":">=2.1.8","yjs":">=13.6.27"},"_id":"@akrv7591/valtio-y@1.2.0-beta-1","gitHead":"c68196f015ce509d7a19ec7c06203728df4fc8e2","bugs":{"url":"https://github.com/valtiojs/valtio-y/issues"},"homepage":"https://github.com/valtiojs/valtio-y#readme","_nodeVersion":"20.19.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-5R3zioGsiN4HMJdsZlonNF8M4VTjNtwSvZaGXJAEazqNWZX+MU40wNeJr0RkqWeyf3WABmYB7O7tvVAEpZSRJw==","shasum":"e4f7b578dbf33ee321b5d5f45c863c2992daf644","tarball":"https://registry.npmjs.org/@akrv7591/valtio-y/-/valtio-y-1.2.0-beta-1.tgz","fileCount":6,"unpackedSize":294262,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCS1JswCifmeB3G+XYPaFWNFsJBffudnQHCGxklz5xrbQIhAPfk3dYV/eC60/bW7VWMsfEekXubXT/CGRgAreIuMmRU"}]},"_npmUser":{"name":"akrv7591","email":"akrv7591@gmail.com"},"directories":{},"maintainers":[{"name":"akrv7591","email":"akrv7591@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/valtio-y_1.2.0-beta-1_1770253211605_0.0540005446702152"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-05T01:00:11.510Z","1.2.0-beta-1":"2026-02-05T01:00:11.771Z","modified":"2026-02-05T01:00:11.980Z"},"maintainers":[{"name":"akrv7591","email":"akrv7591@gmail.com"}],"description":"Collaborative Valtio state","homepage":"https://github.com/valtiojs/valtio-y#readme","keywords":["valtio","yjs","crdt"],"repository":{"type":"git","url":"git+https://github.com/valtiojs/valtio-y.git"},"author":{"name":"Alex Gogl"},"bugs":{"url":"https://github.com/valtiojs/valtio-y/issues"},"license":"MIT","readme":"# valtio-y\n\n[![npm version](https://img.shields.io/npm/v/valtio-y)](https://www.npmjs.com/package/valtio-y)\n[![bundle size](https://img.shields.io/bundlephobia/minzip/valtio-y)](https://bundlephobia.com/result?p=valtio-y)\n\nTwo-way sync between [Valtio](https://github.com/pmndrs/valtio) proxies and [Yjs](https://github.com/yjs/yjs) CRDTs. Build collaborative apps with automatic conflict resolution and offline support—just mutate objects naturally.\n\n### Effortless Collaborative State\n\n**Write normal JavaScript. Sync in real-time automatically.**\n\n```typescript\nstate.todos.push({ text: \"Buy milk\", done: false });\nstate.users[0].name = \"Alice\";\nstate.dashboard.widgets[2].position = { x: 100, y: 200 };\n\n// Move item from index 0 to 2 (handled efficiently)\nconst [todo] = state.todos.splice(0, 1);\nstate.todos.splice(2, 0, todo);\n```\n\n<br />\n<p align=\"center\">\n  <a href=\"https://valtio-y-stickynotes.agcty.workers.dev/\">\n    <img src=\"https://i.imgur.com/a36KJ2a.gif\" alt=\"Sticky Notes Demo (valtio-y)\" width=\"100%\" />\n  </a>\n</p>\n<br />\n\n## Live Examples\n\n**Open any demo in multiple browser tabs and watch them sync in real-time:**\n\n🎮 **[Minecraft Clone](https://valtio-y-minecraft.agcty.workers.dev)** - Simple showcase inspired by Minecraft. Lets multiple users place and remove blocks in real time using Three.js and valtio-y.\n\n🎨 **[Whiteboard](https://valtio-y-whiteboard.agcty.workers.dev)** - Collaborative drawing with shapes, colors, and real-time cursors. Google Docs for drawing.\n\n📝 **[Sticky Notes](https://valtio-y-stickynotes.agcty.workers.dev/)** - Production-ready app running on Cloudflare Workers (this is real infrastructure, not a demo server).\n\n✅ **[Todos App](https://valtio-y-todos.agcty.workers.dev)** - Classic collaborative todo list. Real-time updates, no refresh needed.\n\n🧪 **[Simple Demo](https://valtio-y-simple.agcty.workers.dev/)** – Best for understanding the basic sync patterns (objects, arrays, primitives); other demos above are more production-focused.\n\n## Quick Start\n\nCreate a synchronized proxy and mutate it like any normal object. Changes automatically sync across clients.\n\n```js\nimport * as Y from \"yjs\";\nimport { createYjsProxy } from \"valtio-y\";\n\n// Create a Yjs document\nconst ydoc = new Y.Doc();\n\n// Create a synchronized proxy\nconst { proxy: state } = createYjsProxy(ydoc, {\n  getRoot: (doc) => doc.getMap(\"root\"),\n});\n\n// Mutate state like a normal object\nstate.text = \"hello\";\nstate.count = 0;\n\n// Nested objects work too\nstate.user = { name: \"Alice\", age: 30 };\nstate.user.age = 31;\n\n// Arrays work naturally\nstate.todos = [{ text: \"Learn valtio-y\", done: false }];\nstate.todos.push({ text: \"Build something cool\", done: false });\nstate.todos[0].done = true;\n```\n\nThat's it! State is now synchronized via Yjs. Add a provider to sync across clients.\n\n## Installation\n\n```bash\n# npm\nnpm install valtio-y valtio yjs\n\n# pnpm\npnpm add valtio-y valtio yjs\n\n# bun\nbun add valtio-y valtio yjs\n```\n\n## React Integration\n\nUse Valtio's `useSnapshot` hook to automatically re-render components when data changes:\n\n```jsx\nimport { useSnapshot } from \"valtio/react\";\n\nfunction TodoList() {\n  const snap = useSnapshot(state);\n\n  return (\n    <ul>\n      {snap.todos.map((todo, i) => (\n        <li key={i}>\n          <input\n            type=\"checkbox\"\n            checked={todo.done}\n            onChange={() => (state.todos[i].done = !state.todos[i].done)}\n          />\n          {todo.text}\n        </li>\n      ))}\n    </ul>\n  );\n}\n```\n\n**Key principle:** Read from the snapshot (`snap`), mutate the proxy (`state`).\n\nvaltio-y works with any framework that Valtio supports: React, Vue, Svelte, Solid, and vanilla JavaScript.\n\n**For optimizing large lists** with thousands of items, see the [Performance Guide](../guides/performance-guide.md#optimizing-lists).\n\n**Note for text inputs:** When using controlled text inputs (like `<input>` or `<textarea>`), add `{ sync: true }` to prevent cursor jumping:\n\n```jsx\nconst snap = useSnapshot(state, { sync: true });\n<input value={snap.text} onChange={(e) => (state.text = e.target.value)} />;\n```\n\nThis forces synchronous updates instead of Valtio's default async batching. See [Valtio issue #270](https://github.com/pmndrs/valtio/issues/270) for details.\n\n## Collaboration Setup\n\nConnect any Yjs provider to sync across clients:\n\n```js\nimport { WebsocketProvider } from \"y-websocket\";\n\nconst provider = new WebsocketProvider(\n  \"ws://localhost:1234\",\n  \"room-name\",\n  ydoc\n);\n// That's it—state syncs automatically\n```\n\nWorks with any provider: [y-websocket](https://github.com/yjs/y-websocket), [y-partyserver](https://github.com/partykit/partykit/tree/main/packages/y-partyserver) (great for Cloudflare), [y-webrtc](https://github.com/yjs/y-webrtc), [y-indexeddb](https://github.com/yjs/y-indexeddb), etc.\n\n## Common Operations\n\n### Initializing State\n\nWhen using network providers, initialize after first sync:\n\n```js\nconst { proxy: state, bootstrap } = createYjsProxy(ydoc, {\n  getRoot: (doc) => doc.getMap(\"state\"),\n});\n\nprovider.once(\"synced\", () => {\n  bootstrap({\n    todos: [],\n    settings: { theme: \"light\" },\n  });\n  // Only writes if the document is empty\n});\n```\n\n### Arrays\n\n```js\nstate.items.push(newItem);\nstate.items[0] = updatedItem;\nstate.items.splice(1, 2, replacement1, replacement2);\nconst [item] = state.items.splice(2, 1);\nstate.items.splice(0, 0, item); // Move item\n```\n\n### Objects\n\n```js\nstate.user.name = \"Alice\";\ndelete state.user.temporaryFlag;\nstate.data.deeply.nested.value = 42;\n```\n\n### Undo/Redo\n\n```js\nconst {\n  proxy: state,\n  undo,\n  redo,\n} = createYjsProxy(ydoc, {\n  getRoot: (doc) => doc.getMap(\"state\"),\n  undoManager: true, // Enable with defaults\n});\n\nstate.count = 1;\nundo(); // state.count -> undefined\nredo(); // state.count -> 1\n```\n\nSee [API documentation](src/undo/setup-undo-manager.ts) for configuration options.\n\n## Features\n\n- **Zero API overhead** - Just mutate objects like normal JavaScript\n- **Fine-grained updates** - Components re-render only when their data changes\n- **Offline-first** - Changes merge automatically when reconnected\n- **TypeScript** - Full type safety and inference\n- **Production-ready** - Comprehensive tests and benchmarks\n- **Framework-agnostic** - Works with React, Vue, Svelte, Solid, and vanilla JS\n\n## Why valtio-y?\n\nStop writing sync logic. Just mutate objects.\n\n- **Valtio** gives you reactive state with zero boilerplate\n- **Yjs** gives you conflict-free sync and offline support\n- **valtio-y** connects them - you get both, write neither\n\nNo reducers, no actions, no manual sync code. Just: `state.count++`\n\n## Limitations\n\n- Don't use `undefined` (use `null` or delete the property)\n- Don't store functions or class instances (not serializable)\n- Use `array.splice()` instead of `array.length = N`\n\nFor text editors, use native Yjs integrations: [Lexical](https://lexical.dev/), [TipTap](https://tiptap.dev/), or [ProseMirror](https://prosemirror.net/).\n\n## API Reference\n\n### `createYjsProxy(doc, options)`\n\n```typescript\nconst { proxy, bootstrap } = createYjsProxy(ydoc, {\n  getRoot: (doc: Y.Doc) => Y.Map<any>,\n});\n```\n\nReturns:\n\n- `proxy` - Valtio proxy for state mutations\n- `bootstrap(data)` - Initialize state (no-op if doc not empty)\n\n## Resources\n\n- [GitHub Repository](https://github.com/valtiojs/valtio-y)\n- [Documentation](https://github.com/valtiojs/valtio-y/tree/main/docs)\n- [Issues](https://github.com/valtiojs/valtio-y/issues)\n- [Discord](https://discord.gg/MrQdmzd)\n","readmeFilename":"README.md","_rev":"1-f89f31b24b3ccfc5a68951e602e2bbfb"}