Skip to content

Advanced Web Clipper Templates

Clip Templates are JSON files that control how the Web Clipper processes a web page: what metadata fields appear in the clip sheet, how page content is formatted into the document body, which pages the template activates on, and how images are handled.

Atlas uses the .atlasclip.json format, which is fully compatible with the Obsidian Web Clipper template format (schema version 0.1.0). Templates exported from Atlas can be imported directly into Obsidian, and Obsidian Web Clipper templates can be imported into Atlas.

Template Structure

Every .atlasclip.json template is a JSON file with the following top-level fields:

Field Type Description
schemaVersion string Always "0.1.0"
name string Display name shown in the template picker
behavior string "create" — new document; "prepend" — add to top of existing; "append" — add to bottom
noteNameFormat string Template string for the document title, e.g. "{{title}}"
path string Suggested folder path within the project
properties array Metadata field definitions (see Metadata Properties)
triggers array URL or schema patterns that activate this template (see Triggers)
noteContentFormat string The body template using Rosetta markup (see Variables, Filters, Logic)
atlas object Atlas-specific extension fields (see Atlas Extension Fields)

Metadata Properties

The properties array defines the metadata fields that appear in the clip sheet's Details tab. Each item defines one field:

Field Type Description
name string Field label shown to the user
value string Default value or Rosetta markup template for auto-population
type string Field type: text, multitext, number, checkbox, date, datetime, url

The value field can be a static string or a Rosetta markup expression — for example, "{{schema:@Recipe:author.name ?? author}}" to auto-populate an author field from Schema.org data with a fallback to the page's meta author.

Triggers

Triggers determine which template activates for a given page. When you clip a page, Atlas evaluates triggers in order — your custom templates first, then bundled templates — and uses the first match. If nothing matches, the Default template is used.

Each trigger is a string in one of these forms:

Form Example Matches
Domain "nytimes.com" Any URL on that domain
URL prefix "https://github.com/" URLs starting with this prefix
Regex "/^https:\\/\\/.*\\.wikipedia\\.org\\//" URLs matching the pattern
Schema.org type "schema:@Recipe" Pages with Schema.org data of that type

The order of templates in your list matters — the first matching trigger wins.

Atlas Extension Fields

The atlas object inside a template contains Atlas-specific settings that extend the base format:

Field Type Description
synopsisFormat string Rosetta markup template for the Synopsis field
notesFormat string Rosetta markup template for the document's Notes field
tagMappings array Automatic tag suggestions (see below)
imageHandling string Default image action: prompt, downloadAll, linkAll, skip
addWebPageChild boolean If true, "Save original page" defaults to on
icon string Template icon identifier
color string Template color name

Tag Mappings

Each item in tagMappings has a source field that controls where tags come from:

Source Description
"metaKeywords" Uses the page's <meta name="keywords"> tag
"schemaType" Uses the Schema.org @Type of the page
"schemaCategory" Uses the Schema.org category field
"ogType" Uses the Open Graph og:type value
"contentKeywords" Extracts keywords from the article body
"fixed" Uses a hardcoded list; requires "fixedTags": ["tag1", "tag2"]

Variables

Variables are written as {{variableName}} and are replaced with values extracted from the page. Unknown variables resolve to an empty string — no error is produced.

Preset Variables

Variable Type Description
{{title}} string The page title
{{url}} string The full source URL
{{content}} string Extracted body as Markdown (see content cascade below)
{{contentHtml}} string Same cascade as {{content}} but raw HTML
{{description}} string Meta description tag content
{{author}} string Page author from meta tags or Schema.org
{{date}} string Date the clip was taken, formatted as YYYY-MM-DD (UTC)
{{time}} string Full ISO 8601 timestamp of when the clip was taken
{{image}} string URL of the page's main or hero image
{{site}} string Site name from og:site_name or equivalent
{{domain}} string Domain only, e.g. github.com
{{favicon}} string Absolute URL of the page's favicon
{{selection}} string User's selected text on the page, as Markdown
{{selectionHtml}} string User's selected text on the page, as HTML
{{highlights}} array Array of highlight objects; each has text and timestamp properties
{{words}} number Word count of the article body
{{fullHtml}} string Complete raw HTML of the entire page

Content cascade: {{content}} follows a priority order rather than always returning the full article:

  1. If the user highlighted text before sharing — use only the highlights
  2. Otherwise, if the user selected text before sharing — use the selection
  3. Otherwise — use the full extracted article body

This means selecting a specific passage before tapping Share will clip only that passage.

Meta Tag Variables

Access any HTML <meta> tag using the meta: prefix:

{{meta:og:image}}       → content of <meta property="og:image">
{{meta:author}}         → content of <meta name="author">
{{meta:keywords}}       → content of <meta name="keywords">
{{meta:description}}    → same as {{description}}

Schema.org Variables

Access JSON-LD and Schema.org structured data embedded in the page using schema:@Type:path:

{{schema:@Recipe:author.name}}               → Author name from Recipe schema
{{schema:@Recipe:recipeIngredient}}          → Array of ingredient strings
{{schema:@Recipe:recipeInstructions[*].text}} → Extract .text from each instruction
{{schema:@Book:image ?? image}}              → Book cover image, fallback to meta image
{{schema:@Product:offers.price}}             → Product price

Path syntax:

  • . for nested property access: author.namename inside the author object
  • [*] for array extraction: recipeInstructions[*].text → array of text values from each item

CSS Selector Variables

Extract content from the page HTML directly using CSS selectors:

{{selector:h1}}                  → Text content of the first <h1> element
{{selector:.article-author}}     → Text content of .article-author element
{{selectorHtml:article}}         → Inner HTML of the <article> element

Fallback Chains

Use ?? to try alternatives left-to-right, returning the first non-null, non-empty value:

{{schema:@Recipe:image ?? image}}
{{schema:@Book:author.name ?? schema:@Book:author ?? author}}

Filters

Filters transform a variable's value using the pipe operator |. They chain left-to-right:

{{title | upper | trim | truncate: 60}}

Text Filters

Filter Example Result
upper {{"hello" | upper}} HELLO
lower {{"HELLO" | lower}} hello
capitalize {{"hello world" | capitalize}} Hello world
title {{"hello world" | title}} Hello World
trim {{" hello " | trim}} hello
replace: "a","b" {{"foo baz" | replace: "foo","bar"}} bar baz
safe_name {{"File/Name?" | safe_name}} File-Name
safe_name: "_" {{"File/Name?" | safe_name: "_"}} File_Name
truncate: N {{"hello world" | truncate: 7}} hello w...
camel {{"hello world" | camel}} helloWorld
pascal {{"hello world" | pascal}} HelloWorld
snake {{"hello world" | snake}} hello_world
kebab {{"hello world" | kebab}} hello-world
uncamel {{"helloWorld" | uncamel}} hello world

Number and Math Filters

Filter Description
length Number of items in an array, or characters in a string
round Round to nearest integer
round: N Round to N decimal places
calc: "expr" Apply arithmetic: number \| calc: "*2" (supports +, -, *, /)
decodeURI URL-decode a string

Array Filters

Filter Description
first First item of the array
last Last item of the array
join: "," Join array items with a separator string
split: "," Split a string into an array by separator
slice: 1,3 Extract a sub-array from index 1 to 3
nth: N Get the Nth item (1-indexed)
map: "prop" Extract a named property from each array object
object: "key" Convert array to an object keyed by a property
merge Merge two objects together

Markdown Output Filters

Filter Output
blockquote > text
callout: "type" Obsidian-style callout block
footnote: "note" Markdown footnote reference
fragmentLink: "heading" Link to a heading anchor
image: "alt" ![alt](url)
link: "text" [text](url)
wikilink [[page]]
list Unordered Markdown list from an array
table Markdown table from structured data
template Render the value as a Rosetta template string

HTML Processing Filters

Filter Description
removeHtml Strip all HTML tags, leaving plain text
stripTags: "br,hr" Remove specific tags but keep their content
removeTags: "script" Remove tags and their inner content
replaceTags: "b","strong" Rename a tag, keeping content and attributes
stripAttr: "class" Remove specific attributes from all tags
removeAttr: "onclick" Remove attributes (alias of stripAttr)
stripMarkdown Remove all Markdown syntax, leaving plain text
markdownConversion Convert HTML to Markdown

Date Filters

Filter Description
date: "format" Format a date using tokens: YYYY, MM, DD, HH, mm, ss
dateModify: "+1 day" Add or subtract time (seconds, minutes, hours, days, weeks, months, years)
duration Format milliseconds as human-readable duration, e.g. "2 hours 30 minutes"

Logic

Conditionals

Use {% if %} / {% else if %} / {% else %} / {% endif %} to include content conditionally:

{% if author %}
By {{author}}
{% else if site %}
From {{site}}
{% else %}
Author unknown
{% endif %}

Truthiness: A value is falsy if it is null, false, 0, "", [], or {}. Everything else is truthy.

Comparison operators:

{% if author == "Jane Doe" %}    → equality
{% if count != 0 %}              → inequality
{% if price > 10 %}              → greater than
{% if price < 100 %}             → less than
{% if score >= 90 %}             → greater than or equal
{% if length <= 5 %}             → less than or equal

Loops

Use {% for item in collection %} / {% endfor %} to iterate over an array:

{% for item in schema:@Recipe:recipeIngredient %}
- {{item}}
{% endfor %}

A loop object is available inside each iteration:

Property Description
loop.index Current iteration number, 1-based
loop.index0 Current iteration number, 0-based
loop.first true if this is the first iteration
loop.last true if this is the last iteration
loop.length Total number of items

Example with numbered steps:

{% for step in schema:@Recipe:recipeInstructions[*].text %}
{{loop.index}}. {{step}}
{% endfor %}

To iterate over the keys of an object (in sorted order):

{% for key in meta:og %}
{{key}}: {{meta:og[key]}}
{% endfor %}

Variable Assignment

Use {% set name = value %} to create a local variable:

{% set slug = title | safe_name | lower %}
File: {{slug}}.md

{% set displayDate = time | date: "MMMM D, YYYY" %}
Saved on {{displayDate}}

Set variables can use filters and are scoped to the template render.


Full Example

A complete Recipe template:

{
  "schemaVersion": "0.1.0",
  "name": "Recipe",
  "behavior": "create",
  "noteNameFormat": "{{title | safe_name}}",
  "path": "Recipes/",
  "properties": [
    { "name": "author",    "value": "{{schema:@Recipe:author.name ?? author}}", "type": "text" },
    { "name": "prep_time", "value": "{{schema:@Recipe:prepTime}}",              "type": "text" },
    { "name": "yield",     "value": "{{schema:@Recipe:recipeYield}}",           "type": "text" }
  ],
  "triggers": ["schema:@Recipe"],
  "noteContentFormat": "# {{title}}\n\n{{description}}\n\n## Ingredients\n\n{% for item in schema:@Recipe:recipeIngredient %}- {{item}}\n{% endfor %}\n\n## Instructions\n\n{% for step in schema:@Recipe:recipeInstructions[*].text %}{{loop.index}}. {{step}}\n{% endfor %}",
  "atlas": {
    "synopsisFormat": "{{description}}",
    "tagMappings": [
      { "source": "schemaType" },
      { "source": "fixed", "fixedTags": ["recipe", "cooking"] }
    ],
    "imageHandling": "prompt"
  }
}

See Also