bueckerlars_obsidian-note-m.../docs/destination-templates.md
larsbuecker 54eaac7714 feat: add date components to destination template placeholders
Allow {{property.<key>.<component>}} syntax so folder paths can be built
from date frontmatter (e.g. Archive/{{property.created.year}}) without
separate year/month fields. Supports year, month, day, iso, monthName, and
dayOfWeek with literal-key precedence and timezone-safe ISO parsing.

Closes #98
2026-06-13 21:36:50 +02:00

7.4 KiB
Raw Permalink Blame History

Destination templates

Instead of a fixed folder path, a rule's destination can include placeholders that are filled in from the note's own tags and frontmatter properties at move time. This lets one rule route notes to many different folders based on their content.


Syntax

Placeholders are wrapped in double braces: {{ … }}.

The inner text must start with tag. or property., followed by a key:

{{tag.<key>}}
{{property.<key>}}

Static path segments can appear before, between, or after placeholders:

Clients/{{property.client}}/Notes
Archive/{{property.year}}/{{property.project}}
Areas/{{tag.work}}

Valid examples

Template What it produces
Projects/{{property.client}}/Notes Projects/Acme/Notes (if client: Acme)
Areas/{{tag.work/personal}} Areas/work/personal (if tag #work/personal exists)
Archive/{{property.year}} Archive/2025 (if year: 2025)
Inbox/{{property.status}} Inbox/done (if status: done)

Invalid examples (will fall back to raw string)

Template Problem
Clients/{{property.client Unclosed {{
Clients/{{}} Empty placeholder
Clients/{{property}} Missing key after prefix
Clients/{{category.foo}} Unknown prefix (only tag and property allowed)

{{property.<key>}}

Looks up <key> in the note's frontmatter.

Frontmatter value Resolves to
A string The string as-is
A number or boolean Converted to string
An array Items joined with , (comma + space)
Missing, null, or undefined Empty string

If the placeholder resolves to an empty string, that segment of the path is missing. If the entire destination resolves to empty or whitespace, the note is not moved.


Date property components

For date frontmatter properties, append a component suffix to extract parts of the date at move time:

{{property.<key>.<component>}}

Supported components:

Component Example output (created: 2025-06-13) Notes
year 2025 4-digit year
month 06 Zero-padded month (0112)
day 13 Zero-padded day (0131)
iso 2025-06-13 Normalized ISO date (time ignored)
monthName June English full month name
dayOfWeek friday Lowercase English day name

Examples

Template Frontmatter Resolves to
Archive/{{property.created.year}} created: 2025-06-13 Archive/2025
Journal/{{property.created.year}}/{{property.created.month}} created: 2025-06-13 Journal/2025/06
Days/{{property.created.dayOfWeek}} created: 2025-06-13 Days/friday

Type {{property.<dateProperty>. in the destination field to get component suggestions for date properties discovered in your vault.

Literal property keys take precedence

If a frontmatter key exactly matches the full placeholder path (including the suffix), the raw property value is used instead of date extraction. For example, if you have a property literally named created.year, then {{property.created.year}} resolves to that property's value — not the year from created.

To gate moves on a date property, add a trigger: propertiescreated (date) → has any value.


{{tag.<key>}}

Looks for a tag that matches <key>, adding a # prefix if not present.

Resolution works in two steps:

  1. Exact match: if any tag on the note equals #<key> exactly, the placeholder becomes that tag without the #.
  2. Prefix match: otherwise, find all tags that equal #<key> or start with #<key>/. The longest (most specific) match is used, stripped of #.

If no tag matches, the placeholder becomes an empty string.

Examples:

Note's tags Template Resolves to
#tasks/personal {{tag.tasks}} tasks/personal (prefix match, longest tag)
#work, #work/design {{tag.work}} work/design (longest match)
#inbox {{tag.tasks}} `` (empty — no match)
#project/alpha {{tag.project}} project/alpha

Combining static and dynamic segments

You can freely mix literal segments and placeholders:

Archive/{{property.year}}/{{property.project}}

If year: 2025 and project: Atlas, this resolves to Archive/2025/Atlas.

If year is missing, you get Archive//Atlas — a valid path with an empty segment. To avoid this, add a trigger condition that requires the property to have a value:

  • Trigger: propertiesyear (text) → has any value

This ensures the rule only matches (and only moves) notes where year is set.


Multiple placeholders for nested organization

{{property.year}}/{{property.client}}/{{property.project}}

This creates a three-level hierarchy purely from frontmatter. Notes with matching properties are filed exactly where they belong. Notes with any missing property resolve to a path with empty segments — consider gating the rule with has any value triggers for each property.


When the destination resolves to empty

If a rendered destination is empty or whitespace, the note is not moved. No error is shown; the note is simply skipped. This is intentional — it prevents notes with missing metadata from being dropped at the vault root.


Templates and rule matching

Templates are applied after a rule matches. They do not affect which rule wins — they only compute the final folder path. This means you can have a rule with a broad trigger (e.g. tag includes item #client) and a narrow template (using {{property.client}}). Every note with that tag is caught by the rule; the property value determines exactly where it lands.


See also