Documentation Index
Fetch the complete documentation index at: https://mintlify.com/kepano/obsidian-skills/llms.txt
Use this file to discover all available pages before exploring further.
The obsidian-bases skill teaches AI coding assistants to create and edit Obsidian Bases — .base files that provide database-like views over the notes in a vault. A base file is valid YAML that defines which notes to include (via filters), how to compute derived values (via formulas), and how to display results (via one or more views: table, cards, list, or map). Load this skill when the user mentions Bases, table views, card views, filters, or formulas in Obsidian, or when you need to create a .base file from scratch.
Workflow
Create the file
Create a .base file in the vault with valid YAML content.
Define scope
Add filters to select which notes appear — filter by tag, folder, property value, or date.
Add formulas
Optionally define computed properties in the formulas section for arithmetic, conditional logic, string formatting, or date math.
Configure views
Add one or more views (table, cards, list, or map) with an order list specifying which properties to display.
Validate
Verify the file is valid YAML with no syntax errors. Check that all referenced properties and formulas exist. Common issues: unquoted strings containing special YAML characters, mismatched quotes in formula expressions, referencing formula.X without defining X in formulas.
Test in Obsidian
Open the .base file in Obsidian to confirm the view renders correctly. If it shows a YAML error, check the quoting rules in the Troubleshooting section below.
Base File Schema
Base files use the .base extension and contain valid YAML. The top-level keys are filters, formulas, properties, summaries, and views.
# Global filters apply to ALL views in the base
filters:
# Can be a single filter string
# OR a recursive filter object with exactly ONE key: and, or, or not
and:
- 'status == "active"'
- not:
- 'file.hasTag("archived")'
# Define formula properties that can be used across all views
formulas:
formula_name: 'expression'
# Configure display names and settings for properties
properties:
property_name:
displayName: "Display Name"
formula.formula_name:
displayName: "Formula Display Name"
file.ext:
displayName: "Extension"
# Define custom summary formulas
summaries:
custom_summary_name: 'values.mean().round(3)'
# Define one or more views
views:
- type: table | cards | list | map
name: "View Name"
limit: 10 # Optional: limit results
groupBy: # Optional: group results
property: property_name
direction: ASC | DESC
filters: # View-specific filters follow the same rules
and:
- 'status == "active"'
order: # Properties to display in order
- file.name
- property_name
- formula.formula_name
summaries: # Map properties to summary formulas
property_name: Average
See /reference/bases-schema for the complete schema reference.
Filter Syntax
Filters narrow down which notes appear in the base. They can be applied globally (top-level filters) or per-view.
A filter is either a single expression string or a recursive filter object with exactly one key: and, or, or not.
# Single filter
filters: 'status == "done"'
# AND - all conditions must be true
filters:
and:
- 'status == "done"'
- 'priority > 3'
# OR - any condition can be true
filters:
or:
- 'file.hasTag("book")'
- 'file.hasTag("article")'
# NOT - exclude matching items
filters:
not:
- 'file.hasTag("archived")'
# Nested filters
filters:
or:
- file.hasTag("tag")
- and:
- file.hasTag("book")
- file.hasLink("Textbook")
- not:
- file.hasTag("book")
- file.inFolder("Required Reading")
Filter Operators
| Operator | Description |
|---|
== | equals |
!= | not equal |
> | greater than |
< | less than |
>= | greater than or equal |
<= | less than or equal |
&& | logical and |
|| | logical or |
! | logical not |
See /reference/bases-filters for the complete filter reference.
Properties
There are three types of properties that can appear in a base view’s order list.
- Note properties — Values from a note’s frontmatter:
note.author or just author
- File properties — File system metadata:
file.name, file.mtime, etc.
- Formula properties — Computed values defined in
formulas: formula.my_formula
File Properties Reference
| Property | Type | Description |
|---|
file.name | String | File name |
file.basename | String | File name without extension |
file.path | String | Full path to file |
file.folder | String | Parent folder path |
file.ext | String | File extension |
file.size | Number | File size in bytes |
file.ctime | Date | Created time |
file.mtime | Date | Modified time |
file.tags | List | All tags in file |
file.links | List | Internal links in file |
file.backlinks | List | Files linking to this file |
file.embeds | List | Embeds in the note |
file.properties | Object | All frontmatter properties |
The this Keyword
The this keyword refers to a context-dependent file:
- In main content area: refers to the base file itself
- When embedded: refers to the embedding file
- In sidebar: refers to the active file in main content
Formula Syntax
Formulas are defined in the formulas section and compute derived values from note or file properties. Reference them in views as formula.formula_name.
formulas:
# Simple arithmetic
total: "price * quantity"
# Conditional logic
status_icon: 'if(done, "✅", "⏳")'
# String formatting
formatted_price: 'if(price, price.toFixed(2) + " dollars")'
# Date formatting
created: 'file.ctime.format("YYYY-MM-DD")'
# Calculate days since created (use .days for Duration)
days_old: '(now() - file.ctime).days'
# Calculate days until due date
days_until_due: 'if(due_date, (date(due_date) - today()).days, "")'
When subtracting two dates, the result is a Duration type — not a number. Always access a numeric field like .days before applying number functions such as .round().
See /reference/bases-formulas for the complete formula reference.
Key Functions
| Function | Signature | Description |
|---|
date() | date(string): date | Parse string to date (YYYY-MM-DD HH:mm:ss) |
now() | now(): date | Current date and time |
today() | today(): date | Current date (time = 00:00:00) |
if() | if(condition, trueResult, falseResult?) | Conditional |
duration() | duration(string): duration | Parse duration string |
file() | file(path): file | Get file object |
link() | link(path, display?): Link | Create a link |
See /reference/bases-functions for all types: Date, String, Number, List, File, Link, Object, RegExp.
View Types
The table view displays notes in rows with configurable columns. Supports summaries for column-level aggregations and groupBy for row grouping.views:
- type: table
name: "My Table"
order:
- file.name
- status
- due_date
summaries:
price: Sum
count: Average
The cards view displays notes as visual cards, ideal for galleries with cover images.views:
- type: cards
name: "Gallery"
order:
- file.name
- cover_image
- description
The list view displays notes as a simple vertical list with minimal property columns.views:
- type: list
name: "Simple List"
order:
- file.name
- status
The map view plots notes on a geographic map. Requires latitude/longitude properties and the Maps community plugin.views:
- type: map
name: "Locations"
# Map-specific settings for lat/lng properties
Summary Formulas
Summaries aggregate a column’s values into a single result, displayed at the bottom of the column in a table view.
| Name | Input Type | Description |
|---|
Average | Number | Mathematical mean |
Min | Number | Smallest number |
Max | Number | Largest number |
Sum | Number | Sum of all numbers |
Range | Number | Max - Min |
Median | Number | Mathematical median |
Stddev | Number | Standard deviation |
Earliest | Date | Earliest date |
Latest | Date | Latest date |
Range | Date | Latest - Earliest |
Checked | Boolean | Count of true values |
Unchecked | Boolean | Count of false values |
Empty | Any | Count of empty values |
Filled | Any | Count of non-empty values |
Unique | Any | Count of unique values |
Complete Examples
Task Tracker
filters:
and:
- file.hasTag("task")
- 'file.ext == "md"'
formulas:
days_until_due: 'if(due, (date(due) - today()).days, "")'
is_overdue: 'if(due, date(due) < today() && status != "done", false)'
priority_label: 'if(priority == 1, "🔴 High", if(priority == 2, "🟡 Medium", "🟢 Low"))'
properties:
status:
displayName: Status
formula.days_until_due:
displayName: "Days Until Due"
formula.priority_label:
displayName: Priority
views:
- type: table
name: "Active Tasks"
filters:
and:
- 'status != "done"'
order:
- file.name
- status
- formula.priority_label
- due
- formula.days_until_due
groupBy:
property: status
direction: ASC
summaries:
formula.days_until_due: Average
- type: table
name: "Completed"
filters:
and:
- 'status == "done"'
order:
- file.name
- completed_date
Reading List
filters:
or:
- file.hasTag("book")
- file.hasTag("article")
formulas:
reading_time: 'if(pages, (pages * 2).toString() + " min", "")'
status_icon: 'if(status == "reading", "📖", if(status == "done", "✅", "📚"))'
year_read: 'if(finished_date, date(finished_date).year, "")'
properties:
author:
displayName: Author
formula.status_icon:
displayName: ""
formula.reading_time:
displayName: "Est. Time"
views:
- type: cards
name: "Library"
order:
- cover
- file.name
- author
- formula.status_icon
filters:
not:
- 'status == "dropped"'
- type: table
name: "Reading List"
filters:
and:
- 'status == "to-read"'
order:
- file.name
- author
- pages
- formula.reading_time
Daily Notes Index
filters:
and:
- file.inFolder("Daily Notes")
- '/^\d{4}-\d{2}-\d{2}$/.matches(file.basename)'
formulas:
word_estimate: '(file.size / 5).round(0)'
day_of_week: 'date(file.basename).format("dddd")'
properties:
formula.day_of_week:
displayName: "Day"
formula.word_estimate:
displayName: "~Words"
views:
- type: table
name: "Recent Notes"
limit: 30
order:
- file.name
- formula.day_of_week
- formula.word_estimate
- file.mtime
Embedding Bases
A .base file can be embedded inside any Markdown note using the standard embed syntax. You can embed the entire base or target a specific named view.
![[MyBase.base]]
![[MyBase.base#View Name]]
Troubleshooting
Unquoted special characters in YAML: Strings containing :, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, or ` must be quoted.# WRONG - colon in unquoted string
displayName: Status: Active
# CORRECT
displayName: "Status: Active"
Mismatched quotes in formulas: When a formula contains double quotes, wrap the entire formula in single quotes.# WRONG - double quotes inside double quotes
formulas:
label: "if(done, "Yes", "No")"
# CORRECT - single quotes wrapping double quotes
formulas:
label: 'if(done, "Yes", "No")'
Duration math without field access: Subtracting two dates returns a Duration, not a number. Always access .days, .hours, etc. before calling number functions.# WRONG - Duration is not a number
"(now() - file.ctime).round(0)"
# CORRECT - access .days first, then round
"(now() - file.ctime).days.round(0)"
Missing null checks: Properties may not exist on all notes. Use if() to guard against empty values.# WRONG - crashes if due_date is empty
"(date(due_date) - today()).days"
# CORRECT - guard with if()
'if(due_date, (date(due_date) - today()).days, "")'
Referencing undefined formulas: Every formula.X used in order or properties must have a matching entry in the formulas block.# This will fail silently if 'total' is not defined in formulas
order:
- formula.total
# Fix: define it
formulas:
total: "price * quantity"