A keyboard-first reactive variable, declarative rule engine, and structural formatting system for Obsidian.
Define custom text wrappers, inline color styles, font families, declarative commands, CSS variables, and structural layouts directly inside your notes using a simple, readable syntax. Copy styled content to external apps and protect LaTeX from formatting collisions — all from a single :::vars block.
[!WARNING] This plugin is currently in Beta and there may be bugs. If you encounter any issues, please report them on the GitHub Issues page.
(text) red, "text" blue, or ^text^ into a bold header by defining a simple rule.hh text hh or ft1 text ft1 for styling. Tokens are spaced from the content to avoid false matches with normal words._&text&_).##colors and ##text to stack color and text styling simultaneously.:::vars block gets a clickable swatch. Click to open the system color picker and update values inline.header_size = 24 or text_ft1_font = Inter become standard CSS variables (--header_size: 24px, --text_ft1_font: 'Inter', sans-serif) on the document container.##text##text
ft1 = Inter
codefont = JetBrains Mono
text_quote_font = Merriweather
ft1 text in Inter ft1.font = <family> (e.g., font = Arial or font = "Space Grotesk") under ##text to apply that font across the active note's editing canvas (.cm-content) and reading view (.markdown-rendered).monospace for mono/code fonts, serif for serif families, and sans-serif otherwise).##commands rule engineif line 0 "(" + number + ")" then rd
if line 0 word then rd
Applies the target style (rd) strictly to the matched word/token at index 0 ((1), (2), etc.).if line ">" then ft_quote
if line 0 ">" then ft_quote
if line word then ft_quote
Applies the target style (e.g., ft_quote font) across the entire line whenever the condition is matched.if rd then ft1
Whenever text is styled with rd (red), font ft1 (Inter) is chained and applied as well.+:number: \d+word: \S+alpha: [a-zA-Z]+heading / #: #{1,6}- / bullet: [-*+]">" / quote: >"..." or '...' (e.g., "(", ")")- and + list markers are intercepted and replaced with aesthetic bullet characters (•, ◦, ▸, ▹, ⁃, ·) per indent level.![[...]] or ) are preserved without list bullet modifications.# on a color line inside a :::vars block triggers a floating swatch palette with 9 preset colors and a custom color picker button.:::vars blocks and copies clean text.Ctrl+C / Cmd+C) preserves formatting across applications:text/plain: Clean, variable-stripped markdown.text/html: Compiled HTML with inline CSS (<span style="...">) so styles survive when pasting into external editors like Google Docs, Word, or web apps.:::vars blocks automatically inherit and override these defaults.$...$ and $$...$$) are protected from formatting collisions with LaTeX underscores, carets, or braces.view.visibleRanges for zero input latency even in massive documents.:::vars blockPlace a :::vars block anywhere in your note (usually at the top):
:::vars
##colors
rd = #ef4444
bl = #3b82f6
##text
header_size = 28
text_ft1_font = Inter
ft_quote = Merriweather
##commands
if rd then ft1
if line 0 "(" + number + ")" then rd
if line ">" then ft_quote
:::
Sections are defined by ## headers:
| Section | Purpose |
|---|---|
##colors (or ##colour, ##colours) |
Color definitions. Keys are wrapper tokens, values are hex codes or color names. |
##text |
Text sizes, typography, font family variables, and style aliases. |
##commands |
Declarative formatting directives (if ... then ...). |
Assign hex codes or built-in abbreviations under ##colors:
##colors
() = #ef4444
"" = #3b82f6
rd = #FF0000
gn = #00FF00
bl = #0000FF
Supported shortcuts:
hp / black → #000000wt / white → #FFFFFFrd / red → #FF0000gn / green → #00FF00bl / blue → #0000FFyl / yellow → #FFFF00mg / magenta → #FF00FFcy / cyan → #00FFFFor / orange → #FFA500pl / purple → #800080pr / pink → #FFC0CBtl / teal → #008080br / brown → #A52A2ADefine font families and sizes under ##text:
##text
# Note-wide canvas font
font = Arial
# Font variables
ft1 = Inter
text_code_font = JetBrains Mono
ft_quote = Merriweather
# Size variables
header_size = 28
text_title_size = 32
# Style aliases
^^ = header
__ = bold
Use in text:
ft1 This text will render in Inter ft1
^^This will render as a large header^^
Automate styling with declarative rules under ##commands:
##commands
# Style first word matching pattern (1), (2), etc. in red
if line 0 "(" + number + ")" then rd
# Style the first word of any line in red
if line 0 word then rd
# Style entire blockquote lines in Merriweather font
if line ">" then ft_quote
# Style chaining: wherever rd is applied, also apply ft1 font
if rd then ft1
main.js, manifest.json, and styles.css from the Latest Release.VaultFolder/.obsidian/plugins/concrete/.main.js, manifest.json, and styles.css into that folder.git clone https://github.com/apokaliptics/concrete-extension.git
cd concrete-extension
npm install
npm run dev # Watch mode
npm run build # Production bundle
npm run lint # ESLint verification
MIT © apokaliptics