Skip to content

Haslab-dev/nodeflow-lite

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

6 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

NodeFlow Lite

A lightweight workflow automation engine for Bun inspired by n8n and Node-RED. Build powerful automation workflows with a visual node-based editor and real-time HTML dashboards.

Features

  • πŸš€ Fast & Lightweight - Built on Bun for maximum performance
  • 🎨 Visual Editor - Drag-and-drop workflow builder with React Flow
  • πŸ“‘ Real-time Communication - Built-in MQTT & WebSocket brokers
  • 🌐 HTTP Endpoints - Create REST APIs with HTTP In/Out nodes
  • πŸ€– AI Integration - Connect to OpenAI, DeepSeek, OpenRouter, and more
  • πŸ“Š HTML Dashboards - Serve real-time HTML pages with WebSocket updates
  • ⏰ Interval Triggers - Schedule recurring tasks with dynamic payloads
  • οΏ½ THyperflow DAG - Advanced parallel execution with dependencies
  • πŸ’Ύ Persistent Deployments - Workflows survive server restarts
  • πŸ” Authentication - Built-in user authentication system

Quick Start

# Install dependencies
bun install

# Start the server
bun run dev

# Open in browser
open http://localhost:3000

Node Types

Input Nodes

Node Description
Inject πŸ’‰ Manually trigger a flow with static payload
Interval ⏰ Send messages at regular intervals
HTTP In 🌐 Create REST endpoints
MQTT In πŸ“Ά Subscribe to MQTT topics
WebSocket In πŸ”Œ Subscribe to WebSocket topics

Output Nodes

Node Description
Debug πŸ” Log messages for debugging
HTTP Response πŸ“€ Send HTTP response
MQTT Out πŸ“’ Publish to MQTT topic
WebSocket Out πŸ”Œ Publish to WebSocket topic
HTML Output 🌐 Serve HTML page with real-time data
UI Gauge/Text/Number/Switch πŸ“Š Dashboard widgets

Logic Nodes

Node Description
Function βš™οΈ Run custom JavaScript code
Filter πŸ”€ Route messages by condition
Transform πŸ”„ Modify message properties
Template πŸ“ Generate text from template
Loop πŸ” Iterate over arrays or count
AI Generate πŸ€– Generate text with AI
Hyperflow 🌊 Execute DAG pipelines

Data Nodes

Node Description
HTTP Request πŸ”— Make API calls
Delay ⏱️ Pause flow execution
Split βœ‚οΈ Split array into messages
Join πŸ”— Combine messages into array
Data Table πŸ“Š Create/manipulate data tables

HTML Output Node

Serve dynamic HTML pages with real-time data updates via WebSocket.

Basic Usage

  1. Add an Interval node to generate data
  2. Connect to an HTML Output node
  3. Configure the slug (e.g., demo)
  4. Deploy the workflow
  5. Visit http://localhost:3000/demo/ui

Data Binding

Simple Binding

<!-- Bind text content to a property -->
<div data-bind="value">--</div>

<!-- Nested properties -->
<div data-bind="user.name">--</div>
<div data-bind="sensor.temperature">--</div>

HTML Content Binding

<!-- Render HTML (not escaped) -->
<div data-bind-html="htmlContent"></div>

Style Binding

<!-- Dynamic styles (format: property:path) -->
<div data-bind-style="width:progress">0%</div>
<div data-bind-style="backgroundColor:statusColor"></div>

Custom JavaScript Formatting

Use the htmloutput:update event for complex transformations:

<div id="formatted-temp">--</div>
<div id="status-badge">--</div>

<script>
  window.addEventListener('htmloutput:update', (e) => {
    const data = e.detail;
    
    // Format temperature with unit
    document.getElementById('formatted-temp').textContent = 
      data.temperature.toFixed(1) + 'Β°C';
    
    // Conditional styling
    const badge = document.getElementById('status-badge');
    if (data.value > 80) {
      badge.textContent = '⚠️ HIGH';
      badge.style.color = 'red';
    } else {
      badge.textContent = 'βœ“ Normal';
      badge.style.color = 'green';
    }
    
    // Calculate derived values
    const heatIndex = data.temperature + (data.humidity * 0.1);
    document.getElementById('heat-index').textContent = heatIndex.toFixed(1);
  });
</script>

JavaScript API

// Get current data
const data = HtmlOutput.getData();

// Send data back to workflow (bidirectional)
HtmlOutput.send({ buttonClicked: true, value: 42 });

// Listen for updates
window.addEventListener('htmloutput:update', (e) => {
  console.log('New data:', e.detail);
});

Complete Example

Interval Node Payload:

{
  value: Math.round(Math.random() * 100),
  temperature: 20 + Math.random() * 15,
  humidity: 40 + Math.random() * 40,
  status: Math.random() > 0.5 ? 'online' : 'warning',
  timestamp: Date.now()
}

HTML Template:

<!DOCTYPE html>
<html>
<head>
  <title>Dashboard</title>
  <style>
    body { font-family: system-ui; background: #1a1a2e; color: #fff; padding: 2rem; }
    .card { background: rgba(255,255,255,0.05); border-radius: 12px; padding: 1.5rem; margin: 1rem 0; }
    .value { font-size: 3rem; color: #00d9ff; }
    .label { color: #888; font-size: 0.9rem; }
  </style>
</head>
<body>
  <h1>πŸ“Š Real-time Dashboard</h1>
  
  <!-- Simple data-bind -->
  <div class="card">
    <div class="label">Current Value</div>
    <div class="value" data-bind="value">--</div>
  </div>
  
  <!-- Custom JS formatting -->
  <div class="card">
    <div class="label">Temperature</div>
    <div class="value" id="temp-display">--</div>
  </div>
  
  <!-- Status with conditional styling -->
  <div class="card">
    <div class="label">Status</div>
    <div id="status-display">Waiting...</div>
  </div>
  
  <!-- History chart -->
  <div class="card">
    <div class="label">History</div>
    <div id="chart" style="display:flex;gap:2px;height:60px;align-items:flex-end;"></div>
  </div>

  <script>
    const history = [];
    
    window.addEventListener('htmloutput:update', (e) => {
      const data = e.detail;
      
      // Format temperature
      document.getElementById('temp-display').textContent = 
        data.temperature.toFixed(1) + 'Β°C';
      
      // Status with color
      const status = document.getElementById('status-display');
      status.textContent = data.status === 'online' ? '🟒 Online' : '🟑 Warning';
      
      // Update history chart
      history.push(data.value);
      if (history.length > 20) history.shift();
      
      document.getElementById('chart').innerHTML = history
        .map(v => `<div style="flex:1;background:#00d9ff;height:${v}%;border-radius:2px;"></div>`)
        .join('');
    });
  </script>
</body>
</html>

Interval Node

Send messages at regular intervals with dynamic JavaScript payloads.

Configuration

Field Description
Interval (ms) Time between messages (default: 1000)
Payload JavaScript expression that returns an object
Max Count Stop after N messages (0 = infinite)

Example Payloads

// Random sensor data
{
  value: Math.round(Math.random() * 100),
  temperature: (20 + Math.random() * 15).toFixed(1),
  timestamp: new Date().toISOString()
}

// Counter
{
  count: Date.now() % 1000,
  tick: true
}

// Simulated metrics
{
  cpu: Math.random() * 100,
  memory: 30 + Math.random() * 50,
  requests: Math.floor(Math.random() * 1000)
}

AI Generate Node

Connect to various AI providers using the Vercel AI SDK.

Supported Providers

  • OpenAI Compatible - Any OpenAI-compatible API
  • DeepSeek - DeepSeek AI models
  • OpenRouter - Access multiple models via OpenRouter
  • Zhipu - Zhipu AI (GLM models)

Configuration

  1. Click "Add New AI Config"
  2. Select a preset or enter custom settings
  3. Enter your API key
  4. Select the model

Prompt Templates

Use {{path}} syntax to inject message data:

Summarize this text: {{payload.text}}

User: {{payload.question}}
Context: {{payload.context}}

API Endpoints

Endpoint Method Description
/api/workflow/deploy POST Deploy a workflow
/api/workflow/undeploy POST Undeploy a workflow
/api/workflow/stop POST Stop intervals without undeploy
/api/workflow/deployed GET List deployed workflows
/api/workflow/inject POST Trigger an inject node
/api/status GET Get server status
/api/metrics GET Get execution metrics
/:slug/ui GET Serve HTML output page

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    NodeFlow Server                       β”‚
β”‚                    (Bun + React)                         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚ HTTP In β”‚  β”‚ MQTT    β”‚  β”‚ WS      β”‚  β”‚ Intervalβ”‚    β”‚
β”‚  β”‚ :3001   β”‚  β”‚ :1883   β”‚  β”‚ :1884   β”‚  β”‚ Timer   β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜    β”‚
β”‚       β”‚            β”‚            β”‚            β”‚          β”‚
β”‚       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚
β”‚                         β”‚                                β”‚
β”‚              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”‚
β”‚              β”‚   Workflow Engine   β”‚                    β”‚
β”‚              β”‚   (Node Executor)   β”‚                    β”‚
β”‚              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
β”‚                         β”‚                                β”‚
β”‚       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
β”‚       β”‚                 β”‚                 β”‚             β”‚
β”‚  β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”        β”‚
β”‚  β”‚ Debug   β”‚      β”‚ HTML Out  β”‚     β”‚ MQTT Outβ”‚        β”‚
β”‚  β”‚ Logs    β”‚      β”‚ /slug/ui  β”‚     β”‚ Publish β”‚        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Development

# Run in development mode
bun run dev

# Run tests
bun test

# Type check
bun run lint

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors