On this page
Your first PDF.
Create a project
Install Satzstrom and create a project. Its dependencies are installed for you.
Requires Node.js 20 or newer on Windows x64 or Linux x64.
npm install -g satzstromsatzstrom init my-documentWhat’s in your project
A document is an ordinary React project. Add components, hooks and libraries as you need them.
my-document/├─ document.tsx React document├─ styles.css Document styles├─ package.json Project dependencies└─ tsconfig.json TypeScript configuration- document.tsx
- Exports the React component that describes your document.
- styles.css
- Controls typography, spacing and layout. Import it from your document or its components.
- package.json
- Holds your project dependencies, including @satzstrom/primitives.
Open the preview
Your document opens in the browser. The first run completes the required setup automatically.
cd my-documentsatzstrom dev document.tsxMake it yours
Edit document.tsx and styles.css. The preview updates as you work. Here is a complete, one-page document to start with.
Page creates a fixed page. For content that needs to flow over several pages, use PageMaster.
import "./styles.css";import { Document, Page } from "@satzstrom/primitives";export default function MyFirstDocument() { return ( <Document title="My first document" lang="en"> <Page size="A4"> <h1>My first document</h1> </Page> </Document> );}Create the PDF
In the browser preview, choose Check and review any reported issues. Then choose Create PDF. You can also run the commands below in a second terminal. Strict mode stops on layout warnings.
The PDF is saved as document.pdf beside your source file, with the same page breaks as the preview.
satzstrom check document.tsx --strictsatzstrom render document.tsx --strictLet content flow across pages
Use Page for a single, fixed page. Use PageMaster when the content should continue across as many pages as it needs. Both can appear in the same document.
Here, the page layout repeats an annual-report header and a page count. The article flows through the space between them.
import "./styles.css";import { Document, Flow, PageMaster, type PageLayoutProps,} from "@satzstrom/primitives";function ReportPage({ page, pages }: PageLayoutProps) { return ( <div style={{ display: "flex", flexDirection: "column", height: "100%", padding: "20mm", boxSizing: "border-box", }} > <header>Annual report</header> <Flow style={{ flex: 1 }} /> <footer> Page {page} of {pages} </footer> </div> );}export default function Report() { return ( <Document title="Annual report" lang="en"> <PageMaster size="A4" layout={ReportPage}> <h1>Annual report</h1> <p>This content flows automatically across all required pages.</p> </PageMaster> </Document> );}- PageMaster
- Creates each required page using your layout. Its children are the content that flows through those pages.
- Flow
- Marks the content area in the layout. Here, flex: 1 gives it the space between the header and footer.
- page / pages
- The current page number and the total page count, supplied to the layout.
Add more paragraphs inside PageMaster and watch the preview grow. You edit the content; Satzstrom calculates where the pages break.
Number chapters and build a table of contents
Define the chapters once. Their numbers, contents entries and PDF bookmarks all follow the same structure.
import "./styles.css";import { Contents, Document, PageMaster, Ref, Sequence, defineSequence,} from "@satzstrom/primitives";const chapters = defineSequence({ name: "chapters", titleRequired: true,});export default function Report() { return ( <Document bookmarks={chapters}> <PageMaster size="A4"> <h1>Annual report</h1> <Contents sequence={chapters} /> <Sequence sequence={chapters} id="revenue" title="Revenue"> {({ number, title }) => <h2>{number}. {title}</h2>} </Sequence> <p>Revenue increased compared with the previous year.</p> <Sequence sequence={chapters} title="Outlook"> {({ number, title }) => <h2>{number}. {title}</h2>} </Sequence> <p> Building on chapter <Ref target="revenue" />, we expect further growth in the coming year. </p> </PageMaster> </Document> );}- defineSequence
- Creates the shared chapter sequence. titleRequired makes every chapter supply a title.
- Sequence
- Registers a chapter and supplies its calculated number and title to your component.
- Contents
- Lists those chapters with their final page numbers.
- bookmarks
- Uses the same sequence for the PDF viewer’s navigation.
- Ref
- Links to the chapter’s id. It can display the chapter number, title or page number.
Insert another chapter before Revenue. Its number, contents entry and the reference in Outlook update together.
Use existing Markdown
Markdown becomes semantic HTML inside your React document. Combine it with your own components, including tables, footnotes and mathematics.
import { Document, Markdown, Page,} from "@satzstrom/primitives";export default function Report() { return ( <Document> <Page size="A4"> <Markdown>{`# Project status- Design complete- Release prepared`}</Markdown> </Page> </Document> );}