Skip to main content

Overview

Font pairings combine three fonts (heading, body, and mono) with complete CSS configurations for typography across all HTML elements. Each pairing includes metadata, dependencies, CSS variables, and styles.

Schema Structure

Root Fields

name
string
required
Unique identifier for the pairing, typically prefixed with pairing-Example: "pairing-minimal", "pairing-brutalist"
type
string
required
Registry type identifier. Always "registry:style" for pairings.
extends
string
required
Base style to extend from. Use "none" for standalone pairings.
title
string
required
Human-readable title showing the pairing name and font combinationFormat: "{Name} — {Heading} + {Body} + {Mono}"Example: "Minimal — Geist + Geist + Geist Mono"
description
string
required
Descriptive text explaining the pairing’s aesthetic and design philosophy
categories
string[]
required
Array of category tags for filtering and discoveryCommon categories: "sans-serif", "serif", "minimal", "modern", "brutalist", "display", "bold"

Dependencies

registryDependencies
string[]
required
Array of URLs pointing to font configurations in the registryEach URL typically references 2-3 fonts:
  • Heading font
  • Body font
  • Monospace font
Format: "https://www.fonttrio.xyz/r/{font-name}.json"

CSS Variables

cssVars
object
required
Defines CSS custom properties for theme integration
theme
object
required
Theme-level CSS variables
--font-heading
string
required
CSS variable reference for heading fontExample: "var(--font-geist)"
--font-body
string
required
CSS variable reference for body fontExample: "var(--font-inter)"
--font-mono
string
required
CSS variable reference for monospace fontExample: "var(--font-geist-mono)"

CSS Styles

css
object
required
Complete typography styles for all HTML elements. Keys are CSS selectors, values are style objects.
h1
object
required
Styles for primary headings
font-family
string
required
Font family, typically referencing var(--font-heading)
font-size
string
required
Font size in rem, em, or pxExample: "2.25rem"
line-height
string
required
Unitless line height valueExample: "1.15"
letter-spacing
string
required
Letter spacing in em unitsExample: "-0.025em"
font-weight
string
required
Font weight value (100-900)Example: "700"
h2, h3, h4, h5, h6
object
Similar structure to h1, can target multiple selectors
body, p
object
required
Styles for body text and paragraphs
font-family
string
required
Body font family, typically var(--font-body)
line-height
string
required
Line height for body textExample: "1.6"
code, pre
object
required
Styles for code elements
font-family
string
required
Monospace font family, typically var(--font-mono)

Metadata

meta
object
Additional metadata for preview and categorization
preview
string
Sample text for font previewDefault: "The quick brown fox jumps over the lazy dog"
mood
string[]
Array of mood descriptorsExamples: ["modern", "minimal"], ["raw", "brutalist"]
useCase
string[]
Suggested use cases for the pairingExamples: ["SaaS", "developer tools"], ["portfolio", "art"]

Complete Examples

Minimal Pairing

A clean, modern single-font pairing using Geist:
{
  "name": "pairing-minimal",
  "type": "registry:style",
  "extends": "none",
  "title": "Minimal — Geist + Geist + Geist Mono",
  "description": "Ultra-minimal Vercel-style pairing. One font family for everything, clean and modern.",
  "categories": ["sans-serif", "minimal", "modern"],
  "registryDependencies": [
    "https://www.fonttrio.xyz/r/geist.json",
    "https://www.fonttrio.xyz/r/geist-mono.json"
  ],
  "cssVars": {
    "theme": {
      "--font-heading": "var(--font-geist)",
      "--font-body": "var(--font-geist)",
      "--font-mono": "var(--font-geist-mono)"
    }
  },
  "css": {
    "h1": {
      "font-family": "var(--font-heading)",
      "font-size": "2.25rem",
      "line-height": "1.15",
      "letter-spacing": "-0.025em",
      "font-weight": "700"
    },
    "h2": {
      "font-family": "var(--font-heading)",
      "font-size": "1.875rem",
      "line-height": "1.2",
      "letter-spacing": "-0.02em",
      "font-weight": "600"
    },
    "h3": {
      "font-family": "var(--font-heading)",
      "font-size": "1.5rem",
      "line-height": "1.3",
      "letter-spacing": "-0.015em",
      "font-weight": "500"
    },
    "h4, h5, h6": {
      "font-family": "var(--font-heading)",
      "letter-spacing": "-0.01em"
    },
    "body, p": {
      "font-family": "var(--font-body)",
      "line-height": "1.6"
    },
    "code, pre": {
      "font-family": "var(--font-mono)"
    }
  },
  "meta": {
    "preview": "The quick brown fox jumps over the lazy dog",
    "mood": ["modern", "minimal", "Vercel-style"],
    "useCase": ["SaaS", "developer tools", "Vercel-style"]
  }
}

Brutalist Pairing

A bold, high-contrast pairing with Archivo Black:
{
  "name": "pairing-brutalist",
  "type": "registry:style",
  "extends": "none",
  "title": "Brutalist — Archivo Black + Archivo + Source Code Pro",
  "description": "Raw typographic power. Archivo Black's heavy weight fills every pixel of the headline, while regular Archivo maintains the same DNA in a readable body weight. No decoration, pure function.",
  "categories": ["display", "brutalist", "bold"],
  "registryDependencies": [
    "https://www.fonttrio.xyz/r/archivo-black.json",
    "https://www.fonttrio.xyz/r/archivo.json",
    "https://www.fonttrio.xyz/r/source-code-pro.json"
  ],
  "cssVars": {
    "theme": {
      "--font-heading": "var(--font-archivo-black)",
      "--font-body": "var(--font-archivo)",
      "--font-mono": "var(--font-source-code-pro)"
    }
  },
  "css": {
    "h1": {
      "font-family": "var(--font-heading)",
      "font-size": "2.75rem",
      "line-height": "1.05",
      "letter-spacing": "-0.035em",
      "font-weight": "800"
    },
    "h2": {
      "font-family": "var(--font-heading)",
      "font-size": "2.25rem",
      "line-height": "1.1",
      "letter-spacing": "-0.025em",
      "font-weight": "700"
    },
    "h3": {
      "font-family": "var(--font-heading)",
      "font-size": "1.75rem",
      "line-height": "1.2",
      "letter-spacing": "-0.02em",
      "font-weight": "700"
    },
    "h4, h5, h6": {
      "font-family": "var(--font-heading)",
      "letter-spacing": "-0.01em"
    },
    "body, p": {
      "font-family": "var(--font-body)",
      "line-height": "1.6"
    },
    "code, pre": {
      "font-family": "var(--font-mono)"
    }
  },
  "meta": {
    "preview": "The quick brown fox jumps over the lazy dog",
    "mood": ["raw", "brutalist"],
    "useCase": ["portfolio", "art", "experimental"]
  }
}

CSS Override Behavior

When query parameters are provided to the API endpoint, the CSS properties are dynamically overridden:

Example Request

GET /api/r/minimal?h1-size=3rem&body-lh=1.8

Resulting CSS

The returned JSON will have modified CSS:
{
  "css": {
    "h1": {
      "font-family": "var(--font-heading)",
      "font-size": "3rem",  // ← Overridden from 2.25rem
      "line-height": "1.15",
      "letter-spacing": "-0.025em",
      "font-weight": "700"
    },
    "body, p": {
      "font-family": "var(--font-body)",
      "line-height": "1.8"  // ← Overridden from 1.6
    }
  }
}
Implementation: app/api/r/[name]/route.ts:47-85

Usage in Next.js

import { NextResponse } from 'next/server';

interface PairingConfig {
  name: string;
  title: string;
  cssVars: {
    theme: Record<string, string>;
  };
  css: Record<string, Record<string, string>>;
}

export async function loadPairing(
  name: string,
  overrides?: Record<string, string>
): Promise<PairingConfig> {
  const params = new URLSearchParams(overrides);
  const url = `https://www.fonttrio.xyz/api/r/${name}${
    params.toString() ? `?${params}` : ''
  }`;
  
  const response = await fetch(url);
  
  if (!response.ok) {
    throw new Error(`Failed to load pairing: ${name}`);
  }
  
  return response.json();
}

// Usage
const pairing = await loadPairing('minimal');
const customPairing = await loadPairing('brutalist', {
  'h1-size': '3.5rem',
  'body-lh': '1.7'
});

See Also

Font Schema

Schema for individual font configurations

API Endpoints

Complete endpoint reference with examples

Build docs developers (and LLMs) love