Create and edit Obsidian Bases with views, filters, formulas

Obsidian Bases Skill

by obsidianmd · MIT license · ★ 52,291 on GitHub

Obsidian Bases Skill cover

Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries. Use when working with .base files, creating database-like views of notes, or when the user mentions Bases, table views, card views, kanban…

---
name: obsidian-bases
description: Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries. Use when working with .base files, creating database-like views of notes, or when the user mentions Bases, table views, card views, kanban boards, filters, or formulas in Obsidian.
---

# Obsidian Bases Skill

## Workflow

1. **Create the file**: Create a `.base` file in the vault with valid YAML content
2. **Define scope**: Add `filters` to select which notes appear (by tag, folder, property, or date)
3. **Add formulas** (optional): Define computed properties in the `formulas` section
4. **Configure views**: Add one or more views (`table`, `cards`, `list`, `map`, or `kanban`) with `order` specifying which properties to display
5. **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`
6. **Test in Obsidian**: Open the `.base` file in Obsidian to confirm the view renders correctly. If it shows a YAML error, check quoting rules below. If it doesn't open as a base at all, check that Bases is turned on in Settings → Core plugins

## Schema

Overview

Filters narrow down results. They can be applied globally or per-view.

Manual install (npx, ZIP)
Claude Codenpx skills add obsidianmd/obsidian-skills --skill obsidian-bases -g -a claude-code
Claude Code (degit)npx degit obsidianmd/obsidian-skills/plugins/obsidian/skills/obsidian-bases#main ~/.claude/skills/obsidian-bases
Claude.ai / desktopZip the folder and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md16.7 KB
Read SKILL.md here
obsidianmd/main1 file shown
SKILL.md
Show the full text602 lines

Obsidian Bases Skill

Workflow

  1. Create the file: Create a .base file in the vault with valid YAML content
  2. Define scope: Add filters to select which notes appear (by tag, folder, property, or date)
  3. Add formulas (optional): Define computed properties in the formulas section
  4. Configure views: Add one or more views (table, cards, list, map, or kanban) with order specifying which properties to display
  5. 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
  6. Test in Obsidian: Open the .base file in Obsidian to confirm the view renders correctly. If it shows a YAML error, check quoting rules below. If it doesn't open as a base at all, check that Bases is turned on in Settings → Core plugins

Schema

Base files use the .base extension and contain valid YAML.

# 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.
# Note properties need the `note.` prefix here, or the setting is ignored.
properties:
  note.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 | kanban
    name: "View Name"
    limit: 10                    # Optional: limit results
    groupBy:                     # Optional: group results
      property: property_name
      direction: ASC | DESC
    groupOrder:                  # Optional: only these groups, in this order
      - value_one
      - null                     # Files with no value for the groupBy property
    sort:                        # Optional: sort results (supports multiple properties)
      - 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

Filter Syntax

Filters narrow down results. They can be applied globally or per-view.

Filter Structure
# 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

Properties

Three Types of Properties
  1. Note properties - From frontmatter: note.author or just author
  2. File properties - File metadata: file.name, file.mtime, etc.
  3. Formula properties - Computed values: formula.my_formula

In order, filters, groupBy, and sort, a note property can be written bare (author) or prefixed (note.author). In the top-level properties: section, always write note.author, because Obsidian ignores a bare key there and shows the raw name as the column header.

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. Slow in large vaults and doesn't refresh when the vault changes; prefer reversing the lookup with file.links
file.embeds List Embeds in the note
file.properties Object All frontmatter properties. Doesn't refresh when the vault changes
file.file File File object, only usable in specific functions
The this Keyword
  • 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 compute values from properties. Defined in the formulas section.

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, "")'

Key Functions

Most commonly used functions. For the complete reference of all types (Date, String, Number, List, File, Link, Object, RegExp), see FUNCTIONS_REFERENCE.md.

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
Duration Type

When subtracting two dates, the result is a Duration type (not a number).

Duration Fields: duration.days, duration.hours, duration.minutes, duration.seconds, duration.milliseconds

IMPORTANT: Duration does NOT support .round(), .floor(), .ceil() directly. Access a numeric field first (like .days), then apply number functions.

# CORRECT: Calculate days between dates
"(date(due_date) - today()).days"                    # Returns number of days
"(now() - file.ctime).days"                          # Days since created
"(date(due_date) - today()).days.round(0)"           # Rounded days

# WRONG - will cause error:
# "((date(due) - today()) / 86400000).round(0)"      # Duration doesn't support division then round
Date Arithmetic
# Duration units: y/year/years, M/month/months, d/day/days,
#                 w/week/weeks, h/hour/hours, m/minute/minutes, s/second/seconds
"now() + \"1 day\""       # Tomorrow
"today() + \"7d\""        # A week from today
"now() - file.ctime"      # Returns Duration
"(now() - file.ctime).days"  # Get days as number

View Types

Table View
views:
  - type: table
    name: "My Table"
    order:
      - file.name
      - status
      - due_date
    summaries:
      price: Sum
      count: Average
Cards View
views:
  - type: cards
    name: "Gallery"
    order:
      - file.name
      - cover_image
      - description
List View
views:
  - type: list
    name: "Simple List"
    order:
      - file.name
      - status
Kanban View

Requires Obsidian 1.14+. Cards are grouped into columns by the groupBy property, which a kanban view needs. groupOrder sets which columns show and in what order; use null to include files with no value. Without groupOrder, every value gets a column. Dragging a card to another column updates that property in the note. Only Markdown notes can be moved, except when grouping by file.folder, where moving a card moves the file to that folder. When grouping by a formula or by a file property other than file.folder, cards and columns can't be moved and notes can't be created from a column.

views:
  - type: kanban
    name: "Projects"
    groupBy:
      property: note.status
      direction: ASC
    groupOrder:
      - Planned
      - In progress
      - Done
    order:
      - file.name
      - due_date
Map View

Requires latitude/longitude properties and the Maps community plugin.

views:
  - type: map
    name: "Locations"
    # Map-specific settings for lat/lng properties

Sorting

Sort results by one or more properties. Each sort entry specifies a property and direction, which must be uppercase ASC or DESC; an entry with any other value, or a sort written as a string, is silently ignored. Multiple sort entries are applied in order — the first entry is the primary sort key, subsequent entries break ties.

views:
  - type: table
    name: "Sorted Tasks"
    sort:
      - property: due
        direction: ASC
      - property: file.name
        direction: ASC
    order:
      - file.name
      - due
      - status

Sort options depend on the property type:

Property Type ASC DESC
Text A→Z Z→A
Number 0→9 9→0
Date Old→New New→Old

You can sort by any property including formulas (formula.my_formula), file properties (file.mtime), and note properties.

Default Summary Formulas

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 Base
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:
  note.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
    sort:
      - property: due
        direction: ASC
      - property: file.name
        direction: ASC
    summaries:
      formula.days_until_due: Average

  - type: table
    name: "Completed"
    filters:
      and:
        - 'status == "done"'
    order:
      - file.name
      - completed_date
Reading List Base
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:
  note.author:
    displayName: Author
  formula.status_icon:
    displayName: "Status"
  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

Embed a .base file

Embed an external .base file in any Markdown note:

![[MyBase.base]]

<!-- Specific view -->
![[MyBase.base#View Name]]
Embed inline with a code block

Bases can also be embedded inline directly inside a note using a base fenced code block. This is useful for note-level filters (e.g. using this.file.links) and avoids creating a separate .base file:

```base
filters:
  and:
    - file.hasTag("example")
views:
  - type: table
    name: Table
    order:
      - file.name
      - status
```

When embedded inline this way, the this keyword refers to the containing note, so you can build per-note views such as showing all notes linked from the current file.

YAML Quoting Rules

  • Use single quotes for formulas containing double quotes: 'if(done, "Yes", "No")'
  • Use double quotes for simple strings: "My View Name"
  • Escape nested quotes properly in complex expressions

Troubleshooting

YAML Syntax Errors

Unquoted special characters: Strings containing :, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, %, @, `, ! 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")'
Common Formula Errors

Duration math without field access: Subtracting dates returns a Duration, not a number. Always access .days, .hours, etc.

# 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.

# WRONG - crashes if due_date is empty
"(date(due_date) - today()).days"

# CORRECT - guard with if()
'if(due_date, (date(due_date) - today()).days, "")'

displayName ignored, column shows the raw name: prefix note properties with note. in the properties: section.

# WRONG - displayName ignored, column header shows "status"
properties:
  status:
    displayName: Status

# CORRECT - column header shows "Status"
properties:
  note.status:
    displayName: Status

Empty displayName doesn't hide a header: displayName: "" falls back to the property name, the same as leaving it out, so formula.status_icon shows status_icon. Use a non-empty name such as displayName: "Status".

Referencing undefined formulas: Ensure every formula.X in order or properties has a matching entry in formulas.

# This will fail silently if 'total' is not defined in formulas
order:
  - formula.total

# Fix: define it
formulas:
  total: "price * quantity"

References

1---
2name: obsidian-bases
3description: Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries. Use when working with .base files, creating database-like views of notes, or when the user mentions Bases, table views, card views, kanban boards, filters, or formulas in Obsidian.
4---
5 
6# Obsidian Bases Skill
7 
8## Workflow
9 
101. **Create the file**: Create a `.base` file in the vault with valid YAML content
112. **Define scope**: Add `filters` to select which notes appear (by tag, folder, property, or date)
123. **Add formulas** (optional): Define computed properties in the `formulas` section
134. **Configure views**: Add one or more views (`table`, `cards`, `list`, `map`, or `kanban`) with `order` specifying which properties to display
145. **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`
156. **Test in Obsidian**: Open the `.base` file in Obsidian to confirm the view renders correctly. If it shows a YAML error, check quoting rules below. If it doesn't open as a base at all, check that Bases is turned on in Settings → Core plugins
16 
17## Schema
18 
19Base files use the `.base` extension and contain valid YAML.
20 
21```yaml
22# Global filters apply to ALL views in the base
23filters:
24 # Can be a single filter string
25 # OR a recursive filter object with exactly ONE key: and, or, or not
26 and:
27 - 'status == "active"'
28 - not:
29 - 'file.hasTag("archived")'
30 
31# Define formula properties that can be used across all views
32formulas:
33 formula_name: 'expression'
34 
35# Configure display names and settings for properties.
36# Note properties need the `note.` prefix here, or the setting is ignored.
37properties:
38 note.property_name:
39 displayName: "Display Name"
40 formula.formula_name:
41 displayName: "Formula Display Name"
42 file.ext:
43 displayName: "Extension"
44 
45# Define custom summary formulas
46summaries:
47 custom_summary_name: 'values.mean().round(3)'
48 
49# Define one or more views
50views:
51 - type: table | cards | list | map | kanban
52 name: "View Name"
53 limit: 10 # Optional: limit results
54 groupBy: # Optional: group results
55 property: property_name
56 direction: ASC | DESC
57 groupOrder: # Optional: only these groups, in this order
58 - value_one
59 - null # Files with no value for the groupBy property
60 sort: # Optional: sort results (supports multiple properties)
61 - property: property_name
62 direction: ASC | DESC
63 filters: # View-specific filters follow the same rules
64 and:
65 - 'status == "active"'
66 order: # Properties to display in order
67 - file.name
68 - property_name
69 - formula.formula_name
70 summaries: # Map properties to summary formulas
71 property_name: Average
72```
73 
74## Filter Syntax
75 
76Filters narrow down results. They can be applied globally or per-view.
77 
78### Filter Structure
79 
80```yaml
81# Single filter
82filters: 'status == "done"'
83 
84# AND - all conditions must be true
85filters:
86 and:
87 - 'status == "done"'
88 - 'priority > 3'
89 
90# OR - any condition can be true
91filters:
92 or:
93 - 'file.hasTag("book")'
94 - 'file.hasTag("article")'
95 
96# NOT - exclude matching items
97filters:
98 not:
99 - 'file.hasTag("archived")'
100 
101# Nested filters
102filters:
103 or:
104 - file.hasTag("tag")
105 - and:
106 - file.hasTag("book")
107 - file.hasLink("Textbook")
108 - not:
109 - file.hasTag("book")
110 - file.inFolder("Required Reading")
111```
112 
113### Filter Operators
114 
115| Operator | Description |
116|----------|-------------|
117| `==` | equals |
118| `!=` | not equal |
119| `>` | greater than |
120| `<` | less than |
121| `>=` | greater than or equal |
122| `<=` | less than or equal |
123| `&&` | logical and |
124| `\|\|` | logical or |
125| <code>!</code> | logical not |
126 
127## Properties
128 
129### Three Types of Properties
130 
1311. **Note properties** - From frontmatter: `note.author` or just `author`
1322. **File properties** - File metadata: `file.name`, `file.mtime`, etc.
1333. **Formula properties** - Computed values: `formula.my_formula`
134 
135In `order`, `filters`, `groupBy`, and `sort`, a note property can be written bare (`author`) or prefixed (`note.author`). In the top-level `properties:` section, always write `note.author`, because Obsidian ignores a bare key there and shows the raw name as the column header.
136 
137### File Properties Reference
138 
139| Property | Type | Description |
140|----------|------|-------------|
141| `file.name` | String | File name |
142| `file.basename` | String | File name without extension |
143| `file.path` | String | Full path to file |
144| `file.folder` | String | Parent folder path |
145| `file.ext` | String | File extension |
146| `file.size` | Number | File size in bytes |
147| `file.ctime` | Date | Created time |
148| `file.mtime` | Date | Modified time |
149| `file.tags` | List | All tags in file |
150| `file.links` | List | Internal links in file |
151| `file.backlinks` | List | Files linking to this file. Slow in large vaults and doesn't refresh when the vault changes; prefer reversing the lookup with `file.links` |
152| `file.embeds` | List | Embeds in the note |
153| `file.properties` | Object | All frontmatter properties. Doesn't refresh when the vault changes |
154| `file.file` | File | File object, only usable in specific functions |
155 
156### The `this` Keyword
157 
158- In main content area: refers to the base file itself
159- When embedded: refers to the embedding file
160- In sidebar: refers to the active file in main content
161 
162## Formula Syntax
163 
164Formulas compute values from properties. Defined in the `formulas` section.
165 
166```yaml
167formulas:
168 # Simple arithmetic
169 total: "price * quantity"
170 
171 # Conditional logic
172 status_icon: 'if(done, "✅", "⏳")'
173 
174 # String formatting
175 formatted_price: 'if(price, price.toFixed(2) + " dollars")'
176 
177 # Date formatting
178 created: 'file.ctime.format("YYYY-MM-DD")'
179 
180 # Calculate days since created (use .days for Duration)
181 days_old: '(now() - file.ctime).days'
182 
183 # Calculate days until due date
184 days_until_due: 'if(due_date, (date(due_date) - today()).days, "")'
185```
186 
187## Key Functions
188 
189Most commonly used functions. For the complete reference of all types (Date, String, Number, List, File, Link, Object, RegExp), see [FUNCTIONS_REFERENCE.md](references/FUNCTIONS_REFERENCE.md).
190 
191| Function | Signature | Description |
192|----------|-----------|-------------|
193| `date()` | `date(string): date` | Parse string to date (`YYYY-MM-DD HH:mm:ss`) |
194| `now()` | `now(): date` | Current date and time |
195| `today()` | `today(): date` | Current date (time = 00:00:00) |
196| `if()` | `if(condition, trueResult, falseResult?)` | Conditional |
197| `duration()` | `duration(string): duration` | Parse duration string |
198| `file()` | `file(path): file` | Get file object |
199| `link()` | `link(path, display?): Link` | Create a link |
200 
201### Duration Type
202 
203When subtracting two dates, the result is a **Duration** type (not a number).
204 
205**Duration Fields:** `duration.days`, `duration.hours`, `duration.minutes`, `duration.seconds`, `duration.milliseconds`
206 
207**IMPORTANT:** Duration does NOT support `.round()`, `.floor()`, `.ceil()` directly. Access a numeric field first (like `.days`), then apply number functions.
208 
209```yaml
210# CORRECT: Calculate days between dates
211"(date(due_date) - today()).days" # Returns number of days
212"(now() - file.ctime).days" # Days since created
213"(date(due_date) - today()).days.round(0)" # Rounded days
214 
215# WRONG - will cause error:
216# "((date(due) - today()) / 86400000).round(0)" # Duration doesn't support division then round
217```
218 
219### Date Arithmetic
220 
221```yaml
222# Duration units: y/year/years, M/month/months, d/day/days,
223# w/week/weeks, h/hour/hours, m/minute/minutes, s/second/seconds
224"now() + \"1 day\"" # Tomorrow
225"today() + \"7d\"" # A week from today
226"now() - file.ctime" # Returns Duration
227"(now() - file.ctime).days" # Get days as number
228```
229 
230## View Types
231 
232### Table View
233 
234```yaml
235views:
236 - type: table
237 name: "My Table"
238 order:
239 - file.name
240 - status
241 - due_date
242 summaries:
243 price: Sum
244 count: Average
245```
246 
247### Cards View
248 
249```yaml
250views:
251 - type: cards
252 name: "Gallery"
253 order:
254 - file.name
255 - cover_image
256 - description
257```
258 
259### List View
260 
261```yaml
262views:
263 - type: list
264 name: "Simple List"
265 order:
266 - file.name
267 - status
268```
269 
270### Kanban View
271 
272Requires Obsidian 1.14+. Cards are grouped into columns by the `groupBy` property, which a kanban view needs. `groupOrder` sets which columns show and in what order; use `null` to include files with no value. Without `groupOrder`, every value gets a column. Dragging a card to another column updates that property in the note. Only Markdown notes can be moved, except when grouping by `file.folder`, where moving a card moves the file to that folder. When grouping by a formula or by a file property other than `file.folder`, cards and columns can't be moved and notes can't be created from a column.
273 
274```yaml
275views:
276 - type: kanban
277 name: "Projects"
278 groupBy:
279 property: note.status
280 direction: ASC
281 groupOrder:
282 - Planned
283 - In progress
284 - Done
285 order:
286 - file.name
287 - due_date
288```
289 
290### Map View
291 
292Requires latitude/longitude properties and the Maps community plugin.
293 
294```yaml
295views:
296 - type: map
297 name: "Locations"
298 # Map-specific settings for lat/lng properties
299```
300 
301## Sorting
302 
303Sort results by one or more properties. Each sort entry specifies a `property` and `direction`, which must be uppercase `ASC` or `DESC`; an entry with any other value, or a sort written as a string, is silently ignored. Multiple sort entries are applied in order — the first entry is the primary sort key, subsequent entries break ties.
304 
305```yaml
306views:
307 - type: table
308 name: "Sorted Tasks"
309 sort:
310 - property: due
311 direction: ASC
312 - property: file.name
313 direction: ASC
314 order:
315 - file.name
316 - due
317 - status
318```
319 
320Sort options depend on the property type:
321 
322| Property Type | ASC | DESC |
323|---------------|-----|------|
324| Text | A→Z | Z→A |
325| Number | 0→9 | 9→0 |
326| Date | Old→New | New→Old |
327 
328You can sort by any property including formulas (`formula.my_formula`), file properties (`file.mtime`), and note properties.
329 
330## Default Summary Formulas
331 
332| Name | Input Type | Description |
333|------|------------|-------------|
334| `Average` | Number | Mathematical mean |
335| `Min` | Number | Smallest number |
336| `Max` | Number | Largest number |
337| `Sum` | Number | Sum of all numbers |
338| `Range` | Number | Max - Min |
339| `Median` | Number | Mathematical median |
340| `Stddev` | Number | Standard deviation |
341| `Earliest` | Date | Earliest date |
342| `Latest` | Date | Latest date |
343| `Range` | Date | Latest - Earliest |
344| `Checked` | Boolean | Count of true values |
345| `Unchecked` | Boolean | Count of false values |
346| `Empty` | Any | Count of empty values |
347| `Filled` | Any | Count of non-empty values |
348| `Unique` | Any | Count of unique values |
349 
350## Complete Examples
351 
352### Task Tracker Base
353 
354```yaml
355filters:
356 and:
357 - file.hasTag("task")
358 - 'file.ext == "md"'
359 
360formulas:
361 days_until_due: 'if(due, (date(due) - today()).days, "")'
362 is_overdue: 'if(due, date(due) < today() && status != "done", false)'
363 priority_label: 'if(priority == 1, "🔴 High", if(priority == 2, "🟡 Medium", "🟢 Low"))'
364 
365properties:
366 note.status:
367 displayName: Status
368 formula.days_until_due:
369 displayName: "Days Until Due"
370 formula.priority_label:
371 displayName: Priority
372 
373views:
374 - type: table
375 name: "Active Tasks"
376 filters:
377 and:
378 - 'status != "done"'
379 order:
380 - file.name
381 - status
382 - formula.priority_label
383 - due
384 - formula.days_until_due
385 groupBy:
386 property: status
387 direction: ASC
388 sort:
389 - property: due
390 direction: ASC
391 - property: file.name
392 direction: ASC
393 summaries:
394 formula.days_until_due: Average
395 
396 - type: table
397 name: "Completed"
398 filters:
399 and:
400 - 'status == "done"'
401 order:
402 - file.name
403 - completed_date
404```
405 
406### Reading List Base
407 
408```yaml
409filters:
410 or:
411 - file.hasTag("book")
412 - file.hasTag("article")
413 
414formulas:
415 reading_time: 'if(pages, (pages * 2).toString() + " min", "")'
416 status_icon: 'if(status == "reading", "📖", if(status == "done", "✅", "📚"))'
417 year_read: 'if(finished_date, date(finished_date).year, "")'
418 
419properties:
420 note.author:
421 displayName: Author
422 formula.status_icon:
423 displayName: "Status"
424 formula.reading_time:
425 displayName: "Est. Time"
426 
427views:
428 - type: cards
429 name: "Library"
430 order:
431 - cover
432 - file.name
433 - author
434 - formula.status_icon
435 filters:
436 not:
437 - 'status == "dropped"'
438 
439 - type: table
440 name: "Reading List"
441 filters:
442 and:
443 - 'status == "to-read"'
444 order:
445 - file.name
446 - author
447 - pages
448 - formula.reading_time
449```
450 
451### Daily Notes Index
452 
453```yaml
454filters:
455 and:
456 - file.inFolder("Daily Notes")
457 - '/^\d{4}-\d{2}-\d{2}$/.matches(file.basename)'
458 
459formulas:
460 word_estimate: '(file.size / 5).round(0)'
461 day_of_week: 'date(file.basename).format("dddd")'
462 
463properties:
464 formula.day_of_week:
465 displayName: "Day"
466 formula.word_estimate:
467 displayName: "~Words"
468 
469views:
470 - type: table
471 name: "Recent Notes"
472 limit: 30
473 order:
474 - file.name
475 - formula.day_of_week
476 - formula.word_estimate
477 - file.mtime
478```
479 
480## Embedding Bases
481 
482### Embed a `.base` file
483 
484Embed an external `.base` file in any Markdown note:
485 
486```markdown
487![[MyBase.base]]
488 
489<!-- Specific view -->
490![[MyBase.base#View Name]]
491```
492 
493### Embed inline with a code block
494 
495Bases can also be embedded **inline** directly inside a note using a `base` fenced code block. This is useful for note-level filters (e.g. using `this.file.links`) and avoids creating a separate `.base` file:
496 
497````markdown
498```base
499filters:
500 and:
501 - file.hasTag("example")
502views:
503 - type: table
504 name: Table
505 order:
506 - file.name
507 - status
508```
509````
510 
511When embedded inline this way, the `this` keyword refers to the containing note, so you can build per-note views such as showing all notes linked from the current file.
512 
513## YAML Quoting Rules
514 
515- Use single quotes for formulas containing double quotes: `'if(done, "Yes", "No")'`
516- Use double quotes for simple strings: `"My View Name"`
517- Escape nested quotes properly in complex expressions
518 
519## Troubleshooting
520 
521### YAML Syntax Errors
522 
523**Unquoted special characters**: Strings containing `:`, `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `%`, `@`, `` ` ``, `!` must be quoted.
524 
525```yaml
526# WRONG - colon in unquoted string
527displayName: Status: Active
528 
529# CORRECT
530displayName: "Status: Active"
531```
532 
533**Mismatched quotes in formulas**: When a formula contains double quotes, wrap the entire formula in single quotes.
534 
535```yaml
536# WRONG - double quotes inside double quotes
537formulas:
538 label: "if(done, "Yes", "No")"
539 
540# CORRECT - single quotes wrapping double quotes
541formulas:
542 label: 'if(done, "Yes", "No")'
543```
544 
545### Common Formula Errors
546 
547**Duration math without field access**: Subtracting dates returns a Duration, not a number. Always access `.days`, `.hours`, etc.
548 
549```yaml
550# WRONG - Duration is not a number
551"(now() - file.ctime).round(0)"
552 
553# CORRECT - access .days first, then round
554"(now() - file.ctime).days.round(0)"
555```
556 
557**Missing null checks**: Properties may not exist on all notes. Use `if()` to guard.
558 
559```yaml
560# WRONG - crashes if due_date is empty
561"(date(due_date) - today()).days"
562 
563# CORRECT - guard with if()
564'if(due_date, (date(due_date) - today()).days, "")'
565```
566 
567**`displayName` ignored, column shows the raw name**: prefix note properties with `note.` in the `properties:` section.
568 
569```yaml
570# WRONG - displayName ignored, column header shows "status"
571properties:
572 status:
573 displayName: Status
574 
575# CORRECT - column header shows "Status"
576properties:
577 note.status:
578 displayName: Status
579```
580 
581**Empty `displayName` doesn't hide a header**: `displayName: ""` falls back to the property name, the same as leaving it out, so `formula.status_icon` shows `status_icon`. Use a non-empty name such as `displayName: "Status"`.
582 
583**Referencing undefined formulas**: Ensure every `formula.X` in `order` or `properties` has a matching entry in `formulas`.
584 
585```yaml
586# This will fail silently if 'total' is not defined in formulas
587order:
588 - formula.total
589 
590# Fix: define it
591formulas:
592 total: "price * quantity"
593```
594 
595## References
596 
597- [Bases Syntax](https://help.obsidian.md/bases/syntax)
598- [Functions](https://help.obsidian.md/bases/functions)
599- [Views](https://help.obsidian.md/bases/views)
600- [Formulas](https://help.obsidian.md/formulas)
601- [Complete Functions Reference](references/FUNCTIONS_REFERENCE.md)
602 
View all files on GitHub →

Details

License
MIT
Stars on the repo
★ 52,291
Checked
Source
obsidianmd/obsidian-skills ↗
Creator
obsidianmd · 1 listing
View creator

Similar skills

See all →
SkillReverse engineer native, managed, Electron/JavaScriptREAmorluto/rea · by morlutoReverse engineer native, managed, Electron/JavaScript, packaged, firmware, and browser targets with REA. Use shipped-artifact or requested runtime evidence to explain features, compare versions, decompile code, or guide a reconstruction. Skip REA for ordinary source-repository architecture analysis.★ 316k GitHub starsSkillBrainstorms ideas into designs before any creative workBrainstorming Ideas Into Designsobra/superpowers · by obraYou MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation.★ 290k GitHub starsSkillRequires technical rigor and verificationCode Review Receptionobra/superpowers · by obraUse when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation★ 290k GitHub starsSkillDiagnosis loop for hard bugs and performance regressionsDiagnosing bugsmattpocock/skills · by mattpocockDiagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.★ 267k GitHub starsSkillImplement the result of /to-spec and /to-tickets in codeImplement specmattpocock/skills · by mattpocockImplement the result of /to-spec and /to-tickets in code.★ 267k GitHub starsSkillWriting a PR bodymattpocock/skills · by mattpocockUse when writing a PR body.★ 267k GitHub stars