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
Recommended Solution: N8N Demo Component¶
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:
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:
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.
Alternative Approach: Iframe Embedding (Not Recommended)¶
For completeness, here's why iframe embedding doesn't work well:
Iframe Approach Issues¶
Attempted Implementation:
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 Production:
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¶
- Simple workflow (1-3 nodes)
- Complex workflow (10+ nodes with multiple connections)
- Workflow with no connections (single node)
- Workflow with error nodes
- Mobile/tablet viewports
Future Enhancements¶
- Interactive Mode: Enable node clicking to show node details
- Export: Add button to export workflow visualization as image
- Zoom Controls: Add zoom in/out controls
- Minimap: Show minimap for large workflows
- Self-Hosted Component: Bundle component locally instead of CDN for offline support
- Theme Sync: Match component theme to Pico CSS theme (light/dark mode)
References¶
- N8N Demo Component Docs: https://n8n-io.github.io/n8n-demo-webcomponent/
- N8N Demo Component NPM: https://www.npmjs.com/package/@n8n_io/n8n-demo-component
- Community Discussion: https://community.n8n.io/t/how-to-embed-a-read-only-workflow-into-a-webpage/27202
- Current Implementation: app/n8nmanager/templates/workflow_detail.html.j2
- Existing N8N Integration Example: app/chat/templates/n8n_chat_embedded.html.j2
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