Plugin Creation Guide
AutoPipe plugins extend the Results Viewer with custom file previews. Plugins are HTML/JavaScript-based and run directly in the browser.
1. What is a Plugin?
The AutoPipe Results Viewer includes built-in viewers for images, PDFs, text files, BAM/VCF/BED (via igv.js), and h5ad (via jsfive). Plugins let you add support for additional file formats beyond what's built in.
For example, if you need a custom visualization for .xyz files,
you can create a plugin that handles that format.
2. Plugin Structure
my-viewer-plugin/ ├── manifest.json # Plugin metadata (required) ├── index.js # Main entry point (required) ├── style.css # Stylesheet (optional) └── lib/ # Additional libraries (optional)
manifest.json
{
"name": "my-viewer-plugin",
"version": "1.0.0",
"description": "Custom viewer for .xyz files",
"author": "your-github-username",
"extensions": ["xyz", "abc"],
"entry": "index.js",
"style": "style.css"
}| Field | Required | Description |
|---|---|---|
name | Yes | Unique plugin name |
version | Yes | Semantic version (e.g., 1.0.0) |
description | Plugin description | |
extensions | Yes | Array of supported file extensions |
entry | Yes | Path to main JavaScript file |
style | Path to CSS file (optional) |
3. Plugin JavaScript API
In your entry file (index.js), define the window.AutoPipePlugin object:
window.AutoPipePlugin = {
// Required: render the file
render: function(container, fileUrl, filename) {
// container: DOM element to render into
// fileUrl: URL to fetch file data (e.g., "/file/result.xyz")
// filename: the file name (e.g., "result.xyz")
fetch(fileUrl)
.then(resp => resp.text())
.then(data => {
container.innerHTML = '<pre>' + data + '</pre>';
});
},
// Optional: cleanup when switching to another file
destroy: function() {
// Remove event listeners, timers, etc.
}
};render() is called when the user selects a file with a matching extension.
Render your content into container.
Use fetch(fileUrl) to retrieve the file data.
4. Quick Start with CLI
The easiest way to create a new plugin is with the autopipe-ext CLI tool:
- Install the CLI tool
npm install -g @pnucolab/autopipe-ext
- Scaffold a new plugin
autopipe-ext init
Interactive prompts will ask for the plugin name, description, and supported file extensions. It generates
manifest.json,index.js, andREADME.mdautomatically.
Alternatively, you can create the files manually (see Section 2 and 3 above).
5. Development & Testing
- Copy the plugin to the plugins directory
Default location:
~/.local/share/autopipe/plugins/my-plugin/(configurable in app settings) - Edit
index.jswith your rendering logic - Run
show_resultsin AutoPipeVerify that files with the matching extension are rendered by your plugin in the viewer.
6. GitHub Account
A GitHub account is required to publish plugins to the registry. If you don't have one, sign up at github.com/signup.
7. GitHub Personal Access Token
- Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
- Click Generate new token (classic)
- Configure:
- Note:
autopipe-plugin - Expiration: 90 days recommended
- Scopes: check
public_repoonly
- Note:
- Click Generate token
- Copy the token starting with
ghp_...(shown only once)
8. Create a GitHub Repository
- Create a new public repository on GitHub.
- Push your plugin files:
cd my-viewer-plugin git init git add . git commit -m "Initial plugin" git remote add origin https://github.com/username/my-viewer-plugin.git git push -u origin main
9. Packaging & Publishing
- Validate
autopipe-ext package
Checks manifest.json validity, entry file existence, and AutoPipePlugin pattern.
- Publish
autopipe-ext publish --token ghp_xxx # Or via environment variable: GITHUB_TOKEN=ghp_xxx autopipe-ext publish # Or interactive prompt: autopipe-ext publish
Automatically detects the GitHub URL from git remote and registers the plugin in the registry.
10. Example: CSV Heatmap Plugin
manifest.json
{
"name": "csv-heatmap-viewer",
"version": "1.0.0",
"description": "Display CSV data as a color heatmap",
"extensions": ["csv"],
"entry": "index.js"
}index.js
window.AutoPipePlugin = {
render: function(container, fileUrl, filename) {
fetch(fileUrl)
.then(function(resp) { return resp.text(); })
.then(function(text) {
var lines = text.trim().split('\n');
var headers = lines[0].split(',');
var html = '<table style="border-collapse:collapse;font-size:12px;">';
html += '<tr>' + headers.map(function(h) {
return '<th style="padding:4px 8px;border:1px solid #ddd;">' + h + '</th>';
}).join('') + '</tr>';
for (var i = 1; i < Math.min(lines.length, 100); i++) {
var cells = lines[i].split(',');
html += '<tr>' + cells.map(function(c) {
var n = parseFloat(c);
var bg = isNaN(n) ? '#fff' :
'hsl(' + Math.max(0, Math.min(240, 240 - n * 2.4)) + ',70%,85%)';
return '<td style="padding:4px 8px;border:1px solid #eee;background:' + bg + '">' + c + '</td>';
}).join('') + '</tr>';
}
html += '</table>';
container.innerHTML = html;
});
}
};