Obsidian October talks week 3: Use Plugin Settings + Creating theme for Obsidian 1.0
Based on Obsidian's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
Define a typed settings object with sensible defaults so first-run behavior doesn’t depend on existing data.json.
Briefing
Obsidian 1.0’s biggest practical shift for plugin and theme builders is that customization now has a cleaner, more durable interface: plugins can persist user-facing settings through a formal settings tab and disk-backed data.json, while themes can be authored with far fewer brittle CSS selectors thanks to centralized variables and a new theme versioning system.
The stream’s first half walks through adding persistent settings to a plugin using a “spooky plugin” example. The workflow starts by defining a settings type (e.g., a single configurable string like “spooky text”) and providing defaults via a partial default settings object. Those defaults matter because users need sensible behavior on first run, before any saved configuration exists. The plugin then loads settings from the plugin’s data.json using Obsidian’s API: loadData pulls stored JSON into runtime, and the tutorial emphasizes merging it with defaults correctly. A key pitfall is avoiding accidental reference-sharing—updating the default object can unintentionally mutate the defaults themselves—so objectAssign is used to clone defaults first and then overlay saved values.
Once settings are loaded during plugin initialization, the plugin’s command/ribbon action can read from settings (e.g., showing the user-defined text instead of a hardcoded “boo”). The next step is wiring a UI: Obsidian’s PluginSettingTab is extended, and the tab is registered via addSettingTab. Inside the tab’s display method, the code builds HTML into the provided containerEl and uses Obsidian’s Setting API to create labeled controls with descriptions. A text field is bound to the settings value, and on change the plugin updates its in-memory settings and persists them back to disk using saveData. The result is tangible: disable and re-enable the plugin and the customized value reappears, confirming persistence.
The second half shifts from plugin settings to theme development with Kepano, focusing on how Obsidian 1.0 makes theming less selector-heavy and more future-proof. Previously, small UI tweaks often required digging through deeply nested DOM structures and writing narrow CSS selectors. Now, Obsidian exposes a large set of top-level CSS variables (around 400) that let theme authors control major interface elements directly with minimal CSS. That reduces maintenance burden—less code to keep consistent—and helps themes survive internal UI refactors because variable-based overrides don’t depend as tightly on DOM structure.
Theme versioning is the other major change. Themes now use the same versioning approach as plugins, including a minimum Obsidian app version compatibility field. This prevents older themes from being installed on incompatible Obsidian versions and allows the theme manager to serve the right updates over time.
To demonstrate the new approach, the stream starts with a CSS snippet (snippet.css) in the vault’s CSS Snippets folder, using Obsidian’s developer tools to inspect elements and identify the relevant variables. The example modifies inline title sizing and removes checkbox strike-through by overriding checklist done decoration. It then shows how color variables differ by light/dark mode using theme-light and theme-dark selectors, including the option to base a palette on “base colors” for faster theme creation. Finally, it turns the snippet into a full theme by creating a theme folder under .obsidian/themes, adding manifest.json and theme.css, and enabling the theme in Appearance settings. For sharing, themes are submitted via GitHub to Obsidian’s community theme index, with screenshots and repo references.
Together, the stream frames Obsidian 1.0 as a platform where user customization—whether through plugin settings or theme variables—becomes easier to build, easier to maintain, and less likely to break as Obsidian evolves.
Cornell Notes
Obsidian 1.0 streamlines customization by pairing persistent plugin settings with a more maintainable theming system. Plugin settings are defined with typed defaults, loaded from data.json via loadData, merged safely with defaults using objectAssign, and exposed through a registered PluginSettingTab using the Setting API. Changes made in the settings UI are saved back to disk with saveData, so user choices survive restarts. On the theming side, Obsidian 1.0 introduces centralized CSS variables (about 400) that reduce fragile, deeply nested selectors, plus theme versioning with a minimum compatible app version. Snippets can be promoted into full themes using manifest.json and theme.css, then shared through the community theme index on GitHub.
How does a plugin persist user-customizable settings in Obsidian 1.0, and why does default merging matter?
What is the minimal set of steps to expose plugin settings in the Obsidian UI?
Why does the tutorial insist on calling load settings during plugin load rather than only when a command runs?
What changed in Obsidian theming that reduces the need for brittle CSS selectors?
How does theme versioning work in Obsidian 1.0, and what problem does it solve?
How do you turn a CSS snippet into a full theme in Obsidian 1.0?
Review Questions
- When merging defaults with saved settings, what failure mode can happen if the plugin mutates the default settings object directly, and how does objectAssign prevent it?
- In the theming workflow, how do CSS variables and developer tools (inspector) work together to identify what to override without writing deep DOM selectors?
- What does the minimum app version field in a theme’s manifest.json protect users from, and how does it affect theme updates?
Key Points
- 1
Define a typed settings object with sensible defaults so first-run behavior doesn’t depend on existing data.json.
- 2
Load settings from the plugin’s data.json during plugin initialization using loadData, then merge with defaults safely via objectAssign.
- 3
Expose settings through a registered PluginSettingTab and render controls using the Setting API bound to the plugin’s settings state.
- 4
Persist user changes by updating in-memory settings on input change and calling saveData with the updated settings object.
- 5
Use Obsidian 1.0’s centralized CSS variables (around 400) to avoid fragile, deeply nested CSS selectors.
- 6
Adopt theme versioning with a minimum compatible Obsidian app version to prevent incompatible theme installs and enable correct updates.
- 7
Prototype styling in a CSS snippet, then promote it to a full theme using manifest.json and theme.css under .obsidian/themes.