@lacspace/og
v1.2.0
Published
Dynamic Open Graph images — a share-card design system you configure once and call per page. Produces a next/og element tree AND a zero-dependency SVG from the same options, with auto-fitting titles, presets, badges and gradients. Zero-dependency, isomorp
Maintainers
Readme
@lacspace/og
Dynamic Open Graph images — configure the look once, call it per page.
Every page deserves a gorgeous share card.
@lacspace/oggives you one design system that renders two ways from the same options — anext/ogelement tree (real PNG via Satori) and a standalone SVG (no browser, no deps) — with auto-fitting titles, eyebrows, badges, logos and gradients.
New in 1.2.0 — a zero-dependency SVG template renderer (
ogTemplateSvg) with 7 layouts (classic·minimal·split·article·product·quote·event), named gradient & surface presets (ogGradients,ogSurfaces) plus full custom colours, image/avatar embedding (pass a data URI), an auto text-fit helper (fitTitle— multi-line wrap + font-shrink), background patterns/accent bars, and two more element-tree layouts (ogQuote,ogEvent). All additive — nothing existing changed.
Install
npm i @lacspace/ogUse it with next/og (dynamic PNG)
// app/og/route.tsx
import { ImageResponse } from "next/og";
import { ogCard } from "@lacspace/og";
export const runtime = "edge";
export function GET(req: Request) {
const title = new URL(req.url).searchParams.get("title") ?? "My site";
return new ImageResponse(
ogCard({
title,
eyebrow: "Guide",
subtitle: "my-site.com",
logo: "M",
from: "#22d3ee",
to: "#6366f1",
}) as any,
{ width: 1200, height: 630 },
);
}Then point your metadata at it: openGraph.images = ["/og?title=" + encodeURIComponent(pageTitle)].
Use it anywhere (zero-dependency SVG)
ogSvg() needs no browser and no Satori — perfect for previews, email headers, README banners, or a guaranteed fallback:
import { ogSvg, ogSvgDataUri } from "@lacspace/og";
const svg = ogSvg({ title: "Launch day", badge: "NEW", from: "#f43f5e", to: "#f59e0b" });
// -> "<svg …>…</svg>" (write to a file, return as image/svg+xml, embed inline)
const uri = ogSvgDataUri({ title: "Hello" });
// -> "data:image/svg+xml;utf8,…" (drop straight into <img src> or background-image)Options
| Option | Meaning |
| --- | --- |
| title | Headline — font size auto-fits to length |
| subtitle | Secondary line (often your domain) |
| eyebrow | Small uppercase label above the title |
| badge | A pill (e.g. "NEW", "Guide") |
| logo | Initial / emoji for the corner mark |
| footer | Bottom-left line (e.g. your URL) |
| from / to | Accent gradient stops |
| theme | "dark" (default) or "light" |
| preset | "gradient" · "split" · "minimal" · "terminal" |
| width / height | Canvas — defaults to the OG standard 1200×630 |
Also exports fitFontSize(title) if you want the sizing math for your own layout.
Pairs with @lacspace/seo — feed the generated URL to defineSite().meta({ image }).
More card layouts (new)
Beyond ogCard, the package ships four more ready-made layouts — all return the
same element tree, work in the edge runtime, and degrade gracefully when
optional fields are missing.
import {
ogCardSplit, // title/subtitle on the left, gradient accent panel + logo on the right
ogCardMinimal, // big centered title on a full-bleed gradient, minimal chrome
ogArticle, // category · title · footer row with author · date · reading time
ogProduct, // title · subtitle/badge · large price with currency
ogThemes, // named gradient presets: lacspace, ocean, sunset, forest, grape, slate
} from "@lacspace/og";
// Two-column split (logo falls back to the title's first letter)
ogCardSplit({ title: "Ship faster", subtitle: "docs.example.com", logo: "L", theme: "dark" });
// Minimal centered — pick a named gradient instead of from/to
ogCardMinimal({ title: "Launch day", gradient: "sunset", pattern: "glow" });
// Article card
ogArticle({
title: "How we cut cold starts in half",
eyebrow: "Engineering",
author: "Ada Lovelace",
date: "Sep 5, 2026",
readingTime: "6 min read",
pattern: "dots",
});
// Product / pricing card
ogProduct({ title: "Pro plan", subtitle: "Everything you need", badge: "POPULAR", price: 49, currency: "$" });Extra options accepted by all four (on top of the existing OgOptions):
| Option | Meaning |
| --- | --- |
| gradient | A named preset from ogThemes (lacspace · ocean · sunset · forest · grape · slate) — shorthand for from/to; explicit from/to still win |
| pattern | Faint background texture: "dots" · "glow" · "none" (default) |
| author / date / readingTime | Footer meta for ogArticle |
| price / currency | Large price for ogProduct (e.g. price: 49, currency: "$" → $49) |
ogCard, ogSvg, ogSvgDataUri and fitFontSize are unchanged and fully
backward compatible.
SVG templates (new in 1.2.0)
ogTemplateSvg() renders any of seven layouts as a standalone SVG — no
browser, no Satori — with named presets, image embedding and auto-fitting
titles. Great for previews, email headers, README banners and edge fallbacks.
import { ogTemplateSvg, ogTemplateSvgDataUri } from "@lacspace/og";
const svg = ogTemplateSvg({
template: "article", // classic | minimal | split | article | product | quote | event
title: "How we cut cold starts in half",
eyebrow: "Engineering",
author: "Ada Lovelace",
date: "Sep 7, 2026",
readingTime: "6 min read",
gradient: "aurora", // a named gradient preset
image: "data:image/png;base64,iVBORw0KG…", // logo/avatar as a data URI
pattern: "dots",
});
const uri = ogTemplateSvgDataUri({ template: "quote", title: "Stay hungry.", author: "S. Jobs" });Template options (all optional, superset of OgOptions)
| Option | Meaning |
| --- | --- |
| template | classic · minimal · split · article · product · quote · event (default classic) |
| gradient | A named preset from ogGradients — shorthand for from/to (explicit wins) |
| surface | A named ground palette from ogSurfaces (ink · midnight · slate · paper · cream) |
| bg / fg / muted | Full custom colour control (override theme/surface) |
| pattern | Background texture: "dots" · "grid" · "glow" · "none" |
| accentBar | Show the top accent bar (default true) |
| image | Logo/avatar as a data URI — rendered in the corner mark |
| initials | Initials shown in the mark when no image/logo |
| icon | An emoji/icon glyph slot |
| handle | A handle/URL line, bottom-right |
| maxTitleLines | Cap before the headline truncates with … |
| author / date / readingTime | article meta |
| price / currency | product price |
| cite | quote source (alongside author) |
| when / location | event date-time & place |
Named presets
import { ogGradients, ogSurfaces } from "@lacspace/og";
// ogGradients — a SUPERSET of ogThemes: lacspace, ocean, sunset, forest, grape,
// slate, midnight, aurora, ember, gold, rose, mint, cosmos, candy, mono
// ogSurfaces — ground palettes: ink, midnight, slate, paper, creamAuto text-fit
import { fitTitle } from "@lacspace/og";
const { fontSize, lines } = fitTitle("A very long headline…", { maxWidth: 1000, maxLines: 3 });
// Wraps into ≤ maxLines lines, shrinking the font (2px steps, from max→min) to fit,
// then truncates the last line with "…" if it still overflows.Auto-fit is a pure text-measurement heuristic — there is no canvas, so glyph width is approximated as
fontSize * charRatio(default0.56). Treat sizing as a close estimate, not pixel-perfect.
More element-tree layouts
import { ogQuote, ogEvent } from "@lacspace/og";
ogQuote({ title: "Ship it.", author: "Ada", image: "data:image/png;base64,…" });
ogEvent({ title: "DevConf 2026", eyebrow: "Meetup", when: "Oct 3, 6pm", location: "Kathmandu" });Licensing
This package is free under the Lacspace Free Licence — permissive freedoms. Use it in personal and commercial projects at no cost; just keep the notice.
Not every Lacspace package is free. We also offer Commercial (paid), Client-specific, and Private (proprietary) packages under separate terms. See the full Lacspace Licence Centre.
The Lacspace Developer Platform
@lacspace/og is part of 80+ zero-dependency, isomorphic TypeScript packages — one standard library for the modern web. Explore the ecosystem:
- 📦 This package, documented — https://developer.lacspace.com/packages/og
- 🗂️ All 80+ packages — https://developer.lacspace.com/packages
- 🧭 Developer handbook — guides & runnable recipes — https://developer.lacspace.com/handbook
- 🧪 Live playground — run any package in your browser — https://developer.lacspace.com/playground
- 🖥️ Finished app templates — https://templates.lacspace.com
- 🚀 Scaffold a full app —
npm create lacspace-app@latest
Free under the Lacspace Free Licence — a permissive, free-to-use licence.
