gc-letters
v1.1.5
Published
An npm package for Government of Canada departments to generate Federal Identity Program (FIP) compliant letters as PDFs
Maintainers
Readme
gc-letters
An npm package for Government of Canada departments to generate Federal Identity Program (FIP) compliant letters as PDFs directly in the browser.
Features
- ✅ FIP Compliant - Follows Government of Canada Federal Identity Program standards
- ✅ Browser-Based - No server required; generates PDFs client-side using jsPDF
- ✅ Markdown Support - Write letter content in markdown for easy formatting (including tables)
- ✅ React Components - Simple, declarative API using React
- ✅ Flexible Typography - Control fonts, sizes, spacing at document and block levels
- ✅ Page Management - Automatic page breaks, page numbering, and next-page indicators
- ✅ Letter Metadata - Support for letter numbers, versions, and tracking
- ✅ Multiple Page Sizes - Letter, Legal, and A4 formats
- ✅ TypeScript - Full TypeScript support with type definitions
Installation
npm install gc-lettersPeer Dependencies
Requires React 17, 18, or 19:
npm install react react-domQuick Start
import React, { useState } from 'react';
import { GcLetter, LetterBlock } from 'gc-letters';
function MyLetter() {
const [downloadFn, setDownloadFn] = useState(null);
return (
<div>
<button onClick={() => downloadFn?.()}>
Download PDF
</button>
<GcLetter
fileName="my-letter"
deptSignature="https://example.com/signature.png"
onReady={(download) => setDownloadFn(() => download)}
>
{/* Note: Use {` ... `} for multi-line markdown content */}
<LetterBlock>{`# Dear Recipient
This is my letter written in **markdown**.
## Key Points
- First point
- Second point
- Third point
Thank you for your attention.`}</LetterBlock>
</GcLetter>
</div>
);
}Components
GcLetter
Main wrapper component that handles document-level settings and PDF generation.
<GcLetter
fileName="my-letter" // Required: PDF filename
deptSignature="https://..." // Required: Department signature URL
pageType="letter" // Optional: 'letter' | 'legal' | 'a4'
showPageNumbers={true} // Optional: Display page numbers
onReady={(download) => download()} // Optional: Callback with download function
>
{children}
</GcLetter>See API Reference for complete props documentation.
LetterBlock
Content section component for rendering markdown.
{/* Option 1: Using content prop */}
<LetterBlock
content="# Heading\n\nParagraph text"
allowPagebreak={true}
textAlign="left"
/>
{/* Option 2: Using children (recommended for readability) */}
<LetterBlock allowPagebreak={true}>
{`# Heading
Paragraph text with **bold** and *italic*.
- List item 1
- List item 2`}
</LetterBlock>💡 Important: For multi-line markdown content, you must use template literals with curly braces: {...}. This preserves newlines in your markdown. Without them, React will collapse multi-line content into a single line, breaking your formatting.
{/* ✅ Correct - Template literal preserves newlines */}
<LetterBlock>{`
Line 1
Line 2
`}</LetterBlock>
{/* ❌ Wrong - JSX collapses whitespace */}
<LetterBlock>
Line 1
Line 2
</LetterBlock>
{/* ✅ Alternative - Use content prop with \n */}
<LetterBlock content="Line 1\n\nLine 2" />Supported Markdown:
- Headings:
#,##,### - Bold:
**text** - Italic:
*text* - Lists:
- itemor1. item - Tables: Standard markdown table syntax with column alignment
SeparatorLine
Horizontal line for visual separation.
<SeparatorLine
topMargin="5mm" // Optional: spacing before line
bottomMargin="10mm" // Optional: spacing after line
/>Default spacing: 1x paragraph spacing above, 2x below
Examples
Basic Letter
<GcLetter fileName="basic" deptSignature="https://...">
<LetterBlock>
Simple letter content.
</LetterBlock>
</GcLetter>Multi-Page with Page Numbers
<GcLetter
fileName="multi-page"
deptSignature="https://..."
showPageNumbers="skip-first"
pageNumberFormat="Page #"
showNextPage={true}
>
<LetterBlock content={longContent} />
</GcLetter>Custom Formatting
<GcLetter
fileName="formatted"
deptSignature="https://..."
fontFace="Times"
textSizeNormal="12pt"
paragraphSpacing="15mm"
>
<LetterBlock content="# Title" textAlign="center" />
<LetterBlock content="Body text" />
<LetterBlock content="Signature" textAlign="right" />
</GcLetter>Tables
Markdown tables are fully supported with column alignment:
<LetterBlock content={`
| Item | Q1 | Q2 | Q3 | Q4 | Total |
|------|---:|---:|---:|---:|------:|
| Revenue | $2.5M | $2.8M | $3.1M | $2.6M | $11.0M |
| Expenses | $1.8M | $2.1M | $2.3M | $1.9M | $8.1M |
| **Net** | **$0.7M** | **$0.7M** | **$0.8M** | **$0.7M** | **$2.9M** |
`} />Table styling options (optional props on LetterBlock):
tableTheme- 'striped' | 'grid' | 'plain' (default: 'grid')tableHeaderBold- Bold headers (default: true)tableHeaderFillColor- Header background color RGB arraytableBorderColor- Border color RGB array
More examples: See examples/ directory
Documentation
- 📖 API Reference - Complete component and prop documentation
- 📘 Usage Guide - Practical examples and patterns
- 🍁 FIP Compliance Guide - Federal Identity Program standards
- 🔧 Troubleshooting - Common issues and solutions
FIP Compliance
This package helps create letters that comply with the Government of Canada's Federal Identity Program:
Requirements:
- ✅ Helvetica typeface (default)
- ✅ Department signature with flag symbol
- ✅ Appropriate margins (38mm × 13mm default)
- ✅ Bilingual support
- ✅ Canada wordmark (included automatically in the package)
Read the FIP Compliance Guide for detailed requirements.
Browser Support
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- Not supported: Internet Explorer
TypeScript
Fully typed with TypeScript. Import types:
import type { GcLetterProps, LetterBlockProps, PageType, Alignment } from 'gc-letters';Testing
The package includes comprehensive tests:
npm test # Run all tests
npm test -- --coverage # Run with coverage reportTest Coverage:
- 124 tests passing
- 87%+ coverage on utility functions
- Visual test samples for manual verification
Development
# Install dependencies
npm install
# Run tests
npm test
# Build the package
npm run build
# Type check
npm run typecheck
# Lint
npm run lintImportant Notes
Component Nesting
⚠️ LetterBlock components cannot be nested. Each must be a direct child of GcLetter:
// ✅ Correct
<GcLetter {...props}>
<LetterBlock content="First" />
<LetterBlock content="Second" />
</GcLetter>
// ❌ Incorrect
<GcLetter {...props}>
<LetterBlock>
<LetterBlock /> {/* Will throw error */}
</LetterBlock>
</GcLetter>Image Loading
Supported image formats: PNG, JPG/JPEG only
⚠️ SVG is not supported by the underlying jsPDF library. Convert SVG files to PNG before use.
Department signatures must be accessible:
- Same domain: Works automatically
- External domain: Requires CORS configuration
- For testing: Use data URLs
// ✅ Supported
deptSignature="signature.png"
deptSignature="signature.jpg"
// ❌ Not supported
deptSignature="signature.svg" // Convert to PNG firstRoadmap
Future enhancements being considered:
- [ ] Image embedding in markdown
- [ ] Server-side rendering option
- [ ] Additional fonts
- [ ] Custom templates
- [ ] Advanced table features (merged cells, custom cell styling)
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new features
- Ensure all tests pass
- Submit a pull request
See CONTRIBUTING.md for details.
License
MIT © [Your Organization]
See LICENSE file for details.
Support
Acknowledgments
Built with:
- jsPDF - PDF generation
- jsPDF-AutoTable - Table rendering
- marked - Markdown parsing
- React - Component framework
Related Resources
Made with 🍁 for the Government of Canada
Disclaimer
This project is currently a proof of concept and is not officially endorsed as a Government of Canada tool. While it aims to help generate FIP-compliant letters, it should be used for development and testing purposes only. Organizations should conduct their own compliance reviews before using this package in production environments.
