Generate social meta images (Open Graph and share-card images) for the posts of a static website, driven by each post's frontmatter.
You describe an image in frontmatter with a title, a subtitle, a version and a template name, and Colophon renders branded PNGs at the sizes you need. The name comes from the printer's colophon, the emblem a publisher stamps on a finished work.
- Frontmatter-driven. Props are read from a post rather than fixed by a schema.
- Templates. A small registry of layouts, picked per post from frontmatter.
- Syntax-highlighted code images. The
codetemplate renders a snippet from frontmatter with real VS Code theme colours. - Configurable branding. Colours, gradient, fonts, footer and badge come from config, not from any one site's stylesheet.
- Themes. Eight named looks, or your own colours with a mesh, a dot grid or ruled lines over them.
- Multiple sizes from one input. A 1:1 square and a 1.91:1 landscape by default, or whatever set you configure.
- Manifest and meta tags. A JSON record of what was generated, and the Open Graph and Twitter tags that go with it.
- Small, reusable API. A render core with no filesystem concerns, plus an optional content walker and CLI.
pnpm add @kensio/colophon@resvg/resvg-js rasterises the SVG to PNG, and shiki provides the grammars
and themes for the code template. No headless browser is involved. Outfit and
JetBrains Mono ship with the package and are used by default, so a build renders
the same image everywhere without configuring anything; point fonts at your
own files to use those instead.
Add image props to a post's frontmatter:
---
title: My post
meta_img_props:
template: banner
title: "@kensio/colophon"
subtitle: Generate social meta images from frontmatter
version: 1.2.0
---Create a config module, or omit it to use the neutral defaults:
// colophon.config.ts
import { defineConfig } from "@kensio/colophon";
export default defineConfig({
colors: { brand: "#2563eb", brandDark: "#1e3a8a", brandWarm: "#f59e0b" },
footer: "example.com",
badge: { text: "npm" },
});colophon init writes that file for you, guessing where your content lives.
Run it over a content tree:
colophon content --config colophon.config.tsFor every file that declares meta_img_props, Colophon writes one PNG per
output size next to it, named <slug>-<size>.png, so post/index.md produces
post/post-og.png and post/post-square.png. Set format to webp, jpeg or
avif for a quarter of the bytes.
While tuning a template, colophon preview <file> renders one post and opens
it, --watch rebuilds on every change, and --dry-run reports what would
change without writing anything.
There is also a programmatic API. renderMetaImages takes props and config and
returns rendered bytes, and generate ties walking, rendering and writing
together.
Full documentation is in docs/.
- Getting started
- The command line
- Templates
- The code template
- Astro
- The browser-safe core
- The layout toolkit
- Themes and background treatments
- Logos and photographs
- Configuration
- Output formats
- File size
- Rebuilds
- Programmatic use
- Upgrading
These are generated by scripts/gen-samples.ts from
the sample list in test/samples.ts. Run pnpm samples to
regenerate them after changing a template, then commit the updated PNGs so this
gallery stays in sync.
One line of config each: theme: "midnight". See
Themes and background treatments for what a
theme sets and how to override part of one.
![]() midnight
|
![]() aurora
|
![]() ember
|
![]() forest
|
![]() bloom
|
![]() slate
|
![]() paper
|
![]() sandstone
|
| Script | What it does |
|---|---|
pnpm build |
Compile to dist/. |
pnpm test, pnpm test:coverage |
Run Vitest. |
pnpm lint |
Oxlint, ESLint and oxfmt check, run together. |
pnpm fmt |
Auto-fix. |
pnpm samples |
Regenerate the sample images into docs/samples/. |
pnpm baselines |
Re-record the visual regression baselines in test/baselines/. |
pnpm fta |
FTA scores, failing on any file 50 or above. |
pnpm check |
Format, FTA, typecheck, build and test with coverage. Run before committing. |
Templates are pictures, so pnpm test renders every sample and compares it
against a committed baseline in test/baselines/. A change to a template shows
up as a failure naming how far the image moved, and writes what it rendered to
test/.visual/ so you can open the two side by side. CI uploads the same
images as an artifact when the check fails.
When the change was the point, run pnpm baselines and commit the new PNGs with
it. The diff is then the before and after, which is the review the check exists
to make possible.
The baselines are rendered with font files rather than whatever the machine has installed, and at a fraction of the width they are laid out at, which keeps them reproducible anywhere and small enough to live in the repository. The gallery above is rendered separately, as a project would render it.
Apache-2.0
























