Skip to content

Built-in metadata vocabularies

Four built-ins describe a document to something outside your docs site. A platform schema says what your generator will parse. A taxonomy schema says what kind of page this is. These four say how the page presents itself to a social card renderer, a catalogue, or another publisher’s build.

Id Speaks to Requires
ogp:article:1.0 Social and link-preview renderers og:title, og:type, og:url, og:image
dcmi:elements:1.1 Catalogues, repositories, library systems nothing
microsoft:learn:1.0 The Microsoft Learn publishing build title, description, author, ms.author, ms.date
x:cards:1.0 X, when someone shares the link twitter:card

The Open Graph protocol basic properties plus the article object type. This is the built-in that checks something no build tool checks. Nothing fails when og:image is missing. The page builds and deploys perfectly, then renders as a grey box everywhere it is shared.

In HTML these live on <meta property="…">. docmeta reads property alongside name, so an ordinary HTML page needs no special handling:

<meta property="og:title" content="Validate document metadata in CI" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://example.com/docs/ci" />
<meta property="og:image" content="https://example.com/img/card.png" />

In front matter they are ordinary keys, quoted because they contain a colon:

---
"og:title": Validate document metadata in CI
"og:type": article
---
Property Type Notes
og:title string Required. Non-empty.
og:type string Required. Not enumerated, because the protocol allows namespaced and vendor types.
og:url URI Required. Absolute. A site-root path is not a canonical URL.
og:image URI | array Required.
og:description string One or two sentences.
og:site_name string
og:determiner enum a, an, the, "", auto.
og:locale string language_TERRITORY, such as en_US.
og:locale:alternate string | array Same form.
og:audio, og:video URI | array
article:published_time date-time ISO 8601.
article:modified_time date-time ISO 8601.
article:expiration_time date-time ISO 8601.
article:author string | array
article:section string
article:tag string | array

The fifteen elements of the Dublin Core Metadata Element Set, as published in the DCMI Recommendation of 2020-01-20. That date is worth noticing: this is a frozen specification, so unlike the toolchain pins, 1.1 will stay accurate indefinitely.

contributor, coverage, creator, date, description, format, identifier, language, publisher, relation, rights, source, subject, title, type.

DCMI marks no element mandatory, so the schema requires nothing. Every element is repeatable in Dublin Core, so each accepts a single value or a list:

---
creator:
- Ada Lovelace
- Charles Babbage
date: 2026-08
---

date is the one element with a format. It is encoded as W3CDTF, which permits reduced precision, so 2026, 2026-08, and 2026-08-23 are all valid. A full datetime carries a timezone. June 5th is not.

The front matter Microsoft Learn requires and recommends on a documentation article. Of every built-in, this is the closest analogue to what docmeta itself does: five attributes whose absence fails a real publishing build.

Attribute Type Notes
title string Required.
description string Required. 75–300 characters.
author string Required. The author’s GitHub account ID, not a display name.
ms.author string Required. Microsoft alias, without @microsoft.com.
ms.date string Required. MM/DD/YYYY.
ms.topic string The kind of article. Not enumerated.
ms.service, ms.subservice string
ms.custom, ms.collection, ms.devlang, keywords string | array
ms.reviewer string
ms.prod, ms.technology string For repos that use ms.prod instead of ms.service.
zone_pivot_groups string

Three of these encode a rule that a generic check would miss:

  • ms.date is MM/DD/YYYY, not ISO 8601. 2026-08-23 is the correct spelling nearly everywhere else and is wrong here; 08/23/2026 is right. A format: date check would have passed the wrong one.
  • description has a floor, not just a ceiling. Microsoft documents the hard range as 75–300 characters and recommends 115–145. Only the hard range is enforced, because the recommendation is guidance and the range is the build rule.
  • ms.author rejects an email address. The alias goes in bare, and writing the full address is the common error.

The twitter:* meta tags that decide how a link renders when someone shares it on X. It is the companion to ogp:article:1.0, on the same <meta> channel and through the same extractor. The two normally ship together, which is why a site with Open Graph tags and no card tags is the usual half-finished state.

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@exampledocs" />
<meta name="twitter:title" content="Validate document metadata in CI" />
<meta name="twitter:description" content="Fail the build when frontmatter is missing." />
<meta name="twitter:image" content="https://example.com/img/card.png" />
Field Type Notes
twitter:card summary | summary_large_image | app | player Required.
twitter:site, twitter:creator string A handle, with or without the @.
twitter:site:id, twitter:creator:id string | integer Numeric account ids.
twitter:title string 70 characters.
twitter:description string 200 characters.
twitter:image string An HTTPS URL.
twitter:image:alt string 420 characters.
twitter:player, twitter:player:stream string HTTPS URLs. Player cards.
twitter:player:width, twitter:player:height string | integer Pixels.
twitter:app:* string Name, id, and URL per platform, plus twitter:app:country.

Every other tag on the card has an Open Graph fallback: X reads og:title, og:description and og:image when the twitter: equivalents are absent. A page carrying good Open Graph tags and no twitter:title is correct, so requiring one here would fail it.

twitter:card is the exception. It has no fallback, and X will not infer a card type from Open Graph alone. Without it no card renders at all, however complete the rest of the markup is. That is the whole of what this schema insists on.

The length caps are real limits rather than style advice: X truncates past them. And twitter:image must be HTTPS, because an image served over plain HTTP is dropped and the card renders without it.