Developer docs
Setup·

Setup

Scaffold with pnpm and the niyase-plugin CLI, then build, lint, and run a local preview.

Requirements

  • Node.js 24+
  • pnpm (the niyase repository uses pnpm exclusively — not npm or yarn)
  • A modern browser (for local preview)

About the SDK

@niyase/plugin-sdk is already published on npm (MIT). @niyase/plugin-preview, which local preview depends on, is coming to npm soon. If you're building an official plugin inside niyase, you can already use the niyase-plugin CLI directly from the pnpm workspace in the monorepo (monorepo/packages/@niyase/).

Scaffold a project

niyase-plugin new generates a plugin project.

pnpm dlx @niyase/plugin-sdk new @your-org/tasks
cd tasks
pnpm install

To build an official plugin inside niyase, run niyase-plugin new @niyase/<short-id> from monorepo/packages/@niyase/.

Generated files:

tasks/
├── package.json        # niyase-plugin scripts + SDK devDeps
├── tsconfig.json
└── src/
    ├── manifest.ts     # defineManifest({...})
    ├── Root.tsx        # the main component that uses useNiyase()
    └── index.tsx       # createNiyase(); register("@your-org/tasks", Root)

CLI commands

CommandRole
niyase-plugin newScaffold a plugin
niyase-plugin buildGenerate the distributable IIFE bundle (dist/bundle.js)
niyase-plugin linttsc + validateManifest() (zod) + forbidden-API scan
niyase-plugin testRun vitest (verify against the MOCK with createTestHost())
niyase-plugin devLocal preview (see below)
niyase-plugin publishBuild + validate + submit (see Submission)

register() and local preview

Your entry file (src/index.tsx) calls createNiyase() to initialize the bridge, then register(pluginId, Root) to register the root component with the host. These two lines are your plugin's entry point, shared by both production and local preview.

pnpm dev          # = niyase-plugin dev
# ▸ http://localhost:4190

niyase-plugin dev runs your plugin inside a true-to-life generic shell (sidebar-equivalent / tabs), executing it with <iframe sandbox> + postMessage and connecting it to a MOCK backend that seeds itself automatically once register() is called (recreating tables in memory from the manifest's tables[]). Use the DevBar at the top to switch theme, role (executive / employee / customer), space type, language (ja / en), and fault injection while you check it.

Because preview and production both run on the same useNiyase() contract (one interface, two implementations), what you see here becomes the production look as-is.

Minimal plugin

// src/Root.tsx
import { useEffect, useState } from "react";
import { useNiyase } from "@niyase/plugin-sdk";

export function Root() {
  const niyase = useNiyase();
  const [items, setItems] = useState<{ id: string; title: string }[]>([]);

  useEffect(() => {
    niyase.data
      .list<{ id: string; title: string }>("task")
      .then((r) => setItems(r.items));
  }, []);

  return (
    <ul>
      {items.map((it) => (
        <li key={it.id}>{it.title}</li>
      ))}
    </ul>
  );
}

Next, check the contents of manifest.ts in Manifest.