Skip to content

Repository files navigation

Developing Apps for Cytoscape Web

Reference implementations and documentation for Cytoscape Web app development

Introduction

This repository is for third-party developers who want to build apps for Cytoscape Web.

You do not need to change the host source code. Your app is loaded by the host through Module Federation (Vite). Apps can add:

  • panel components in the right-side App Panel
  • menu items in the Apps dropdown
  • context menu actions for right-click workflows

Quick Start

Set up the local workspace

Both the host application and this examples repository are needed side by side. The host runs the Cytoscape Web UI at localhost:5500 and loads your app from your own dev server, so you never rebuild the host to work on your app.

Editing your app does not hot-reload inside the host. Vite's HMR does not cross the federation boundary — that is a separate feature (dev.remoteHmr), off by default. Your dev server rebuilds the changed module immediately, but you reload the host page to pick it up.

mkdir cytoscape-web-dev && cd cytoscape-web-dev
git clone https://github.com/cytoscape/cytoscape-web.git
git clone https://github.com/cytoscape/cytoscape-web-app-examples.git

1. Run the example apps

cd cytoscape-web-app-examples
npm install
npm run dev

2. Run the host with the local app registry

cd cytoscape-web
npm install
npm run dev:local

3. Check that it works

  1. Open http://localhost:5500
  2. Open Apps -> App Settings
  3. Enable one of the example apps
  4. Open the Apps menu or the right-side App Panel

Publishing to the public Cytoscape Web site

The production instance of Cytoscape Web loads apps from a curated allowlist (apps.json) maintained by the core team. There are plans for a dynamic loading mechanism and the public App store in the future, but for now public app registration is manual. If you would like to publish your app, please contact the Cytoscape team.


Build Your First App

Copy project-template/ and follow the 5 steps:

cp -r project-template my-app && cd my-app
  1. package.json — change name and version
  2. vite.config.ts — change name in federation() and DEV_SERVER_PORT
  3. src/TemplateApp.tsx — change id (must match MF name), name, resources
  4. Host registry — add an entry for your app in cytoscape-web/src/assets/apps.local.json:
    {
      "id": "myApp",
      "name": "My App (display name)",
      "url": "http://localhost:6000/remoteEntry.js",
      "version": "0.1.0"
    }

    id is the unique identifier (must match the federation name and your CyApp.id); name is the human-readable label shown in App Settings.

    To test the template before copying, add:

    { "id": "template", "name": "App Template", "url": "http://localhost:5555/remoteEntry.js", "version": "0.1.0" }
  5. Verifynpm run dev, then confirm in browser

See project-template/README.md for details.


App Entry Point

Every app exports one CyAppWithLifecycle object:

import { lazy } from 'react'
import { CyAppWithLifecycle } from 'cyweb/ApiTypes'
import packageJson from '../package.json'

const { version } = packageJson

export const MyApp: CyAppWithLifecycle = {
  id: 'myApp',
  name: 'My App',
  description: 'Short description of your app',
  version,
  apiVersion: '1.0',

  // Declarative resource registration — panels and menu items
  resources: [
    {
      slot: 'right-panel',
      id: 'MyPanel',
      title: 'My Panel',
      component: lazy(() => import('./components/MyPanel')),
    },
    {
      slot: 'apps-menu',
      id: 'MyMenuItem',
      title: 'My Action',
      component: lazy(() => import('./components/MyMenuItem')),
      closeOnAction: true,
    },
  ],

  // Context menus and event listeners — registered in mount()
  mount(context) {
    context.apis.contextMenu.addContextMenuItem({
      label: 'My App: Log Node Info',
      targetTypes: ['node'],
      handler: (ctx) => {
        const result = context.apis.element.getNode(ctx.networkId, ctx.id!)
        if (result.success) console.info('Node:', result.data)
      },
    })
  },
  unmount() {
    /* clean up event listeners only — context menus are auto-cleaned */
  },
}

Documentation Map

Developer Guides

Guide Topics
Getting Started Scaffold, configure, register, run
Architecture Overview Module Federation, type system, API layers
Registration Patterns Panels, menus, context menus, upsert, batch
Lifecycle & Cleanup mount/unmount, auto-cleanup, re-enable
Troubleshooting Build errors, runtime errors, FAQ

API Reference

Resource Description
App API Reference Complete reference for all domain APIs, ResourceApi, Event Bus, error codes, and lifecycle
@cytoscape-web/api-types (README) TypeScript types package — install for IDE support
CHANGELOG Version history for the types package

Specifications (Advanced)

Spec Scope
App API Specification Full 2000-line spec for all 10 domain APIs
Resource Registration Specification Slot model, lifecycle, cleanup, error boundaries
Registration Minimal App Example End-to-end code walkthrough of all registration paths

Available APIs

All API methods return ApiResult<T>. Always check result.success before reading result.data.

API Import Purpose
WorkspaceApi cyweb/WorkspaceApi Current network ID, workspace info, switch network
ElementApi cyweb/ElementApi Create/delete nodes and edges, graph traversal queries
NetworkApi cyweb/NetworkApi Create/delete networks, import CX2
SelectionApi cyweb/SelectionApi Read and mutate the current selection
ViewportApi cyweb/ViewportApi Pan, zoom, fit, read/write node positions
TableApi cyweb/TableApi Read and write node/edge attribute tables
VisualStyleApi cyweb/VisualStyleApi Set defaults, bypasses, and mappings
LayoutApi cyweb/LayoutApi Run layout algorithms
ExportApi cyweb/ExportApi Export network as CX2
EventBus cyweb/EventBus Subscribe to host events (useCyWebEvent)
AppIdContext cyweb/AppIdContext Per-app context (useAppContext) for resource and context menu APIs
ApiTypes cyweb/ApiTypes TypeScript types for all of the above

Available Events

Event Fires when
network:created A new network is added to the workspace
network:deleted A network is removed
network:switched The user navigates to a different network
selection:changed Node or edge selection changes
layout:started A layout algorithm begins
layout:completed A layout algorithm finishes
style:changed A visual style property changes
data:changed Node or edge attribute data changes

Non-React Access

Outside React components, the same APIs are available via window.CyWebApi:

window.addEventListener('cywebapi:ready', () => {
  const api = window.CyWebApi
  const result = api.workspace.getCurrentNetworkId()
  // ...
})

Note: window.CyWebApi does not include resource or per-app contextMenu. Those are only available inside mount() via context.apis or via useAppContext().


Example Apps

Example Best for Details
project-template/ Your first app — panel, menu action, and context menu README
hello-world/ Full API coverage — 13 examples covering all APIs README
network-statistics/ Non-React — graph traversal, event-driven logging README
network-workflows/ CX2 import, Jupyter integration, menu workflows README

Recommended reading order: project-template → hello-world → network-statistics → network-workflows


Type Setup

Install the types package for IDE support:

npm install --save-dev @cytoscape-web/api-types

Reference the package's bundled declarations from your tsconfig.json so TypeScript resolves the cyweb/* ambient modules:

{
  "include": ["src/**/*"],
  "compilerOptions": {
    "moduleResolution": "bundler",
    "types": ["@cytoscape-web/api-types"]
  }
}

Listing the package in types is what pulls in its ambient cyweb/* declarations. Do not set typeRoots: the example apps used to point it at ./node_modules/@types, a directory that does not exist in a workspace, and setting it suppresses the default lookup that actually finds the types. See any of the example apps' tsconfig.json for a working reference.


Development Commands

npm run dev                     # run all workspaces concurrently
npm run dev:hello-world         # run one app
npm run dev:network-statistics
npm run dev:network-workflows
npm run dev:project-template
npm run dev:claude-bridge       # MCP bridge (optional, internal tool)
npm run build                   # build all workspaces
npm run deploy                  # build and copy each workspace's dist/ into docs/

Verification

npm run verify:federation       # the built dist/ has the right federation shape
npm run preflight:host -- <hostUrl>              # the host publishes a usable descriptor
npm run preflight:apps -- <hostUrl> <appsBase>   # the PUBLISHED apps load in that host

The three cover different layers, and the gap between the first two is why the third exists. verify:federation reads dist/, preflight:host reads the host — so a fault in the serving layer between them is invisible to both. That is not hypothetical: GitHub Pages ran this repo's docs/ through Jekyll, which drops _-prefixed paths, and silently 404'd the _virtual_mf-* chunk every app imports first while both other checks stayed green.

preflight:apps loads each published app through a real dynamic import() inside a real host page, so transitive chunk fetches, CORS and MIME are the real ones. -- --selftest proves it can still fail.


Deprecated APIs

Older examples used direct store imports. They still work, but new apps should use the App API hooks instead — they return ApiResult<T> and provide a stable, documented contract. See Architecture Overview → Host Exposes Reference for the full list of legacy cyweb/*Store exposes.

Deprecated pattern Recommended replacement
useNetworkStore useNetworkApi
useTableStore useTableApi
useWorkspaceStore useWorkspaceApi

About

Example Apps for Cytoscape Web.

Resources

Stars

5 stars

Watchers

11 watching

Forks

Releases

Packages

Used by

Contributors

Languages