Documentation Index
Fetch the complete documentation index at: https://react-docx.com/llms.txt
Use this file to discover all available pages before exploring further.
import { render } from "@cordel/react-docx";
const { outputPath, diagnostics } = await render(<MyDocument />, "./output.docx");
Returns a Promise<RenderResult> with the output path and any diagnostics collected during rendering.
Basic usage
import { render, Document, Section, H1, Paragraph } from "@cordel/react-docx";
const MyDocument = () => (
<Document>
<Section>
<H1>Hello</H1>
<Paragraph>World</Paragraph>
</Section>
</Document>
);
const { outputPath, diagnostics } = await render(<MyDocument />, "./hello.docx");
renderToBuffer
For serverless or HTTP scenarios where you don’t want to write to disk:
import { renderToBuffer } from "@cordel/react-docx";
const { buffer, diagnostics } = await renderToBuffer(<MyDocument />);
Returns a Promise<RenderToBufferResult> with a Uint8Array buffer and diagnostics.
HTTP response
const { buffer } = await renderToBuffer(<Invoice />);
res.setHeader(
"Content-Type",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
);
res.send(buffer);
Write to file manually
import fs from "node:fs";
const { buffer } = await renderToBuffer(<MyDocument />);
fs.writeFileSync("output.docx", buffer);
Variables
Pass dynamic data to your document:
await render(<Invoice />, "./invoice.docx", {
variables: {
invoiceNumber: "INV-001",
customer: "Acme Corp",
total: 420.00,
},
});
Variable component
import { Variable } from "@cordel/react-docx";
const Invoice = () => (
<Document>
<Section>
<H1>
Invoice #<Variable name="invoiceNumber" />
</H1>
<Paragraph>
Customer: <Variable name="customer" defaultValue="N/A" />
</Paragraph>
</Section>
</Document>
);
useVariables hook
For more control:
import { useVariables } from "@cordel/react-docx";
const Invoice = () => {
const vars = useVariables<{
invoiceNumber: string;
customer: string;
total: number;
}>();
return (
<Document>
<Section>
<H1>Invoice #{vars.invoiceNumber}</H1>
<Paragraph>Customer: {vars.customer}</Paragraph>
<Paragraph>
<Text className="font-bold">Total: ${vars.total.toFixed(2)}</Text>
</Paragraph>
</Section>
</Document>
);
};
<Variable
name="price"
format={(value) => `$${Number(value).toFixed(2)}`}
/>
Render options
| Option | Type | Description |
|---|
variables | Record<string, VariableValue> | Dynamic data passed to Variable components and useVariables |
strict | boolean | Throw StrictModeError if any error-severity diagnostic is emitted |
tailwindParser | TailwindParser | Custom parser for overriding colors, fonts, or adding class handlers |
await render(<MyDocument />, "./output.docx", {
variables: { name: "John" },
strict: true,
});
Diagnostics
Both render and renderToBuffer return a diagnostics array. These are structured warnings and errors collected during rendering — images that failed to load, invalid nesting, unsupported Tailwind classes, etc.
const { outputPath, diagnostics } = await render(<MyDocument />, "./output.docx");
for (const d of diagnostics) {
console.log(`[${d.severity}] ${d.code}: ${d.message}`);
}
Diagnostic interface
interface Diagnostic {
code: string; // e.g. "IMAGE_LOAD_FAILED"
severity: "error" | "warning" | "info";
message: string;
element?: string; // Component name, e.g. "Image"
suggestion?: string; // How to fix the issue
path?: string; // Tree path, e.g. "Document > Section > Td"
url?: string; // Link to documentation
}
Common codes
| Code | Severity | Description |
|---|
IMAGE_LOAD_FAILED | error | Image file not found or URL unreachable |
INVALID_NESTING | error | Component placed in an unsupported parent |
UNSUPPORTED_TAILWIND_CLASS | warning | Tailwind class has no DOCX equivalent |
TAILWIND_CONFIG_LOAD_FAILED | warning | Failed to parse tailwind.config file |
VARIABLE_NOT_FOUND | info | Variable not provided and no defaultValue set |
Custom handler
Override how diagnostics are reported:
import { setDiagnosticHandler } from "@cordel/react-docx";
setDiagnosticHandler((d) => {
if (d.severity === "error") {
console.error(`[${d.code}] ${d.message}`);
}
});
Pass null to restore the default console-based handler:
setDiagnosticHandler(null);
Strict mode
Throws a StrictModeError if any diagnostic with "error" severity is emitted:
import { render, StrictModeError } from "@cordel/react-docx";
try {
await render(<MyDocument />, "./output.docx", { strict: true });
} catch (error) {
if (error instanceof StrictModeError) {
console.error("Document has errors:", error.message);
}
}
Works with renderToBuffer too:
const { buffer } = await renderToBuffer(<MyDocument />, { strict: true });
Error handling
Three levels of error handling:
Diagnostics — non-fatal issues returned in the result. The document still generates.
const { diagnostics } = await render(<MyDocument />, "./output.docx");
if (diagnostics.length > 0) {
console.warn(`${diagnostics.length} issue(s) found`);
}
Strict mode — promote error-severity diagnostics to thrown exceptions.
await render(<MyDocument />, "./output.docx", { strict: true });
Try/catch — handle unexpected failures (invalid JSX tree, filesystem errors, etc.).
try {
await render(<MyDocument />, "./output.docx");
} catch (error) {
console.error("Failed:", error);
}
Full example
import {
render,
Document,
Section,
H1,
Paragraph,
Text,
Table,
Thead,
Tbody,
Tr,
Th,
Td,
useVariables,
} from "@cordel/react-docx";
interface InvoiceData {
number: string;
date: string;
customer: { name: string; email: string };
items: { name: string; qty: number; price: number }[];
}
const Invoice = () => {
const vars = useVariables<InvoiceData>();
const total = vars.items.reduce((sum, item) => sum + item.qty * item.price, 0);
return (
<Document>
<Section>
<H1 className="text-blue-700">Invoice #{vars.number}</H1>
<Paragraph className="mt-4">
<Text className="font-bold">Date: </Text>{vars.date}
</Paragraph>
<Paragraph>
<Text className="font-bold">Customer: </Text>{vars.customer.name}
</Paragraph>
<Table className="mt-6 border">
<Thead>
<Tr>
<Th className="border p-2 bg-gray-100">Item</Th>
<Th className="border p-2 bg-gray-100">Qty</Th>
<Th className="border p-2 bg-gray-100">Price</Th>
</Tr>
</Thead>
<Tbody>
{vars.items.map((item, i) => (
<Tr key={i}>
<Td className="border p-2">{item.name}</Td>
<Td className="border p-2">{item.qty}</Td>
<Td className="border p-2">${item.price}</Td>
</Tr>
))}
</Tbody>
</Table>
<Paragraph className="mt-4 text-right">
<Text className="text-xl font-bold">Total: ${total}</Text>
</Paragraph>
</Section>
</Document>
);
};
const { outputPath, diagnostics } = await render(<Invoice />, "./invoice.docx", {
variables: {
number: "INV-001",
date: "2024-01-15",
customer: { name: "Acme Corp", email: "billing@acme.com" },
items: [
{ name: "Widget", qty: 10, price: 25 },
{ name: "Gadget", qty: 5, price: 50 },
],
},
});
if (diagnostics.length > 0) {
console.warn("Warnings:", diagnostics.map((d) => d.message));
}