npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@magicborn/dialogue-forge

v0.1.6

Published

Visual node-based dialogue editor with Yarn Spinner support

Downloads

613

Readme

Dialogue Forge

A visual node-based dialogue editor with Yarn Spinner support for game development.

🚀 Quick Start

Run the Demo

npx @magicborn/dialogue-forge

This will download the package and start an interactive demo server at http://localhost:3000.

Install as Library

npm install @magicborn/dialogue-forge

Quick Start

1. Define Your Flags

import { FlagSchema, FLAG_TYPE, FLAG_VALUE_TYPE } from '@magicborn/dialogue-forge';

const flagSchema: FlagSchema = {
  categories: ['quests', 'items', 'stats'],
  flags: [
    {
      id: 'quest_dragon_slayer',
      name: 'Dragon Slayer Quest',
      type: FLAG_TYPE.QUEST,  // ✅ Use constant, not 'quest'
      category: 'quests',
      valueType: FLAG_VALUE_TYPE.STRING
    },
    {
      id: 'item_ancient_key',
      name: 'Ancient Key',
      type: FLAG_TYPE.ITEM,  // ✅ Use constant
      category: 'items'
    },
    {
      id: 'stat_gold',
      name: 'Gold',
      type: FLAG_TYPE.STAT,  // ✅ Use constant
      category: 'stats',
      valueType: FLAG_VALUE_TYPE.NUMBER,
      defaultValue: 0
    }
  ]
};

2. Load Dialogue from Yarn

import { importFromYarn } from '@magicborn/dialogue-forge';

const yarnContent = await loadFile('merchant.yarn');
const dialogue = importFromYarn(yarnContent, 'Merchant Dialogue');

3. Edit Dialogue

import { DialogueEditor, exportToYarn } from '@magicborn/dialogue-forge';

<DialogueEditor
  dialogue={dialogue}
  onChange={(updated) => {
    const yarn = exportToYarn(updated);
    saveFile('merchant.yarn', yarn);
  }}
  flagSchema={flagSchema}
/>

4. Run Dialogue with Game State

import { DialogueSimulator } from '@magicborn/dialogue-forge';

// Get current game flags
const gameFlags = {
  quest_dragon_slayer: 'complete',
  item_ancient_key: true,
  stat_gold: 1000
};

<DialogueSimulator
  dialogue={dialogue}
  initialFlags={gameFlags}
  onComplete={(result) => {
    // Update game state with new flags
    gameState.flags = {
      ...gameState.flags,
      ...result.updatedFlags
    };
  }}
/>

Features

  • Visual Node Editor - Drag nodes, connect edges, right-click menus
  • Yarn Spinner Import/Export - Work with .yarn files
  • Flag System - Reference game flags with autocomplete dropdown
  • Simulation Mode - Test dialogues with current game state
  • Built-in Guide - Click book icon for complete documentation

Flag System

Flags represent game state (quests, items, achievements, etc.). The editor:

  • Shows available flags in dropdowns when setting flags
  • Validates flag references
  • Exports flags to Yarn format
  • Returns updated flags after dialogue completes

Flag Types (use FLAG_TYPE constant):

  • FLAG_TYPE.QUEST - Quest state and completion
  • FLAG_TYPE.ACHIEVEMENT - Unlocked achievements
  • FLAG_TYPE.ITEM - Inventory items
  • FLAG_TYPE.STAT - Player statistics
  • FLAG_TYPE.TITLE - Earned titles
  • FLAG_TYPE.DIALOGUE - Temporary, dialogue-scoped
  • FLAG_TYPE.GLOBAL - Global game state

Important: Always use the exported constants (FLAG_TYPE, NODE_TYPE, etc.) instead of string literals for type safety.

See DATA_STRUCTURES.md for complete type documentation and FLAG_SYSTEM.md for flag system details.

API Reference

Components

  • DialogueEditor - Visual editor for creating/editing dialogues
  • DialogueSimulator - Run dialogues with game state, returns updated flags
  • GuidePanel - Built-in documentation panel
  • FlagSelector - Flag autocomplete component

Utilities

  • importFromYarn(yarnContent, title) - Parse Yarn file to DialogueTree
  • exportToYarn(dialogue) - Convert DialogueTree to Yarn format
  • initializeFlags(schema) - Create default flag state from schema
  • mergeFlagUpdates(current, updates, schema) - Merge flag updates
  • validateFlags(flags, schema) - Validate flags against schema

Types

  • DialogueTree - Dialogue structure
  • DialogueNode - Individual dialogue node (NPC or Player)
  • FlagSchema - Flag definitions
  • GameFlagState - Current flag values { [flagId]: value }
  • DialogueResult - Result from running dialogue (updated flags, visited nodes)

Dialogue Editor V2 with View Modes

DialogueEditorV2 supports graph, yarn, and play views. Use the exported VIEW_MODE constant (instead of string literals) alongside the ViewMode type so consumers get auto-complete and type safety when switching views.

import { DialogueEditorV2, VIEW_MODE, type DialogueTree, type ViewMode } from '@magicborn/dialogue-forge';
import { useState } from 'react';

export function DialogueEditorDemo() {
  const [dialogue, setDialogue] = useState<DialogueTree | null>(null);
  const [viewMode, setViewMode] = useState<ViewMode>(VIEW_MODE.GRAPH);

  return (
    <DialogueEditorV2
      dialogue={dialogue}
      onChange={setDialogue}
      viewMode={viewMode}
      onViewModeChange={setViewMode}
    />
  );
}

Authoring dialogue data programmatically

You can build dialogue content without the editor and still take advantage of the types and constants that power the scene player. This makes it easy to script nonlinear stories, export them, or feed them directly into ScenePlayer.

import {
  NODE_TYPE,
  type DialogueTree,
  type DialogueNode,
  ScenePlayer,
} from '@magicborn/dialogue-forge';

const nodes: Record<string, DialogueNode> = {
  npc_1: {
    id: 'npc_1',
    type: NODE_TYPE.NPC,
    speaker: 'Merchant',
    content: 'Welcome, traveler! Looking for supplies?',
    nextNodeId: 'player_1',
    x: 0,
    y: 0,
  },
  player_1: {
    id: 'player_1',
    type: NODE_TYPE.PLAYER,
    content: ' ',
    choices: [
      { id: 'buy', text: 'Show me your wares.', nextNodeId: 'npc_2' },
      { id: 'chat', text: 'Any rumors?', nextNodeId: 'npc_3' },
    ],
    x: 320,
    y: 0,
  },
  npc_2: {
    id: 'npc_2',
    type: NODE_TYPE.NPC,
    content: 'Take a look! Fresh stock just arrived.',
    x: 640,
    y: -120,
  },
  npc_3: {
    id: 'npc_3',
    type: NODE_TYPE.NPC,
    content: 'Bandits have been spotted near the bridge—stay sharp.',
    x: 640,
    y: 120,
  },
};

const merchantIntro: DialogueTree = {
  id: 'merchant_intro',
  title: 'Merchant Greeting',
  startNodeId: 'npc_1',
  nodes,
};

// Render or test the dialogue without the editor
// <ScenePlayer dialogue={merchantIntro} gameState={yourGameState} onComplete={...} />

Complete Example

import {
  DialogueEditor,
  DialogueSimulator,
  importFromYarn,
  exportToYarn,
  FlagSchema,
  GameFlagState
} from '@magicborn/dialogue-forge';

// Define flags
import { FLAG_TYPE } from '@magicborn/dialogue-forge';

const flagSchema: FlagSchema = {
  flags: [
    { id: 'quest_complete', type: FLAG_TYPE.QUEST, category: 'quests' },
    { id: 'item_key', type: FLAG_TYPE.ITEM, category: 'items' },
  ]
};

// Load dialogue
const dialogue = importFromYarn(yarnFile, 'Merchant');

// Get current game state
const gameFlags: GameFlagState = {
  quest_complete: 'complete',
  item_key: true
};

// Edit dialogue
<DialogueEditor
  dialogue={dialogue}
  onChange={(updated) => {
    const yarn = exportToYarn(updated);
    saveFile(yarn);
  }}
  flagSchema={flagSchema}
  initialFlags={gameFlags}
/>

// OR run dialogue
<DialogueSimulator
  dialogue={dialogue}
  initialFlags={gameFlags}
  onComplete={(result) => {
    // Update game with new flags
    gameState.flags = result.updatedFlags;
    // Next dialogue will have different options
    // based on updated flags
  }}
/>

Documentation

Click the book icon in the editor to open the built-in guide.

Key Concepts

Flags = Yarn Variables: Flags you define in Dialogue Forge become $variable in Yarn Spinner. These variables are stored in Yarn Spinner's Variable Storage at runtime, not in the .yarn file.

Bidirectional Flow:

  • Edit in Dialogue Forge → Export .yarn → Import to Unreal
  • Game sets variables → Yarn reads them → Dialogue reacts
  • Dialogue sets variables → Yarn stores them → Game reads them

See UNREAL_INTEGRATION.md for complete details.