🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Obsidian Bases

by @sadlay

Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries. Use when working with .base files, creating database-like views of...

Versionv1.0.0
Downloads1,967
TERMINAL
clawhub install obsidian-bases

πŸ“– About This Skill


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, 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, or map) 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

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 and/or/not
  and: []
  or: []
  not: []

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 and: [] 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

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

  • 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
    

    Map View

    Requires latitude/longitude properties and the Maps community plugin.

    views:
      - type: map
        name: "Locations"
        # Map-specific settings for lat/lng 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: 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 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: 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

    Embed in Markdown files:

    ![[MyBase.base]]

    ![[MyBase.base#View Name]]

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

    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

  • Bases Syntax
  • Functions
  • Views
  • Formulas
  • Complete Functions Reference
  • πŸ“‹ Tips & Best Practices

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

    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"

    πŸ“¦ Core Types

    Global filters apply to ALL views in the base
    Define formula properties that can be used across all views
    Configure display names and settings for properties
    Define custom summary formulas
    Define one or more views