Hi community!
For a long time, n8n didn’t have any frontend features for third-party users. This has changed over the last months with the Form Trigger and Chat Trigger nodes. Also, a dedicated HTML node is available, but more on that later.
Let’s discuss how to deliver frontend pages to users in a more universal way.
This topic is a bit in-depth, but I promise you’ll see some nice screenshots from the ongoing projects
Why frontend for external users?
n8n excels at automations, especially when connecting multiple “backend” services (databases, code execution, under-the-hood logic).
However, there are 3 specific cases when users need custom HTML pages:
- To present complex data
- To manipulate data with visuals/charts
- To input data back into systems (i.e. human-in-the-loop for AI tasks)
When connecting purely backend services, there’s no built-in way to deliver custom HTML. And developing a standalone user-facing app is often overkill.
Here’s how I deliver interactive HTML pages with n8n
Already published:
-
- Serves pure XML + XSLT template
- Browser handles all rendering
- Uses native browser XML templating (W3C standard)
-
Workflow visualizer dashboard
- HTML page with Mermaid.js integration
- JSON data delivery
- AJAX for individual chart requests
UPD: already published
Work in progress:
3. n8n workflow auto documentation with Docsify
- Integrates docsify.js within HTML pages
- Serves markdown text segments
- Supports auto-generated documentation
- Allows for live documentation editing with markdown preview
Main page features all workflows with links to docs
New workflow documentation starts from a template + a Mermaid chart
New doc pages are generated automatically
Work in progress:
4. If the previous example wasn’t exciting enough, here’s another use-case. Take a no-code database, NocoDB is a cool project. They recently introduced a Button column; it can make HTTP Requests. And guess what? You can call n8n webhooks that serve HTML pages with some elements from the database. I’ve built an editor (powered by Konva.js) that connects with FLUX.1 inpainting API. Here’s how it works
select data and press the button
Work on one of the image from this DB record
Edited images are uploaded back to the DB automatically
This enables both seamless image editing and further automated inpainting: combine single image mask with multiple prompts and get multiple variations of the same product.
Cool? Yeah, but here’s a catch
I’ve tried these approaches and found several limitations:
- Writing and debugging code is challenging
- Serving complete HTML pages with a single node is cumbersome
- Poor separation of HTML content and CSS styling
- Adding dynamic data is complicated
Is there a universal way for delivering interactive content?
I’m not sure. Maybe I’m not going in the right direction at all.
The easiest template for page delivery I know looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Some Cool Lib Demo</title>
<!-- CSS for some-cool-lib -->
<link rel="stylesheet" href="https://cdn.example.com/some-cool-lib/v1.0/some-cool-lib.css">
<!-- JavaScript for some-cool-lib -->
<script src="https://cdn.example.com/some-cool-lib/v1.0/some-cool-lib.js"></script>
</head>
<body>
<div id="cool-lib-container">
<script>
const coolLibConfig = {
settings: {
theme: "{{ $json.theme }}",
language: "{{ $json.language }}",
},
data: {
items: {{ $json.items }},
maxResults: {{ $json.maxResults }},
filters: {
category: "{{ $json.filterCategory }}",
dateRange: {
start: "{{ $json.startDate }}",
end: "{{ $json.endDate }}"
}
}
}
};
// Initialize some-cool-lib with config
SomeCoolLib.init('#cool-lib-container', coolLibConfig);
</script>
</div>
</body>
</html>
You can basically abstract all functionality behind a JS file and serve a simple HTML page with some {{JS expessions}}
to put the data.
What do you think? How would you tackle this? Let’s discuss!
Also, feel free to connect with me on LinkedIn.