スキル一覧に戻る
Nymfarious

connecting-widget-pipelines

by Nymfarious

StickerNest V3 - A sticker canvas application

0🍴 0📅 2025年12月28日
GitHubで見るManusで実行

SKILL.md


name: connecting-widget-pipelines description: Connecting StickerNest widgets via pipelines and ports. Use when the user asks about widget communication, connecting widgets, ports, inputs, outputs, pipelines, event routing, widget I/O, or making widgets talk to each other. Covers port definitions, type compatibility, event emission, and pipeline configuration.

Connecting Widget Pipelines

This skill covers how widgets communicate in StickerNest v2 through the port and pipeline system. Widgets expose typed input/output ports that can be connected to create data flows.

Core Concepts

Ports

Typed connection points on widgets. Inputs receive data, outputs emit data.

Pipelines

Named collections of connections between widget ports on a canvas.

Events

The actual data flowing through connections. Each event has a type and payload.


Defining Ports in Manifest

Input Ports

inputs: {
  trigger: {
    type: 'trigger',
    description: 'Activates the widget',
  },
  data: {
    type: 'any',
    description: 'Receives data from other widgets',
    default: null,
  },
  count: {
    type: 'number',
    description: 'Numeric input value',
    default: 0,
    required: false,
  },
}

Output Ports

outputs: {
  result: {
    type: 'any',
    description: 'Processed output data',
  },
  clicked: {
    type: 'trigger',
    description: 'Emitted when widget is clicked',
  },
  valueChanged: {
    type: 'number',
    description: 'Current value after change',
  },
}

Port Types

TypeDescriptionCompatible With
triggerSignal with no data (void)trigger, any
stringText datastring, any
numberNumeric datanumber, any
booleanTrue/falseboolean, any
objectJSON objectobject, any
arrayJSON arrayarray, any
anyAccepts anythingAll types

Type Compatibility Rules

  1. Exact match: Same types always connect
  2. Any accepts all: any input accepts any output type
  3. Any outputs to all: any output connects to any input
  4. Trigger is special: Only connects to trigger or any

I/O Capability Declarations

The io field provides AI-friendly hints for automatic wiring:

io: {
  inputs: [
    'trigger.activate',      // Trigger to activate widget
    'data.set',              // Set widget data
    'ui.show',               // Show the widget
    'ui.hide',               // Hide the widget
  ],
  outputs: [
    'data.result',           // Output result data
    'ui.clicked',            // User clicked
    'state.changed',         // State changed
  ],
}

Common I/O Patterns

PatternDescription
trigger.*Activation signals
data.*Data transfer
ui.*User interaction events
state.*State changes
text.*Text-specific operations
media.*Media events (play, pause, etc.)

Receiving Input Events

Using WidgetAPI

const API = window.WidgetAPI;

// Single input handler
API.onInput('data.set', function(value) {
  console.log('Received data:', value);
  // Process the input
  updateDisplay(value);
});

// Multiple inputs
API.onInput('trigger.activate', function() {
  performAction();
});

API.onInput('text.set', function(text) {
  if (typeof text === 'string') {
    state.text = text;
  } else if (text?.content) {
    state.text = text.content;
  }
  updateDisplay();
});

Using postMessage (Protocol v3.0)

window.addEventListener('message', (event) => {
  if (event.data.type === 'widget:event') {
    const { type, payload } = event.data.payload || {};

    switch (type) {
      case 'trigger.activate':
        performAction();
        break;
      case 'data.set':
        handleData(payload);
        break;
    }
  }

  // Alternative pipeline input format
  if (event.data.type === 'pipeline:input') {
    const { portName, value } = event.data;
    handleInput(portName, value);
  }
});

Emitting Output Events

Using WidgetAPI

const API = window.WidgetAPI;

// Emit to specific output port
API.emitOutput('data.result', {
  value: 42,
  processed: true
});

// Emit trigger (no payload needed)
API.emitOutput('ui.clicked', {});

// Emit with state update
function handleClick() {
  state.clickCount++;
  API.setState({ clickCount: state.clickCount });
  API.emitOutput('state.changed', {
    clickCount: state.clickCount
  });
}

Using postMessage (Protocol v3.0)

function emit(portId, data) {
  window.parent.postMessage({
    type: 'widget:emit',
    payload: {
      type: portId,      // MUST match io.outputs[].id
      payload: data
    }
  }, '*');
}

// Usage
emit('data.result', { value: 42 });
emit('ui.clicked', {});

Broadcast Events (Canvas-Wide)

For events that should reach all widgets on the canvas:

Emitting Broadcasts

// Using WidgetAPI
API.emit('weather.update', {
  sunny: true,
  temperature: 72
});

// These go to ALL widgets, not just connected ones
API.emit('theme.changed', { dark: true });

Listening to Broadcasts

API.on('weather.update', function(payload) {
  // Handle weather update from any widget
  updateWeatherDisplay(payload);
});

Declaring Broadcast Events in Manifest

events: {
  emits: ['weather.update', 'game.tick'],
  listens: ['theme.changed', 'canvas.resize'],
}

Pipeline Structure

Pipelines are stored in the canvas state:

interface Pipeline {
  id: string;
  canvasId: string;
  name: string;
  enabled: boolean;
  nodes: PipelineNode[];
  connections: PipelineConnection[];
}

interface PipelineNode {
  id: string;
  widgetId: string;           // Widget instance ID
  config?: Record<string, any>;
}

interface PipelineConnection {
  id: string;
  sourceNodeId: string;       // Source widget node
  sourcePortId: string;       // Output port ID
  targetNodeId: string;       // Target widget node
  targetPortId: string;       // Input port ID
  transformFn?: string;       // Optional transform code
}

Common Connection Patterns

Button -> Action

[Button Widget]          [Action Widget]
  ui.clicked ---------> trigger.activate

Data Producer -> Consumer

[API Widget]            [Display Widget]
  data.result --------> data.set

Counter -> Multiple Displays

[Counter Widget]        [Display A]
  valueChanged -------> data.set
        |
        +-------------> [Display B]
                        data.set

Chained Processing

[Input] -> [Transform A] -> [Transform B] -> [Output]
result     data.set         data.set         data.set
           result           result

Transform Functions

Connections can include transform functions to modify data:

// In pipeline connection
{
  sourceNodeId: 'widget-a',
  sourcePortId: 'data.result',
  targetNodeId: 'widget-b',
  targetPortId: 'data.set',
  transformFn: `
    // 'value' is the incoming data
    return {
      ...value,
      transformed: true,
      timestamp: Date.now()
    };
  `
}

Debugging Connections

Using Debug Panel

  1. Open Debug tab in StickerNest
  2. Watch "Events" section for real-time event flow
  3. Check "Pipeline" section for connection status

Console Logging

API.onInput('data.set', function(value) {
  API.log('Received on data.set: ' + JSON.stringify(value));
  // Process...
});

Common Issues

IssueCauseFix
Events not receivedPort ID mismatchEnsure port IDs in code match manifest exactly
Wrong data formatType incompatibilityCheck type compatibility or use any
No events flowingMissing connectionVerify pipeline connection exists in canvas
Events to wrong widgetWrong targetNodeIdCheck pipeline configuration

Example: Complete Connected Widget

Manifest

export const DataProcessorManifest: WidgetManifest = {
  id: 'stickernest.data-processor',
  name: 'Data Processor',
  version: '1.0.0',
  kind: 'interactive',
  entry: 'index.html',
  description: 'Transforms incoming data and outputs result',
  inputs: {
    rawData: {
      type: 'any',
      description: 'Raw data to process',
    },
    trigger: {
      type: 'trigger',
      description: 'Process immediately',
    },
  },
  outputs: {
    processed: {
      type: 'object',
      description: 'Processed data output',
    },
    error: {
      type: 'string',
      description: 'Error message if processing fails',
    },
  },
  capabilities: { draggable: true, resizable: true, rotatable: true },
  io: {
    inputs: ['data.raw', 'trigger.process'],
    outputs: ['data.processed', 'error.message'],
  },
  size: { width: 180, height: 120 },
};

HTML Implementation

<script>
(function() {
  const API = window.WidgetAPI;
  let pendingData = null;

  function process() {
    if (!pendingData) return;

    try {
      const result = {
        original: pendingData,
        processed: true,
        timestamp: Date.now(),
      };
      API.emitOutput('data.processed', result);
      API.log('Processing complete');
    } catch (err) {
      API.emitOutput('error.message', err.message);
    }
  }

  API.onInput('data.raw', function(data) {
    pendingData = data;
    // Auto-process on data receive
    process();
  });

  API.onInput('trigger.process', function() {
    process();
  });

  API.onMount(function(context) {
    pendingData = context.state?.pendingData || null;
  });
})();
</script>

Reference Files

  • Port types: src/types/manifest.ts (WidgetInputSchema, WidgetOutputSchema)
  • Pipeline runtime: src/runtime/PipelineRuntime.ts
  • Port compatibility: src/runtime/PortCompatibility.ts
  • Event bus: src/runtime/EventBus.ts
  • Protocol spec: Docs/WIDGET-PROTOCOL-SPEC.md

スコア

総合スコア

50/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です