This commit is contained in:
2026-11-04 20:35:46 +01:00
parent 5f4de5e60c
commit 86abc097f4
348 changed files with 10300 additions and 0 deletions
@@ -0,0 +1,9 @@
{
"files": {
"README.md": "d2019dea2880c57b792e54cd1c72ff4e",
"apply.sh": "eb7d60658e8fa4543c6aef0c6e04dd46",
"obsidian.css": "954948473c66774481e1571a3554d1aa",
"template.toml": "036ac6fef7ee94e7699ae12579ec7fff"
},
"version": 1
}
@@ -0,0 +1,46 @@
# Obsidian — Noctalia Community Template
Applies noctalia's generated color palette to [Obsidian](https://obsidian.md) as a CSS snippet.
Both dark and light mode variants are generated, and Obsidian will use whichever matches its
current appearance setting.
## How it works
This template renders a CSS snippet (`noctalia.css`) into each discovered Obsidian vault's
`snippets/` directory. The snippet overrides Obsidian's CSS custom properties to match
noctalia's active palette — backgrounds, text, accents, headings, links, tags, graph view,
and more.
The apply script automatically enables the snippet in each vault's `appearance.json`.
## Vault discovery
The apply script searches `$HOME` (up to 4 directories deep) for `.obsidian/` folders.
If your vault lives deeper or on an external drive, you can add a user template override
in your noctalia config with an explicit `output_path`:
```toml
[theme.templates.user.obsidian_extra]
input_path = "obsidian/obsidian.css"
output_path = "/mnt/data/MyVault/.obsidian/snippets/noctalia.css"
```
## Requirements
- Obsidian (any recent version with CSS snippet support)
- `python3` (for enabling the snippet in `appearance.json`)
## Setup
1. Enable **Obsidian** in **Noctalia Settings -> Templates**.
2. In Obsidian, open **Settings → Appearance** and set **Base color scheme** to **Adapt to system**, so the
dark or light variant follows Noctalia's mode.
3. Check that the `noctalia` snippet is on under **Settings → Appearance → CSS Snippets**.
## Notes
- The snippet layers on top of any installed Obsidian theme — it overrides color
variables without removing your base theme.
- Obsidian hot-reloads CSS snippets from disk on most platforms. If colors don't
update after a wallpaper change, toggle the snippet off/on in
Settings → Appearance → CSS Snippets.
@@ -0,0 +1,59 @@
#!/usr/bin/bash
set -euo pipefail
# Discover Obsidian vaults by finding .obsidian directories.
# Creates the snippets/ folder if it doesn't exist and enables the snippet
# in each vault's appearance.json.
snippet_name="noctalia"
find_vaults() {
# Search common locations for Obsidian vaults (up to 4 levels deep)
local search_dirs=("$HOME")
for dir in "${search_dirs[@]}"; do
find "$dir" -maxdepth 4 -name ".obsidian" -type d 2>/dev/null || true
done | sort -u
}
case "${1:-}" in
output)
# Called by noctalia to determine output paths.
# Print one path per line for each discovered vault.
find_vaults | while read -r obsidian_dir; do
snippets_dir="$obsidian_dir/snippets"
mkdir -p "$snippets_dir"
echo "$snippets_dir/$snippet_name.css"
done
;;
apply)
# Called after rendering. Enable the snippet in each vault's appearance.json.
find_vaults | while read -r obsidian_dir; do
appearance_file="$obsidian_dir/appearance.json"
if [ ! -f "$appearance_file" ]; then
printf '{\n "enabledCssSnippets": ["%s"]\n}\n' "$snippet_name" > "$appearance_file"
continue
fi
# Add noctalia to enabledCssSnippets if not already present
python3 -c "
import json, sys
with open('$appearance_file') as f:
data = json.load(f)
snippets = data.get('enabledCssSnippets', [])
if '$snippet_name' not in snippets:
snippets.append('$snippet_name')
data['enabledCssSnippets'] = snippets
with open('$appearance_file', 'w') as f:
json.dump(data, f, indent=2)
f.write('\n')
" 2>/dev/null || true
done
;;
*)
echo "Usage: $0 {output|apply}" >&2
exit 1
;;
esac
@@ -0,0 +1,297 @@
/* Obsidian theme snippet generated by noctalia */
.theme-dark {
/* Background layers */
--background-primary: {{colors.surface.default.hex}};
--background-primary-alt: {{colors.surface_container_low.default.hex}};
--background-secondary: {{colors.surface_container.default.hex}};
--background-secondary-alt: {{colors.surface_container_high.default.hex}};
--background-modifier-border: {{colors.outline_variant.default.hex}};
--background-modifier-form-field: {{colors.surface_container_lowest.default.hex}};
--background-modifier-form-field-highlighted: {{colors.surface_container_low.default.hex}};
--background-modifier-box-shadow: {{colors.shadow.default.hex}};
--background-modifier-success: {{colors.primary.default.rgba | set_alpha 0.15}};
--background-modifier-error: {{colors.error.default.rgba | set_alpha 0.15}};
--background-modifier-error-rgb: {{colors.error.default.rgb_csv}};
--background-modifier-error-hover: {{colors.error.default.rgba | set_alpha 0.25}};
--background-modifier-cover: {{colors.shadow.default.rgba | set_alpha 0.6}};
/* Text colors */
--text-normal: {{colors.on_surface.default.hex}};
--text-muted: {{colors.on_surface_variant.default.hex}};
--text-faint: {{colors.outline.default.hex}};
--text-on-accent: {{colors.on_primary.default.hex}};
--text-on-accent-inverted: {{colors.primary.default.hex}};
--text-error: {{colors.error.default.hex}};
--text-success: {{colors.primary.default.hex}};
--text-selection: {{colors.primary.default.rgba | set_alpha 0.2}};
--text-accent: {{colors.primary.default.hex}};
--text-highlight-bg: {{colors.tertiary.default.rgba | set_alpha 0.25}};
/* Interactive accent */
--interactive-normal: {{colors.surface_container.default.hex}};
--interactive-hover: {{colors.surface_container_high.default.hex}};
--interactive-accent: {{colors.primary.default.hex}};
--interactive-accent-hover: {{colors.primary.default.hex | lighten 1}};
--interactive-accent-rgb: {{colors.primary.default.rgb_csv}};
--interactive-success: {{colors.primary.default.hex}};
/* Scrollbar */
--scrollbar-bg: {{colors.surface.default.hex}};
--scrollbar-thumb-bg: {{colors.outline_variant.default.rgba | set_alpha 0.3}};
--scrollbar-active-thumb-bg: {{colors.outline.default.rgba | set_alpha 0.5}};
/* Tab styling */
--tab-text-color: {{colors.on_surface_variant.default.hex}};
--tab-text-color-focused: {{colors.on_surface.default.hex}};
--tab-text-color-focused-active: {{colors.primary.default.hex}};
--tab-background-active: {{colors.surface.default.hex}};
--tab-divider-color: {{colors.outline_variant.default.hex}};
/* Navigation */
--nav-item-color: {{colors.on_surface_variant.default.hex}};
--nav-item-color-hover: {{colors.on_surface.default.hex}};
--nav-item-color-active: {{colors.on_primary.default.hex}};
--nav-item-background-hover: {{colors.surface_container_high.default.hex}};
--nav-item-background-active: {{colors.primary.default.rgba | set_alpha 0.12}};
--nav-collapse-icon-color: {{colors.outline.default.hex}};
/* Titlebar */
--titlebar-background: {{colors.surface_container.default.hex}};
--titlebar-background-focused: {{colors.surface_container.default.hex}};
--titlebar-text-color: {{colors.on_surface.default.hex}};
--titlebar-text-color-focused: {{colors.on_surface.default.hex}};
/* Tags */
--tag-color: {{colors.secondary.default.hex}};
--tag-background: {{colors.secondary.default.rgba | set_alpha 0.12}};
--tag-color-hover: {{colors.secondary.default.hex | lighten 1}};
--tag-background-hover: {{colors.secondary.default.rgba | set_alpha 0.2}};
/* Headings */
--h1-color: {{colors.primary.default.hex}};
--h2-color: {{colors.primary.default.hex | darken 1}};
--h3-color: {{colors.secondary.default.hex}};
--h4-color: {{colors.secondary.default.hex | darken 1}};
--h5-color: {{colors.tertiary.default.hex}};
--h6-color: {{colors.tertiary.default.hex | darken 1}};
/* Links */
--link-color: {{colors.primary.default.hex}};
--link-color-hover: {{colors.primary.default.hex | lighten 1}};
--link-decoration-color: {{colors.primary.default.rgba | set_alpha 0.4}};
--link-external-color: {{colors.tertiary.default.hex}};
--link-external-color-hover: {{colors.tertiary.default.hex | lighten 1}};
--link-unresolved-color: {{colors.error.default.rgba | set_alpha 0.7}};
/* Code */
--code-normal: {{colors.secondary.default.hex}};
--code-background: {{colors.surface_container_highest.default.hex}};
--code-comment: {{colors.outline.default.hex}};
/* Blockquotes */
--blockquote-border-color: {{colors.primary.default.rgba | set_alpha 0.5}};
/* Checkbox */
--checkbox-color: {{colors.primary.default.hex}};
--checkbox-color-hover: {{colors.primary.default.hex | lighten 1}};
--checkbox-border-color: {{colors.outline.default.hex}};
/* Graph view */
--graph-line: {{colors.outline_variant.default.rgba | set_alpha 0.4}};
--graph-node: {{colors.primary.default.hex}};
--graph-node-focused: {{colors.tertiary.default.hex}};
--graph-node-tag: {{colors.secondary.default.hex}};
--graph-node-attachment: {{colors.tertiary.default.hex}};
/* Vault name */
--vault-name-color: {{colors.on_surface.default.hex}};
/* Indentation guide */
--indentation-guide-color: {{colors.outline_variant.default.rgba | set_alpha 0.3}};
--indentation-guide-color-active: {{colors.outline_variant.default.rgba | set_alpha 0.6}};
/* Obsidian 1.0+ variables */
--color-accent: {{colors.primary.default.hex}};
--color-accent-1: {{colors.primary.default.rgba | set_alpha 0.12}};
--color-accent-2: {{colors.primary.default.rgba | set_alpha 0.25}};
/* Icon colors */
--icon-color: {{colors.on_surface_variant.default.hex}};
--icon-color-hover: {{colors.on_surface.default.hex}};
--icon-color-active: {{colors.primary.default.hex}};
--icon-color-focused: {{colors.primary.default.hex}};
/* Divider */
--divider-color: {{colors.outline_variant.default.hex}};
--divider-color-hover: {{colors.outline.default.hex}};
/* Status bar */
--status-bar-background: {{colors.surface_container.default.hex}};
--status-bar-text-color: {{colors.on_surface_variant.default.hex}};
/* Modal */
--modal-background: {{colors.surface_container.default.hex}};
--modal-border-color: {{colors.outline_variant.default.hex}};
/* Prompt / suggestion */
--prompt-border-color: {{colors.outline_variant.default.hex}};
/* Inline title */
--inline-title-color: {{colors.on_surface.default.hex}};
/* Bold / italic */
--bold-color: {{colors.on_surface.default.hex}};
--italic-color: {{colors.on_surface.default.hex}};
/* List markers */
--list-marker-color: {{colors.primary.default.rgba | set_alpha 0.7}};
}
.theme-light {
/* Background layers */
--background-primary: {{colors.surface.light.hex}};
--background-primary-alt: {{colors.surface_container_low.light.hex}};
--background-secondary: {{colors.surface_container.light.hex}};
--background-secondary-alt: {{colors.surface_container_high.light.hex}};
--background-modifier-border: {{colors.outline_variant.light.hex}};
--background-modifier-form-field: {{colors.surface_container_lowest.light.hex}};
--background-modifier-form-field-highlighted: {{colors.surface_container_low.light.hex}};
--background-modifier-box-shadow: {{colors.shadow.light.hex}};
--background-modifier-success: {{colors.primary.light.rgba | set_alpha 0.1}};
--background-modifier-error: {{colors.error.light.rgba | set_alpha 0.1}};
--background-modifier-error-rgb: {{colors.error.light.rgb_csv}};
--background-modifier-error-hover: {{colors.error.light.rgba | set_alpha 0.2}};
--background-modifier-cover: {{colors.shadow.light.rgba | set_alpha 0.4}};
/* Text colors */
--text-normal: {{colors.on_surface.light.hex}};
--text-muted: {{colors.on_surface_variant.light.hex}};
--text-faint: {{colors.outline.light.hex}};
--text-on-accent: {{colors.on_primary.light.hex}};
--text-on-accent-inverted: {{colors.primary.light.hex}};
--text-error: {{colors.error.light.hex}};
--text-success: {{colors.primary.light.hex}};
--text-selection: {{colors.primary.light.rgba | set_alpha 0.15}};
--text-accent: {{colors.primary.light.hex}};
--text-highlight-bg: {{colors.tertiary.light.rgba | set_alpha 0.2}};
/* Interactive accent */
--interactive-normal: {{colors.surface_container.light.hex}};
--interactive-hover: {{colors.surface_container_high.light.hex}};
--interactive-accent: {{colors.primary.light.hex}};
--interactive-accent-hover: {{colors.primary.light.hex | darken 1}};
--interactive-accent-rgb: {{colors.primary.light.rgb_csv}};
--interactive-success: {{colors.primary.light.hex}};
/* Scrollbar */
--scrollbar-bg: {{colors.surface.light.hex}};
--scrollbar-thumb-bg: {{colors.outline_variant.light.rgba | set_alpha 0.3}};
--scrollbar-active-thumb-bg: {{colors.outline.light.rgba | set_alpha 0.5}};
/* Tab styling */
--tab-text-color: {{colors.on_surface_variant.light.hex}};
--tab-text-color-focused: {{colors.on_surface.light.hex}};
--tab-text-color-focused-active: {{colors.primary.light.hex}};
--tab-background-active: {{colors.surface.light.hex}};
--tab-divider-color: {{colors.outline_variant.light.hex}};
/* Navigation */
--nav-item-color: {{colors.on_surface_variant.light.hex}};
--nav-item-color-hover: {{colors.on_surface.light.hex}};
--nav-item-color-active: {{colors.on_primary.light.hex}};
--nav-item-background-hover: {{colors.surface_container_high.light.hex}};
--nav-item-background-active: {{colors.primary.light.rgba | set_alpha 0.1}};
--nav-collapse-icon-color: {{colors.outline.light.hex}};
/* Titlebar */
--titlebar-background: {{colors.surface_container.light.hex}};
--titlebar-background-focused: {{colors.surface_container.light.hex}};
--titlebar-text-color: {{colors.on_surface.light.hex}};
--titlebar-text-color-focused: {{colors.on_surface.light.hex}};
/* Tags */
--tag-color: {{colors.secondary.light.hex}};
--tag-background: {{colors.secondary.light.rgba | set_alpha 0.1}};
--tag-color-hover: {{colors.secondary.light.hex | darken 1}};
--tag-background-hover: {{colors.secondary.light.rgba | set_alpha 0.18}};
/* Headings */
--h1-color: {{colors.primary.light.hex}};
--h2-color: {{colors.primary.light.hex | lighten 1}};
--h3-color: {{colors.secondary.light.hex}};
--h4-color: {{colors.secondary.light.hex | lighten 1}};
--h5-color: {{colors.tertiary.light.hex}};
--h6-color: {{colors.tertiary.light.hex | lighten 1}};
/* Links */
--link-color: {{colors.primary.light.hex}};
--link-color-hover: {{colors.primary.light.hex | darken 1}};
--link-decoration-color: {{colors.primary.light.rgba | set_alpha 0.4}};
--link-external-color: {{colors.tertiary.light.hex}};
--link-external-color-hover: {{colors.tertiary.light.hex | darken 1}};
--link-unresolved-color: {{colors.error.light.rgba | set_alpha 0.7}};
/* Code */
--code-normal: {{colors.secondary.light.hex}};
--code-background: {{colors.surface_container_highest.light.hex}};
--code-comment: {{colors.outline.light.hex}};
/* Blockquotes */
--blockquote-border-color: {{colors.primary.light.rgba | set_alpha 0.5}};
/* Checkbox */
--checkbox-color: {{colors.primary.light.hex}};
--checkbox-color-hover: {{colors.primary.light.hex | darken 1}};
--checkbox-border-color: {{colors.outline.light.hex}};
/* Graph view */
--graph-line: {{colors.outline_variant.light.rgba | set_alpha 0.4}};
--graph-node: {{colors.primary.light.hex}};
--graph-node-focused: {{colors.tertiary.light.hex}};
--graph-node-tag: {{colors.secondary.light.hex}};
--graph-node-attachment: {{colors.tertiary.light.hex}};
/* Vault name */
--vault-name-color: {{colors.on_surface.light.hex}};
/* Indentation guide */
--indentation-guide-color: {{colors.outline_variant.light.rgba | set_alpha 0.3}};
--indentation-guide-color-active: {{colors.outline_variant.light.rgba | set_alpha 0.6}};
/* Obsidian 1.0+ variables */
--color-accent: {{colors.primary.light.hex}};
--color-accent-1: {{colors.primary.light.rgba | set_alpha 0.1}};
--color-accent-2: {{colors.primary.light.rgba | set_alpha 0.2}};
/* Icon colors */
--icon-color: {{colors.on_surface_variant.light.hex}};
--icon-color-hover: {{colors.on_surface.light.hex}};
--icon-color-active: {{colors.primary.light.hex}};
--icon-color-focused: {{colors.primary.light.hex}};
/* Divider */
--divider-color: {{colors.outline_variant.light.hex}};
--divider-color-hover: {{colors.outline.light.hex}};
/* Status bar */
--status-bar-background: {{colors.surface_container.light.hex}};
--status-bar-text-color: {{colors.on_surface_variant.light.hex}};
/* Modal */
--modal-background: {{colors.surface_container.light.hex}};
--modal-border-color: {{colors.outline_variant.light.hex}};
/* Prompt / suggestion */
--prompt-border-color: {{colors.outline_variant.light.hex}};
/* Inline title */
--inline-title-color: {{colors.on_surface.light.hex}};
/* Bold / italic */
--bold-color: {{colors.on_surface.light.hex}};
--italic-color: {{colors.on_surface.light.hex}};
/* List markers */
--list-marker-color: {{colors.primary.light.rgba | set_alpha 0.7}};
}
@@ -0,0 +1,8 @@
[catalog.obsidian]
name = "Obsidian"
category = "editor"
[templates.obsidian]
input_path = "obsidian.css"
output_path_dynamic = "bash '{{ config_dir }}/apply.sh' output"
post_hook = "bash '{{ config_dir }}/apply.sh' apply"