Skip to content

React Integration (Full Guide)

This guide walks through a complete React integration: loading the SDK, rendering the editor, listening for events, and generating PDFs via the API. For the component wrapper reference, see React.

Terminal window
npm install @glyph-sdk/web

Register once at your app entry point:

src/main.tsx
import '@glyph-sdk/web';

The <glyph-editor> web component works directly in JSX. Pass data as a JSON string:

function InvoiceEditor({ invoice }) {
const editorRef = useRef<HTMLElement>(null);
return (
<glyph-editor
ref={editorRef}
api-key={import.meta.env.VITE_GLYPH_API_KEY}
base-url="https://api.glyph.you"
template="quote-modern"
data={JSON.stringify(invoice)}
/>
);
}

The editor emits Custom Events. Attach listeners in a useEffect:

useEffect(() => {
const el = editorRef.current;
if (!el) return;
const onReady = () => console.log('Editor ready');
const onModified = (e: CustomEvent) => {
console.log('Modified:', e.detail.prompt);
// e.detail.html contains the updated HTML
};
const onError = (e: CustomEvent) => {
console.error(e.detail.code, e.detail.message);
};
el.addEventListener('glyph:ready', onReady);
el.addEventListener('glyph:modified', onModified);
el.addEventListener('glyph:error', onError);
return () => {
el.removeEventListener('glyph:ready', onReady);
el.removeEventListener('glyph:modified', onModified);
el.removeEventListener('glyph:error', onError);
};
}, []);

Available events: glyph:ready, glyph:modified, glyph:saved, glyph:error, glyph:region-selected. See Events for details.

Call methods on the element ref:

async function applyChange(prompt: string) {
const editor = editorRef.current as any;
await editor.modify(prompt);
}
// Undo / redo
editor.undo();
editor.redo();

You can generate PDFs either through the SDK or by calling the API directly from your server.

async function downloadPdf() {
const editor = editorRef.current as any;
const blob = await editor.generatePdf();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'document.pdf';
a.click();
URL.revokeObjectURL(url);
}

Keep your API key on the server. Fetch the session HTML from the client, then call the generate endpoint:

// pages/api/generate-pdf.ts (Next.js example)
export default async function handler(req, res) {
const { html } = req.body;
const response = await fetch('https://api.glyph.you/v1/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.GLYPH_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ html, format: 'pdf' }),
});
if (!response.ok) {
const error = await response.json();
return res.status(response.status).json(error);
}
const buffer = Buffer.from(await response.arrayBuffer());
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', 'attachment; filename="document.pdf"');
res.send(buffer);
}

A minimal but complete React app:

import { useRef, useEffect, useState } from 'react';
import '@glyph-sdk/web';
const sampleData = {
client: { name: 'Acme Corp', email: 'billing@acme.com' },
lineItems: [
{ description: 'API Integration', quantity: 1, unitPrice: 5000, total: 5000 },
{ description: 'Support (monthly)', quantity: 3, unitPrice: 500, total: 1500 },
],
totals: { subtotal: 6500, tax: 520, total: 7020 },
meta: { quoteNumber: 'Q-2025-001', date: 'Jan 15, 2025' },
};
export default function App() {
const ref = useRef<HTMLElement>(null);
const [ready, setReady] = useState(false);
useEffect(() => {
const el = ref.current;
if (!el) return;
const handler = () => setReady(true);
el.addEventListener('glyph:ready', handler);
return () => el.removeEventListener('glyph:ready', handler);
}, []);
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
<header style={{ padding: '1rem', borderBottom: '1px solid #e5e5e5' }}>
<button
disabled={!ready}
onClick={async () => {
const blob = await (ref.current as any).generatePdf();
const url = URL.createObjectURL(blob);
window.open(url);
}}
>
Download PDF
</button>
</header>
<glyph-editor
ref={ref}
api-key={import.meta.env.VITE_GLYPH_API_KEY}
base-url="https://api.glyph.you"
template="quote-modern"
data={JSON.stringify(sampleData)}
style={{ flex: 1 }}
/>
</div>
);
}