From forge-obsidian
Obsidian template management — dual-file creation, editing, rendering, promotion from legacy, frontmatter schemas, dynamic query blocks, Templater config updates. USE WHEN creating templates, editing templates, rendering templates, promoting templates, modifying template schemas, updating Templater folder mappings, adding query blocks, or checking template compliance.
npx claudepluginhub n4m3z/forge-obsidianThis skill uses the workspace's default tool permissions.
Manages the Obsidian template lifecycle: authoring dual-file template pairs, promoting legacy templates from Assets/Templater/ to the Templates/ submodule, maintaining frontmatter schema conventions, and keeping the Templater plugin config in sync.
Creates and edits Obsidian Bases (.base files) with table, card, list, map views, filters, formulas, properties, and summaries. Validates YAML and tests rendering for note database views.
Creates and edits Obsidian Bases (.base files) for database-like note views with global/view filters, formulas, properties, table/card/list/map displays, and summaries.
Creates and edits Obsidian .base files for database-like views of notes using global/view filters, formulas, properties, summaries, and table/card/list/map views.
Share bugs, ideas, or general feedback.
Manages the Obsidian template lifecycle: authoring dual-file template pairs, promoting legacy templates from Assets/Templater/ to the Templates/ submodule, maintaining frontmatter schema conventions, and keeping the Templater plugin config in sync.
| Location | Role | Status |
|---|---|---|
Templates/ | Canonical submodule (obsidian-templates repo) | Source of truth |
Assets/Templater/ | Active legacy (Templater scripts) | Being promoted |
Assets/Templates/ | Deprecated static templates | Archive — do not modify |
Templates/ (submodule root)
Blocks/ Reusable snippets (TODO, FIXME, Key Results)
Daily Notes/ Core Daily Notes plugin templates (no date math)
Journals/ Journals plugin templates (Daily, Weekly, Monthly, etc.)
Legacy/ Archived template versions (v0-v4)
Orchestration/ Agent, Avatar, Collection, Pattern, Skill
Memory/ Idea, Imperative, Insight
PARA/ Area, Project, Resource
Resources/ Flat — zettel type conveyed by tags, not subfolders
Projects/ Event, Key Result, Objective, Quarter
Zettelkasten/ Fleeting, Literature, Permanent, Publishable
Templates may exist in up to three tiers, targeting different Obsidian plugins:
| Tier | File | Plugin | Date math | Dynamic fields |
|---|---|---|---|---|
| Core | Name.md in Daily Notes/ | Core Daily Notes + Templates | {{date:FORMAT}}, {{title}} only | Title, created date |
| Journals | Name.md in category dir | Journals plugin | {{date-1d:FORMAT}} offsets | Title, created, related (prev/next), upstream (parent period) |
| Templater | Name.js.md in category dir | Templater plugin | Full moment.js + tp.file.include() | Everything — computed fields, KR injection, cursor, CSS classes |
Not every template needs all three tiers. The minimum is:
.md — the standard version with date offsets for navigation links.js.md — the full-featured version with JavaScript logicThe Core .md tier is only needed for templates used with the core Daily Notes plugin (no Journals plugin dependency). It lives in a separate Daily Notes/ directory since core Daily Notes points to a single template file.
| Feature | Core Templates | Journals | Templater |
|---|---|---|---|
| Title | {{title}} | {{title}} | <% tp.file.title %> |
| Date | {{date:FORMAT}} | {{date:FORMAT}} | <% tp.date.now("FORMAT") %> |
| Date offsets | Not supported | {{date-1d:FORMAT}}, {{date+1d:FORMAT}} | moment().add() |
| Week number | Not supported | {{date:YYYY-[W]ww}} | moment().format("YYYY-[W]ww") |
| JavaScript | Not supported | Not supported | <%* ... %> blocks |
| Include | Not supported | Not supported | <% tp.file.include("[[...]]") %> |
Body structure (sections, embeds, query blocks) MUST be identical across tiers. Only dynamic field expressions differ. When editing a template, update all existing tiers.
.dv.js.md)A Templater template may have alternative variants for different plugin dependencies. Name them Name.dv.js.md (Dataview variant), Name.js.md (Tasks plugin variant). The Templater config folder mapping points to whichever variant is active.
tp.file.include()Reusable logic blocks live in Templates/Blocks/. Templates include them via:
<% tp.file.include("[[Block Name]]") %>
Templater resolves <%* tR += %> blocks through includes — cascading works. Use this for:
This keeps core templates clean and shareable.
Pitfalls:
tp.file.find_tfile("Name") resolves by basename — fails silently when multiple files share the same name. Use app.vault.getAbstractFileByPath("full/path/to/File.md") for explicit resolution.<% %>: Templater's WASM parser cannot handle => inside <% %> tags (Unexpected token '>'). Use <%* %> execution blocks for multi-line logic instead of <% (async () => { ... })() %>.tp.file.include() preserves leading/trailing whitespace from the included file. Use .trim() on tR += output to prevent extra blank lines in rendered notes.title:
aliases: []
tags: # system/structural only (type/*, note/*)
keywords: # wikilinks for topics/categories
- "[[Topic]]"
description:
icon: # Lucide icon name (LiCalendarFold, LiUser, etc.) — never emoji
image:
cssclasses:
created: # YYYY-MM-DD HH:mm Z (empty in .md, Templater in .js.md)
updated:
related:
- "[[Note]]"
collection: # parent collection wikilink
root: # parent hierarchy wikilink
Primary tag: type/<noun> — what the note IS.
Secondary tag: note/<category> — zettel provenance (optional, for notes in the knowledge pipeline).
type/journal note/daily | note/weekly | note/monthly | note/quarterly | note/yearly
type/contact (no secondary — reference data, not zettel)
type/project (no secondary)
type/book note/literature
type/event (no secondary)
type/collection (no secondary)
type/skill (no secondary)
type/item note/permanent
type/topic note/permanent
type/repository note/literature
type/exercise note/literature
DEPRECATED — do not use in new templates:
file/* (use type/*)schema/*, process/*, project/*, book/* (use frontmatter fields for status/metadata)lang/* (remove — language is obvious from content)journal: Daily | Weekly | Monthly | Quarterly | Yearly
timeframe: YYYY-MM-DD
contact.email:
contact.linkedin:
contact.phone:
contact.website:
location.address:
location.city:
location.country:
location.region:
person.birthday:
person.organization:
person.surname:
source.authors:
-
source.links:
-
source.published:
book.subtitle:
book.publisher:
book.cover:
book.isbn:
book.language:
book.pages:
book.status: unread | reading | read
book.rating: # 1-5 scale
project.status: planned | active | on-hold | completed
project.priority: Critical | High | Medium | Low
project.deadline:
project.objectives:
project.owner:
project.team:
-
See ProjectConventions skill for full project runtime conventions (Base files, embeds, Dataview).
contact.email:
contact.linkedin:
contact.phone:
contact.website:
location.address:
location.city:
location.country:
location.region:
organization.taxid:
place.country:
place.region:
item.authors:
item.owned: 0 | 1
item.price:
item.published:
event.time:
event.participants:
-
metric.current:
metric.objectives:
metric.projects:
metric.start:
metric.target:
metric.timeframe:
metric.unit:
Li*), never emoji.Name.md) — Use {{title}}, {{date:FORMAT}}, {{date-1d:FORMAT}} for dynamic fields. Populate related: with prev/next period, upstream: with parent period.Name.js.md) — Use <% tp.file.title %>, <% tp.date.now() %>, moment.js for computed fields. Use tp.file.include() for reusable blocks. Add <% tp.file.cursor() %> at first user-input point.Daily Notes/) — Use only {{title}}, {{date}}, {{time}}. No date math. Only needed if the template must work without the Journals plugin..md and Templater .js.md in Templates/<Category>/. Core .md in Templates/Daily Notes/.Assets/Templater/. If versioned (e.g., Daily.v0-v4), promote ONLY the latest version. The submodule file has no version suffix.file/* with type/*. Remove lang/*, schema/*, process/*, project/*, book/*. Move status/metadata to frontmatter fields.Blocks/ templates using tp.file.include(). Replace vault-specific embeds with inline placeholder text or document as dependencies.root:, image:, collection:, description: are present..md (static) and .js.md (Templater)..md has a matching .js.md (and vice versa).type/*, note/* convention. No deprecated tags..md and .js.md.icon: values use Lucide names (Li*), not emoji.Z (offset), not z (timezone name).Daily Notes/, Journals .md, Templater .js.md, Dataview variant .dv.js.md).collection: fields) cause YAMLParseError: Map keys must be unique at render time.Templates are rendered by Obsidian, not by Claude. Use the Obsidian CLI (preferred) or Actions URI plugin to trigger rendering.
# Create a note from a template
obsidian create name="New Note" template=Daily
# Create with explicit path
obsidian create name="2026-02-20" template="Journals/Daily.js.md"
Requires Obsidian 1.12+ with Templater trigger_on_file_creation: true for Templater templates to auto-execute. See /ObsidianCLI for full reference.
Deprecated — Use the CLI above when available.
# Actions URI with Templater rendering
open "obsidian://actions-uri/note/create?vault=Personal&file=<target-path>&apply=templater&template-file=<template-path>"
# Actions URI with core Templates rendering
open "obsidian://actions-uri/note/create?vault=Personal&file=<target-path>&apply=templates&template-file=<template-path>"
_Test Render.md)Templates can embed dynamic queries that display task lists, logs, or aggregations. Two query engines are available:
Use query.file.property() to read frontmatter values dynamically. Requires the timeframe field in frontmatter.
> [!tasks]- Tasks due this day
> ```tasks
> not done
> filter by function task.due && task.due.format("YYYY-MM-DD") <= query.file.property('timeframe')
> limit 20
> ```
For topic/collection pages — aggregate tasks that reference the current note:
> [!tasks]- Open Tasks
> ```tasks
> not done
> description includes {{query.file.filenameWithoutExtension}}
> tag does not include #log
> ```
> [!tasks]- Logs
> ```tasks
> description includes {{query.file.filenameWithoutExtension}}
> tag includes #log
> ```
Pros: No Dataview dependency. Clean syntax.
Cons: Full vault scan per query — slow on large vaults without limit. No pagination (only limit, no offset).
Use dv.view() with shared view scripts in Assets/Scripts/Dataview/views/. Dataview uses an in-memory index — faster for cross-vault aggregation.
> [!tasks]- Tasks due this day
> ```dataviewjs
> await dv.view("Scripts/Dataview/views/daily", {flags: 'tasks', container: false});
> ```
For topic pages:
> [!tasks]- Tasks
> ```dataviewjs
> await dv.view("Scripts/Dataview/views/logs");
> await dv.view("Scripts/Dataview/views/tasks");
> ```
Available views: daily (tasks/created/updated/journals), tasks (open/closed by topic), logs (effort by topic), repository (collection listing), plus type-specific views (area, city, contact, country, event, project, weekly, monthly, quarterly, yearly).
Pros: Indexed — fast on large vaults. Graph-aware (outlinks, backlinks). Complex filtering. Cons: Dataview plugin dependency. JavaScript view scripts to maintain.
| Criterion | Tasks plugin | Dataview |
|---|---|---|
| Speed on large vaults | Slow (vault scan) | Fast (indexed) |
| Plugin dependency | Tasks only | Dataview + DataviewJS |
| Dynamic date from frontmatter | query.file.property() | dv.current().file.day |
| Topic aggregation | description includes | outlinks.includes() + text.includes() |
| Pagination | limit only (no offset) | Custom in view scripts |
Use Tasks plugin for simple queries with limit. Use Dataview for heavy aggregation (daily notes, topic pages with many references).
Templater config: .obsidian/plugins/templater-obsidian/data.json
folder_templates — Change paths from Assets/Templater/<path>/<Name>.md to Templates/<Category>/<Name>.js.md. Folder templates MUST point to .js.md files.enabled_templates_hotkeys — Update paths for any hotkey-enabled templates that were promoted.templates_folder — Must remain "Templates" (the submodule root).Plans/ instead of Journals/).