Easy and fast UI development with Svelte
Based on Obsidian's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
Svelte’s compiled reactivity updates only the DOM elements that depend on changed variables, avoiding manual render logic.
Briefing
Svelte is presented as a practical way to build Obsidian plugin UIs with far less boilerplate than imperative DOM manipulation—by writing mostly HTML templates plus small bits of TypeScript, then letting Svelte compile the updates automatically. The core payoff is reactivity without manual render logic: when a variable used in the template changes, Svelte updates only the necessary parts of the DOM. That approach matters for plugin authors because UIs often need to track fast-changing state (timers, charts, dynamic lists) and imperative updates quickly become cumbersome.
The walkthrough starts by contrasting Svelte with React and Vue. React/Vue rely on a rendering engine that checks state changes and reconciles what should update, while Svelte “surgically” updates the HTML it needs and ships only the JavaScript required for the component—avoiding a heavy runtime footprint. In the Obsidian context, that translates to lighter plugins and a simpler mental model for UI updates.
A demo component is then recreated inside a Svelte file (e.g., a “Svelte demo view” component). Instead of calling Obsidian APIs to create headers, paragraphs, buttons, and styling imperatively, the component is written as a template: standard HTML elements with optional styling. The Obsidian view class becomes simpler too—its job is mainly to mount the Svelte component onto a content element. The result is a UI that can be edited directly in the template file, making the rendered output easier to reason about.
Interactivity is added next with a counter button. A TypeScript script block defines a `counter` variable and an `increment` function. The template binds the button label to `{counter}` and triggers `increment` on click. The “magic” is framed as compilation: Svelte analyzes which variables the template uses and automatically re-renders the affected text when `counter` changes, without explicit render calls.
To show how components can be reused and configured, the demo introduces exported props (like `title`). The exported value can be set from the Obsidian view when mounting the component. For more flexibility, the tutorial shifts from prop-based text to composition using nested content via slots—so the parent can pass arbitrary markup (not just a string) into a child component.
Finally, the session tackles global state with Svelte stores. Instead of threading props through deeply nested components, a `writable` store holds the vault’s file list. The plugin populates the store on load using `this.app.vault.getFiles()` and keeps it in sync by registering Obsidian vault events for create, delete, and rename. In the Svelte template, an `{#each}` block iterates over the reactive store (using the `$` store syntax) to render a live-updating `<ul>` of filenames. Creating, deleting, or renaming notes in Obsidian immediately updates the list, demonstrating how Svelte stores and compiled reactivity reduce both complexity and glue code.
Cornell Notes
Svelte is positioned as a lightweight, compiled UI approach for Obsidian plugins: write HTML-like templates plus TypeScript, and let Svelte update the DOM automatically when used variables change. The tutorial demonstrates replacing imperative element creation with a Svelte component mounted into an Obsidian view, then adding interactivity via a `counter` variable and click handler. It shows how to pass data into components using exported props and how to make components more reusable with slots for arbitrary nested markup. For cross-component state, it uses Svelte stores: a `writable` store holds the vault’s file list, updated on load and on Obsidian vault events (create/delete/rename). An `{#each}` block renders the store reactively, producing a live list without manual refresh logic.
Why does Svelte feel simpler than React or Vue for plugin UI work?
How does the tutorial replace imperative DOM creation in an Obsidian view?
What makes the counter button update automatically without manual re-render code?
How can a component be configured from outside—without hardcoding text?
When should slots be used instead of string props?
How does a Svelte store solve the “prop drilling” problem in nested plugin UIs?
Review Questions
- In the counter example, what specific template dependency causes Svelte to update the button label after each click?
- What’s the difference between passing data via exported props and passing content via slots, and when would each be preferable?
- How do Obsidian vault events (create/delete/rename) connect to Svelte stores to keep a rendered list synchronized?
Key Points
- 1
Svelte’s compiled reactivity updates only the DOM elements that depend on changed variables, avoiding manual render logic.
- 2
Obsidian view code can be simplified by mounting a Svelte component onto a content element instead of imperatively creating many HTML nodes.
- 3
Interactivity is added by declaring TypeScript variables and functions in a `<script lang=