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

@skaile/forge-editor

v6.4.2

Published

Vue and React editor library on TipTap v3 (Vue: Nuxt UI; React: shadcn/ui): framework-free features with Vue and React bindings, simple and advanced presets, tree-shakeable entries. Built ESM with type declarations.

Readme

@skaile/forge-editor

A Vue and React editor library on TipTap v3. Editors are assembled from features: the simple editor is the core features alone (formatting, headings, lists, quotes, code, undo/redo) and needs no backend, no Yjs and no feature code; the advanced editor composes every feature (media, mentions, transcripts, composites, authors, comments, AI, collaboration, block UI, site-wide Obsidian themes and their integrations) on both surfaces. The framework-free ./core holds the feature model, and every feature's logic is framework-free too (./<feature>): a feature is built from a typed UI binding (<x>FeatureCore(ui)) that the Vue layer (./<feature>/vue, Nuxt UI chrome) and the React layer (./<feature>/react, shadcn/ui on Radix and Tailwind) fill with their components, node views and notice seam. Toolbar, settings panel and modal, outline, AI sidebar, comments margin, composite table and inspector, and the file browser are components you place anywhere beside an editor; both layers ship the simple editor (./vue/simple, ./react/simple) and the advanced editor (./vue/advanced, ./react/advanced).

Prerequisites

  • Node ≥ 22 and Bun (the repository is a Bun workspace: packages/*, examples/*).
  • A Vite- or Nuxt-based app (@vitejs/plugin-vue / @vitejs/plugin-react, or Nuxt). The published package is a built ESM package: every exports subpath resolves to dist/**/*.js with .d.ts (Vue SFCs are compiled, React .tsx is compiled to JSX-runtime JS), the CSS sheets are copied, and the source maps embed the sources (src itself is not published). Output is one module per source file, so entries stay tree-shakeable.
  • Required peer dependencies (install them in the consuming app so the host and the library share one instance of each): @tiptap/core, @tiptap/pm, yjs, @hocuspocus/provider. Yjs and the provider are required peers because shared prop types in the .d.ts reference them; a simple-editor bundle does not contain their implementation (proven below). Per layer (all optional peers): Vue vue, @nuxt/ui, @tiptap/vue-3; React react, react-dom, @tiptap/react, @iconify/react; code surface (/code) @codemirror/state, @codemirror/view, @codemirror/language, @codemirror/commands, @codemirror/search, @lezer/highlight, plus the @codemirror/lang-* packs you register (the package ships none).
  • Tailwind CSS 4 (tailwindcss) for the Nuxt UI theme (Vue) or the shadcn classes (React), and the icon collection @iconify-json/lucide. React hosts also need tw-animate-css (enter/exit animations of the dialog, dropdown and tooltip).

Install

From npmjs (public, no token and no .npmrc needed):

npm install @skaile/forge-editor      # or: bun add @skaile/forge-editor / pnpm add @skaile/forge-editor

Inside this repository the package is a workspace member, so consumers there declare "@skaile/forge-editor": "workspace:*".

Nuxt quick start

Install the peers next to the package (vue, @nuxt/ui, @tiptap/core, @tiptap/pm, @tiptap/vue-3, yjs, @hocuspocus/provider, tailwindcss, @iconify-json/lucide), then register the module after @nuxt/ui:

// nuxt.config.ts
export default defineNuxtConfig({
  ssr: false, // TipTap renders on the client only
  modules: ['@nuxt/ui', '@skaile/forge-editor/nuxt'],
  css: ['~/assets/main.css'],
})
/* app/assets/main.css */
@import "tailwindcss";
@import "@nuxt/ui";

Wrap the app in <UApp> (app/app.vue: <UApp><NuxtPage /></UApp>) and mount an editor on a page (the simple editor needs no backend):

<script setup lang="ts">
import { SimpleEditor } from '@skaile/forge-editor/vue/simple'
import { ref } from 'vue'
const content = ref()
</script>

<template>
  <SimpleEditor v-model="content" />
</template>

The module's API routes call the host's EditorPorts (identity first, then one port per capability: documents, collabState, directory, assets, settings, themes, models, comments). Provide them in a Nitro plugin with provideEditorServer({ ports }); without them the client logs „Einstellungen konnten nicht geladen werden“ and every route answers 500. A route whose port you leave out answers 501. These minimal ports keep everything in memory and let any visitor in (replace authenticate and the storage with yours):

// server/plugins/editor-adapter.ts
import type { JSONContent } from '@tiptap/core'
import { type AssetStore } from '@skaile/forge-editor/server'
import { provideEditorServer } from '@skaile/forge-editor/server/nitro'

export default defineNitroPlugin(() => {
  const contents = new Map<string, JSONContent>()
  const states = new Map<string, Uint8Array>()
  const assets = new Map<string, Parameters<AssetStore['storeAsset']>[1]>()
  provideEditorServer({
    ports: {
      // `null` = 401 on API routes; on /collab the socket is closed with 4401 (HTTP 401 at the upgrade with `collab.authenticateUpgrade`)
      identity: { authenticate: async () => ({ id: 'demo', username: 'demo' }) },
      documents: {
        loadContent: async id => contents.get(id) ?? null,
        storeContent: async (id, content) => { contents.set(id, content) },
        listContents: async () => [...contents].map(([id, content]) => ({ id, content })),
      },
      collabState: {
        loadState: async id => states.get(id) ?? null,
        storeState: async (id, state) => { states.set(id, state) },
        removeState: async (id) => { states.delete(id) },
      },
      directory: { listUsers: async () => [] },
      assets: {
        storeAsset: async (id, asset) => { assets.set(`${id}/${asset.name}`, asset) },
        loadAsset: async (id, name) => {
          const asset = assets.get(`${id}/${name}`)
          if (!asset) return null
          const { data, ...record } = asset
          return { record, data }
        },
      },
    },
  })
})

The advanced editor, every adapter method, collaboration and AI are covered in the Nuxt quick start and the EditorPorts guide.

Building and developing in this repository

bun run build:editor (tsdown, config packages/editor/tsdown.config.ts) writes packages/editor/dist: ESM plus .d.ts for every exports subpath (the entries are read from the skaile-source condition of package.json#exports, so a new export is built as soon as it is declared), unbundled one module per source file, source maps with embedded sources, CSS copied, and the Nuxt runtime directory (dist/nuxt/runtime: plugin, server routes, utils) as separate files next to the module that Nuxt and Nitro compile in the host. Dependencies and peers are never bundled.

Each exports entry carries a custom skaile-source condition first (pointing at src) followed by types/import (or default) pointing into dist. This repository's Nuxt app (nuxt.config.ts) and the examples (examples/*/vite.config.ts, tsconfig.json#customConditions) enable that condition for Vite, Nitro and the type checker, so editing the library needs no build step in dev. Consumers outside the repository never set the condition and get dist. bun run check:editor-entries builds first and judges the built output through exports (no skaile-source), so it proves what is published; bun run check:editor-composition builds first and loads the built entries; bun run typecheck:editor resolves through src (customConditions: ["skaile-source"] in packages/editor/tsconfig.json).

Documentation

The documentation lives at https://skaile-ai.github.io/forge-editor/ (the package itself no longer ships guides):

  • Getting started: what the package is, installation, quick starts for Nuxt, plain Vue and React, glossary.
  • Tutorial: build one editor step by step, including an own block, the backend, AI and the React surface.
  • Guides: feature composition, Nuxt module, EditorPorts, collaboration, AI, themes, composites, file browser, production, storage adapters, migration.
  • Reference: every public export, presets and features, the feature contract, CSS and UI-provider requirements, dependency rules, commands, changelog.
  • AI agents: how coding agents read these docs, integrate and extend the editor, invariants and verification.

Machine-readable entry points: llms.txt, llms-full.txt, and an installable Agent Skill:

npx skills add https://skaile-ai.github.io/forge-editor

Runnable examples live in the repository: examples/ and the Nuxt app (bun run dev, port 3056). To work on the documentation site from a checkout of the repository, run bun run docs:dev (development server) or bun run docs:build (static build); see docs/README.md.