Skip to content

Repository files navigation

Craft Print Server

Turns documents from Craft.do into clean, print-ready HTML and PDF files, using the official Craft API.

Default page size: 170 × 240 mm, two columns · Output: HTML (browser print) or PDF (Puppeteer)

Two ways to use it:

Tool Use it for
CLI (craft-print-cli.js) One-off conversions on the command line, good for scripts
HTTP server (craft-print-server.js) A running service with URLs for preview and PDF download

Contents


Requirements

  • Node.js 22.12 or newer (node --version) – required by Puppeteer 25
  • A Craft workspace where you can create an API connection
  • About 400 MB of disk space – npm install downloads its own copy of Chrome for Testing for PDF generation (Puppeteer).

Quick start

1. Get the repository from GitHub

With Git:

git clone https://github.com/<YOUR-GITHUB-NAME>/PrintReport.git
cd PrintReport

Without Git: on GitHub click Code → Download ZIP, unzip it, then open the folder.

2. Install dependencies

npm install

3. Add your credentials

Copy the template into the private/ folder and fill it in:

cp .env.example private/.env

Then open private/.env and enter the values from Craft (see Set up the Craft API):

CRAFT_API_TOKEN=your-token-here
CRAFT_API_ENDPOINT=https://connect.craft.do/links/YOUR-CONNECTION-ID/api/v1
PORT=3000

The .gitignore file excludes the whole private/ folder from Git, so your token, images, signatures and finished reports never leave your machine. A classic .env in the project root works too (also ignored).

4. Create your first report

node craft-print-cli.js <DOCUMENT-ID> --title "My Report" --pdf --output private/output/my-report

Result: private/output/my-report.pdf


Set up the Craft API

The tool reads your documents through a Craft API connection. You create the connection inside the Craft app and it only ever exposes the documents you pick – the rest of your workspace stays private.

1. Create the connection in Craft

  1. Open Craft (desktop or web) and go to the Connections tab in the left sidebar. In some versions this sits under Imagine → API.
  2. Click "Add Your First API Connection" (or add another connection).
  3. Give it a name, for example print-server.
  4. Click "Add Document" and select every document you want to convert. You can add more documents to the same connection later.

Alternatively you can connect all documents or all daily notes – but a connection limited to specific documents is the safer choice.

2. Copy the endpoint and the token

At the top of the connection Craft shows:

  • an API URL in the form https://connect.craft.do/links/<CONNECTION-ID>/api/v1
  • an API token – use the Set token / Copy control next to the URL

<CONNECTION-ID> is the random ID Craft generated for this connection (the same string that appears in the URL). Copy both values.

The "Download AI Bundle" button gives you the full API reference plus a snapshot of the connected documents – handy for exploring the API.

3. Put the values into private/.env

CRAFT_API_TOKEN=<the token you copied>
CRAFT_API_ENDPOINT=https://connect.craft.do/links/<CONNECTION-ID>/api/v1
PORT=3000

Internally the tool sends the token as Authorization: Bearer <token> and calls GET <endpoint>/blocks?id=<document-id> to fetch a document as Markdown.

Keeping it working

Problem Fix
Unauthorized / HTTP 401 Token expired or revoked – open the connection in Craft, set a new token, update private/.env.
HTTP 404 Wrong document ID, or that document is not part of this connection – add it under "Add Document".

Official docs: https://connect.craft.do/api-docs · https://support.craft.do/en/integrate/api


Using the CLI

node craft-print-cli.js <command> [options]
Command Meaning
<document-id> Convert the document with this ID
list-themes Show the available layout presets
help Show help
Option Default Meaning
--title "…" Document Document title
--author "…" Author name
--pdf Save as PDF (uses Puppeteer / Chromium)
--html Print HTML to stdout
--output FILE title Target file name without extension
--theme NAME standard Layout preset (see list-themes)
--dry-run Only show what would happen
--verbose Detailed output

Examples

# Write HTML to a file
node craft-print-cli.js abc123 --title "Handbook" --html > private/output/handbook.html

# PDF with an author
node craft-print-cli.js abc123 --title "Report" --author "Jane Doe" --pdf \
  --output private/output/report

# Just test (write nothing)
node craft-print-cli.js abc123 --pdf --dry-run --verbose

Your own build script

Put recurring commands into a personal script inside private/ (that folder is never pushed to GitHub). A starting point is already in private/make.sh:

./private/make.sh

Using the server

npm start          # normal mode
npm run dev        # auto-reload (nodemon)

The server listens on http://localhost:3000 (or PORT from your .env).

Route Purpose
GET /print/:documentId?title=…&author=… HTML preview in the browser (then Cmd/Ctrl + P)
GET /print-pdf/:documentId?title=…&author=… Download the PDF directly
GET /health Status check (JSON)

Example:

http://localhost:3000/print/abc123xyz?title=My%20Handbook&author=Jane%20Doe

When printing from the browser: choose "Save as PDF", turn margins off if you want, and enable "Background graphics".


Finding the document ID

  • From the share URL: https://www.craft.do/s/<DOCUMENT-ID> – the part after /s/.
  • As a block / document UUID: for example A1B2C3D4-0000-0000-0000-1234567890AB (available in Craft via Copy Link or the GET /blocks API call).

Project layout

PrintReport/
├── craft-print-server.js   # HTTP server + core functions (fetch, HTML, PDF)
├── craft-print-cli.js      # command-line tool
├── print-themes.js         # layout presets (page size, columns, fonts)
├── print-template.html     # HTML/CSS skeleton for printing
├── examples.js             # example integrations for developers
├── .env.example            # credentials template
├── .gitignore              # excludes private/, node_modules/, outputs
├── package.json
├── LICENSE
└── private/                # LOCAL ONLY – never on GitHub (see below)
    ├── .env                #   token & endpoint
    ├── make.sh             #   personal build script
    ├── images/             #   your own images for reports
    ├── signatures/         #   signature graphics
    └── output/             #   generated HTML / PDF reports

The private/ folder

Everything personal and confidential lives in one place: private/. The .gitignore file lists /private/, so Git ignores the entire folder – a git push never uploads:

  • the API token (private/.env)
  • your own images (private/images/)
  • signatures (private/signatures/)
  • finished reports with personal content (private/output/)

Anyone who clones the repository creates these files themselves, using .env.example and private/README.md. The folders images/, signatures/ and output/ may need to be re-created:

mkdir -p private/images private/signatures private/output

Changing the layout

The print parameters live in craft-print-server.js in the config object:

const config = {
  pageWidth: 170,   // mm
  pageHeight: 240,  // mm
  margins: { top: 20, right: 20, bottom: 40, left: 40 }  // mm
};

Fine-tuning (columns, font sizes, page breaks) is in the CSS of print-template.html:

.print-content { column-count: 1; column-gap: 1.5rem; }  /* number of columns */
.heading-1 { font-size: 2.4rem; }                         /* main heading      */
.text-body { font-size: 0.95rem; line-height: 1.4; }      /* body text         */

print-themes.js contains ready-made format presets (standard, technical, novel, academic, magazine, catalog), each with its own page size, column count and typography. List them with node craft-print-cli.js list-themes.


Supported Markdown

The server renders with marked (GitHub-flavored):

  • Headings #####
  • Bold **…**, italic *…*
  • Lists (ordered and unordered)
  • Inline code `…` and code blocks ```
  • Quotes > …
  • Links [text](url)
  • Tables (GitHub-flavored Markdown)

Web images (https://…) are downloaded and embedded automatically for PDF generation. Formats that Chromium cannot render (TIFF, BMP) are converted to JPEG with sharp.

Page-break control inside the Craft document (as an HTML block):

<div class="break-before"></div>   <!-- force a page break   -->
<div class="no-break"></div>    <!-- prevent a page break -->

Troubleshooting

Symptom Cause / fix
CRAFT_API_TOKEN is not set private/.env is missing or empty – run cp .env.example private/.env
Unauthorized / HTTP 401 token expired, or the document is not shared in the API connection
Puppeteer will not start (Linux) install the Chrome libraries: sudo apt-get install -y libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxrandr2 libgbm1 libasound2
Could not find Chrome after install run npx puppeteer browsers install chrome
PDF is blank / has no colors enable "Background graphics" when printing from the browser
Columns too narrow increase pageWidth in config, or reduce column-count
Port already in use change PORT in .env, or kill -9 $(lsof -t -i :3000)

For developers

Architecture

craft-print-cli.js ─┐
                     ├─→ craft-print-server.js
examples.js ─────────┘        │
                              ├─ fetchCraftContent(id)      → Markdown from the Craft API
                              ├─ transformMarkdownToHtml()  → semantic HTML (marked)
                              ├─ generatePrintHtml(content, meta)
                              │        └─ fills print-template.html
                              └─ htmlToPdf(html, path)      → Puppeteer + image preload

Public exports from craft-print-server.js

const {
  fetchCraftContent,   // (documentId: string) => Promise<string>   Markdown
  generatePrintHtml,   // (content: string, meta?) => string        full HTML
  htmlToPdf            // (html: string, outputPath: string) => Promise<string>
} = require('./craft-print-server');

print-themes.js exports themes, getTheme(name), listThemes() and generateThemeCss(theme). More patterns (batch, caching, Express integration) are shown in examples.js.

Dependencies

Package Version Notes
puppeteer ^25 bundles Chrome for Testing; needs Node ≥ 22.12
express ^5 server routes
axios ^1.20 HTTP client for the Craft API and image downloads
sharp ^0.35 converts TIFF/BMP images to JPEG for the PDF
marked ^11 pinned – the custom renderer in transformMarkdownToHtml() uses the v11 positional-argument API; v12+ passes token objects instead

npm audit is clean. Run npm outdated to see the pinned packages.

Local development

npm run dev        # server with nodemon
npm run cli -- <document-id> --html --dry-run

How the configuration is loaded

craft-print-server.js loads private/.env on startup; if that file does not exist, it falls back to .env in the project root. Both are listed in .gitignore.

Contributing

  1. Fork the repository, create a feature branch (feat/short-description).
  2. Never commit personal data – anything confidential belongs in private/.
  3. Open a pull request with a short description of its purpose.

License

MIT © 2026 Jörg Drees

About

Turns Craft.do documents into print-ready HTML and PDF via the Craft API

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages