Feature request: import from Markdown with expanded frontmatter
Right now the Markdown component renders content, but it doesn’t read anything from YAML frontmatter. Other CMS platforms use frontmatter to build schema and metadata automatically. Elements could do the same.
I’d want to upload a Markdown file with frontmatter and have Elements build out the page details on import: title, meta description, tags, whatever fields make sense. This should work on native Elements pages, not just the Markdown component.
I know this is all doable with a script and a proper markdown parser, if the team is looking at where AI fits into Elements, this is a good candidate.
Frontmatter Schema Reference
Each block below is a page type, the schema.org type it maps to, a sample frontmatter with example content, and the JSON-LD that frontmatter would generate on import. All URLs use elements.com.
A field dictionary follows the examples, defining every field once so there’s no ambiguity about what goes where.
Article
Schema type: Article
---
type: article
title: "Why We Rebuilt the Elements Component Engine"
slug: why-we-rebuilt-the-component-engine
description: "A look at the performance problems that pushed us to rewrite how components render, and what changed under the hood."
lang: en
canonical_url: https://elements.com/articles/why-we-rebuilt-the-component-engine
robots: index
image: /images/component-engine-hero.jpg
og_image: /images/component-engine-social.jpg
author: "Dan Counsell"
author_url: https://elements.com/about
author_image: /images/dan-counsell-headshot.jpg
date_published: 2026-07-01
date_modified: 2026-07-10
tags:
- engineering
- performance
- components
category: Engineering
publisher: "Elements"
publisher_logo: /images/elements-logo.png
---
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Why We Rebuilt the Elements Component Engine",
"description": "A look at the performance problems that pushed us to rewrite how components render, and what changed under the hood.",
"inLanguage": "en",
"image": "https://elements.com/images/component-engine-hero.jpg",
"author": {
"@type": "Person",
"name": "Dan Counsell",
"url": "https://elements.com/about",
"image": "https://elements.com/images/dan-counsell-headshot.jpg"
},
"publisher": {
"@type": "Organization",
"name": "Elements",
"logo": {
"@type": "ImageObject",
"url": "https://elements.com/images/elements-logo.png"
}
},
"datePublished": "2026-07-01",
"dateModified": "2026-07-10",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://elements.com/articles/why-we-rebuilt-the-component-engine"
},
"keywords": "engineering, performance, components",
"articleSection": "Engineering"
}
Blog Post
Schema type: BlogPosting
---
type: blog_post
title: "Five Lessons From Ten Years of Building Mac Software"
slug: five-lessons-ten-years-mac-software
description: "What a decade of shipping desktop apps taught us about focus, pricing, and saying no to feature requests."
lang: en
canonical_url: https://elements.com/blog/five-lessons-ten-years-mac-software
robots: index
image: /images/ten-years-hero.jpg
og_image: /images/ten-years-social.jpg
author: "Dan Counsell"
author_url: https://elements.com/about
author_image: /images/dan-counsell-headshot.jpg
date_published: 2026-06-15
date_modified: 2026-06-15
tags:
- company
- lessons-learned
category: Blog
reading_time_minutes: 6
---
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Five Lessons From Ten Years of Building Mac Software",
"description": "What a decade of shipping desktop apps taught us about focus, pricing, and saying no to feature requests.",
"inLanguage": "en",
"image": "https://elements.com/images/ten-years-hero.jpg",
"author": {
"@type": "Person",
"name": "Dan Counsell",
"url": "https://elements.com/about",
"image": "https://elements.com/images/dan-counsell-headshot.jpg"
},
"datePublished": "2026-06-15",
"dateModified": "2026-06-15",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://elements.com/blog/five-lessons-ten-years-mac-software"
},
"keywords": "company, lessons-learned",
"articleSection": "Blog",
"timeRequired": "PT6M"
}
About Page
Schema type: AboutPage (with an embedded Person or Organization)
---
type: about_page
title: "About"
slug: about
description: "Who Dan Counsell is and why he founded Elements."
lang: en
canonical_url: https://elements.com/about
robots: index
image: /images/dan-counsell-headshot.jpg
og_image: /images/dan-counsell-social.jpg
entity_type: Person
name: "Dan Counsell"
job_title: "Founder"
founded_organization: "Elements"
same_as:
- https://elements.com
- https://twitter.com/dancounsell
---
{
"@context": "https://schema.org",
"@type": "AboutPage",
"url": "https://elements.com/about",
"description": "Who Dan Counsell is and why he founded Elements.",
"inLanguage": "en",
"mainEntity": {
"@type": "Person",
"name": "Dan Counsell",
"image": "https://elements.com/images/dan-counsell-headshot.jpg",
"jobTitle": "Founder",
"sameAs": [
"https://elements.com",
"https://twitter.com/dancounsell"
],
"worksFor": {
"@type": "Organization",
"name": "Elements"
}
}
}
Commentary
Schema type: Article with about pointing to the subject (works well for ongoing analysis or review series)
---
type: commentary
title: "The Shift From Themes to Components"
slug: shift-from-themes-to-components
description: "Why website builders are moving away from fixed themes and toward composable components, and what that means for design freedom."
lang: en
canonical_url: https://elements.com/commentary/shift-from-themes-to-components
robots: index
author: "Dan Counsell"
author_url: https://elements.com/about
author_image: /images/dan-counsell-headshot.jpg
date_published: 2026-05-01
date_modified: 2026-05-20
tags:
- static-site-generator
- design-system
series: "Elements Commentary"
series_position: 1
about: "Component-based website design"
---
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "The Shift From Themes to Components",
"description": "Why website builders are moving away from fixed themes and toward composable components, and what that means for design freedom.",
"inLanguage": "en",
"author": {
"@type": "Person",
"name": "Dan Counsell",
"url": "https://elements.com/about",
"image": "https://elements.com/images/dan-counsell-headshot.jpg"
},
"datePublished": "2026-05-01",
"dateModified": "2026-05-20",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://elements.com/commentary/shift-from-themes-to-components"
},
"about": {
"@type": "Thing",
"name": "Component-based website design"
},
"isPartOf": {
"@type": "CreativeWorkSeries",
"name": "Elements Commentary",
"position": 1
},
"mentions": [
{ "@type": "DefinedTerm", "name": "static-site-generator" },
{ "@type": "DefinedTerm", "name": "design-system" }
]
}
Define Terms (Glossary Entry)
Schema type: DefinedTerm (inside a DefinedTermSet)
---
type: glossary_entry
title: "Static Site Generator"
slug: static-site-generator
description: "A tool that builds a website's pages ahead of time into plain HTML files, rather than generating them on each request."
lang: en
canonical_url: https://elements.com/glossary/static-site-generator
robots: index
tags:
- jamstack
- build-process
term_set: "Elements Glossary"
letter: S
referenced_in:
- /commentary/shift-from-themes-to-components
date_modified: 2026-04-12
---
{
"@context": "https://schema.org",
"@type": "DefinedTerm",
"name": "Static Site Generator",
"description": "A tool that builds a website's pages ahead of time into plain HTML files, rather than generating them on each request.",
"url": "https://elements.com/glossary/static-site-generator",
"inLanguage": "en",
"inDefinedTermSet": {
"@type": "DefinedTermSet",
"name": "Elements Glossary",
"url": "https://elements.com/glossary"
},
"dateModified": "2026-04-12"
}
Photo Gallery
Schema type: ImageGallery (containing multiple ImageObject entries)
---
type: photo_gallery
title: "Elements 3.0 Redesign, Behind the Scenes"
slug: elements-3-redesign-behind-the-scenes
description: "Screenshots and early sketches from the Elements 3.0 interface redesign."
lang: en
canonical_url: https://elements.com/gallery/elements-3-redesign-behind-the-scenes
robots: index
image: /images/gallery/redesign-cover.jpg
og_image: /images/gallery/redesign-social.jpg
date_published: 2026-03-01
images:
- src: /images/gallery/redesign-01.jpg
caption: "Early wireframes for the new component panel"
- src: /images/gallery/redesign-02.jpg
caption: "First working build of the theme studio"
- src: /images/gallery/redesign-03.jpg
caption: "Final interface, ready for release"
---
{
"@context": "https://schema.org",
"@type": "ImageGallery",
"name": "Elements 3.0 Redesign, Behind the Scenes",
"description": "Screenshots and early sketches from the Elements 3.0 interface redesign.",
"url": "https://elements.com/gallery/elements-3-redesign-behind-the-scenes",
"inLanguage": "en",
"datePublished": "2026-03-01",
"image": "https://elements.com/images/gallery/redesign-cover.jpg",
"associatedMedia": [
{
"@type": "ImageObject",
"contentUrl": "https://elements.com/images/gallery/redesign-01.jpg",
"caption": "Early wireframes for the new component panel"
},
{
"@type": "ImageObject",
"contentUrl": "https://elements.com/images/gallery/redesign-02.jpg",
"caption": "First working build of the theme studio"
},
{
"@type": "ImageObject",
"contentUrl": "https://elements.com/images/gallery/redesign-03.jpg",
"caption": "Final interface, ready for release"
}
]
}
Terms and Conditions
Schema type: WebPage (legal pages don’t get rich schema; the useful fields are the ones that keep the page current and correctly indexed)
---
type: legal_page
title: "Terms and Conditions"
slug: terms-and-conditions
description: "The terms that govern use of elements.com."
lang: en
canonical_url: https://elements.com/terms-and-conditions
robots: index
date_published: 2025-01-01
date_modified: 2026-06-01
version: "2.3"
---
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "Terms and Conditions",
"description": "The terms that govern use of elements.com.",
"url": "https://elements.com/terms-and-conditions",
"inLanguage": "en",
"datePublished": "2025-01-01",
"dateModified": "2026-06-01"
}
Field Dictionary
Every field used above, defined once. If a field isn’t listed here, it doesn’t belong in the frontmatter.
Core fields — required on every page type
| Field | Type | Definition |
|---|---|---|
title |
string | The page’s headline or name. Maps to headline on content types, name on entity and page types. |
slug |
string | The URL segment for the page, lowercase, hyphenated. Not sent to JSON-LD directly; used to build canonical_url. |
description |
string | A one- to two-sentence summary. Maps to description in every schema type and doubles as the meta description tag. |
lang |
string | The page’s language, as a two-letter ISO code (en, fr, de). Maps to inLanguage in JSON-LD and to the page’s <html lang> attribute. Required even on single-language sites. |
canonical_url |
URL | The full, final URL of the page. Maps to url or @id depending on schema type. Prevents duplicate-content issues if the page is ever reachable at more than one address. |
robots |
string | Either index or noindex. Controls whether search engines are allowed to list the page. Every page type needs this, not just legal pages. |
date_published |
date (YYYY-MM-DD) |
When the page went live. Maps to datePublished. |
date_modified |
date (YYYY-MM-DD) |
When the page was last edited. Maps to dateModified. Should update automatically on every save, not just be typed in once. |
Media fields — required where the page has visuals
| Field | Type | Definition |
|---|---|---|
image |
path | The primary image for the page: hero image, headshot, or gallery cover. Maps to image in JSON-LD. One name, used consistently across every page type — no more cover_image as a separate concept. |
og_image |
path | The image used for social sharing cards (Facebook, Twitter/X, Slack previews). Kept separate from image because social cards crop to a fixed ratio, usually 1200×630, and the hero image on the page is rarely that shape. Falls back to image if left blank. |
Author fields — required on content types (article, blog post, commentary)
| Field | Type | Definition |
|---|---|---|
author |
string | The author’s display name. Maps to Person.name. |
author_url |
URL | A link to the author’s own page, usually their About page. Maps to Person.url. This is what lets schema.org treat the author as a real, connected entity instead of a bare string. |
author_image |
path | A photo of the author. Maps to Person.image. |
Tagging — required on content types, optional elsewhere
| Field | Type | Definition |
|---|---|---|
tags |
list of strings | Keywords or related concepts for the page. One field name used everywhere content can be tagged. Replaces the old split between tags and related_terms — they were doing the same job under two names. Maps to keywords on articles and blog posts, and to mentions on commentary. |
category |
string | A single broad grouping, distinct from tags. Maps to articleSection. Optional; use when a site has a small number of top-level sections (Engineering, Blog, Company). |
Type-specific fields
| Field | Type | Applies to | Definition |
|---|---|---|---|
publisher / publisher_logo |
string / path | Article | The organization behind the content, separate from the individual author. Maps to Organization.name and Organization.logo. |
reading_time_minutes |
integer | Blog post | Estimated read time. Maps to timeRequired, formatted as an ISO 8601 duration (PT6M). |
entity_type |
string | About page | Either Person or Organization. Determines which schema.org type the mainEntity block uses. |
job_title |
string | About page (Person) | Maps to Person.jobTitle. |
founded_organization |
string | About page (Person) | The company or project the person founded. Maps to Person.worksFor.name. |
same_as |
list of URLs | About page | Links to the person’s or organization’s other official profiles (social accounts, other sites). Maps to sameAs. |
series / series_position |
string / integer | Commentary | The name of an ongoing series and this entry’s position in it. Maps to CreativeWorkSeries.name and .position. |
about |
string | Commentary | The subject the commentary covers. Maps to about.name. |
term_set |
string | Glossary entry | The name of the glossary or reference collection this term belongs to. Maps to DefinedTermSet.name. |
letter |
string | Glossary entry | The alphabetical grouping for the term. Used for building an A–Z index; not sent to JSON-LD. |
referenced_in |
list of paths | Glossary entry | Other pages that link to or cite this term. Used for building “referenced in” sections; not sent to JSON-LD. |
images |
list of objects (src, caption) |
Photo gallery | The individual photos in the gallery. Maps to associatedMedia, one ImageObject per entry. |
version |
string | Legal page | The document’s version number, for tracking changes to terms over time. Not sent to JSON-LD; used for display and changelog purposes. |
The JSON-LD blocks above map field-for-field to the frontmatter. That mapping is the actual feature: on import, Elements would read the YAML, drop the matching values into the right schema.org properties, and inject the JSON-LD into the page head automatically.