Home/Documentation
Documentation

See the output.
Then copy the code.

Use @santi020k/og v0.4 portable page metadata, framework-neutral content helpers, visual presets, custom renderers, deterministic caching, and safe output management. Start with a useful visual default and customize only what your project needs.

v0.4.0 Current docsNode.js 22.18+ Runtime4 presets Included

Use a complete preset for conventional social cards, share page data with portable metadata, connect Markdown or MDX directly, or keep full visual control with a custom renderer.

Fastest

Preset config

Brand, theme, route data, and optional images. No renderer file.

Every framework

Shared metadata

One page definition for the image, canonical URL, Open Graph, X, HTML, and Next.js.

Full control

Custom renderer

Sharp, Satori, workers, or an existing encoded image function.

01

Quick start

Install the package with your preferred package manager, initialize a preset config, and generate the first image.

bash
pnpm add -D @santi020k/og
pnpm exec santi-og init
pnpm exec santi-og generate
pnpm exec santi-og check
pnpm exec santi-og compare --threshold 0.01
pnpm exec santi-og migrate --report --json
pnpm exec santi-og upgrade --to 0.4.0

santi-og init now creates a preset-based configuration. It works immediately; writing SVG is optional.

Choose your starting point

javascript
import { createPathCards } from '@santi020k/og'
import { definePresetConfig } from '@santi020k/og/presets'

export default definePresetConfig({
  outputDirectory: 'public/og/pages',
  cards: createPathCards([
    {
      pathname: '/',
      data: {
        title: 'Ship the card. Delete the renderer.',
        description: 'A complete social image from a small config.',
        badge: 'Product',
        variant: 'product',
      },
    },
  ]),
  preset: {
    brand: {
      name: 'Example',
      domain: 'example.com',
      logo: 'public/logo.png',
    },
    theme: { accent: '#7c3aed' },
  },
})
02

Visual presets

Every preset shares the same accessible title, description, badge, brand, logo, domain, accent, and image data contract. Bundled Inter typography and glyph-aware wrapping make output portable across build machines. A config-level variant is the default; any card can override it.

Actual package output.

These four images are rendered by this site’s og.config.mjs during every build.

Theme and card overrides

Set preset.brand, preset.theme, and preset.variant once. Override accent, brand, domain, image, or variant on individual cards.

Generated preset SVG uses portable fill and stroke opacity attributes instead of CSS rgba() colors, improving compatibility with SVG validators and consumer tooling.

03

Page metadata from the same source

definePageMetadata keeps the title, description, route, and social image together. Derive a card with an explicit renderer mapping, portable tag descriptors, escaped HTML, or a Next.js Metadata API object without adding a framework runtime.

import { createMetaTags, createPageCard, definePageMetadata } from '@santi020k/og/metadata'
import { renderMetaTags } from '@santi020k/og/metadata/html'
import { toNextMetadata } from '@santi020k/og/metadata/next'

export const page = definePageMetadata({
  pathname: '/docs',
  title: 'Documentation',
  description: 'Learn how to generate deterministic social images.',
  image: {
    output: 'pages/docs.webp',
    alt: 'Example documentation social card',
    width: 1200,
    height: 630,
  },
})

export const card = createPageCard(page, {
  data: ({ description, title }) => ({
    title,
    description,
    badge: 'Guide',
    variant: 'docs',
  }),
})

const site = { siteUrl: 'https://example.com', siteName: 'Example' }
export const tags = createMetaTags(page, site)
export const html = renderMetaTags(tags)
export const metadata = toNextMetadata(page, site)

The helpers resolve absolute canonical and image URLs, infer image MIME types, include dimensions and alternative text, remove canonical fragments, and validate empty text or invalid dimensions. Article pages can add dates, authors, section, and tags.

Metadata functions

FunctionPurpose
definePageMetadataValidate a portable page definition while preserving TypeScript inference.
resolvePageMetadataResolve defaults, title templates, canonical and image URLs, MIME types, and robots settings.
createPageCardDerive an OgCard; use data to map SEO fields into renderer-specific data explicitly.
createMetaTagsCreate renderer-neutral title, link, Open Graph, article, robots, and X tag descriptors.
renderMetaTagsEscape and render descriptors as HTML for static templates, Astro, Eleventy, or server output.
toNextMetadataCreate the dependency-free structural object accepted by the Next.js App Router Metadata API.

Page definition

PropertyRequiredDescription
pathnameYesPage route used for its canonical URL and default image output.
titleYesPage, Open Graph, X, and default card title.
descriptionYesPage, Open Graph, X, and default card description.
canonicalNoCanonical override as a relative or absolute HTTP(S) URL; fragments are removed.
imageNoalt, public url, generated output, width (1200), height (630), and inferred or explicit MIME type.
typeNowebsite, article, or profile; article data selects article automatically.
articleNoPublication and modification dates, authors, section, and tags.
authors / keywordsNoStandard author and keyword metadata; article authors are the fallback.
locale / alternateLocalesNoPrimary and alternate Open Graph locales.
robotsNoDefaults to index/follow, large image previews, and unlimited snippet and video previews.
twitterNoX card, site, and creator overrides; defaults to large-image with an image and summary without one.

Site defaults

PropertyDefaultDescription
siteUrlRequiredAbsolute HTTP(S) base used for canonical and social image URLs.
siteNameOmittedOpen Graph site name.
publicImagePath/ogPublic directory joined with generated image outputs.
defaultImageOmittedFallback image contract for pages without their own image.
localeen_USFallback Open Graph locale.
titleTemplateOmittedTitle composition containing %s, such as %s — Example.
twitterOmittedDefault X card, site, and creator settings; page settings override them.
04

Framework-neutral Markdown and MDX

collectContentCards reads YAML frontmatter without starting Astro, Next.js, or another framework. It understands nested index.md routes, excludes drafts by default, and tracks each content file as a source.

import { collectContentCards } from '@santi020k/og/content'
import { definePresetConfig } from '@santi020k/og/presets'

export default definePresetConfig({
  outputDirectory: 'public/og',
  cards: () => collectContentCards({
    directory: 'src/content/blog',
    basePath: 'blog',
    map: entry => ({
      title: String(entry.frontmatter.title),
      description: String(entry.frontmatter.description ?? ''),
      ...(typeof entry.frontmatter.cover === 'string'
        ? { image: entry.frontmatter.cover }
        : {}),
      variant: 'article',
    }),
    sources: entry => typeof entry.frontmatter.cover === 'string'
      ? [entry.filePath, entry.frontmatter.cover]
      : [entry.filePath],
  }),
  preset: {
    brand: { name: 'Example Journal' },
    variant: 'article',
  },
})

Use readContent when you only need the normalized entries. Each entry exposes its body, absolute file path, parsed frontmatter, directory-relative ID, and nested-index-aware slug.

Existing @santi020k/og/astro imports remain compatibility aliases for the same implementation.

OptionDefaultPurpose
directoryRequiredMarkdown/MDX content directory, relative to root.
rootWorking directoryBase for the content directory and relative paths.
include**/*.md, **/*.mdxGlob patterns evaluated before parsing.
exclude[]Glob patterns removed before parsing.
filterInclude allAsync-capable predicate evaluated on parsed entries.
draftfrontmatter.draftCustom async-capable draft predicate.
includeDraftsfalseInclude entries identified as drafts.
mapPreset frontmatter mappingMap an entry to typed card data or return null to omit it.
coverFieldsimage, cover, heroImagePreferred frontmatter image fields for the default mapper.
basePathEmptyRoute prefix used by deterministic output mapping.
extensionwebpDefault generated image extension.
outputPathname outputOverride the output filename for each mapped entry.
sourcesContent fileAdd covers or other files that invalidate the card cache.
aggregateOmittedAppend pagination, tag, locale, or collection cards after entry mapping.
05

Typed catalogs and derived collections

createCards maps arrays, JSON, CMS results, products, tag archives, or pagination into typed cards without consumer-side expansion. Shared output rules, sources, dimensions, formats, and aliases stay in one place.

import { createCards } from '@santi020k/og'

const cards = createCards(products, product => ({
  title: product.name,
  description: product.summary,
  image: product.image,
  variant: 'product',
}), {
  output: product => 'products/' + product.slug + '.webp',
  formats: ['png', 'svg'],
  formatAliases: product => ({
    png: ['social/' + product.slug + '.png'],
  }),
  sources: product => product.image ? [product.image] : [],
})

The mapper receives the item and index. Every option callback receives the original item, mapped card data, and index, so output names and cache sources can use either representation. formats applies to every logical card; formatAliases can derive encoding-specific destinations per item.

OptionPurpose
outputRequired callback deriving each primary output path.
aliasesDerive same-format string or named-directory aliases per item.
formatsPublish the same logical card as additional SVG, PNG, WebP, JPEG, or AVIF encodings.
formatAliasesDerive aliases for individual additional encodings.
sourcesDerive files or source callbacks that invalidate each mapped card.
width / heightApply shared dimensions to every card in the catalog.
outputDirectoryTarget a configured named output directory for the complete catalog.
06

Route-oriented cards

pathnameOutput and createPathCards remove repeated slug and output mapping from route-heavy sites. URL segments are encoded into portable, deterministic filenames.

import { createPathCards, pathnameOutput } from '@santi020k/og'

pathnameOutput('/')                       // index.webp
pathnameOutput('/docs/api')               // docs--api.webp
pathnameOutput('/guides/getting started') // guides--getting~20started.webp

const cards = createPathCards(pages, {
  directory: 'routes',
  extension: 'png',
})
07

Custom renderers

Use a custom renderer for bespoke editorial art, data visualization, or strict legacy parity. The generation pipeline stays the same.

javascript
import { defineConfig } from '@santi020k/og'
import { createSharpRenderer } from '@santi020k/og/sharp'

export default defineConfig({
  cards: [{ output: 'index.webp', data: { title: 'Home' } }],
  renderer: createSharpRenderer({
    renderSvg: ({ title }, { height, width }) =>
      `<svg viewBox="0 0 ${width} ${height}">...</svg>`,
    webp: { quality: 86 },
  }),
})

Existing functions that already return PNG, WebP, JPEG, or AVIF bytes can use createEncodedRenderer. Large collections can use defineWorkerRenderer or createSatoriWorkerRenderer with bounded automatic concurrency.

Hybrid projects are supported.

Use a preset config for social cards while independent video, diagram, or specialized media scripts retain their custom renderer and own only their outputs.

08

Outputs, aliases, and assets

Define one logical card and publish WebP, PNG, JPEG, AVIF, or SVG variants. Same-format aliases reuse bytes, format aliases add encoding-specific names, and named directories support multi-app repositories.

export default defineConfig({
  outputDirectory: 'public/og',
  outputDirectories: {
    docs: 'apps/docs/public',
    store: 'apps/store/public',
  },
  cards: [{
    output: 'home.webp',
    formats: ['png', 'svg'],
    aliases: [
      'og.webp',
      { directory: 'docs', output: 'social/home.webp' },
    ],
    formatAliases: { png: ['share.png'] },
    data: home,
  }],
  assets: [{
    source: 'assets/app-icon.png',
    directory: 'store',
    output: 'app-icon.png',
  }],
  renderer,
})
One card, several formats.

Each requested encoding renders once; every alias for that encoding reuses its bytes.

09

Deterministic preset typography

Presets bundle Inter Variable, embed it into generated SVG, measure real glyph advances, split long tokens at grapheme boundaries, and truncate safely. Text layout therefore stays portable across build machines, mixed-width scripts, code-heavy titles, and emoji.

export default definePresetConfig({
  cards,
  preset: {
    brand: { name: 'Example' },
    typography: {
      file: 'public/fonts/Brand.woff2',
      family: 'Brand',
    },
  },
})

Set preset.typography.file to a local WOFF, WOFF2, TTF, or OTF font and give it a matching family. The file is automatically included in the preset cache fingerprint. Keep the bundled font by omitting typography.

10

Cache and cleanup guarantees

Fingerprints include card data, dimensions, destinations, config contents, declared sources, the generator version, and an optional semantic cache key. Presets also record their preset version.

FingerprintContent-aware

Only cards affected by an input change are rebuilt.

IntegrityOutput digest

Checks detect missing, edited, or corrupted generated bytes.

CleanupTracked only

Only obsolete outputs recorded by the previous manifest are removed.

Semantic cache revisions

Set cache.key when renderer behavior changes without a directly tracked source change. The key participates in every fingerprint and appears in human-readable and JSON summaries. Preset configs supply their own preset-v1 key automatically.

export default defineConfig({
  cards,
  renderer,
  cache: {
    key: 'editorial-renderer-v2',
    sources: ['public/fonts/*.woff2', 'public/logo.svg'],
  },
})

Output and manifest paths remain constrained to the project root. Commit the manifest with committed images; ignore both when images are CI-only artifacts. Use santi-og check for verification and santi-og compare for non-destructive visual reports.

11

CLI reference

Command or optionPurpose
initCreate a working preset configuration.
generateRender changed cards and clean tracked obsolete output when enabled.
checkReport missing, changed, or stale cards without mutation.
compareReport dimensions, format, size, and pixel differences without replacing files.
migrate --reportInventory cards, outputs, local renderer modules, and remaining custom responsibilities.
upgrade --toUpdate package dependencies, pnpm catalogs, and release-age exclusions.
--jsonPrint machine-readable generation, check, comparison, migration, or upgrade results.
--thresholdFail when the changed-pixel ratio exceeds the accepted value, or whenever an output is missing or changes dimensions.
--config, -cUse a specific config file or package directory.
--concurrencySet active renders to a positive number or auto.
--force, -fRegenerate every card regardless of its fingerprint.
--cleanRemove obsolete outputs tracked by the manifest.

Machine-readable results

Add --json for CI, migration tooling, or adoption reports. Generation and checks expose the exact changed sets, total logical cards, library version, semantic cache key, and elapsed time.

{
  "command": "generate",
  "config": "/project/og.config.mjs",
  "cacheKey": "preset-v1",
  "checked": false,
  "generated": ["home.webp"],
  "skipped": ["docs.webp"],
  "cleaned": [],
  "stale": [],
  "total": 2,
  "version": "0.4.0",
  "elapsedMilliseconds": 184
}
CommandJSON fields
generate / checkcommand, config, cacheKey, checked, generated, skipped, cleaned, stale, total, version, elapsedMilliseconds.
comparecommand, version, and comparisons with output, status, actual/expected image details, and changed-pixel counts and ratio.
migrate --reportConfig path and lines, generator version, cache key, custom-renderer status, local modules, logical and physical counts, and recommendations.
upgradeTarget version, detected package manager, and each changed file with its previous and next values.
12

Config reference

PropertyDefaultDescription
cardsRequiredCards or an asynchronous card collector.
presetNeutralBrand, theme, typography, variant, and Sharp options for definePresetConfig.
rendererCustom configs onlyA function or worker descriptor used by defineConfig.
assets[]Static files copied and tracked alongside cards.
outputDirectorypublic/ogPrimary output directory relative to the project root.
outputDirectories{}Additional named output directories.
width / height1200 × 630Default dimensions; individual cards may override them.
cacheEnabledBoolean or cache options with semantic key, manifest path, and shared sources.
cleanfalseRemove only obsolete outputs previously tracked by the tool.
concurrencyRenderer-basedFixed, automatic, or bounded automatic active renders.
rootConfig directoryProject root used to resolve and constrain paths.
Migration guide

Replace repeated renderers with portable v0.4 workflows.

The ten-project migration removed 2,273 lines of consumer Open Graph code while preserving route data and project-owned branding.

Read the migration guide