The manifest
The manifest is the flare field of a plugin's package.json. It declares everything the plugin adds and everything it may do. Flare reads it to list contributions and permissions before running any plugin code. Your code then implements each contribution under the same id, with definePlugin.
{
"name": "flare-plugin-stripe",
"version": "1.0.0",
"flare": {
"id": "flare.stripe",
"title": "Stripe",
"description": "Customers and payments beside your rows.",
"author": "Flare",
"permissions": { "data": "read", "network": ["api.stripe.com"] },
"preferences": [
{ "name": "key", "title": "Secret key", "type": "password", "required": true }
],
"contributes": {
"widgets": [
{ "id": "mrr", "title": "Monthly revenue", "size": { "w": 6, "h": 3 } }
],
"cells": [
{
"id": "customer",
"title": "Stripe customer",
"match": { "fields": ["stripe_*"] }
}
],
"columns": [{ "id": "plan", "title": "Stripe plan" }],
"rowActions": [
{ "id": "open", "title": "Open in Stripe", "icon": "external-link" }
],
"commands": [
{
"id": "lookup",
"title": "Look up a customer",
"arguments": [
{ "name": "email", "title": "Email", "type": "text", "required": true }
],
"view": true
}
],
"transforms": [{ "id": "chart", "title": "Chart", "view": true }]
}
}
}The schema is manifestSchema in @flare/plugin/manifest. This page is checked against it when the docs build. flare-plugin validate runs Flare's own checks on a manifest and reports each problem by its path, such as flare.contributes.widgets.0.id.
The package
Flare reads three fields of package.json:
| Field | What it is |
|---|---|
name | The npm package name. Required. |
version | The version, such as 1.0.0. Required. An update needs a higher version. |
flare | The manifest, described below. A package without it isn't a plugin. |
Top level
| Field | Type | Default | What it is |
|---|---|---|---|
id | string | required | The plugin's id: lower case words separated by dots or hyphens, 3 to 64 characters, such as flare.stripe-lookup. It's also the plugin's origin, flare-plugin://flare.stripe-lookup, which keeps its frames and storage separate. Don't change it. |
title | string | required | The name people see. 1 to 60 characters. |
description | string | required | One sentence on what it does. Up to 280 characters. |
icon | string | An image file in the package, such as icon.svg, shown next to the plugin's name. Included when you pack. | |
author | string | required | A person or company name. Up to 80 characters. |
api | string | "^0.1.0" | The plugin API version range it was built for, as semver. Flare refuses a plugin whose range it doesn't satisfy. |
permissions | object | none | What it may do. See permissions. |
preferences | FormField[] | [] | Plugin wide settings the user fills in once, such as an API key. Up to 20. Read them from ctx.preferences. |
contributes | object | {} | Everything it adds. See contributes. |
permissions
Anything not asked for here is refused. Flare shows each permission to the user as a scope before any plugin code runs: data:read, data:write, network:<host> or clipboard:write. Scopes and permissions explains the whole model.
| Field | Type | Default | What it allows |
|---|---|---|---|
data | "none", "read" or "write" | "none" | read reads the open database. write also changes records, through Flare's guarded write. |
network | string[] | [] | Up to 20 https hosts ctx.fetch may reach: api.stripe.com, or *.example.com for every name under it. No ports, paths or IPs. |
clipboard | boolean | false | Whether ctx.copy may copy text. Nothing can read the clipboard. |
optional | string[] | [] | Scopes the plugin works without, which the user can untick at install, such as data:write or network:api.stripe.com. Up to 30. Each must be asked for above. data:read can't be optional in a plugin with widgets, columns or result views. |
Production access isn't a permission. The user turns it on at install, and it starts off. See Production is the user's switch.
preferences
A list of form fields that Flare shows on the plugin's card in Settings, Plugins. password preferences are stored encrypted on the computer and only given to this plugin. Functions and components read them from ctx.preferences, keyed by each field's name.
contributes
Each kind of contribution is a list. Every entry's id must be unique within its kind. Ids are lower case letters, digits and hyphens, start with a letter and are at most 40 characters, such as revenue or copy-as-csv.
| Field | Up to | Entry | Guide |
|---|---|---|---|
widgets | 20 | A widget | Your first widget |
cells | 20 | A cell formatter | Cell formatters |
columns | 20 | A computed column | Computed columns |
rowActions | 20 | A row action | Row and bulk actions |
commands | 40 | A command | Commands |
transforms | 20 | A result view | Result views |
themes | 40 | A theme | Themes |
Most entries share these fields:
title: the name people see, 1 to 60 characters.description: up to 280 characters, shown where the contribution is offered.icon: a Lucide icon name in kebab case, such aschart-line.engines: the databases it works on, fromfirebase,postgres,mysql,sqlite,supabase,mongodb,cassandra,redisands3. Leave it out for all of them.
widgets
A widget on the dashboard, drawn by the Vue component with the same id.
| Field | Type | Default | What it is |
|---|---|---|---|
id | string | required | Matches a key of widgets in definePlugin. |
title | string | required | Its name in Add widget, and the title Flare draws above it. |
description | string | A sentence in Add widget. | |
icon | string | A Lucide icon name. | |
engines | string[] | every engine | The databases it's offered on. |
size | { w, h } | { "w": 6, "h": 4 } | Its starting size on the dashboard grid of 24 columns and 40px rows. Each from 2 to 24. |
minSize | { w, h } | The smallest size it can be resized to. | |
settings | FormField[] | [] | Up to 20 settings, in a form Flare draws. The component reads them with useWidget(). |
cells
Formats the table cells that match covers. The formatter returns what to show, never HTML.
| Field | Type | Default | What it is |
|---|---|---|---|
id | string | required | Matches a key of cells in definePlugin. |
title | string | required | Its name on the plugin's card. |
description | string | What it does. | |
engines | string[] | every engine | The databases whose tables it formats. |
match | object | required | Which cells it formats. See match. |
match
Needs at least one selector. With more than one, a cell must match all of them. Names and column types accept * for any run of characters and ignore case.
| Field | Type | What it matches |
|---|---|---|
fields | string[] | The field or column name, such as email or *_url. Up to 20. |
types | ValueType[] | The kind of value, whatever the engine calls the column. |
columnTypes | string[] | The column type the database declares, such as uuid or json*. Only on engines that declare column types. Up to 20. |
columns
A column computed from each row, shown after the table's own. Needs permissions.data of read or write.
| Field | Type | Default | What it is |
|---|---|---|---|
id | string | required | Matches a key of columns in definePlugin. |
title | string | required | The column heading. |
description | string | Shown when hovering the heading. | |
engines | string[] | every engine | The databases whose tables get it. |
rowActions
An action in a row's menu and, with bulk, on the selection toolbar.
| Field | Type | Default | What it is |
|---|---|---|---|
id | string | required | Matches a key of rowActions in definePlugin. |
title | string | required | Its name in the menu. |
description | string | What it does. | |
icon | string | A Lucide icon name. | |
engines | string[] | every engine | The databases it's offered on. |
write | boolean | false | Marks it as changing data. The manifest is refused unless permissions.data is write. |
bulk | boolean | false | Also shows it on the selection toolbar, called with every selected row. |
commands
An entry in the command palette, in a Plugins group.
| Field | Type | Default | What it is |
|---|---|---|---|
id | string | required | Matches a key of commands in definePlugin, and of commandViews when view is set. |
title | string | required | Its name in the palette. |
description | string | Shown under the name. | |
icon | string | A Lucide icon name. | |
engines | string[] | every engine | The databases it's offered on. |
keywords | string[] | [] | Up to 10 extra search words, each up to 30 characters. |
arguments | FormField[] | [] | Up to 10 fields Flare asks for before running it. |
view | boolean | false | Opens the component with the same id in a dialog, with the props the command returns. |
transforms
A result view: another tab next to Table and JSON for a query's results. Needs permissions.data of read or write.
| Field | Type | Default | What it is |
|---|---|---|---|
id | string | required | Matches a key of transforms in definePlugin. |
title | string | required | The tab's name. |
description | string | What it shows. | |
icon | string | A Lucide icon name. | |
engines | string[] | every engine | The databases whose results get it. |
view | boolean | false | A Vue component draws the results. Without it, a function returns new rows for Flare to show. |
themes
A colour theme. Themes are data only, so a plugin can be nothing but themes, with no code and no permissions.
| Field | Type | Default | What it is |
|---|---|---|---|
id | string | required | Its id within the plugin. Flare selects it as plugin:<plugin id>/<theme id>. |
title | string | required | Its name in Settings, Appearance. |
description | string | A sentence under the name. | |
mode | "light" or "dark" | required | The Flare theme it's laid over. |
colors | ThemeColors | required | Every colour by role, as #rrggbb. |
Rules across fields
On top of each field's type, Flare refuses a manifest when:
- a row action has
"write": truebutpermissions.dataisn'twrite; - it has widgets, columns or result views but
permissions.dataisnone; - a scope in
permissions.optionalisn't one the permissions ask for; data:readis optional but the plugin has widgets, columns or result views;- two entries of the same kind share an id;
- a
dropdownform field has nooptions, or afieldform field has noof.
Read a manifest in code
@flare/plugin/manifest exports the functions Flare uses, for your own tools and tests:
const result = readManifest({ name: 'flare-plugin-x', version: '1.0.0', flare: {} });
if (!result.ok) console.log(result.problems);
| Export | What it does |
|---|---|
readManifest(packageJson) | Checks a whole package.json. Returns the manifest, or every problem with its path. |
manifestSchema | The zod schema. |
worksOn(contribution, engine) | Whether a contribution is offered on an engine. |
hostAllowed(host, declared) | Whether a host matches the declared ones. *.example.com covers every name under it. |
cellMatches(match, cell) | Whether a cell formatter's match covers a cell. |
pluginHasCode(manifest) | Whether the plugin has anything besides themes, and so needs dist/plugin.js. |