Plugin Development
A software development kit for developing plugins to Recogito Studio, an open source platform for collaborative annotation of TEI, IIIF and PDF documents.
The Recogito Studio SDK is designed to facilitate plugin development for the Recogito Studio Client without the need to set up your own full-stack installation or forking the platform. It provides essential tools and abstractions to help you build useful extensions for the Recogito Studio ecosystem.
Getting Started
Section titled “Getting Started”The following steps walk you through the development of a Hello World plugin that adds a simple message to the annotation editor.
Prerequisites
Section titled “Prerequisites”Before starting, make sure you have the following installed:
- NodeJS (version 20 recommended)
- npm
Create Your Project
Section titled “Create Your Project”Step 1: Choose from GitHub Template or Manual Setup
Section titled “Step 1: Choose from GitHub Template or Manual Setup”There is a GitHub template that you can use to quickly bootstrap your new project. However if you prefer you can build your project from scratch.
Step 1.1.1: Create New Project From Template
Section titled “Step 1.1.1: Create New Project From Template”- In your browser, go to the template repository
- Above the file list, click Use this template.
- Select Create a new repository.
- Use the Owner dropdown menu to select the account you want to own the repository.
- Type a name for your repository, and an optional description.
-
Choose a repository visibility.
-
Click
Create repository
.
Step 1.1.2: Clone Repository to Your Local Workspace
Section titled “Step 1.1.2: Clone Repository to Your Local Workspace”In a terminal window clone the repository that you just created:
git clone https://github.com/[Your Repository].git
Change your directory to the cloned repository and run:
npm install
Open your package.json
file and name your plugin. It should match the name you created above (i.e. @performant/plugin-hello-world).
{ "name": "@recogito/plugin-template", "name": "@performant/plugin-hello-world" "version": "0.1.0", "description": "A template to boot-strap a new Recogito Studio plugin project.", "description": "My new Recogito Studio Plugin" ...}
You can now proceed to Step 2. You will find that some of the proceeding steps have been taken care of by the template.
Step 1.2.1: Initialize a New Plugin Project
Section titled “Step 1.2.1: Initialize a New Plugin Project”Create a new directory for your plugin and initialize an npm project:
mkdir plugin-hello-worldcd plugin-hello-worldnpm init
Install the following dev dependencies:
npm install --save-dev @types/node @types/react @types/react-dom typescript copyfilesnpm install --save-dev astro react react-dom
Then, install the Recogito Studio SDK as runtime dependencies:
npm install @recogito/studio-sdk
Step 1.2.2: Configure TypeScript
Section titled “Step 1.2.2: Configure TypeScript”Create a tsconfig.json file in your project root:
{ "compilerOptions": { "allowJs": true, "allowSyntheticDefaultImports": true, "baseUrl": ".", "declaration": true, "declarationMap": true, "isolatedModules": true, "jsx": "react-jsx", "lib": ["ESNext", "DOM", "DOM.Iterable"], "module": "ESNext", "moduleResolution": "bundler", "outDir": "dist", "resolveJsonModule": true, "skipLibCheck": true, "strict": true, "target": "ESNext" }, "include": ["src", "test"], "exclude": ["node_modules", "dist"]}
Make sure the following lines are in your package.json
:
{ // ... "type": "module", "files": ["dist"], "scripts": { "build": "tsc && npm run copy-files", "copy-files": "copyfiles -u 1 \"src/extensions/**/*.css\" \"src/extensions/**/*.jpg\" \"src/extensions/**/*.png\" dist" }}
Step 2: Create the Plugin Entry Point
Section titled “Step 2: Create the Plugin Entry Point”The entry point is a TypeScript file (src/index.ts
) that exports an Astro Integration and registers a Plugin. Here’s a sample implementation:
import type { AstroIntegration } from "astro";import { Plugin, registerPlugin } from "@recogito/studio-sdk";
const HelloWorldPlugin: Plugin = { name: "My Hello World Plugin", module_name: '@performant/plugin-hello-world', description: "An example Hello World plugin.", author: "Performant Software", homepage: "https://www.performantsoftware.com/",};
const plugin = (): AstroIntegration => ({ name: "plugin-hello-world", hooks: { "astro:config:setup": ({ config, logger }) => { registerPlugin(HelloWorldPlugin, config, logger); }, },});
export default plugin;
Step 3: Install the Test Application Template
Section titled “Step 3: Install the Test Application Template”Run the following command to set up the test application:
npx copy-template
Add a development script to your package.json
:
{ "scripts": { "dev": "npm start --prefix .dev/" }}
Step 4: Configure the Test Application
Section titled “Step 4: Configure the Test Application”Update .dev/package.json
to include your plugin:
{ "dependencies": { "@performant/plugin-hello-world": "file:../" }}
Modify .dev/astro.config.mjs
:
import { defineConfig } from 'astro/config';import react from '@astrojs/react';import node from '@astrojs/node';import HelloWorldPlugin from '@performant/plugin-hello-world';
export default defineConfig({ integrations: [ react(), HelloWorldPlugin() ], // ... other configurations});
Step 5: Create a UI Extension
Section titled “Step 5: Create a UI Extension”Create a React component in src/extensions/HelloWorldMessage.tsx
:
export const HelloWorldMessage = () => { return <div>Hello World</div>;};
Update the index.ts
file to register the component as a UI extension:
import type { AstroIntegration } from 'astro';import { Plugin, registerPlugin } from '@recogito/studio-sdk';
const HelloWorldPlugin: Plugin = { name: 'My Hello World Plugin', module_name: '@performant/plugin-hello-world', description: 'An example Hello World plugin.', author: 'Performant Software', homepage: 'https://www.performantsoftware.com/',
extensions: [{ name: 'hello-world-message', component_name: 'HelloWorldMessage', extension_point: 'annotation:*:annotation-editor' }]};
const plugin = (): AstroIntegration => ({ name: 'plugin-hello-world', hooks: { 'astro:config:setup': ({ config, logger }) => { registerPlugin(HelloWorldPlugin, config, logger); } }});
export default plugin;
In the package.json
, add an export for the UI extension:
{ "exports": { ".": "./dist/index.js", "./HelloWorldMessage": "./dist/extensions/HelloWorldMessage.js" }}
Test Your Extension
Section titled “Test Your Extension”- Build the plugin package:
npm run build
- Add plugin to test application dependencies in
.dev/package.json
:
{ "dependencies": { "@performant/plugin-hello-world": "file:../" }}
- Configure Astro integration in
.dev/astro.config.mjs
:
import HelloWorldPlugin from "@performant/plugin-hello-world";
export default defineConfig({ integrations: [ react(), HelloWorldPlugin(), ], // other configurations...});
- Run the development process:
npm installnpm run dev
- Open browser to
http://localhost:4321/
Installing Plugins
Section titled “Installing Plugins”Plugins can be installed via:
- npm registry publication
- Direct GitHub repository installation
Installation steps:
- Install package in Recogito Studio Client folder
- Add plugin to
astro.config.mjs
Component Styling
Section titled “Component Styling”The Recogito Studio Client utilizes Radix UI primitives for building accessible and consistent interface components. We recommend that plugin developers also adopt Radix when developing extension components.
To make it easier to build visually consistent extensions that match Recogito Studio’s native look and feel, the SDK provides a set of pre-defined CSS classes for common UI primitives. The following primitives and classes are currently available:
- Accordion. Base styles for the Radix Accordion primitive.
- Avatar. The Recogito-themed user avatar.
- Button. A range of button variant styles (primary, minimal, unstyled, danger, etc.)
- Checkbox. Base styles for the Radix checkbox primitive.
- Dialog. Default Radix popup dialog styles.
- Dropdown. Base styles for Recogito-themed dropdown menus.
- Form. Minimal styles for form input elements.
- Popover. Base styles for the Radix popover primitive.
- Radio. Base styles for the Radix Radio primitive.
- Select. Base styles for the Radix Select primitive.
- Switch. Base styles for the Radix Switch primitive.
- Tooltip. Styles for Recogito-themed mouse hover tooltips.
To apply SDK-provided theming, all that’s needed is to add the appropriate CSS classes to your components. For example:
// Use Radix Accordion in your extension componentimport * as Accordion from '@radix-ui/react-accordion';
// ...
<Accordion.Root // Apply Recogito-provided `accordion-root` class className="accordion-root" type="multiple"> <Accordion.AccordionItem value="item-1" // Recogito-provided `accordion-item` class className="accordion-item"> <Accordion.Header // Recogito-provided `accordion-header` class className="accordion-header"> <Accordion.Trigger // Recogito-provided `accordion-trigger` class className="accordion-trigger"> Accordion Item 1 Trigger </Accordion.Trigger> </Accordion.Header>
<Accordion.AccordionContent // Recogito-provided `accordion-content` class className="accordion-content"> Accordion Item 1 Content </Accordion.AccordionContent> </Accordion.AccordionItem></Accordion.Root>
Styled example:
For details, classes and other components, check the stylesheet files directly.
Available Plugins
Section titled “Available Plugins”Here are the existing plugins available for Recogito Studio:
-
Geotagging - Recogito Geotagging Plugin.
-
Named Entity Recognition - Recogito Studio plugin which can perform Named Entity Recognition on TEI and Plain Text.
-
Revisions - Allows users to make a read-only annotation editable, by cloning it into the active layer.
-
TEI Inliner - A plugin for exporting TEI annotations as inline markup.
-
Reconciliation Service - Use a Reconciliation Service API endpoint as a tag source in Recogito Studio projects.
-
Sandcastle Export - A custom annotation export for Duke University’s Unreal 3D importer.