Guides · Content pipelines · Published 2026-09-13 · 3 min read

Generating a Book Cover in Node — Compositing SVG Text Over a Background With sharp, Getting Thai and Other Scripts to Render, and Sizing for KDP, Kobo and Play Books

A repeatable cover pipeline for e-books: a background image, a title block drawn as SVG, composited and resized with sharp. The font pitfalls for non-Latin scripts, why some system fonts drop Thai glyphs, and the pixel sizes the stores expect.

If you publish more than one e-book, or the same book to several stores, hand-making covers in a design tool stops scaling quickly. A cover is a background image with a title block on top, and that is a job for a script: render the text as SVG, composite it over the background with sharp, and export at each store's required size. The only hard part is fonts.

The pipeline

  1. Background. A photograph or generated image at least as large as the largest output, cropped to a portrait ratio near 1:1.6. A soft dark gradient over the lower half keeps light text readable on any image.
  2. Text as SVG. Build an SVG string with the title, subtitle and author as <text> elements, sized in pixels relative to the canvas, with font-family, font-weight and fill. SVG gives you exact positioning and wraps nothing, so break long titles into separate <text> lines yourself.
  3. Composite. sharp(background).composite([{ input: Buffer.from(svg), top: 0, left: 0 }]), then .resize() to each target and .jpeg({ quality }) to a file.
  4. Outputs. One file per store size, plus a small version for your own site.

The font problem

sharp renders SVG through librsvg, which uses the system's font configuration. Two things go wrong. First, the font you name may not be installed on the machine running the script, in which case a fallback is used silently and the cover looks different from your test. Second, the fallback for a Latin font often has no glyphs for Thai, Lao, Khmer or other scripts, so those characters render as empty boxes, or in a mismatched font that breaks the tone-mark positioning Thai depends on.

The fixes, in order of reliability:

Approach Effect
Name a font that is installed and contains the script, such as Tahoma or Noto Sans Thai on Windows Correct glyphs; test once per machine
Install the exact font on the build machine and in the Docker image, and name it in a font stack with the script-capable font first Reproducible across machines
Embed the font in the SVG with @font-face and a base64 data URL Fully self-contained; largest SVG string, but immune to system differences

Always render a test image and look at it before batch-producing; the failure is visual and produces no error. The same care applies to the fonts used inside the book itself, described in building an EPUB from Markdown with Node.

Sizes the stores want

Requirements change, so check each store's current page, but the pattern is stable: Kindle wants a tall portrait around 1.6:1 at a minimum of a couple of thousand pixels on the long side; Kobo and Google Play accept similar portrait JPEGs; your own product pages want something around a few hundred pixels wide. Export from the same composited master so the covers match everywhere.

Text layout tips

Common mistakes

Summary

Treat the cover as background plus SVG text, composite with sharp, and export per store from one master. Choose and test a font that actually contains your script, or embed it in the SVG, and look at the first render before you trust the pipeline. The image-processing basics are in resizing, cropping and composing images with sharp.

Related guides