@abraca/nuxt

First-class Nuxt module for the Abracadabra CRDT collaboration platform
22,147
Install
npm install @abraca/nuxt
Latest Version:2.102.0
Vue:3
License:MIT
Last Updated:Sep 11, 2026
Links: npm
Maintainer: rgby

@abraca/nuxt

npm version npm downloads License Nuxt

First-class Nuxt 4 module for the Abracadabra CRDT collaboration platform. Drop real-time collaborative documents, multi-user awareness, offline-first sync, and a full rich-text editor into any Nuxt app.

Documentation

Full, code-derived documentation lives in docs/ — a numbered Nuxt-Content site, the single source of truth (prior AUDIT.md/audit-*.md/gaps/ were untrusted and moved to ../DEPRECATED/abracadabra-nuxt/; where this README or CLAUDE.md drifted, the docs win). Seven sections:

Section Covers
Getting Started install, peers, the exhaustive options schema, quick start
Core setup() internals, client/server bootstrap, plugins & registry, state & types, Nitro RPC runners
Composables all ~107 auto-imported composables (incl. the useYDoc.ts Yjs primitives — there is no useYDoc())
Components the 210 components (44 top-level + 166 across eight subdirs), incl. the 52 Aware components
Editor Extensions the ~41 collaborative TipTap nodes/marks/behaviours
Guides doc page, plugin, RPC method, theming, auth, custom renderer, i18n
Reference utils, awareness sharing modes, server API routes, gotchas

Features

  • Real-time collaborative editing via WebSocket + Yjs CRDT
  • Offline-first with IndexedDB persistence and background sync queue
  • Multi-user awareness — cursors, presence, typing indicators, voice/video
  • TipTap rich-text editor with ~41 built-in collaborative extensions
  • 15+ built-in page renderers: doc/prose/code, Kanban, Table, Calendar, Gallery, Outline, Checklist, Timeline, Call, Graph, Dashboard, Map, Slides
  • Full-text search with trigram indexing
  • File uploads with offline blob caching
  • Passkey (WebAuthn) authentication
  • Server-side rendering with Nitro plugin system and doc cache
  • Extensible plugin architecture

Requirements

  • Nuxt >= 4, Vue >= 3.4, @nuxt/ui >= 3
  • @abraca/dabra, @abraca/convert, @abraca/plugin (all ^2.3)
  • @tiptap/* 3 collaboration set, lowlight, @noble/ed25519, @noble/hashes
  • yjs >= 13

See Getting Started → Installation for the full required/optional peer matrix.

Setup

pnpm add @abraca/nuxt @abraca/dabra yjs @tiptap/core @tiptap/vue-3 @tiptap/extension-collaboration @tiptap/extension-collaboration-caret
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@abraca/nuxt'],
  abracadabra: {
    url: 'https://your-abracadabra-server.example.com',
  }
})

Wrap your app with <AProvider> and you're live:

<template>
  <AProvider>
    <NuxtPage />
  </AProvider>
</template>

Configuration

abracadabra: {
  // Connection
  url?: string                    // Server URL (default: 'https://abra.cou.sh')
  entryDocId?: string             // Root doc ID (skips space discovery)

  // Auth
  persistAuth?: boolean           // Persist JWT in localStorage (default: true)
  authStorageKey?: string         // localStorage key (default: 'abracadabra:auth')
  auth?: {
    middleware?: boolean          // Register abracadabra-auth middleware
    globalMiddleware?: boolean    // Apply to all routes
    loginPath?: string            // Redirect target (default: '/login')
  }

  // Features (control what code is included)
  features?: {
    editor?: boolean              // TipTap editor (default: true)
    search?: boolean              // Full-text search (default: true)
    backgroundSync?: boolean      // Offline sync queue (default: true)
    renderers?: boolean           // Built-in page renderers (default: true)
    serverCache?: boolean         // Server doc-tree cache runner (default: true)
  }

  // UI
  prefix?: string                 // Component name prefix (default: '')
  locale?: Partial<AbracadabraLocale>
  docBasePath?: string            // Doc route base (default: '/doc')

  // Server-side service account (for Nitro runners)
  service?: {
    publicKey?: string            // Ed25519 public key (base64url)
    privateKey?: string           // Ed25519 private key (base64url)
  }

  debug?: boolean
}

Auto-imported Composables

Composable Description
useAbracadabra() Full collaboration state (client, provider, identity, docs)
useAbracadabraAuth() Auth — login, passkey, identity management
useAwareness() All connected users' raw awareness states
useAwarenessPeers() Typed peer list with idle detection
useAAField(key) Per-field interaction awareness (hover, press, focus)
useSyncedMap / useSyncedArray / useSyncedText / useSyncedXml / useAwarenessOf / useSmoothedCursors Reactive Yjs primitives (the useYDoc.ts helper module — there is no useYDoc() and no useMultiplayerObject)
useEditor(ydoc, opts) TipTap setup with collaboration + cursor extensions
useChildTree(docId) Document tree scoped to a parent
useDocumentPermissions(role) RBAC flags (canWrite, canDelete, etc.)
useChat(channel) Real-time group & DM chat
useNotifications() Server-pushed notifications
useSearchIndex() Full-text search over synced docs
useBackgroundSync() Offline sync queue status
useDocExport() Export docs as markdown, HTML, or ZIP
useDocImport() Import .md, .txt, .html files
useFileBlobStore() Offline file blob cache (IndexedDB)
useVoice() WebRTC voice/video state
useWindowManager() Floating window (PiP/panel) management
useCommandPalette() ⌘K command palette state & commands
useConnectionStatus() Connection status as UI-ready label + color
useRendererBase(docId) Shared setup for custom page renderers
useTrash() Document trash (move, restore, permanent delete)
usePasskeyAccounts() WebAuthn passkey account management
useFollowUser(userId) Cursor following for pair programming

Auto-imported Components

Core

Component Description
<AProvider> Root wrapper — initializes SDK and syncs root doc
<AEditor> Full TipTap collaborative editor
<ADocumentTree> Hierarchical doc tree with drag-drop
<ANodePanel> Slide-over panel with doc metadata and children
<ACommandPalette> ⌘K search and command palette
<AConnectionStatus> Connection state badge
<APresence> Connected users presence indicator
<ANotifications> Notification center
<AVoiceBar> Voice/video call controls
<ADocTypeSelect> Page type selector
<APermissionGuard> Conditional render based on role
<ARoleBadge> Role badge (Owner, Editor, Viewer, etc.)
<AFloatingWindow> Floating/PiP window container
<AWindowLayer> Portal for floating windows

Aware Interaction Components

Interaction components that broadcast awareness state to other users:

<AArea> <AAvatar> <AButton> <AInput> <ATextarea> <ASelect> <ACursorLabel> <AFacepile> <AUserList> <ADocBadge>

Page Renderers (requires features.renderers)

<AKanbanRenderer> <ATableRenderer> <ACalendarRenderer> <AGalleryRenderer> <AOutlineRenderer>

Server-Side Usage

Configure a service account for server-side doc access:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@abraca/nuxt'],
  runtimeConfig: {
    abracadabra: {
      servicePublicKey: process.env.ABRA_SERVICE_PUBLIC_KEY,
      servicePrivateKey: process.env.ABRA_SERVICE_PRIVATE_KEY,
    }
  }
})

Register custom server runners via the Nitro hook:

// server/plugins/my-runner.ts
export default defineNitroPlugin((nitro) => {
  nitro.hooks.hook('abracadabra:before-runners', (ctx) => {
    registerServerPlugin({
      name: 'my-runner',
      runners: [{
        name: 'my-background-task',
        run: async ({ provider, client }) => {
          // background work
          return () => { /* cleanup */ }
        }
      }]
    })
  })
})

Plugin System

Extend the editor, add toolbar items, slash commands, and page types:

import type { AbracadabraPlugin } from '@abraca/nuxt'

const myPlugin: AbracadabraPlugin = {
  name: 'my-plugin',
  extensions: () => [/* TipTap extensions */],
  toolbarItems: () => [/* toolbar groups */],
  suggestionItems: () => [/* slash commands */],
  pageTypes: [{ type: 'my-type', label: 'My Page', component: MyRenderer }],
  clientSetup: async (state) => { /* init */ }
}

Contribution

# Install dependencies
pnpm install

# Generate type stubs
pnpm dev:prepare

# Develop with the playground (one route per module feature)
pnpm dev

# Build
pnpm prepack

# Lint
pnpm lint

# Unit + integration tests (requires a running abracadabra-rs at $ABRACADABRA_URL for integration)
pnpm test
pnpm test:watch
pnpm test:integration

# Browser E2E (Playwright against a real spawned abracadabra-rs + abracadabra-aperio)
pnpm test:e2e          # headless
pnpm test:e2e:headed   # headed debug
pnpm test:e2e:ui       # Playwright UI mode

E2E setup

pnpm test:e2e drives Chromium against a freshly-spawned abracadabra-rs (release binary) and abracadabra-aperio (Nuxt dev) — no mocks. The sibling repos must be checked out next to this one:

Abracadabra/
├── abracadabra-nuxt/        (this repo)
├── abracadabra-rs/          # build: cargo build --release -p abracadabra-server
└── abracadabra-aperio/      # consumer app under test

The test harness listens on port 3300 for aperio. Keep that free. Set E2E_VERBOSE=1 to stream rs + aperio logs alongside test output — useful when a test is surprising you.

The playground/ directory is a focused, multi-page sandbox — one route per module feature — used to develop and visually verify the module in isolation. For a full reference application that exercises the entire module surface (auth, spaces, chat, file transfer, settings, etc.), see abracadabra-aperio, the open-source dashboard built on top of @abraca/nuxt.

Related Packages

@abraca/junis

Website-builder Nuxt module for the Abracadabra CRDT platform — page-type render...

2,941
@abraca/convert

Bullet-proof Markdown ↔ Yjs/TipTap round-trip — canonical converter shared by co...

23,017
@abraca/plugin

Shared plugin contract + registry for @abraca/nuxt and cou-shell.

20,071

Version History

Version Released Vue License
2.102.0 ^3.4.0 MIT
2.101.0 ^3.4.0 MIT
2.100.0 ^3.4.0 MIT
2.99.0 ^3.4.0 MIT
2.97.0 ^3.4.0 MIT