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
Copy
npm install @cordel/react-docx
invoice.tsx:
Copy
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:Copy
const Invoice = () => (
<Document>
<Section>
{/* Content goes here */}
</Section>
</Document>
);
Page header and footer
Add repeating header and footer with page numbers:Copy
<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>
Company info
Add company info and invoice number:Copy
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:Copy
<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:Copy
<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:Copy
<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:Copy
<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
Copy
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
Copy
npx tsx invoice.tsx
invoice.docx in Word.
Next steps
- Add variables for dynamic data
- Learn more about headers and footers
- Use custom fonts via Tailwind config
