# FlowGram.AI - Demo Free Layout

Best-practice demo for free layout

## Installation

```shell
npx @flowgram.ai/create-app@latest free-layout
```

## Project Overview

### Core Tech Stack
- **Frontend framework**: React 18 + TypeScript
- **Build tool**: Rsbuild (a modern build tool based on Rspack)
- **Styling**: Less + Styled Components + CSS Variables
- **UI library**: Semi Design (@douyinfe/semi-ui)
- **State management**: Flowgram’s in-house editor framework
- **Dependency injection**: Inversify

### Core Dependencies

- **@flowgram.ai/free-layout-editor**: Core dependency for the free layout editor
- **@flowgram.ai/free-snap-plugin**: Auto-alignment and guide-lines plugin
- **@flowgram.ai/free-lines-plugin**: Connection line rendering plugin
- **@flowgram.ai/free-node-panel-plugin**: Node add-panel rendering plugin
- **@flowgram.ai/minimap-plugin**: Minimap plugin
- **@flowgram.ai/export-plugin**: Download/export plugin
- **@flowgram.ai/free-container-plugin**: Sub-canvas plugin
- **@flowgram.ai/free-group-plugin**: Grouping plugin
- **@flowgram.ai/form-materials**: Form materials
- **@flowgram.ai/runtime-interface**: Runtime interfaces
- **@flowgram.ai/runtime-js**: JS runtime module
- **@flowgram.ai/panel-manager-plugin**:  Sidebar panel management

## Code Guide

### Directory Structure
```
src/
├── app.tsx                  # Application entry file
├── editor.tsx               # Main editor component
├── initial-data.ts          # Initial data configuration
├── assets/                  # Static assets
├── components/              # Component library
│   ├── index.ts
│   ├── add-node/            # Add-node component
│   ├── base-node/           # Base node components
│   ├── comment/             # Comment components
│   ├── group/               # Group components
│   ├── line-add-button/     # Connection add button
│   ├── node-menu/           # Node menu
│   ├── node-panel/          # Node add panel
│   ├── selector-box-popover/ # Selection box popover
│   ├── sidebar/             # Sidebar
│   ├── testrun/             # Test-run module
│   │   ├── hooks/           # Test-run hooks
│   │   ├── node-status-bar/ # Node status bar
│   │   ├── testrun-button/  # Test-run button
│   │   ├── testrun-form/    # Test-run form
│   │   ├── testrun-json-input/ # JSON input component
│   │   └── testrun-panel/   # Test-run panel
│   └── tools/               # Utility components
├── context/                 # React Context
│   ├── node-render-context.ts # Current rendering node context
│   ├── sidebar-context        # Sidebar context
├── form-components/         # Form component library
│   ├── form-content/        # Form content
│   ├── form-header/         # Form header
│   ├── form-inputs/         # Form inputs
│   └── form-item/           # Form item
│   └── feedback.tsx         # Validation error rendering
├── hooks/
│   ├── index.ts
│   ├── use-editor-props.tsx # Editor props hook
│   ├── use-is-sidebar.ts    # Sidebar state hook
│   ├── use-node-render-context.ts # Node render context hook
│   └── use-port-click.ts    # Port click hook
├── nodes/                    # Node definitions
│   ├── index.ts
│   ├── constants.ts         # Node constants
│   ├── default-form-meta.ts # Default form metadata
│   ├── block-end/           # Block end node
│   ├── block-start/         # Block start node
│   ├── break/               # Break node
│   ├── code/                # Code node
│   ├── comment/             # Comment node
│   ├── condition/           # Condition node
│   ├── continue/            # Continue node
│   ├── end/                 # End node
│   ├── group/               # Group node
│   ├── http/                # HTTP node
│   ├── llm/                 # LLM node
│   ├── loop/                # Loop node
│   ├── start/               # Start node
│   └── variable/            # Variable node
├── plugins/                 # Plugin system
│   ├── index.ts
│   ├── context-menu-plugin/ # Right-click context menu plugin
│   ├── runtime-plugin/      # Runtime plugin
│   │   ├── client/          # Client
│   │   │   ├── browser-client/ # Browser client
│   │   │   └── server-client/  # Server client
│   │   └── runtime-service/ # Runtime service
│   └── variable-panel-plugin/ # Variable panel plugin
│       └── components/      # Variable panel components
├── services/                 # Service layer
│   ├── index.ts
│   └── custom-service.ts    # Custom service
├── shortcuts/                # Shortcuts system
│   ├── index.ts
│   ├── constants.ts         # Shortcut constants
│   ├── shortcuts.ts         # Shortcut definitions
│   ├── type.ts              # Type definitions
│   ├── collapse/            # Collapse shortcut
│   ├── copy/                # Copy shortcut
│   ├── delete/              # Delete shortcut
│   ├── expand/              # Expand shortcut
│   ├── paste/               # Paste shortcut
│   ├── select-all/          # Select-all shortcut
│   ├── zoom-in/             # Zoom-in shortcut
│   └── zoom-out/            # Zoom-out shortcut
├── styles/                   # Styles
├── typings/                  # Type definitions
│   ├── index.ts
│   ├── json-schema.ts       # JSON Schema types
│   └── node.ts              # Node type definitions
└── utils/                    # Utility functions
    ├── index.ts
    └── on-drag-line-end.ts  # Handle end of drag line
```

### Key Directory Functions

#### 1. `/components` - Component Library
- **base-node**: Base rendering components for all nodes
- **testrun**: Complete test-run module, including status bar, form, and panel
- **sidebar**: Sidebar components providing tools and property panels
- **node-panel**: Node add panel with drag-to-add capability

#### 2. `/nodes` - Node System
Each node type has its own directory, including:
- Node registration (`index.ts`)
- Form metadata (`form-meta.ts`)
- Node-specific components and logic

#### 3. `/plugins` - Plugin System
- **runtime-plugin**: Supports both browser and server modes
- **context-menu-plugin**: Right-click context menu
- **variable-panel-plugin**: Variable management panel

#### 4. `/shortcuts` - Shortcuts System
Complete keyboard shortcut support, including:
- Basic actions: copy, paste, delete, select-all
- View actions: zoom-in, zoom-out, collapse, expand
- Each shortcut has its own implementation module

## Application Architecture

### Core Design Patterns

#### 1. Plugin Architecture
Highly modular plugin system; each feature is an independent plugin:

```typescript
plugins: () => [
  createFreeLinesPlugin({ renderInsideLine: LineAddButton }),
  createMinimapPlugin({ /* config */ }),
  createFreeSnapPlugin({ /* alignment config */ }),
  createFreeNodePanelPlugin({ renderer: NodePanel }),
  createContainerNodePlugin({}),
  createFreeGroupPlugin({ groupNodeRender: GroupNodeRender }),
  createContextMenuPlugin({}),
  createRuntimePlugin({ mode: 'browser' }),
  createVariablePanelPlugin({})
]
```

#### 2. Node Registry Pattern
Manage different workflow node types via a registry:

```typescript
export const nodeRegistries: FlowNodeRegistry[] = [
  ConditionNodeRegistry,    // Condition node
  StartNodeRegistry,        // Start node
  EndNodeRegistry,          // End node
  LLMNodeRegistry,          // LLM node
  LoopNodeRegistry,         // Loop node
  CommentNodeRegistry,      // Comment node
  HTTPNodeRegistry,         // HTTP node
  CodeNodeRegistry,         // Code node
  // ... more node types
];
```

#### 3. Dependency Injection
Use Inversify for service DI:

```typescript
onBind: ({ bind }) => {
  bind(CustomService).toSelf().inSingletonScope();
}
```

## Core Features

### 1. Editor Configuration System

`useEditorProps` is the configuration center of the editor:

```typescript
export function useEditorProps(
  initialData: FlowDocumentJSON,
  nodeRegistries: FlowNodeRegistry[]
): FreeLayoutProps {
  return useMemo<FreeLayoutProps>(() => ({
    background: true,                    // Background grid
    readonly: false,                     // Readonly mode
    initialData,                         // Initial data
    nodeRegistries,                      // Node registries

    // Core feature configs
    playground: { preventGlobalGesture: true /* Prevent Mac browser swipe gestures */ },
    nodeEngine: { enable: true },
    variableEngine: { enable: true },
    history: { enable: true, enableChangeNode: true },

    // Business rules
    canAddLine: (ctx, fromPort, toPort) => { /* Connection rules */ },
    canDeleteLine: (ctx, line) => { /* Line deletion rules */ },
    canDeleteNode: (ctx, node) => { /* Node deletion rules */ },
    canDropToNode: (ctx, params) => { /* Drag-and-drop rules */ },

    // Plugins
    plugins: () => [/* Plugin list */],

    // Events
    onContentChange: debounce((ctx, event) => { /* Auto save */ }, 1000),
    onInit: (ctx) => { /* Initialization */ },
    onAllLayersRendered: (ctx) => { /* After render */ }
  }), []);
}
```

### 2. Node Type System

The app supports multiple workflow node types:

```typescript
export enum WorkflowNodeType {
  Start = 'start',           // Start node
  End = 'end',               // End node
  LLM = 'llm',               // Large language model node
  HTTP = 'http',             // HTTP request node
  Code = 'code',             // Code execution node
  Variable = 'variable',     // Variable node
  Condition = 'condition',   // Conditional node
  Loop = 'loop',             // Loop node
  BlockStart = 'block-start', // Sub-canvas start node
  BlockEnd = 'block-end',    // Sub-canvas end node
  Comment = 'comment',       // Comment node
  Continue = 'continue',     // Continue node
  Break = 'break',           // Break node
}
```

Each node follows a unified registration pattern:

```typescript
export const StartNodeRegistry: FlowNodeRegistry = {
  type: WorkflowNodeType.Start,
  meta: {
    isStart: true,
    deleteDisable: true,        // Not deletable
    copyDisable: true,          // Not copyable
    nodePanelVisible: false,    // Hidden in node panel
    defaultPorts: [{ type: 'output' }],
    size: { width: 360, height: 211 }
  },
  info: {
    icon: iconStart,
    description: 'The starting node of the workflow, used to set up information needed to launch the workflow.'
  },
  formMeta,                     // Form configuration
  canAdd() { return false; }    // Disallow multiple start nodes
};
```

### 3. Plugin Architecture

App features are modularized via the plugin system:

#### Core Plugin List
1. **FreeLinesPlugin** - Connection rendering and interaction
2. **MinimapPlugin** - Minimap navigation
3. **FreeSnapPlugin** - Auto-alignment and guide-lines
4. **FreeNodePanelPlugin** - Node add panel
5. **ContainerNodePlugin** - Container nodes (e.g., loop nodes)
6. **FreeGroupPlugin** - Node grouping
7. **ContextMenuPlugin** - Right-click context menu
8. **RuntimePlugin** - Workflow runtime
9. **VariablePanelPlugin** - Variable management panel

### 4. Runtime System

Two run modes are supported:

```typescript
createRuntimePlugin({
  mode: 'browser',              // Browser mode
  // mode: 'server',            // Server mode
  // serverConfig: {
  //   domain: 'localhost',
  //   port: 4000,
  //   protocol: 'http',
  // },
})
```

## Design Philosophy and Advantages

### 1. Highly Modular
- **Plugin architecture**: Each feature is an independent plugin, easy to extend and maintain
- **Node registry system**: Add new node types without changing core code
- **Componentized UI**: Highly reusable components with clear responsibilities

### 2. Type Safety
- **Full TypeScript support**: End-to-end type safety from configuration to runtime
- **JSON Schema integration**: Node data validated by schemas
- **Strongly typed plugin interfaces**: Clear type constraints for plugin development

### 3. User Experience
- **Real-time preview**: Run and debug workflows live
- **Rich interactions**: Dragging, zooming, snapping, shortcuts for a complete editing experience
- **Visual feedback**: Minimap, status indicators, line animations

### 4. Extensibility
- **Open plugin system**: Third parties can easily develop custom plugins
- **Flexible node system**: Custom node types and form configurations supported
- **Multiple runtimes**: Both browser and server modes

### 5. Performance
- **On-demand loading**: Components and plugins support lazy loading
- **Debounce**: Performance optimizations for high-frequency operations like auto-save

## Technical Highlights

### 1. In-house Editor Framework
Based on `@flowgram.ai/free-layout-editor`, providing:
- Free-layout canvas system
- Full undo/redo functionality
- Lifecycle management for nodes and connections
- Variable engine and expression system

### 2. Advanced Build Configuration
Using Rsbuild as the build tool:

```typescript
export default defineConfig({
  plugins: [pluginReact(), pluginLess()],
  source: {
    entry: { index: './src/app.tsx' },
    decorators: { version: 'legacy' }  // Enable decorators
  },
  tools: {
    rspack: {
      ignoreWarnings: [/Critical dependency/]  // Ignore specific warnings
    }
  }
});
```

### 3. Internationalization
Built-in multilingual support:

```typescript
i18n: {
  locale: navigator.language,
  languages: {
    'zh-CN': {
      'Never Remind': '不再提示',
      'Hold {{key}} to drag node out': '按住 {{key}} 可以将节点拖出',
    },
    'en-US': {},
  }
}
```

