Developer docs
Manifest·

Manifest (PluginManifest)

The full set of required and optional fields of PluginManifest, declared via manifest.ts and defineManifest(), plus zod validation.

manifest.ts is the plugin's SSOT (Single Source of Truth). You declare it with defineManifest(), which gives you type completion. Nearly everything about your plugin — tables, side menu, tabs, permissions, and exposure in the unified palette — is derived from what you declare here.

// src/manifest.ts
import { defineManifest } from "@niyase/plugin-sdk/manifest";

export const manifest = defineManifest({
  id: "@your-org/tasks",
  scope: "CERTIFIED",
  visibility: "PUBLIC",
  targetWorkspace: "BUSINESS",
  category: "extension",
  displayName: "タスク",
  description: "シンプルな業務タスク管理",
  iconName: "ListTodo",
  defaultRole: "LOCAL",
  audiences: [
    {
      role: "executive",
      nav: {
        label: "タスク",
        href: "/plugin/tasks",
        activeColor: "text-primary",
      },
      tabs: [{ value: "list", label: "一覧" }],
    },
  ],
  tables: [
    {
      name: "task",
      resource: "task",
      columns: {
        title: { type: "TEXT", notNull: true },
        status: { type: "TEXT" },
      },
    },
  ],
  paletteMetadata: {
    intentTags: [
      "タスクを追加",
      "TODO 管理",
      "担当者を割り当て",
      "期限を設定",
      "進捗を確認",
    ],
    intentCategories: ["project"],
    capabilityKeywords: ["タスク管理", "TODO"],
    scenarios: ["朝の段取り", "週次レビュー"],
  },
});

Required fields

FieldTypeDescription
id@scope/nameGlobally unique ID. scope is your claimed namespace (@niyase for official plugins, your own org name for certified ones)
scope"OFFICIAL" | "CERTIFIED"Provider category — built by niyase, or by an external developer and reviewed by niyase
visibility"PUBLIC" | "PRIVATE"Marketplace visibility. PUBLIC can be found and activated from any space; PRIVATE is shown only in spaces that have been allow-listed
targetWorkspace"BUSINESS" | "PERSONAL" | "BOTH"Which space type the plugin targets
categoryPluginSidebarCategorySidebar category (one of 25 values). Determines where the plugin lives
displayNamestringDisplay name in the UI
descriptionstringA 1–2 line description
iconNamestringA lucide-react icon name
defaultRole"PROVIDER" | "CLIENT" | "LOCAL"Default role on activation (see below)
audiencesPluginAudience[]Per-role (executive / employee / customer) nav and tabs. At least one entry is required
tablesPluginTableDef[]Your own table definitions (use [] if none). Naming convention and auto-added columns are covered in Data Model
paletteMetadataPluginPaletteMetadataMetadata for unified-palette search (required, see below)

There is no PRIVATE value for scope. The provider category (scope) only takes OFFICIAL or CERTIFIED. The separate axis of "free and public to every space vs. paid and limited to specific spaces" is handled by visibility plus plugin_allowed_workspace (managed from admin) — don't conflate the two.

paletteMetadata (required)

Required because the unified palette is the primary path for discovering plugins — without it, your plugin never appears in search results. niyase-plugin lint flags a missing declaration.

FieldTypeGuideline
intentTagsstring[]Free-text, concrete phrases, 5–15 entries (e.g. "経費精算したい", "領収書を仕訳に")
intentCategoriesIntentCategory[]Top-level category enum, 1–3 entries (too many dilutes ranking)
capabilityKeywordsstring[]Capability words (e.g. "OCR", "PDF", "CSV import")
scenariosstring[]Business-scene phrases (e.g. "month-end close", "fiscal year-end")
primaryFlow?stringFlow ID to launch when selected from the palette (optional)

Optional fields

FieldTypeDescription
categoryTags?PluginSidebarCategory[]Additional category tags for search
industries?Industry[]Industry tags. These are discovery labels only and never restrict who can install the plugin (an IT company can install a "real-estate" tagged plugin). Empty/unset = for every industry
longDescription?stringA longer description (Markdown allowed) for the marketplace detail page
requiresCloud?boolean (default false)true makes the plugin cloud-only (installable in cloud spaces only). false (default) is hybrid — installable in both local and cloud spaces
pairedPluginId?stringLinks a PROVIDER ↔ CLIENT pair. When set, requiresCloud: true is required (zod enforces this consistency)
publisherName?stringPublisher display name (for CERTIFIED; OFFICIAL plugins default to "niyase")
version?stringsemver
bundleUrl? / bundleHash?stringBundle URL and integrity hash for CERTIFIED dynamic loading (set by the server at submission time)
scheduleProvider?ScheduleProviderDecl[]Declares which date columns on your tables should feed into the home "schedule" view's cross-cutting timeline
industryPresets?PluginIndustryPreset[]Deprecated (2026-05-30). The old per-industry master-data / conditional-table mechanism. Do not use it in new plugins — see Data Model for how to seed master data today

defaultRole and pairedPluginId — declaring the operating pattern

A plugin operates either standalone or as a PROVIDER-CLIENT pair (a two-party collaboration).

defaultRoleMeaningpairedPluginIdrequiresCloud
LOCALStandalone — self-contained within one spaceNot neededOptional (set true if it depends on cloud-only features)
PROVIDERThe providing side of a collaboration — aggregates data and shares it with a CLIENTSet to the paired CLIENT plugin's IDRequired to be true
CLIENTThe receiving side of a collaboration — only sees the data the PROVIDER has sharedSet to the paired PROVIDER plugin's IDRequired to be true

Separately from the role a user picks after activation, defaultRole declares the role a fresh activation starts in. A PROVIDER/CLIENT pair is always cloud-only (requiresCloud: true), since neither side of the pair can exist in a local space. For how defaultRole relates to the executive / employee / customer audiences shown in the UI, see UI Integration.

Validation

niyase-plugin lint validates the manifest with validateManifest() (zod). This is identical to the validator the server uses at submission time, so if lint passes, submission will pass too.

niyase-plugin lint
# ✓ tsc --noEmit
# ✓ manifest validation OK (@your-org/tasks)

The type definition's source of truth is packages/plugins/src/types.ts (PluginManifest).