Skip to main content
import { render } from "@cordel/react-docx";

await render(<MyDocument />, "./output.docx");
Returns a Promise<string> with the output path.

Basic usage

import { render, Document, Section, H1, Paragraph } from "@cordel/react-docx";

const MyDocument = () => (
  <Document>
    <Section>
      <H1>Hello</H1>
      <Paragraph>World</Paragraph>
    </Section>
  </Document>
);

await render(<MyDocument />, "./hello.docx");

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>
  );
};

Formatting

<Variable
  name="price"
  format={(value) => `$${Number(value).toFixed(2)}`}
/>

Error handling

try {
  await render(<MyDocument />, "./output.docx");
  console.log("Done");
} 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>
  );
};

await render(<Invoice />, "./invoice.docx", {
  variables: {
    number: "INV-001",
    date: "2024-01-15",
    customer: { name: "Acme Corp", email: "[email protected]" },
    items: [
      { name: "Widget", qty: 10, price: 25 },
      { name: "Gadget", qty: 5, price: 50 },
    ],
  },
});