Plugins

Frontend Plugins

Extend Rasepi's Vue 3 frontend with custom editor extensions, sidebar widgets, embed components, and navigation items.

Overview

Frontend plugins are Vue 3 modules loaded by the PluginManager. They can add TipTap editor extensions, inject UI components into designated slots, add navigation items, and interact with the Pinia store.

Plugin Types

Editor Extensions

Add custom TipTap nodes, marks, or extensions. Insert new block types into the editor toolbar and handle rendering.

type: 'editor'

Embed Components

Rich embeds that render inside documentation content — diagrams, charts, interactive widgets, code playgrounds.

type: 'embed'

Sidebar Widgets

Panels in the sidebar — table of contents, translation progress, metadata editors, AI assistants.

type: 'widget'

Navigation Items

Add entries to the main navigation or hub sidebar. Custom pages within the Rasepi shell.

type: 'nav'

Plugin Structure

my-frontend-plugin/
├── manifest.json        # Plugin metadata
├── index.ts             # Entry point
├── components/
│   ├── MyEditor.vue     # Editor extension UI
│   └── MyWidget.vue     # Sidebar widget
└── extensions/
    └── myNode.ts        # TipTap node/mark

Plugin Manifest

{
  "id": "my-frontend-plugin",
  "name": "My Plugin",
  "version": "1.0.0",
  "type": "editor",
  "author": "Your Name",
  "description": "Adds a custom block type",
  "entry": "index.ts",
  "slots": ["editor-toolbar", "sidebar-bottom"]
}

Editor Extensions

Create custom TipTap nodes that integrate with Rasepi's block-level translation system.

import { Node, mergeAttributes } from '@tiptap/core'
import { VueNodeViewRenderer } from '@tiptap/vue-3'
import MyComponent from './MyComponent.vue'

export const MyNode = Node.create({
  name: 'myNode',
  group: 'block',
  content: 'inline*',

  addAttributes() {
    return {
      blockId: { default: null },  // Required for translation
      deleted: { default: false },
    }
  },

  parseHTML() {
    return [{ tag: 'my-node' }]
  },

  renderHTML({ HTMLAttributes }) {
    return ['my-node', mergeAttributes(HTMLAttributes), 0]
  },

  addNodeView() {
    return VueNodeViewRenderer(MyComponent)
  },
})
Important: Always include blockId and deleted attributes to maintain compatibility with the block-level translation system.

Widget Components

Widgets receive the current entry and hub context via props and can read/write data via provided APIs.

<script setup lang="ts">
import { inject } from 'vue'

const props = defineProps<{
  entryId: string
  hubId: string
}>()

const pluginApi = inject('pluginApi')

// Access entry data
const entry = await pluginApi.getEntry(props.entryId)
</script>

<template>
  <div class="my-widget">
    <h3>My Widget</h3>
    <p>Entry: </p>
  </div>
</template>

Available Slots

editor-toolbarButtons and controls in the TipTap toolbar
editor-bubble-menuItems in the floating selection menu
sidebar-topTop of the entry sidebar
sidebar-bottomBottom of the entry sidebar
entry-headerBelow the entry title area
entry-footerAfter the entry content
hub-navAdditional hub navigation items

Plugin API

Frontend plugins receive an injected API object with methods for interacting with Rasepi.

getEntry(id: string): Promise<Entry>

Fetch entry with full content blocks

getHub(id: string): Promise<Hub>

Fetch hub with settings

showNotification(msg: string, type?): void

Show a toast notification

openModal(component, props?): Promise<any>

Open a modal dialog with a custom component

registerCommand(id, handler): void

Register a keyboard shortcut or palette command

Installation

Frontend plugins are loaded from the frontend/src/plugins/ directory or from npm packages.

# Local plugin
cp -r my-plugin/ frontend/src/plugins/my-plugin/

# Or via npm
npm install rasepi-plugin-my-plugin

Register in main.ts:

import { PluginManager } from '@/plugins/manager'
import MyPlugin from '@/plugins/my-plugin'

PluginManager.register(MyPlugin)