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/markPlugin 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)
},
})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 toolbareditor-bubble-menuItems in the floating selection menusidebar-topTop of the entry sidebarsidebar-bottomBottom of the entry sidebarentry-headerBelow the entry title areaentry-footerAfter the entry contenthub-navAdditional hub navigation itemsPlugin 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?): voidShow a toast notification
openModal(component, props?): Promise<any>Open a modal dialog with a custom component
registerCommand(id, handler): voidRegister 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)