Skip to main content
Build a complete invoice document from scratch.

What we’re building

A professional invoice with:
  • Page header and footer with page numbers
  • Company info
  • Customer details
  • Line items table
  • Total calculation
  • Payment terms

Setup

npm install @cordel/react-docx
Create invoice.tsx:
import {
  render,
  Document,
  Section,
  Paragraph,
  Text,
  Table,
  Thead,
  Tbody,
  Tr,
  Th,
  Td,
  Hr,
  PageNumber,
} from "@cordel/react-docx";

Document structure

Start with the basic shell:
const Invoice = () => (
  <Document>
    <Section>
      {/* Content goes here */}
    </Section>
  </Document>
);

Add repeating header and footer with page numbers:
<Section>
  <Section.Header>
    <Paragraph className="text-sm text-gray-500">
      Acme Corp - Invoice
    </Paragraph>
  </Section.Header>

  <Section.Footer>
    <Paragraph className="text-center text-xs text-gray-400">
      Page <PageNumber /> of <PageNumber type="total" />
    </Paragraph>
  </Section.Footer>

  {/* Content goes here */}
</Section>
These appear on every page of the section.

Company info

Add company info and invoice number:
const Invoice = () => (
  <Document>
    <Section>
      <Paragraph>
        <Text className="text-2xl font-bold">Acme Corp</Text>
      </Paragraph>
      <Paragraph className="text-gray-500 text-sm">
        123 Business Street, New York, NY 10001
      </Paragraph>

      <Hr className="mt-4 mb-4" />

      <Paragraph>
        <Text className="text-xl font-bold">INVOICE</Text>
      </Paragraph>
      <Paragraph>
        <Text className="font-bold">Invoice #: </Text>INV-2024-001
      </Paragraph>
      <Paragraph>
        <Text className="font-bold">Date: </Text>January 15, 2024
      </Paragraph>
    </Section>
  </Document>
);

Customer details

Add billing information:
<Paragraph className="mt-6">
  <Text className="font-bold">Bill To:</Text>
</Paragraph>
<Paragraph>John Smith</Paragraph>
<Paragraph>456 Customer Ave</Paragraph>
<Paragraph>Los Angeles, CA 90001</Paragraph>
<Paragraph>[email protected]</Paragraph>

Line items table

Add the products/services:
<Table className="mt-6 border" width="full">
  <Thead>
    <Tr className="bg-gray-100">
      <Th className="border p-2 text-left">Description</Th>
      <Th className="border p-2 text-right">Qty</Th>
      <Th className="border p-2 text-right">Price</Th>
      <Th className="border p-2 text-right">Amount</Th>
    </Tr>
  </Thead>
  <Tbody>
    <Tr>
      <Td className="border p-2">Web Development Services</Td>
      <Td className="border p-2 text-right">40</Td>
      <Td className="border p-2 text-right">$75.00</Td>
      <Td className="border p-2 text-right">$3,000.00</Td>
    </Tr>
    <Tr>
      <Td className="border p-2">UI/UX Design</Td>
      <Td className="border p-2 text-right">20</Td>
      <Td className="border p-2 text-right">$85.00</Td>
      <Td className="border p-2 text-right">$1,700.00</Td>
    </Tr>
    <Tr>
      <Td className="border p-2">Hosting (Annual)</Td>
      <Td className="border p-2 text-right">1</Td>
      <Td className="border p-2 text-right">$200.00</Td>
      <Td className="border p-2 text-right">$200.00</Td>
    </Tr>
  </Tbody>
</Table>

Total

Add subtotal, tax, and total:
<Paragraph className="mt-4 text-right">
  <Text className="font-bold">Subtotal: </Text>$4,900.00
</Paragraph>
<Paragraph className="text-right">
  <Text className="font-bold">Tax (10%): </Text>$490.00
</Paragraph>
<Paragraph className="text-right mt-2">
  <Text className="text-xl font-bold">Total: $5,390.00</Text>
</Paragraph>

Payment terms

Add terms at the bottom:
<Hr className="mt-8 mb-4" />

<Paragraph className="text-sm text-gray-500">
  <Text className="font-bold">Payment Terms: </Text>
  Due within 30 days. Please make checks payable to Acme Corp.
</Paragraph>
<Paragraph className="text-sm text-gray-500 mt-2">
  Thank you for your business!
</Paragraph>

Complete code

import {
  render,
  Document,
  Section,
  Paragraph,
  Text,
  Table,
  Thead,
  Tbody,
  Tr,
  Th,
  Td,
  Hr,
  PageNumber,
} from "@cordel/react-docx";

const Invoice = () => (
  <Document>
    <Section
      margins={{ top: "1in", bottom: "1in", left: "1in", right: "1in" }}
    >
      <Section.Header>
        <Paragraph className="text-sm text-gray-500">
          Acme Corp - Invoice
        </Paragraph>
      </Section.Header>

      <Section.Footer>
        <Paragraph className="text-center text-xs text-gray-400">
          Page <PageNumber /> of <PageNumber type="total" />
        </Paragraph>
      </Section.Footer>

      {/* Company Info */}
      <Paragraph>
        <Text className="text-2xl font-bold">Acme Corp</Text>
      </Paragraph>
      <Paragraph className="text-gray-500 text-sm">
        123 Business Street, New York, NY 10001
      </Paragraph>

      <Hr className="mt-4 mb-4" />

      <Paragraph>
        <Text className="text-xl font-bold">INVOICE</Text>
      </Paragraph>
      <Paragraph>
        <Text className="font-bold">Invoice #: </Text>INV-2024-001
      </Paragraph>
      <Paragraph>
        <Text className="font-bold">Date: </Text>January 15, 2024
      </Paragraph>

      {/* Customer */}
      <Paragraph className="mt-6">
        <Text className="font-bold">Bill To:</Text>
      </Paragraph>
      <Paragraph>John Smith</Paragraph>
      <Paragraph>456 Customer Ave</Paragraph>
      <Paragraph>Los Angeles, CA 90001</Paragraph>

      {/* Line Items */}
      <Table className="mt-6 border" width="full">
        <Thead>
          <Tr className="bg-gray-100">
            <Th className="border p-2 text-left">Description</Th>
            <Th className="border p-2 text-right">Qty</Th>
            <Th className="border p-2 text-right">Price</Th>
            <Th className="border p-2 text-right">Amount</Th>
          </Tr>
        </Thead>
        <Tbody>
          <Tr>
            <Td className="border p-2">Web Development</Td>
            <Td className="border p-2 text-right">40</Td>
            <Td className="border p-2 text-right">$75.00</Td>
            <Td className="border p-2 text-right">$3,000.00</Td>
          </Tr>
          <Tr>
            <Td className="border p-2">UI/UX Design</Td>
            <Td className="border p-2 text-right">20</Td>
            <Td className="border p-2 text-right">$85.00</Td>
            <Td className="border p-2 text-right">$1,700.00</Td>
          </Tr>
          <Tr>
            <Td className="border p-2">Hosting (Annual)</Td>
            <Td className="border p-2 text-right">1</Td>
            <Td className="border p-2 text-right">$200.00</Td>
            <Td className="border p-2 text-right">$200.00</Td>
          </Tr>
        </Tbody>
      </Table>

      {/* Totals */}
      <Paragraph className="mt-4 text-right">
        <Text className="font-bold">Subtotal: </Text>$4,900.00
      </Paragraph>
      <Paragraph className="text-right">
        <Text className="font-bold">Tax (10%): </Text>$490.00
      </Paragraph>
      <Paragraph className="text-right mt-2">
        <Text className="text-xl font-bold">Total: $5,390.00</Text>
      </Paragraph>

      {/* Payment Terms */}
      <Hr className="mt-8 mb-4" />
      <Paragraph className="text-sm text-gray-500">
        <Text className="font-bold">Payment Terms: </Text>
        Due within 30 days.
      </Paragraph>
      <Paragraph className="text-sm text-gray-500 mt-2">
        Thank you for your business!
      </Paragraph>
    </Section>
  </Document>
);

await render(<Invoice />, "./invoice.docx");

Run it

npx tsx invoice.tsx
Open invoice.docx in Word.

Next steps