Server side rendering, server side generation
This is an advanced use case and assumes you are already familiar with Svelte Flow. If you’re new to Svelte Flow, check out our getting started guide.
In this guide, you’ll learn how to configure Svelte Flow for server-side rendering, enabling you to:
- Generate static HTML diagrams for documentation
- Render Svelte Flow diagrams in non-JavaScript environments
- Create dynamic Open Graph images for social media sharing
(For client-side image generation, check out our download image example.)
Why Server-Side Rendering is Complex
To understand why server-side rendering in Svelte Flow requires special configuration, let’s look at what Svelte Flow typically handles on the client side:
-
Node Dimension Calculation
- Nodes can contain any content, so their dimensions are determined by the browser’s layout engine
- This dynamic sizing isn’t available during server-side rendering
-
Handle Position Detection
- Edge connections require precise handle positions
- These positions are calculated based on CSS layout, which isn’t available on the server
-
Container Size Adaptation
- Svelte Flow adapts to its container’s dimensions
- Server-side rendering needs explicit dimensions
Node Dimensions
The most crucial aspect of server-side rendering is specifying node dimensions. On the client, Svelte Flow automatically measures nodes and stores dimensions in measured.width and measured.height. For server-side rendering, you must provide these dimensions explicitly using either:
widthandheight: Static dimensions that won’t changeinitialWidthandinitialHeight: Dynamic dimensions that may change after client-side hydration
<script>
const nodes = [
{
id: '1',
type: 'default',
position: { x: 0, y: 0 },
data: { label: 'Node 1' },
width: 100,
height: 50,
},
];
</script>Handle Positions
To render edges on the server, you need to provide handle positions explicitly. On the client, Svelte Flow calculates these positions automatically, but for server-side rendering, you must specify them using the handles property:
<script>
import { Position } from '@xyflow/svelte';
const nodes = [
{
id: '1',
type: 'default',
position: { x: 0, y: 0 },
data: { label: 'Node 1' },
width: 100,
height: 50,
handles: [
{
type: 'target',
position: Position.Top,
x: 100 / 2,
y: 0,
},
{
type: 'source',
position: Position.Bottom,
x: 100 / 2,
y: 50,
},
],
},
];
</script>Using fitView with Server-Side Rendering
If you know your container’s dimensions, you can use fitView during server-side rendering by providing the container’s width and height:
<script>
import { SvelteFlow } from '@xyflow/svelte';
let nodes = $state.raw([/* ... */]);
let edges = $state.raw([/* ... */]);
</script>
<SvelteFlow {nodes} {edges} fitView width={1000} height={500} />Generating Static HTML
To create static HTML output, you can use Svelte’s server-side rendering capabilities. This generates an HTML string that you can use for static files or HTTP responses:
<script>
import { SvelteFlow, Background } from '@xyflow/svelte';
let { nodes, edges, width, height } = $props();
</script>
<SvelteFlow {nodes} {edges} {width} {height} minZoom={0.2} fitView>
<Background />
</SvelteFlow>import { render } from 'svelte/server';
import Flow from './Flow.svelte';
function toHTML({ nodes, edges, width, height }) {
const { body } = render(Flow, {
props: { nodes, edges, width, height },
});
return body;
}