Skip to content

N8N Workflow Visualization Embedding Guide

Date: 2025-11-11 Author: Claude Status: Ready for Implementation

Executive Summary

This report provides a comprehensive guide for adding a nicer, N8N-like workflow visualization display to the workflow detail page (/n8nmanager/workflows/{workflow_id}/detail). Instead of using iframes (which have CORS issues), we'll use the official N8N web component @n8n_io/n8n-demo-component which provides read-only workflow previews.

Current Implementation

The workflow detail page at app/n8nmanager/templates/workflow_detail.html.j2 currently uses:

  • ReactFlow library (v11.10.4) with custom node rendering
  • Custom JavaScript to convert N8N nodes/connections to ReactFlow format
  • Lines 100-258: Workflow diagram section with inline React/ReactFlow initialization

Limitations: - Custom implementation requires maintenance - Less feature-rich than official N8N visualization - Doesn't match N8N's native look and feel - Requires keeping React/ReactFlow versions in sync

Overview

The @n8n_io/n8n-demo-component is an official web component specifically designed for embedding read-only workflow visualizations.

Key Benefits: - Official N8N component - always up-to-date with N8N workflow format - Native N8N look and feel - Simple HTML-based integration - No CORS issues (pure client-side rendering) - Supports theming and customization - Lightweight and maintained by N8N team

Technical Details

Package: @n8n_io/n8n-demo-component Type: LitElement Web Component Distribution: npm, CDN (unpkg, jsdelivr) Documentation: https://n8n-io.github.io/n8n-demo-webcomponent/

CDN URLs:

<!-- Web Components Polyfill -->
<script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2.0.0/webcomponents-loader.js"></script>

<!-- Lit Polyfill -->
<script src="https://www.unpkg.com/lit@2.0.0-rc.2/polyfill-support.js"></script>

<!-- N8N Demo Component -->
<script type="module" src="https://cdn.jsdelivr.net/npm/@n8n_io/n8n-demo-component/n8n-demo.bundled.js"></script>

Basic Usage:

<n8n-demo
    workflow='{"nodes":[...],"connections":{...}}'
    frame="true">
</n8n-demo>

Component Properties: - workflow - JSON string of workflow definition (nodes + connections) - frame - Boolean, adds a frame/border around the visualization - interactive - Boolean, enables/disables interaction (default: true for demos, false for read-only) - Theme customization via CSS variables

Implementation Plan

Step 1: Replace ReactFlow with N8N Demo Component

Location: app/n8nmanager/templates/workflow_detail.html.j2:86-258

Current Section:

<!-- Workflow Diagram -->
<article>
    <header>...</header>
    {% if workflow.nodes and workflow.connections %}
    <!-- ReactFlow CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reactflow@11.10.4/dist/style.css">

    <div id="workflow-diagram" style="width: 100%; height: 500px; background: #f8f9fa;"></div>

    <script>
        // 150+ lines of custom ReactFlow initialization
    </script>
    {% endif %}
</article>

New Implementation:

<!-- Workflow Diagram -->
<article>
    <header style="display: flex; justify-content: space-between; align-items: center;">
        <h3>
            <i data-feather="git-branch"></i> Workflow Diagram
        </h3>
        {% if config.N8N_API_URL %}
        {% set n8n_base_url = config.N8N_API_URL.replace('/api/v1', '').rstrip('/') %}
        <a href="{{ n8n_base_url }}/workflow/{{ workflow.id }}"
           target="_blank"
           role="button"
           class="outline"
           style="font-size: 0.8rem; padding: 0.3rem 0.8rem;">
            <i data-feather="external-link"></i> Open in N8N
        </a>
        {% endif %}
    </header>

    {% if workflow.nodes and workflow.connections %}
        <!-- Load N8N Demo Component -->
        <script src="https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs@2.0.0/webcomponents-loader.js"></script>
        <script src="https://www.unpkg.com/lit@2.0.0-rc.2/polyfill-support.js"></script>
        <script type="module" src="https://cdn.jsdelivr.net/npm/@n8n_io/n8n-demo-component/n8n-demo.bundled.js"></script>

        <!-- N8N Workflow Visualization -->
        <div style="width: 100%; min-height: 500px; background: #f8f9fa; border-radius: 8px; overflow: hidden;">
            <n8n-demo
                id="workflow-demo"
                frame="true">
            </n8n-demo>
        </div>

        <script>
            // Wait for component to load
            customElements.whenDefined('n8n-demo').then(() => {
                const demoElement = document.getElementById('workflow-demo');

                // Set workflow data as property (not attribute - more reliable for large JSON)
                const workflowData = {{ workflow_dict | tojson }};
                demoElement.workflow = workflowData;

                console.log('N8N workflow visualization loaded:', '{{ workflow.name }}');
            }).catch(error => {
                console.error('Failed to load N8N demo component:', error);
            });
        </script>

        <style>
            /* Optional: Theme customization for N8N component */
            n8n-demo {
                --n8n-font-family: var(--pico-font-family);
                --n8n-node-color-default: #f0f0f0;
                --n8n-node-color-highlight: var(--pico-primary);
            }
        </style>
    {% else %}
    <p style="color: var(--pico-muted-color); text-align: center; padding: 2rem;">
        No workflow diagram data available.
    </p>
    {% endif %}
</article>

Step 2: Benefits of This Approach

Advantages: 1. No CORS Issues - Pure client-side rendering, no cross-origin requests 2. Official Component - Maintained by N8N, always compatible with latest N8N workflow format 3. Simpler Code - ~150 lines of custom React code → ~20 lines of HTML 4. Better UX - Native N8N look and feel that users recognize 5. Maintainability - No need to track ReactFlow version updates 6. Performance - Optimized for workflow rendering by N8N team

Considerations: 1. The component uses web components (well-supported in modern browsers) 2. Requires internet connection for CDN resources (can be self-hosted if needed) 3. Less customization than full ReactFlow, but sufficient for read-only display

CORS Configuration Analysis

Current CORS Status

FastAPI Application: - Location: app/main.py - No CORSMiddleware configured - App does not have CORS middleware enabled - This is appropriate for this use case since we're not making cross-origin API calls

N8N CORS: - N8N's CORS settings are not relevant for this implementation - The @n8n_io/n8n-demo-component is a client-side web component - It renders workflows using JavaScript, no API calls to N8N server

CORS Configuration Per Environment

1. Local Development (./start.sh)

Status: ✅ No CORS configuration needed

Reason: - N8N demo component loads via CDN (same-origin for browser) - Workflow data passed from server-side template rendering - No cross-origin requests between slidefactory and N8N

Configuration:

# No changes needed to start.sh or local development setup
./start.sh  # Works as-is

2. Docker Setup (docker-compose.yml)

Status: ✅ No CORS configuration needed

Current Setup: - N8N service: docker-compose.override.yml:44-80 - Slidefactory web service: docker-compose.override.yml:8-18

N8N Settings (Existing):

n8n:
  environment:
    - N8N_BASIC_AUTH_ACTIVE=true
    - N8N_BASIC_AUTH_USER=admin
    - N8N_BASIC_AUTH_PASSWORD=admin
    - N8N_HOST=localhost
    - N8N_PORT=5678
    - N8N_PROTOCOL=http
    - WEBHOOK_URL=http://localhost:5678/

Why No CORS Needed: - Web component loads from CDN - Workflow JSON passed from Slidefactory backend (already has N8N API access) - No direct browser → N8N communication

If Direct N8N Embedding Was Needed (For Reference):

# NOT NEEDED for @n8n_io/n8n-demo-component
# Only if using iframes or direct N8N API calls from browser
n8n:
  environment:
    - N8N_ALLOWED_ORIGINS=http://localhost:8000,http://localhost:5678

3. Azure Deployment

Status: ✅ No CORS configuration needed

Deployment: .github/workflows/preview.yml:68-109

Current Setup: - Slidefactory deployed as Azure Container App - N8N hosted separately (via N8N_API_URL secret) - Environment variables include N8N_API_KEY and N8N_API_URL

Why No CORS Needed: - Web component loads from public CDN (no CORS issues) - Slidefactory backend fetches workflow data from N8N API (server-to-server, no CORS) - Browser only receives rendered HTML with embedded workflow JSON - No client-side API calls to N8N

If Azure N8N Needed CORS (For Reference):

# NOT NEEDED for current implementation
# Only if N8N API was called directly from browser
N8N_ALLOWED_ORIGINS: "https://slidefactory-web-preview.azurecontainerapps.io,https://slidefactory-web-production.azurecontainerapps.io"

Summary: No CORS Changes Required

Environment CORS Needed? Reason
Local (./start.sh) ❌ No Client-side component, server-side data
Docker (docker-compose up) ❌ No Client-side component, server-side data
Azure (Container Apps) ❌ No Client-side component, server-side data

Key Insight: The architecture uses server-side workflow data fetching (Slidefactory → N8N API) followed by client-side visualization (web component). This eliminates CORS concerns entirely.

For completeness, here's why iframe embedding doesn't work well:

Iframe Approach Issues

Attempted Implementation:

<iframe
    src="https://n8n.example.com/workflow/123/view"
    width="100%"
    height="600px">
</iframe>

Problems: 1. CORS/X-Frame-Options: N8N blocks iframe embedding by default 2. Authentication: Iframe requires user to be logged into N8N 3. Read-Only Not Supported: N8N doesn't have a dedicated read-only view URL 4. Customization Limited: Can't style or theme iframe content 5. CORS Configuration Complexity: Would need to configure: - N8N: N8N_ALLOWED_ORIGINS environment variable - N8N: Modify X-Frame-Options headers - Different settings per environment (local/docker/azure)

Required CORS Changes (If Using Iframes):

Local Development:

# docker-compose.override.yml
n8n:
  environment:
    - N8N_ALLOWED_ORIGINS=http://localhost:8000

Docker Production:

# docker-compose.yml
n8n:
  environment:
    - N8N_ALLOWED_ORIGINS=${SLIDEFACTORY_URL}

Azure:

# GitHub Actions workflow
--set-env-vars N8N_ALLOWED_ORIGINS="https://slidefactory-web-preview.azurecontainerapps.io"

Verdict: Iframe approach requires extensive CORS configuration, authentication complexity, and provides worse UX than the web component approach.

Existing CORS Reference

The project already has experience with CORS-free N8N embedding:

Example: app/chat/templates/n8n_chat_embedded.html.j2

This template successfully embeds N8N chat using: - N8N's official @n8n/chat component (similar to @n8n_io/n8n-demo-component) - Client-side JavaScript initialization - No CORS configuration required - Proxy URL for webhook calls (lines 360-362)

Key Pattern (Line 355-362):

import { createChat } from 'https://cdn.jsdelivr.net/npm/@n8n/chat/dist/chat.bundle.es.js';

const chat = createChat({
    // Proxy URL (same-origin, no CORS issues)
    webhookUrl: '{{ chat_proxy_url }}',
    target: '#n8n-chat',
    mode: 'fullscreen'
});

Lesson: N8N's official components are designed to work without CORS configuration when using proper integration patterns.

Implementation Checklist

  • Remove ReactFlow dependencies from workflow_detail.html.j2 (lines 100-258)
  • Add N8N demo component CDN scripts
  • Add <n8n-demo> element with workflow data
  • Test local development (./start.sh)
  • Test Docker environment (docker-compose up)
  • Test workflow visualization with various workflow types
  • Verify mobile responsiveness
  • Optional: Add custom theme variables
  • Document any limitations discovered
  • Consider adding fallback message for browsers without web component support

Testing Plan

Local Development

./start.sh
# Navigate to: http://localhost:8000/n8nmanager/workflows/{workflow_id}/detail
# Verify: Workflow visualization loads and displays correctly

Docker

docker-compose up -d
# Navigate to: http://localhost:8000/n8nmanager/workflows/{workflow_id}/detail
# Verify: Same as local development

Azure Preview

# Trigger deployment via git push to preview branch
# Navigate to: https://slidefactory-web-preview.azurecontainerapps.io/n8nmanager/workflows/{workflow_id}/detail
# Verify: Same as local development

Test Cases

  1. Simple workflow (1-3 nodes)
  2. Complex workflow (10+ nodes with multiple connections)
  3. Workflow with no connections (single node)
  4. Workflow with error nodes
  5. Mobile/tablet viewports

Future Enhancements

  1. Interactive Mode: Enable node clicking to show node details
  2. Export: Add button to export workflow visualization as image
  3. Zoom Controls: Add zoom in/out controls
  4. Minimap: Show minimap for large workflows
  5. Self-Hosted Component: Bundle component locally instead of CDN for offline support
  6. Theme Sync: Match component theme to Pico CSS theme (light/dark mode)

References

Conclusion

Recommendation: Implement the N8N demo component approach

Advantages: - ✅ Zero CORS configuration required (all environments) - ✅ Official N8N component with native look and feel - ✅ Simpler code (~80% reduction in custom JavaScript) - ✅ Better maintainability (N8N team maintains compatibility) - ✅ Proven pattern (already used for chat embedding) - ✅ Works immediately in local/docker/azure without changes

Estimated Implementation Time: 1-2 hours

Risk Level: Low (well-documented component, no infrastructure changes needed)

Next Steps: 1. Review this report with team 2. Test N8N demo component in local environment 3. Implement changes to workflow_detail.html.j2 4. Test across all three environments 5. Deploy to preview for user feedback