Guide

Search and sharing

facet takes care of how a page looks; search engines read what is in the page and its <head>. This page lists what every facet site should add, and what facet already does for you.

What facet already does

The head of every page

Give every page its own title and description. Put the page first and the site name after, within about 60 characters; write the description, 50 to 160 characters, for a reader scanning search results. The canonical link, the share image and og:url are absolute URLs.

<html lang="en" data-accent="moss">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Chasing the red dot · Duna's notes</title>
  <meta name="description" content="Twelve rooms, one red dot, and what Duna learned about light." />
  <link rel="canonical" href="https://example.com/notes/red-dot/" />

  <meta property="og:type" content="article" />
  <meta property="og:title" content="Chasing the red dot" />
  <meta property="og:description" content="Twelve rooms, one red dot, and what Duna learned about light." />
  <meta property="og:url" content="https://example.com/notes/red-dot/" />
  <meta property="og:image" content="https://example.com/notes/red-dot/card.png" />
  <meta name="twitter:card" content="summary_large_image" />

  <link rel="icon" href="/favicon.svg" type="image/svg+xml" />
  <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#13161c" />
  <meta name="theme-color" media="(prefers-color-scheme: light)" content="#f5f7f9" />

  <link rel="preload" href="/facet/dist/fonts/geist.woff2" as="font" type="font/woff2" crossorigin />
  <link rel="stylesheet" href="/facet/dist/facet.css" />
</head>

Structured data for each layout

A block of JSON-LD in the <head> tells search engines what a page is. Each layout usually maps to one schema.org type:

Layout Type Notes
Reading, Margin notes BlogPosting headline, datePublished, image, and an author that points at the site's Person.
Docs TechArticle Plus a BreadcrumbList for its place in the docs.
Resume ProfilePage + Person sameAs lists your profiles elsewhere, tying them to this site.
List CollectionPage An ItemList can name each entry's URL.
Split SoftwareSourceCode For a project page: codeRepository, license, version.
Cover, Story, Panels VideoObject When the page has a video: name, thumbnailUrl, uploadDate, contentUrl.
Deck PresentationDigitalDocument Optional; WebPage is enough for most decks.
App WebApplication applicationCategory, such as GameApplication.
Empty None As a 404 page, the server must really answer 404.
Focus ContactPage For a contact page; a link hub is a WebPage.
Landing ProfilePage For a personal home page; the Person is its mainEntity.
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "Chasing the red dot",
  "datePublished": "2026-10-11T09:00:00-07:00",
  "image": "https://example.com/notes/red-dot/card.png",
  "author": { "@id": "https://example.com/#person" }
}
</script>

Refer to one Person by its @id instead of repeating it: the home page defines it, and every other page names only the @id.

Notes on the layouts

Bilingual sites

Search engines index only the HTML a URL serves, so a language switch that swaps text in the browser leaves the other language unindexed. Give each language its own URL, mark it with lang, and link the two with hreflang:

<html lang="zh-Hans">
<link rel="canonical" href="https://example.com/zh/notes/red-dot/" />
<link rel="alternate" hreflang="en" href="https://example.com/notes/red-dot/" />
<link rel="alternate" hreflang="zh-Hans" href="https://example.com/zh/notes/red-dot/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/notes/red-dot/" />

Sitemaps and robots.txt

How this site does it

Each reference page declares only its <title> and <meta name="description">, each with a Chinese data-zh. When just site assembles the site, scripts/site_meta.py writes every page again under zh/ with the Chinese in the HTML, and the toolbar's EN / 中文 moves between the two URLs (under just serve it still swaps in place). It then adds the rest from the title and description: the canonical link, hreflang alternates, icon, theme-color, Open Graph tags and JSON-LD (WebSite and SoftwareSourceCode on the home page, a WebPage with breadcrumbs elsewhere), writes sitemap.xml, and marks the mockups noindex. scripts/card.py draws the share card from facet's own tokens and fonts.