Skip to Content
LearnAdvanced UseServer Side Rendering

Server side rendering, server side generation

This is an advanced use case and assumes you are already familiar with Vue Flow. If you’re new to Vue Flow, check out our getting started guide.

In this guide, you’ll learn how to configure Vue Flow for server-side rendering, enabling you to:

  • Generate static HTML diagrams for documentation
  • Render Vue Flow diagrams in non-JavaScript environments
  • Create dynamic Open Graph images for social media sharing

Why Server-Side Rendering is Complex

To understand why server-side rendering in Vue Flow requires special configuration, let’s look at what Vue Flow typically handles on the client side:

  1. 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
  2. Handle Position Detection

    • Edge connections require precise handle positions
    • These positions are calculated based on CSS layout, which isn’t available on the server
  3. Container Size Adaptation

    • Vue Flow adapts to its container’s dimensions
    • Server-side rendering needs an explicit viewport

Node Dimensions

The most crucial aspect of server-side rendering is specifying node dimensions. On the client, Vue 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:

Node Dimension Options:
  1. width and height: Static dimensions that won’t change
  2. initialWidth and initialHeight: Dynamic dimensions that may change after client-side hydration
import type { Node } from '@xyflow/vue'; const nodes: Node[] = [ { id: '1', type: 'default', position: { x: 0, y: 0 }, data: { label: 'Node 1' }, width: 100, height: 50, }, ];

Handle Positions

To render edges on the server, you need to provide handle positions explicitly. On the client, Vue Flow calculates these positions automatically, but for server-side rendering, you must specify them using the handles property:

import type { Node } from '@xyflow/vue'; import { Position } from '@xyflow/vue'; const nodes: Node[] = [ { 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, }, ], }, ];

Setting the viewport for Server-Side Rendering

Unlike React Flow and Svelte Flow, Vue Flow’s <VueFlow /> component doesn’t expose width and height props, and fitView relies on measuring the rendered container, which isn’t available on the server. For server-side rendering, give the wrapping element fixed dimensions and set an explicit initial transform with the defaultViewport prop. You can still pass fitView so the flow re-fits on the client once it is measured after hydration:

<script setup lang="ts"> import { VueFlow } from '@xyflow/vue'; const defaultViewport = { x: 0, y: 0, zoom: 1 }; </script> <template> <div style="width: 1000px; height: 500px"> <VueFlow :nodes="nodes" :edges="edges" :default-viewport="defaultViewport" :min-zoom="0.2" fit-view /> </div> </template>

Generating Static HTML

To create static HTML output, you can use Vue’s server renderer. This generates an HTML string that you can use for static files or HTTP responses:

Flow.vue
<script setup lang="ts"> import type { Edge, Node } from '@xyflow/vue'; import { Background, VueFlow } from '@xyflow/vue'; defineProps<{ nodes: Node[]; edges: Edge[] }>(); </script> <template> <div style="width: 1000px; height: 500px"> <VueFlow :nodes="nodes" :edges="edges" :min-zoom="0.2" fit-view> <Background /> </VueFlow> </div> </template>
import { createSSRApp } from 'vue'; import { renderToString } from 'vue/server-renderer'; import Flow from './Flow.vue'; async function toHTML({ nodes, edges }) { const app = createSSRApp(Flow, { nodes, edges }); return await renderToString(app); }
Last updated on