Skip to content
Grafex
GitHub

Getting Started

Go from zero to a rendered image in under 5 minutes.

Install

bash
npm install grafex

Grafex uses WebKit for rendering. The browser binary is downloaded automatically during npm install via a postinstall script — no extra steps needed.

Tip: If the postinstall download fails (corporate firewalls, restricted CI environments), see Browser Setup for manual installation.

Requirements: Node.js >= 20.0.0

Write a composition

Create a file called card.tsx:

card.tsx
import type { CompositionConfig } from 'grafex';

export const config: CompositionConfig = {
  width: 1200,
  height: 630,
};

export default function Card() {
  return (
    <div
      style={{
        width: '100%',
        height: '100%',
        background: 'linear-gradient(135deg, #667eea, #764ba2)',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        color: 'white',
        fontSize: '64px',
        fontWeight: 'bold',
        fontFamily: 'system-ui, sans-serif',
      }}
    >
      Hello, Grafex!
    </div>
  );
}

A composition has two parts:

  1. Default export — a function that returns JSX. This is your image layout.
  2. Named config export — a CompositionConfig object that sets the output dimensions, format, and optional features like custom fonts and CSS files.

TypeScript Setup

Run grafex init to generate the correct tsconfig.json automatically:

bash
npx grafex init

This creates a tsconfig.json and a starter composition.tsx in your current directory. Existing files are never overwritten.

Or add these compiler options to your tsconfig.json manually:

tsconfig.json
{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment"
  }
}

Grafex ships its own JSX type definitions. They are picked up automatically once the package is installed — no extra imports needed. The h and Fragment functions are injected at transpile time, so you never import them in composition files.

Export

bash
npx grafex export -f card.tsx -o card.png

Grafex bundles your composition with esbuild, renders it in a headless WebKit instance, and saves the screenshot as an image. The output is a 1200×630 image with your gradient background and centered text.

See it in action

This is the kind of image Grafex can generate. Write the code, run one command, see the result — no browser window, no server.

og-card.tsx
export const config = {
  width: 600,
  height: 400,
};

export default function OgCard() {
  return (
    <div style={{
      width: '100%',
      height: '100%',
      background: 'linear-gradient(145deg, #0f172a 0%, #1e293b 100%)',
      display: 'flex',
      flexDirection: 'column',
      justifyContent: 'space-between',
      padding: '52px',
      fontFamily: 'system-ui, -apple-system, sans-serif',
      position: 'relative',
      overflow: 'hidden',
    }}>
      {/* Top accent glow */}
      <div style={{
        position: 'absolute',
        top: '-60px',
        right: '-60px',
        width: '300px',
        height: '300px',
        background: 'radial-gradient(circle, rgba(244,114,182,0.2) 0%, transparent 70%)',
      }} />

      {/* Top: tag */}
      <div style={{ display: 'flex', alignItems: 'center', gap: '12px', zIndex: 1 }}>
        <div style={{
          background: 'rgba(163,230,53,0.15)',
          border: '1px solid rgba(163,230,53,0.3)',
          borderRadius: '6px',
          padding: '4px 12px',
          color: '#A3E635',
          fontSize: '12px',
          fontWeight: '600',
          letterSpacing: '0.08em',
          textTransform: 'uppercase',
        }}>
          Tutorial
        </div>
        <span style={{ color: '#475569', fontSize: '13px' }}>5 min read</span>
      </div>

      {/* Middle: title */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', zIndex: 1 }}>
        <div style={{
          color: '#F1F5F9',
          fontSize: '36px',
          fontWeight: '700',
          lineHeight: '1.2',
          letterSpacing: '-0.5px',
        }}>
          Building Modern APIs
        </div>
        <div style={{ color: '#94A3B8', fontSize: '16px', lineHeight: '1.5' }}>
          Best practices for REST and GraphQL in 2026
        </div>
      </div>

      {/* Bottom: author + meta */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', zIndex: 1 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
          <div style={{
            width: '36px',
            height: '36px',
            borderRadius: '50%',
            background: 'linear-gradient(135deg, #F472B6, #38BDF8)',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            color: 'white',
            fontSize: '14px',
            fontWeight: '700',
            flexShrink: 0,
          }}>
            JS
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: '2px' }}>
            <span style={{ color: '#E2E8F0', fontSize: '14px', fontWeight: '600' }}>Jane Smith</span>
            <span style={{ color: '#64748B', fontSize: '12px' }}>March 15, 2026</span>
          </div>
        </div>
        <div style={{
          color: '#475569',
          fontSize: '13px',
          fontWeight: '600',
          letterSpacing: '0.05em',
        }}>
          dev.blog
        </div>
      </div>

      {/* Bottom-left accent stripe */}
      <div style={{
        position: 'absolute',
        bottom: '0',
        left: '0',
        right: '0',
        height: '3px',
        background: 'linear-gradient(90deg, #F472B6, #38BDF8, #A3E635)',
      }} />
    </div>
  );
}
Rendered OG card composition output og-card.png
bash
npx grafex export -f og-card.tsx -o og-card.png

Next steps