Back to all posts
Building a diagram renderer with Svelte
December 7th, 2025
5 min read
Coding
Frontend
Web
I've been hearing about Svelte for a while now. People keep raving about how elegant it is, how it compiles away the framework overhead, how the DX is just chef's kiss. So naturally, I ignored it for way too long lol. But recently I finally decided to give it a proper go, and what better way to learn than by building something?
Enter Mermaider; a small web app I built to render Mermaid diagrams and export them as PNGs. Nothing groundbreaking tbh but I was tired of fighting with online mermaid renderers trying to squeeze every last dollar out of me, so I decided to just build my own. And it turned out to be a great playground to explore Svelte's patterns and Svelte 5's shiny new reactivity system!
Why Svelte?
Before diving into the code, let me quickly explain why Svelte caught my attention. Unlike React or Vue, Svelte is a compiler. It takes your components and compiles them into highly efficient vanilla JavaScript at build time. No virtual DOM, no runtime framework overhead. Your bundle ships just the code it needs. Which means smaller bundle sizes, faster runtime performance and less boilerplate code.
On top of that, with Svelte 5 they've introduced a completely new reactivity system based on "runes" that makes state management even more intuitive. Let's explore what I learned.
Svelte 5 Runes: The New Reactivity Primitives
The biggest thing I wanted to explore was Svelte 5's runes. If you're coming from React, think of them as Svelte's answer to hooks, but with a much cleaner syntax. Here's how I used them in Mermaider:
$state — Declaring Reactive State
In Svelte 5, you declare reactive state using the $state rune. It's beautifully simple:
That's it. No useState hook, no ref() wrapper, no special syntax for updating. You just... use the variable. When you reassign it, Svelte knows to update the DOM. Coming from React where you need setX(newValue) for everything, this kinda felt too good to be true.
$derived — Computed Values
For values that depend on other state, Svelte 5 gives us $derived. In Mermaider, I used it to compute line numbers for the code editor:
Whenever code changes, Svelte automatically recalculates lineNumbers. No dependency arrays to manage, no useMemo to remember. Svelte figures out the dependencies for you.
$effect — Side Effects Done Right
The $effect rune is for running side effects when reactive values change. I used it to re-render the Mermaid diagram whenever the code changes:
Again, no dependency array needed. Svelte tracks which reactive values are read inside the effect and re-runs it when any of them change. This is a huge DX improvement over React's useEffect where forgetting a dependency is a classic source of bugs.
Bindings: Two-Way Data Flow Made Easy
One of Svelte's killer features is its binding system. In React, you'd typically need to wire up an onChange handler to update state. In Svelte, you just... bind:
bind:value — Form Inputs
That's it. The textarea's value is now synced with the code state variable. Type in the textarea, and code updates. Change code programmatically, and the textarea updates. No boilerplate required.
bind:this — Element References
Sometimes you need a reference to the actual DOM element. Svelte makes this trivial:
Now previewDiv and editorTextarea are references to the actual DOM elements. I used this to manipulate the preview container when rendering diagrams and to restore cursor position after inserting tabs.
Conditional Classes
Svelte has a neat shorthand for conditionally applying classes. In Mermaider, I used it to change the cursor style when dragging:
When isDragging is true, the cursor-grabbing class is added. When it's false, it's removed. No ternary operators, no classnames library needed.
Final Thoughts
Aaand that's it! Building Mermaider was a great way to get hands-on with Svelte 5. I'm really enjoying the DX of the runes system, feels like it takes the best ideas from reactive programming and makes them feel natural and unobtrusive. No more juggling dependency arrays or remembering to wrap things in special functions. Everything just feels natural and intuitive.
If you're curious about Svelte, I'd encourage you to just build something small with it. The learning curve is gentle, and the DX is genuinely incredible. The official tutorial is also excellent if you want a more structured introduction.
Oh, and if you want to check out Mermaider or use it to render your own Mermaid diagrams, here's the repo! It's nothing fancy at all but it does the job and it was a fun learning project.
Happy coding!
— Nathan