Skip to main content

booklette

CI Python 3.9+ License: MIT

Turn an ordinary page-by-page PDF into one you can print, fold and staple into a booklet.

Each sheet of the output holds two portrait pages side by side, with the page numbers shuffled into the order a folded booklet needs. Print it double-sided on A4, fold the stack in half, staple the fold - you have an A5 booklet that reads from page 1 to the end.

input.pdf                        booklet.pdf (A4 landscape, 2-up)
+-----+ +-----+ +-----+          +-----+-----+   +-----+-----+
|  1  | |  2  | |  3  |   --->   |  8  |  1  |   |  2  |  7  |  ...
+-----+ +-----+ +-----+          +-----+-----+   +-----+-----+
   ...  8 pages  ...              sheet 1 front   sheet 1 back

(The back sides are additionally turned 180 degrees, which is what makes long-edge duplex printing come out right - see Printing.)

A booklet's page count is always a multiple of four, so most documents end with a page or three of padding. Those come out as ruled note paper rather than blank - see Padding pages.

Install

pip install booklette

Or from a clone of this repository:

git clone https://github.com/nimjal/booklette.git
cd booklette
pip install -e .

The only runtime dependency is pypdf.

Usage

# The common case: A4 booklet with the defaults described below
booklette report.pdf                 # writes report-booklet.pdf

# A little breathing room around the pages and at the staple
booklette report.pdf --margin 8 --gutter 4

# A long document, folded in groups of 16 pages instead of one thick fold
booklette novel.pdf --signature 16

# Ruled lines but no "Notes:" heading, and use up the back cover as well
booklette recipes.pdf --filler lines --filler-back-cover

# See where every page will end up, without writing a file
booklette report.pdf --dry-run

Or from Python:

from booklette import BookletOptions, create_booklet

result = create_booklet("report.pdf", "booklet.pdf", BookletOptions(margin_mm=8))
print(f"{result.source_pages} pages -> {result.sheets} sheets")

Printing

  1. Print the generated PDF double-sided (duplex).
  2. Set scaling to 100% / "actual size" - not "fit to page", which would shrink the pages a second time.
  3. Fold the stack in half and staple the fold.

Two printer habits decide the settings, and both are options:

Option Default Change it when
--duplex long / short long the back of each sheet comes out upside down
--order normal / reverse normal the finished stack is back to front

--duplex describes how the printer turns the paper between the two sides. Because the sheets are landscape but the paper is fed portrait, long-edge flipping needs the back of every sheet rotated by 180 degrees - that rotation is baked into the output, so the printer dialog stays on its own default. Pick short if your driver flips on the short edge instead.

Every second page of the output looks upside down on screen. That is correct. It is the long-edge correction, and it comes out the right way up on paper. If you would rather preview an output that reads upright, use --duplex short and set your printer to flip on the short edge.

--order describes how the printer stacks its output. Most printers drop their pages face down, so the pile is already in reading order and the sheets are written in reading order too - that is the default, normal. Printers that stack face up build the pile "bottom to top", so the last page printed ends up on top; for those, reverse emits the sheets last-first, which cancels it out. If your printer dialog has its own "reverse page order" option, leave it off: two reversals put you back where you started.

If a test print comes out wrong, change one of the two and try again - four pages of scrap paper will tell you which combination your printer wants.

Options

Flag Default What it does
-o, --output PATH <input>-booklet.pdf where to write the result
-p, --paper SIZE a4 a3, a4, a5, a6, b5, letter, legal, tabloid, or WIDTHxHEIGHT in mm
-d, --duplex {long,short} long edge the printer flips on
--order {normal,reverse} normal sheet output order
-s, --signature PAGES 0 fold in groups of PAGES pages (multiple of 4); 0 folds everything at once
-m, --margin MM 0 whitespace at the outer edges of the sheet
-g, --gutter MM 0 extra whitespace either side of the fold
-f, --filler {notes,notes-plain,lines,blank} notes what to print on the padding pages
--filler-title TEXT Notes: heading for those pages
--filler-back-cover off fill the back cover too
--rtl off right-to-left booklet (spine on the right)
--password PASS - password for an encrypted input PDF
-n, --dry-run off print the imposition plan, write nothing
-q, --quiet off only report errors

Pages are scaled to fit their half of the sheet and centred, keeping their aspect ratio; a document of mixed page sizes is handled page by page. The page count is padded up to a multiple of four, because that is how many pages one folded sheet carries.

Padding pages

A 14 page document is printed as 16, and those two spare pages end up at the back of the booklet. By default they are ruled as note paper - a Notes: heading and a set of lines - so a printed handout has somewhere to write.

The last page of the booklet is the outside of the back cover, and is left empty; --filler-back-cover uses it as well.

--filler On each padding page
notes heading and ruled lines (the default)
notes-plain the heading on its own
lines ruled lines on their own
blank nothing

The heading follows --filler-title, so --filler-title "Shopping list:" works as well as Notes:. A filler page is built at the size of the document's first page and scaled onto the sheet exactly like a real page, so its ruled area lines up with the pages before it, whatever paper you print on.

A document whose page count is already a multiple of four has no padding, and so gets no notes pages.

Signatures

One fold through more than about ten sheets bulges badly and the inner pages stick out. --signature 16 instead produces a series of small booklets (four sheets each) that you fold separately and then stack in order - the way real books are bound.

How it works

A saddle-stitched booklet of n pages puts these pages on sheet i (counting from 0):

sheet side left half right half
front n - 2i 2i + 1
back 2i + 2 n - 2i - 1

So an 8 page booklet becomes [8|1] [2|7] [6|3] [4|5]. The code follows the same steps:

Module Responsibility
imposition.py which page goes where - pure Python, no PDF library
layout.py where on the sheet it goes - rectangles and matrices, no PDF library
filler.py what a padding page looks like, as PDF drawing operators
builder.py the only module that talks to pypdf
cli.py the command line

Because everything but builder.py is pure arithmetic and text, the tricky parts are covered by fast unit tests, and you can inspect the plan without a PDF at all (- is a padding page, bc the back cover):

from booklette import format_plan, impose

print(format_plan(impose(12)))

Examples

The examples/ directory has runnable scripts, including a sample PDF generator that uses nothing but the standard library:

python examples/make_sample_pdf.py sample.pdf --pages 12
booklette sample.pdf
python examples/basic_usage.py     # library API, three variations
python examples/print_plan.py      # page ordering, no PDFs involved

Development

python -m venv .venv
.venv/bin/pip install -e ".[dev]"   # Windows: .venv\Scripts\pip
pytest                              # unit tests, end-to-end tests and doctests
ruff check .
ruff format .

See CONTRIBUTING.md for how to send a change.

Limitations

  • Two pages per sheet, folded down the middle: no 4-up, no cut-and-stack, no creep compensation for very thick booklets.
  • The output is a normal PDF; the actual printing is left to your printer dialog, which is where the paper handling settings live anyway.

License

MIT - see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

booklette-0.1.1.tar.gz (38.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

booklette-0.1.1-py3-none-any.whl (28.2 kB view details)

Uploaded Python 3

File details

Details for the file booklette-0.1.1.tar.gz.

File metadata

  • Download URL: booklette-0.1.1.tar.gz
  • Upload date:
  • Size: 38.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for booklette-0.1.1.tar.gz
Algorithm Hash digest
SHA256 2fcb820997bf92a35d2b720d6cdafc39891a85350301fd5fa5e946ff3f5e3cf8
MD5 3118ab0c6af5714c94964927ed21ddf1
BLAKE2b-256 beefa5b5e8d919c9ce5eae77a1445a3064ec124ab8a3eb2e62637edee02f1c3a

See more details on using hashes here.

Provenance

The following attestation bundles were made for booklette-0.1.1.tar.gz:

Publisher: publish.yml on nimjal/booklette

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file booklette-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: booklette-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 28.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for booklette-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 22e315abf5feb120d64a6a7b4c783d5067b987beae023ff2a4819f25147a8067
MD5 f2769986c8b295ae14607150bce18e5b
BLAKE2b-256 c3c84d2aa5552dd4cda1bf5e36ca7b8a96d2e24fb12dd3d178f7186e5f58a43e

See more details on using hashes here.

Provenance

The following attestation bundles were made for booklette-0.1.1-py3-none-any.whl:

Publisher: publish.yml on nimjal/booklette

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page