SVG development
Nue offers a focused development environment for developing SVG graphics. A programmatic alternative to design tools, for creating static and interactive visuals that integrate with your design system.
Setting up
By default, SVG files are served directly without processing. Enable SVG processing at the directory level with app.yaml
:
# In visuals/app.yaml
svg:
process: true
This tells Nue to process SVG files in the visuals/
directory as templates rather than serving them as static assets.
Dynamic SVG markup
Mix SVG elements with HTML and Nue's template syntax:
<!-- table.svg -->
<svg width="500" height="400">
<!-- SVG elements -->
<circle r="100" class="primary"/>
<!-- Mixed HTML content -->
<html>
<table>
<tr :each="user in users">
<td>{ user.name }</td>
<td>{ user.email }</td>
</tr>
</table>
</html>
</svg>
Dynamic syntax - Use the full HTML syntax reference: loops, conditionals, expressions, and data binding.
Data cascade - Variables come from the same sources as HTML templates: parent YAML files, @shared/data/
, and front matter.
HTML embedding - The <html>
tag becomes a <foreignObject>
automatically, letting you embed rich HTML content inside SVG graphics.
Generated output
The above template generates clean, standalone SVG:
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 500 400"
width="500" height="400">
<circle r="100" class="primary"/>
<foreignObject x="0" y="0" width="100%" height="100%">
<table xmlns="http://www.w3.org/1999/xhtml">
<tr><td>Alice Johnson</td><td>alice@example.com</td></tr>
<tr><td>Bob Smith</td><td>bob@example.com</td></tr>
</table>
</foreignObject>
</svg>
Automatic namespaces - SVG and HTML namespaces are added automatically if missing.
Auto viewBox - When not specified, viewBox matches the width/height attributes.
foreignObject wrapper - HTML content gets wrapped with proper positioning and sizing.
Styling and fonts
Embed your design system directly into SVG output for consistent, self-contained graphics.
Design system integration
Include your CSS design system in SVG output:
<!--
@include [base, graphics]
-->
<svg>
<circle class="accent"/>
<rect class="primary-bg"/>
<html>
<div class="card">
<h3>Design system styles work here</h3>
</div>
</html>
</svg>
Your CSS design system styles both SVG elements and HTML content:
/* In @shared/design/graphics.css */
.accent {
fill: var(--accent-color);
stroke: var(--border-color);
}
.primary-bg {
fill: var(--primary-color);
}
.card {
background: var(--surface-color);
border-radius: var(--radius);
}
Explicit inclusion - Unlike HTML pages, SVG processing starts with no styles. Use @include
to add what you need.
Style embedding - CSS gets embedded as <style>
blocks with proper CDATA sections for SVG compatibility.
Font embedding
Configure fonts at the directory level:
# In visuals/app.yaml
svg:
fonts:
Inter: /design/inter.woff2
Mono: /design/mono.woff2
Or customize per file with HTML comments:
<!--
@fonts [Inter, Mono]
-->
<svg>
<text font-family="Inter">Embedded font text</text>
</svg>
Default behavior - All configured fonts are embedded by default.
Per-file control - Use @fonts false
to disable embedding, or @fonts [Inter]
to include specific fonts only.
Hot reloading
View SVG files with live updates during development:
http://localhost:4000/visuals/table.svg?hmr
The ?hmr
parameter generates an HTML wrapper that enables hot reloading:
CSS changes - Styling updates instantly
SVG changes - Graphics update without refresh
Data changes - Template re-renders with new data
Production output
Without the ?hmr
parameter, you get clean, standalone SVG that works anywhere:
<!-- Production SVG output -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 400">
<style><![CDATA[
/* embedded design system styles */
circle { fill: var(--brand-color); }
.card { background: var(--surface-color); }
]]></style>
<!-- embedded font definitions -->
<!-- your dynamic content -->
</svg>
Interactive visuals
For graphics that need user interaction, create SVG components instead of processed files.
Component definition
Define interactive SVG in library files:
<!-- In ui/graphics.html -->
<svg :is="interactive-chart" width="500" height="300">
<rect :each="bar in data"
:onclick="selectBar(bar)"
class="bar { bar.selected ? 'selected' : '' }"
width="{ bar.width }"
height="{ bar.height }"/>
<script>
selectBar(bar) {
this.data.forEach(b => b.selected = false)
bar.selected = true
this.update()
}
</script>
</svg>
Style with your design system:
/* In @shared/design/graphics.css */
.bar {
fill: var(--muted-color);
transition: fill 0.2s;
&.selected {
fill: var(--primary-color);
}
&:hover {
fill: var(--accent-color);
}
}
Usage in content
Use interactive components in Nuemark content:
Here's our quarterly performance:
[]
data:
- width: 100
height: 200
label: Q1
- width: 120
height: 180
label: Q2
Or in HTML templates:
<main>
<h1>Dashboard</h1>
<interactive-chart :data="salesData"/>
</main>
Use cases
Static graphics
Perfect for generating charts, diagrams, and infographics that scale perfectly and integrate with your design system:
<!-- org-chart.svg -->
<svg width="800" height="600">
<html>
<div class="org-chart">
<div :each="person in team" class="person-card">
<h3>{ person.name }</h3>
<p>{ person.role }</p>
</div>
</div>
</html>
</svg>
Dynamic visualizations
Create data-driven graphics that update based on your content:
<!-- progress-chart.svg -->
<svg width="400" height="200">
<rect :each="project in projects"
class="progress-bar { project.status }"
width="{ project.completion * 300 }"
height="30"
y="{ $index * 40 }"/>
</svg>
Style with CSS:
.progress-bar {
fill: var(--muted-color);
&.completed {
fill: var(--success-color);
}
&.in-progress {
fill: var(--warning-color);
}
}
Design system assets
Generate consistent icons and graphics that match your brand:
<!-- icon-set.svg -->
<svg width="100" height="100">
<circle class="icon-bg"/>
<path class="icon-fg" d="..."/>
</svg>
The same design tokens that style your HTML also style your graphics, ensuring complete visual consistency across your entire application.