Schemas

Summary

Schema help you apply consistent structure to all your notes.

As you end up creating more notes, it can be hard to manage them at scale. Think of schemas as an optional type system for your notes that describe the hierarchy of your data and are represented as a hierarchy, themselves.

One of the primary capabilities for schema is to automatically insert templates into new notes.

Features

Schema Completions

Schemas will autosuggest valid children when you create a new project.

Schema Hints

Schemas show up as icons next to lookup results.

Schema Anatomy

A schema is a YAML file with the following naming scheme {name}.schema.yml

Below is an example of a four-level hierarchy describing cli commands. The id field of the schema is used to build a glob pattern which will be used to match notes matching the schema.

version: 1
schemas:
# this will match "cli.*" notes
- id: cli 
  # human readable description of hierarchy
  desc: command line interface reference
  # add this to the domain of your schema hierarchy
  parent: root
  # when a schema is a namespace, it can have arbitrary children. equivalent to cli.* glob pattern
  namespace: true 
  children:
    - cmd
    - env
# will match cli.*.env
- id: env
  desc: cli specific env variables
# will match cli.*.cmd.*
- id: cmd
  desc: subcommands 
  namespace: true

Below is another way of representing the above schema

.
└── cli # matches cli
    └── {cli child} # matches cli.*
        ├── env # matches cli.*.env
        └── cmd # matches cli.*.cmd
            └── {cmd child} # matches cli.*.cmd.*

Inline Schema Anatomy

Another way to specify schemas is to use inline schemas. Which can be simpler to create and maintain.

When we are creating inline schemas only the topmost schema must have an identifier id (this identifier will be used when looking up schemas). Note that this identifier is global and will be applied across all vaults. Child schemas are inlined under children and just require to contain pattern.

While using inline schemas you can take advantage of collapsibility of YAML config.

Here is an example of inline daily journal schema it will match notes such as 'daily.journal.2021.11.12'

version: 1
schemas:
  # Daily is the top most schema since its parent is 'root' it must have an identifier
  # this identifier 'daily' will be used when using 'Lookup (schema)' command.
  - id: daily
    parent: root
    # Children of the top most schema do not need to contain identifier and just 
    # require a 'pattern' to be set to match the hierarchy of notes.
    children:
      - pattern: journal
        children:
          - pattern: "[0-2][0-9][0-9][0-9]"
            children:
              - pattern: "[0-1][0-9]"
                children:
                  - pattern: "[0-3][0-9]"
                    # As with regular schema we can set the template to be used with
                    # the match of our notes. Below is an example usage of shorthand template
                    # definition (which defaults to type: note). 
                    template: templates.daily

Properties

version (optional): number

  • values: 0|1
  • default: 1
  • description: schema version number

imports

  • (optional): str[]

  • values: list of schemas to import

  • default: []

  • description: import schemas from another schema into the current schema

    • when using schemas from an external schema file, you will need to prefix the schema with the file name without the schema.yml suffix
  • NOTE: import is only available in schema version 1

Example:

  • foo.schema. yml
version: 1
imports:
- bar
schemas:
- id: foo
  parent: root
  children:
    - bar.bar # notice that we prefix the id bar with the filename
  • bar.schema.yml
version: 1
schemas:
- id: bar
  parent: root
  children: 
    - one
- id: one

The above would match the following files

foo.bar # match
foo.bar.one #match

schemas

  • list of schema definitions

id

the identifier of the schema. also designates the glob pattern match. this is the only required part of a schema. all other fields are optional

title

This value shows up in the lookup bar, if you have it in your schema configuration file, instead of just showing the pattern value. The title is also applied within the Schema Graph View.

desc

human readable description of the schema node. these will automatically when creating notes that match the schema.

parent

  • only required for schema domain
  • NOTE: at least one schema MUST have parent: root set

namespace

making a schema node a namespace automatically brings its immediate children as part of the schema, even if they are not explicitly defined in the schema definition. it will also automatically set the pattern to {namespace}.*

  • example:
schemas:
- id: project
  parent: root
  namespace: true
  • this will match:
    • project
    • project.foo
    • project.bar
  • it will not match
    • project.foo.bar

pattern

The glob pattern that schema matches. by default, this is the id of the schema. you can override this.

NOTE: Patterns are not supported at the first level of a hierarchy, and can only be defined within children.

For example, take a look at the journal schema below

schemas:
- id: journal
  title: journal
  desc: ""
  parent: root
  children:
    - year
- id: year
  title: year
  pattern: "[0-2][0-9][0-9][0-9]"
  children: 
    - month
- id: month
  title: month
  pattern: "[0-9][0-9]"
  children: 
    - day
- id: day
  title: day
  pattern: "[0-9][0-9]"
  namespace: true

This will match the following queries

# journal
# journal.2020
# journal.2020.09
# journal.2020.09.12
# journal.2020.09.12.foo.md

The glob patterns used here are the same as the Bash Extended Glob patterns, with a few discrepancies. We can use the extended globs to match interesting patterns. Here's a few examples:

  • "[0-9]" will match any digit
  • "[!0-9]" will match anything that's not a digit
  • "*([0-9])" will match 0 or more digits
  • "+([0-9])" will match 1 or more digits
  • "*" will match 0 or more of any character
  • "+([!])" will match 1 or more of any character
  • "@(left|right)" will match left or right, but nothing else
  • "!(thing)" will match anything other than thing

We can then combine these to get interesting patters. Here are more examples:

  • "+([0-9])-+([!])" matches 10-test, but not test or 10 or 10-.
  • "!(temp|scratch)" matches notes, recipes etc. but not temp or scratch, if you are trying to exclude just those hierarchies

children

list of ids of schemas that are the child of the current schema

template

a template you can apply to all notes that match this schema. See Schema Templates for more details.

template:
  # identifier for the template (for a note based template, it would be the name of the note)
  id: journal.template.daily
  # what sort of template we are creating. currently, only 'note' is supported
  type: note

If a template does not exist, a warning message will be shown and the note will created without a schema applied.

Shortened template syntax
# identifier for the template (the name of the note)
# The type will be set to 'note' 
template: journal.template.daily

Shortened template syntax will always uses type: note

If there are multiple templates with the same identifier in multiple vaults, you will be prompted to pick the vault when trying to apply a note template.

Cross-vault template syntax
# Use this to specify a template (If there are multiple or if it lies in a vault separate from your schema)
template: dendron://myVault/journal.template.daily

If the vault does not exist, a warning message will be shown and the note will created without a schema applied.

Schema Templates

Automatically apply a template when it matches a particular hierarchy pattern This is extremely useful whenever you want to re-use the outline of a note. Examples include daily journals, weekly shopping lists, and weekly reviews.

Getting Started

Template Variables

Summary

Pre-defined template variables that are automatically included in your templates at run time

You can apply template variables by using the following syntax: {{ VARIABLE }}

Globally Available

  • CURRENT_YEAR: The current year
  • CURRENT_MONTH: The month as two digits (example '02')
  • CURRENT_WEEK: The week of the year as two digits (example '17')
  • CURRENT_DAY: The day of the month as two digits (example '08')
  • CURRENT_HOUR: The current hour in 24-hour clock format
  • CURRENT_MINUTE: The current minute as two digits
  • CURRENT_SECOND: The current second as two digits
  • CURRENT_QUARTER: The current quarter as one-indexed single digit number (example '1' for Q1)
  • CURRENT_MONTH_NAME: The month as string name (example 'January')
  • CURRENT_MONTH_NAME_SHORT: The month as abbreviated string name (example 'Jan')
  • CURRENT_DAY_OF_WEEK: equivalent of javascript getDay method
  • TITLE: The title of the note as appeared on frontmatter
  • FNAME: name of current file
  • DESC: description of current file (equivalent to the desc field in the Dendron frontmatter)

Variable Substitution

To use variable substitution in your template, use {{ VARIABLE }}.

NOTE: the text enclosed in {{ VARIABLE }} will not be replaced but rendered dynamically in the preview/publishing based on the value in the frontmatter.

  • input:

    ---
    name: John
    ---
    
    Hello {{fm.name}}
    
  • output (in preview):

    Hello John!
    

Unknown Schema

Dendron doesn't force you to use schemas if you don't want to. This is why you can create notes that don't match any schema. Dendron will show you a ? next to these results.

Sometimes rules schemas are meant to be broken

Working with Schemas

Schemas can be modified, created and deleted using the same lookup interface that you use for regular notes. See lookup for further details about working with schemas.

Examples

You can find a vault with templates and schema examples here

Troubleshooting

Error with parsing some schemas during initialization

If you get this error, it means that Dendron encountered some malformed schemas during initialization. You can open the error message to see what schemas are affected.

Common errors:

parent

  • only required for schema domain
  • NOTE: at least one schema MUST have parent: root set

Cookbook

Testing schemas

If you want to test what your schemas will match, you can use a glob tester like Glob tester to do so


Children
  1. Create Schema From Note Hierarchy
  2. Schema Library
  3. Tutorial

Backlinks