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:
- If the user highlighted text before sharing — use only the highlights
- Otherwise, if the user selected text before sharing — use the selection
- 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.name→nameinside theauthorobject[*]for array extraction:recipeInstructions[*].text→ array oftextvalues 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" |
 |
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
- Web Clipper — The Web Clipper feature overview
- Templates — Document templates in Atlas
- Metadata — How metadata fields work in Atlas