Skip to main content

Social images

Favicon and Webmanifest

meta.icon accepts either a single source path or an object with two sources:

// Single source (same icon for all sizes)
meta: { icon: "src/assets/icon.svg" }

// Two sources — simplified design for tiny favicons, detailed for manifest
meta: {
  icon: {
    favicon: "src/assets/favicon.svg",
    manifest: "src/assets/icon-detailed.svg",
  },
}

Use the object form when a detailed 512x512 design becomes illegible at 16-32px. Both favicon and manifest are required in the object form.

File Source Size/Format
/favicon.svg favicon Passthrough (SVG source only)
/favicon.ico favicon 32x32 ICO
/favicon-96x96.png manifest 96x96 PNG
/apple-touch-icon.png manifest 180x180 PNG
/web-app-manifest-192x192.png manifest 192x192 PNG
/web-app-manifest-512x512.png manifest 512x512 PNG
/site.webmanifest JSON manifest with project name and icon refs

The Layout <head> renders the corresponding <link> tags only when meta.icon is set. Uses sharp for image resizing (bundled with the theme).

Open Graph and Twitter Cards

/og.png is always served. By default it uses a built-in satori template; override via meta.og.image:

Tip: in most cases, provide a dedicated image.logo. Your site logo is tuned for the site’s own surface colors (light/dark neutrals), but the OG card uses a theme-hue-tinted background — a logo that reads cleanly on the site can lose contrast or clash on the card. An OG-specific variant with a palette tuned for that background keeps the mark legible across any theme.hue.

// Default: built-in template with fallback logo. No config needed.
// meta: { og: { image: true } }

// Static PNG (served as-is)
meta: { og: { image: "src/assets/og.png" } };

// Built-in template with overrides (all fields optional)
meta: {
  og: {
    image: {
      logo: "src/assets/og-logo.png", // string path | false (skip) | absent (fallback)
      title: "My App",                // override project.name on the card
      description: "Short pitch",     // override project.description on the card
    },
  },
};

// Custom satori template (same override fields apply)
meta: {
  og: {
    image: {
      template: "./src/og-template.ts",
      title: "My App",
    },
  },
};

Built-in and template modes require sharp (same peer dep as meta.icon). The built-in template uses theme.hue for color, bundled Martian Grotesk + Mono, and project.{name,description}. Logo resolution: explicit image.logo (string) → top-level logo → nothing. The resolved logo is rendered in its original colors (no processing) and replaces the project name; pass image: { logo: false } to render only the project name even when a top-level logo is set.

The built-in OG template always uses the bundled Martian fonts — it does not pick up whatever you’ve configured in Astro’s top-level fonts option. Astro’s font pipeline emits woff2 only, but satori requires TTF/OTF, so server-side image generation is decoupled from browser-served fonts. To use different typography in your OG card, switch to a custom template (mode 2 above) and load your own TTF/OTF buffers inside it — ctx.fonts is provided as a convenience but isn’t required.

Custom templates default-export an OgTemplateFn:

// src/og-template.ts
import type { OgTemplateFn } from "astro-pigment";

const template: OgTemplateFn = (ctx) => ({
  type: "div",
  props: {
    style: {
      display: "flex",
      width: "1200px",
      height: "630px",
      color: "white",
      background: `hsl(${ctx.hue} 30% 12%)`,
    },
    children: ctx.projectName,
  },
});

export default template;

Satori’s color parser doesn’t handle oklch() — stick to hex, rgb(), or hsl() inside templates.

ctx exposes projectName, description, siteUrl, pathname, logo ({ src: dataUri, width, height } if meta.og.logo resolves, else undefined), hue, and fonts (Martian Grotesk Std Regular/Bold, Martian Mono Regular) for satori.

Twitter falls back to the OG image when meta.twitter.image is unset; set it independently to use a different mode/path. Twitter card is always summary_large_image when an image is present.

Theme copied