Skip to content

Book Forge v1.4.0 — Typography, Layout & Export Fixes

Latest

Choose a tag to compare

@takzen takzen released this 18 Sep 09:58

Fonts, page layout and the export pipeline are the focus of this release. The interface named a font it never loaded, the preview's font switcher changed nothing, markdown headings and lists came out of the PDF looking like plain body text, and several flows failed without saying so.

Typography

  • Inter is actually loaded. The interface font is now self-hosted through next/font, with latin-ext so Polish diacritics render properly. Previously the stylesheet named Inter but nothing ever fetched it, so the whole UI fell back to whatever the machine happened to have.
  • The font switcher works. Picking Sans or Mono in Preview & PDF now changes the text — verified as Georgia → Segoe UI → Consolas. The manuscript styles sat outside Tailwind's cascade layers, where they silently beat every font-sans / font-mono utility.
  • Headings and lists survive the export. A # heading now renders at 30.4px/700 instead of 16px/400 — identical to body text — and bullet lists regained their markers and indentation. Both were stripped by Tailwind's preflight and never restored. Everything is sized in em, so it scales with the chosen type size.
  • The manuscript has its own typefaces, separate from the interface font. Chromium cannot embed a self-hosted webfont when it exports a PDF: it drew every glyph as a Type3 vector procedure, inflating the file about 2.7× into a form print shops routinely reject. The book now uses locally installed families, which embed as proper CIDFontType2 subsets.
Font Size Pages Embedded
Serif 148 714 B 31 Georgia ×4
Sans 147 031 B 31 Segoe UI ×4
Mono 141 232 B 32 Consolas ×4

Page layout

  • No more blank page in every PDF. The title page was sized with 100vh, which in a headless render is the browser viewport, not the page box — it overflowed and pushed an almost-empty page into every export. The book is now 31 pages where it used to be 34.
  • The table of contents no longer lists itself or gets printed twice, and its dotted leaders now lead to real page numbers.
  • Book settings drive the output. Font, type size, leading, all three margins and recto/verso chapter starts are stored, editable from a new panel in the sidebar, and applied to the PDF. The table existed before but nothing read it — the print layout had its margins hard-coded.
  • One page estimator shared by the editor, the preview and the generated contents, so their numbering agrees. Images now carry weight in the estimate, so less content slips off the bottom of a preview sheet.

Cover export

The PNG export now screenshots the same component the designer draws on screen, so the file cannot drift from the preview. It replaces a canvas re-implementation that used different fonts than the preview, scaled type by a hard-coded factor, recognised only three hard-coded gradients, and supported neither text wrapping nor letter-spacing, opacity or element borders. Scaling is measured rather than assumed, and the export height now follows the book format.

Silent failures

  • ZIP import reported failure on success. redirect() signals by throwing and sat inside a try/catch, so every successful import was caught, logged as an error and redirected to ?error=import-failed — even though the book had been created.
  • Backups over 1MB never uploaded at all. Server Actions cap the request body at 1MB by default, so a real archive died with ERR_CONNECTION_RESET before the action ran, making the advertised 50MB limit unreachable. The limit is raised and transport failures now surface in the UI.
  • Electron stopped orphaning the server. spawn() rejects a numeric pid, so the taskkill call threw into an empty catch and the Next.js process survived every shutdown, holding the port. Zoom shortcuts are also handled once instead of three times, so Ctrl +/- moves one step.
  • The import button works without a file selected. Chrome refuses to submit a form containing an invalid required control it cannot focus, and the input was display: none.

Also

Strict table-of-contents matching, so a chapter that merely mentions one — "Jak czytać spis treści" — is no longer removed from the manuscript. Chapter numbering follows the chapter count rather than sortOrder, which used to name a fourth chapter "Chapter 7". Export filenames transliterate Polish diacritics instead of dropping the letters ("Książka" → ksiazka, not ksi-ka). Settings writes are validated and clamped. Dead code removed: an unreachable b5 format, an unimplemented shape element type, and a fallback form with no submit button.

Verification

  • npm run build — production build succeeds
  • npm run test — 17 tests pass, up from 3; the suite no longer runs against the live library
  • npx eslint . — clean, down from 13 errors and 9 warnings
  • PDF and cover output measured directly from generated files, not assumed