logoSemaphor

Custom Visuals

Build custom React visualizations and filters for Semaphor dashboards

Custom visuals let you bring your own React components into Semaphor dashboards. Build charts, tables, KPIs, maps, or any visualization your users need.

Semaphor handles data fetching, authentication, theming, and state management. You focus on the visualization.

Why Custom Plugins?

Standard chart libraries often fall short for domain-specific needs:

  • Trade Analytics: Specialized maps with import/export flows and custom annotations
  • Financial Dashboards: Tables with precise formatting, sorting, and conditional highlighting
  • HR Tools: Demographic visualizations with compliance requirements
  • Healthcare: Patient flow diagrams, appointment timelines, resource views

Most BI tools lock you into their charting libraries. Semaphor's plugin architecture gives you complete control.

Micro Frontend Architecture

Plugins follow the micro frontend pattern—small, independently deployable applications that integrate at runtime.

+-----------------------------------------------------------------------------+
|                         SEMAPHOR PLATFORM                                   |
|                                                                             |
|   +---------------+    +--------------------------------------------+       |
|   |               |    |                                            |       |
|   |  Built-in     |    |  YOUR PLUGIN (Micro Frontend)              |       |
|   |  Charts       |    |  +------------+ +------------+ +--------+  |       |
|   |               |    |  |RevenueChart| |SummaryTable| | MyMap  |  |       |
|   |  Semaphor     |    |  +------------+ +------------+ +--------+  |       |
|   |  Core         |    |                                            |       |
|   |               |    |  One bundle, multiple visuals & filters    |       |
|   +---------------+    +--------------------------------------------+       |
|                                                                             |
|   Loaded at runtime --------------------------------------------------->    |
|                                                                             |
+-----------------------------------------------------------------------------+

Benefits

BenefitDescription
Independent DeploymentShip plugin updates without touching Semaphor core
Technology FreedomUse any React-compatible libraries (D3, Recharts, ECharts)
Team AutonomyDifferent teams can own different visualizations
IsolationPlugin bugs don't crash the main application
LightweightOnly load what you need, when you need it

What Semaphor Handles vs What You Build

Semaphor handles:

  • Security and multi-tenancy
  • Authentication and permissions
  • Query processing and data fetching
  • State management and filter cascading
  • Theme synchronization
  • Caching and performance

You focus on:

  • Your visualization
  • Your styling preferences
  • Your user experience

Single vs Multi-Input

Choose based on how many data sources your visual needs.

TypeUse WhenData ShapeExample
Single-InputOne query, one visualdata: Record[]Charts, tables, KPIs
Multi-InputCombining multiple queriesdata: Record[][]KPI + trend chart, comparison grids

Most visuals are single-input. Use multi-input when you need to combine data from different cards (like a KPI header with a separate trend chart).

Quick Start

The easiest way to create custom visuals is with Claude Code. The plugin template includes skills that generate complete, working components automatically.

1. Clone the template

git clone https://github.com/semaphor-cloud/semaphor-plugin-quickstart.git
cd semaphor-plugin-quickstart
npm install

2. Create your visual with Claude Code

Open Claude Code in the plugin project and ask it to create your component:

claude

Then describe what you want to build:

> Create a single-input visual called "Revenue KPI" that displays
  a large number with a comparison badge showing percent change

Or for multi-input visuals:

> Create a multi-input visual called "KPI Trend" with two slots:
  one for the hero KPI value and one for the trend line chart

Claude will automatically:

  1. Create the component file with proper TypeScript types
  2. Create sample data for the Showcase
  3. Register the component in components.config.ts
  4. Export from index.ts
  5. Add to sample-data-registry.ts

Tips for better results:

  • Upload a screenshot — Drag and drop an image of the visual you want. Claude can see the design and replicate it
  • Be specific: "A donut chart with center label showing percentage"
  • Mention libraries: "Use Recharts for the bar chart"
  • Describe interactions: "Clicking a bar should highlight it"
  • Specify formatting: "Display currency values with $ prefix"

3. Preview in the Showcase

npm run dev

Open http://localhost:5173 to see the Showcase Gallery with your component.

The Showcase provides:

  • Instant Feedback — Hot reload shows changes immediately
  • Realistic Testing — Sample data mimics production query results
  • Documentation Preview — See how your docs will appear in Semaphor
  • Filter Interaction — Test filter components with real state management

4. Build and publish

One-time setup:

# Install the Semaphor CLI
npm install -g semaphor-cli
 
# Initialize your plugin
semaphor init

During semaphor init, you'll be prompted for:

  • Type: Select Plugin
  • Name: Your plugin name (e.g., my-company-charts)
  • Build path: dist (default)
  • Project ID: From Semaphor project settings
  • Project Secret: From Semaphor project settings

Build and publish:

npm run build
semaphor publish

This uploads to Semaphor:

  • dist/index.js — Bundled components
  • dist/style.css — Styles
  • dist/manifest.json — Component metadata

Your visual now appears in Semaphor's chart type selector under Custom Visuals.

What Claude Creates

When you ask Claude to create a visual, it generates a complete component structure. Here's what each file does:

Project Structure

semaphor-plugin-quickstart/
├── src/
│   ├── components/
│   │   ├── components.config.ts    # Component registration & settings
│   │   ├── config-types.ts         # TypeScript types
│   │   ├── index.ts                # Exports all components
│   │   └── semaphor-components/    # Your components
│   │       └── revenue-kpi/
│   │           ├── revenue-kpi.tsx      # React component
│   │           └── revenue-kpi.data.ts  # Sample data for Showcase
│   └── showcase/                   # Local dev gallery
├── dist/                           # Build output
└── package.json

Key Files

FilePurpose
components.config.tsRegisters components with names, settings, icons, and documentation
index.tsExports all components (names must match config exactly)
[name].tsxThe React component that renders your visualization
[name].data.tsSample data for testing in the Showcase

Props Your Component Receives

Semaphor passes these props to your component:

type SingleInputVisualProps = {
  data: Record<string, string | number | boolean>[];  // Query results
  settings?: Record<string, string | number | boolean>; // User settings
  theme?: {
    colors?: string[];            // Dashboard color palette
    mode?: 'light' | 'dark' | 'system'; // Color mode
  };
  cardMetadata?: CardMetadata;    // Title, formatting, KPI config
  inlineFilters?: ReactNode[];    // Pre-rendered filter components
  filters?: DashboardFilter[];    // Dashboard filters (metadata)
  filterValues?: ActiveFilterValue[]; // Active filter selections
};

Manual Reference

If you prefer to create components without AI assistance, or want to understand the internals for customization, see the detailed guides:

Next Steps