<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Vibe Coding Forem: Mw234324324324Booklet AI Writer</title>
    <description>The latest articles on Vibe Coding Forem by Mw234324324324Booklet AI Writer (@mw234324324324).</description>
    <link>https://vibe.forem.com/mw234324324324</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3842334%2F133a6b5a-9a57-42ec-9b0c-0eb1da62a691.png</url>
      <title>Vibe Coding Forem: Mw234324324324Booklet AI Writer</title>
      <link>https://vibe.forem.com/mw234324324324</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://vibe.forem.com/feed/mw234324324324"/>
    <language>en</language>
    <item>
      <title>How We Built an AI Pipeline That Turns Prompts into Print-Ready Booklets</title>
      <dc:creator>Mw234324324324Booklet AI Writer</dc:creator>
      <pubDate>Mon, 27 Apr 2026 10:34:30 +0000</pubDate>
      <link>https://vibe.forem.com/mw234324324324/how-we-built-an-ai-pipeline-that-turns-prompts-into-print-ready-booklets-4bbe</link>
      <guid>https://vibe.forem.com/mw234324324324/how-we-built-an-ai-pipeline-that-turns-prompts-into-print-ready-booklets-4bbe</guid>
      <description>&lt;h1&gt;
  
  
  How We Built an AI Pipeline That Turns Prompts into Print-Ready Booklets
&lt;/h1&gt;

&lt;p&gt;When we set out to build &lt;a href="https://bookletai.org" rel="noopener noreferrer"&gt;Booklet AI&lt;/a&gt;, the brief was deceptively simple: "Type a topic, get back a print-ready booklet — magazine layout, professional typography, downloadable as PDF."&lt;/p&gt;

&lt;p&gt;In practice, that one sentence hides a small army of problems: prompt-to-content generation, layout decisions across variable content lengths, image sourcing, font fallbacks, headless rendering, PDF export, and an interactive editor sitting on top of it all. This post walks through the architecture we landed on, the parts that surprised us, and the pieces we'd build differently next time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shape of the problem
&lt;/h2&gt;

&lt;p&gt;A "booklet" is not a slide deck and not a long-form article — it's somewhere in between. Think 8–24 A4 pages, magazine-style spreads, with a cover, table of contents, alternating image/text layouts, and pull quotes. Users feed in one of three input types:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A free-text prompt ("Make me a 12-page booklet about regenerative agriculture")&lt;/li&gt;
&lt;li&gt;A PDF or DOCX upload (turn this report into a magazine)&lt;/li&gt;
&lt;li&gt;A URL (turn this article into a designed spread)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The output is an HTML document that renders cleanly to PDF and is also editable inside a web editor.&lt;/p&gt;

&lt;h2&gt;
  
  
  High-level pipeline
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User input
   │
   ▼
[Content extraction]   ← PDFBox / readability / GPT-4 cleanup
   │
   ▼
[Outline generation]   ← LLM, structured JSON output
   │
   ▼
[Per-page content gen] ← LLM with section-aware prompts
   │
   ▼
[Layout assignment]    ← rule-based template picker
   │
   ▼
[Image generation]     ← Replicate / DALL·E, async
   │
   ▼
[HTML assembly]        ← server-side templating (Thymeleaf)
   │
   ▼
[Headless render]      ← Puppeteer
   │
   ▼
[PDF export]           ← Puppeteer pdf() + post-processing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each stage is its own service call, queued and retryable. The whole pipeline takes 30–90 seconds for a typical 12-page booklet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 1: Content extraction
&lt;/h2&gt;

&lt;p&gt;For PDF and DOCX inputs, we tried three approaches before landing on the one we ship:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pure PDFBox text extraction&lt;/strong&gt; — fast but loses heading structure and reading order on multi-column layouts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCR-first (Tesseract)&lt;/strong&gt; — slow and overkill for digital PDFs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PDFBox + GPT cleanup&lt;/strong&gt; — extract raw text, then run a small LLM call to restore structure ("split this into sections with heading levels"). This is what we ended up shipping. ~5–10s for a 30-page report.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For URL inputs, Mozilla's &lt;a href="https://github.com/mozilla/readability" rel="noopener noreferrer"&gt;Readability.js&lt;/a&gt; wrapped in a tiny Node service does almost all the work.&lt;/p&gt;

&lt;p&gt;The lesson: don't over-engineer extraction. The downstream LLM is going to rewrite this content anyway. You just need &lt;em&gt;enough&lt;/em&gt; signal — headings, paragraphs, reading order — for the outline step to make good decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 2: Outline generation
&lt;/h2&gt;

&lt;p&gt;This is where the pipeline either goes well or goes off the rails. The outline determines how many pages, what each page is about, and what kind of layout each page wants. We iterated a lot here.&lt;/p&gt;

&lt;p&gt;The prompt enforces a structured JSON schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subtitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"page_number"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cover"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"toc"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"section_intro"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"content"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"quote"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"back"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"heading"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"key_points"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"suggested_layout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"image_left"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"image_right"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"full_bleed"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"two_column"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"image_prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things made this reliable:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;JSON schema validation in the prompt&lt;/strong&gt; — we paste a small JSON Schema and ask the model to conform. Reject + retry on parse failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Length budgeting upfront&lt;/strong&gt; — we tell the model the target page count and word budget per page. Without this, models love to write 800 words for a page that only fits 180.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layout suggestions generated alongside content&lt;/strong&gt; — letting the model pick &lt;code&gt;suggested_layout&lt;/code&gt; based on the content type produces better-looking books than picking layouts post-hoc.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Stage 3: Per-page content generation
&lt;/h2&gt;

&lt;p&gt;The outline is cheap to generate (one call). Per-page content is where the cost lives. We learned to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Generate pages in parallel&lt;/strong&gt; — pages are independent given the outline, so we fire 6–8 LLM calls concurrently with a small connection pool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pin the model per booklet&lt;/strong&gt; — switching models mid-booklet creates jarring tone shifts. We pick one model per generation job and stick with it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the outline in every prompt's system message&lt;/strong&gt; — gives each page-level call awareness of what comes before and after, which prevents repetition.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Streaming responses don't help here — the user is waiting on the entire booklet, not page-by-page text appearing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 4: Image generation (the surprising bottleneck)
&lt;/h2&gt;

&lt;p&gt;Images turned out to be the slowest, flakiest stage. Why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Image gen APIs have wildly different latencies (Replicate model cold starts can be 30s+).&lt;/li&gt;
&lt;li&gt;Failure rates are non-trivial (~3–5% per image), and a 12-page booklet needs 6–10 images.&lt;/li&gt;
&lt;li&gt;Quality is inconsistent on style adherence — "magazine editorial photography" means different things to different models.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What worked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Async-from-the-start&lt;/strong&gt; — image gen runs in parallel with HTML assembly. We render the booklet with placeholder gradients first; images stream in as they're ready.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-image timeout + fallback&lt;/strong&gt; — if image gen for page 7 fails or takes &amp;gt;40s, we substitute a curated stock image keyed off the page's &lt;code&gt;image_prompt&lt;/code&gt;. Better a relevant photograph than a broken booklet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cropping happens server-side&lt;/strong&gt; — we ask for square (1024x1024) images and crop to the layout's aspect ratio in the same service that handles the upload to OSS. This avoids round-trips and lets us cache aggressively.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stage 5: HTML assembly
&lt;/h2&gt;

&lt;p&gt;The booklet template is server-rendered HTML with a CSS-paged-media stylesheet. Each layout type (&lt;code&gt;image_left&lt;/code&gt;, &lt;code&gt;image_right&lt;/code&gt;, etc.) is a small Thymeleaf fragment composed into a full page.&lt;/p&gt;

&lt;p&gt;Key decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A4 dimensions hardcoded into CSS&lt;/strong&gt; (&lt;code&gt;@page { size: A4; }&lt;/code&gt; plus &lt;code&gt;width: 210mm; height: 297mm&lt;/code&gt; on each page wrapper). Makes the PDF predictable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Print-aware CSS&lt;/strong&gt; — fonts loaded via &lt;code&gt;@font-face&lt;/code&gt;, page breaks via &lt;code&gt;break-after: page&lt;/code&gt;, no &lt;code&gt;position: fixed&lt;/code&gt; (Puppeteer pdf() handles it inconsistently across pages).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One HTML document per booklet, not one per page&lt;/strong&gt; — easier to navigate in the editor, easier to render in one Puppeteer pass.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stage 6: Headless render + PDF export
&lt;/h2&gt;

&lt;p&gt;Puppeteer is the unsung hero here. The export endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puppeteer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--no-sandbox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--disable-setuid-sandbox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--font-render-hinting=none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bookletUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;networkidle0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluateHandle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;document.fonts.ready&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;printBackground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;preferCSSPageSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Things we learned the hard way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;document.fonts.ready&lt;/code&gt; matters.&lt;/strong&gt; Without it, you ship PDFs with fallback fonts on the first page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;networkidle0&lt;/code&gt; is not enough&lt;/strong&gt; for image-heavy pages — we explicitly &lt;code&gt;await Promise.all(images.map(img =&amp;gt; img.complete || new Promise(r =&amp;gt; img.onload = r)))&lt;/code&gt; before calling &lt;code&gt;pdf()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;preferCSSPageSize: true&lt;/code&gt;&lt;/strong&gt; is the difference between "the PDF respects my A4 layout" and "Chrome guesses the page size".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;--font-render-hinting=none&lt;/code&gt;&lt;/strong&gt; produces cleaner text in PDFs across font weights.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Post-processing (page numbering, bookmarks, link annotations) we do with &lt;a href="https://pdf-lib.js.org" rel="noopener noreferrer"&gt;pdf-lib&lt;/a&gt; after Puppeteer hands back the buffer.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we'd build differently
&lt;/h2&gt;

&lt;p&gt;Three things, in priority order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A real document model, not HTML-as-source-of-truth.&lt;/strong&gt; Storing the booklet as JSON (structured content + layout decisions) and rendering to HTML on demand would make collaboration features and version diffing dramatically simpler. We're paying interest on this every sprint.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A proper image queue with priority.&lt;/strong&gt; Right now image gen is a fire-and-forget per booklet. Sharing one queue across all jobs with priority tiers (paid users first, retries scheduled) would smooth out tail latency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server-side font subsetting.&lt;/strong&gt; Booklets ship with the full webfont files embedded in the PDF. For a 12-page booklet using one weight of one font, that's hundreds of KB of unused glyphs. &lt;a href="https://github.com/fonttools/fonttools" rel="noopener noreferrer"&gt;fontTools&lt;/a&gt; subsetting in the export step would cut PDF size by 60–80%.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If you want to see the output of this pipeline, the live tool is at &lt;a href="https://bookletai.org" rel="noopener noreferrer"&gt;bookletai.org&lt;/a&gt; — paste a topic or upload a PDF and you get a booklet in about a minute. The first one is free; we'd love feedback on the layout decisions, especially what the AI gets wrong.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is a write-up of decisions made on the &lt;a href="https://bookletai.org" rel="noopener noreferrer"&gt;Booklet AI&lt;/a&gt; team. Questions, critiques, or "you should have done X instead" comments very welcome.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aiwebdev</category>
    </item>
    <item>
      <title>How AI Turns a One-Line Prompt Into a Full A4 Booklet</title>
      <dc:creator>Mw234324324324Booklet AI Writer</dc:creator>
      <pubDate>Sat, 25 Apr 2026 01:39:00 +0000</pubDate>
      <link>https://vibe.forem.com/mw234324324324/how-ai-turns-a-one-line-prompt-into-a-full-a4-booklet-41hj</link>
      <guid>https://vibe.forem.com/mw234324324324/how-ai-turns-a-one-line-prompt-into-a-full-a4-booklet-41hj</guid>
      <description>&lt;p&gt;A few months ago I wanted a 12-page printable guide for a workshop. The choices were ugly: open InDesign and lose two days, drop content into Canva and fight templates, or paste everything into ChatGPT and copy the result back into Word.&lt;/p&gt;

&lt;p&gt;That gap is what got me building &lt;a href="https://bookletai.org" rel="noopener noreferrer"&gt;Booklet AI&lt;/a&gt;. The idea is simple: describe what you want in chat, the AI asks clarifying questions about audience and tone, gathers material from the web and any files you upload, generates an outline you can tweak, then writes and lays out 8 to 15 A4 pages with images and text mixed in a magazine-style flow.&lt;/p&gt;

&lt;p&gt;Three things I learned while building it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Layout is the hard part, not text.&lt;/strong&gt; Anyone can produce 1500 words; making them fit a fixed A4 grid with figures, captions, and section breaks is where most AI tools quit. Generating each page as a self-contained HTML block instead of streaming Markdown made the layout problem tractable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source quality beats prompt cleverness.&lt;/strong&gt; Letting users upload their own PDF, Word, or image and feeding that into the model gave a much bigger lift than tweaking system prompts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edit modes matter.&lt;/strong&gt; Two flows on every page (natural-language AI Edit and visual drag Quick Edit) cover both kinds of users — those who can describe what they want and those who only know it when they see it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Free to try at &lt;a href="https://bookletai.org" rel="noopener noreferrer"&gt;bookletai.org&lt;/a&gt;. Curious to hear what people use it for.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>pdf</category>
      <category>showdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>BookletAI for turning long content into shareable booklet pages</title>
      <dc:creator>Mw234324324324Booklet AI Writer</dc:creator>
      <pubDate>Fri, 17 Apr 2026 15:13:30 +0000</pubDate>
      <link>https://vibe.forem.com/mw234324324324/bookletai-for-turning-long-content-into-shareable-booklet-pages-516m</link>
      <guid>https://vibe.forem.com/mw234324324324/bookletai-for-turning-long-content-into-shareable-booklet-pages-516m</guid>
      <description>&lt;p&gt;BookletAI helps turn long docs, articles, and reports into clean, shareable booklet pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bookletai.org" rel="noopener noreferrer"&gt;https://bookletai.org&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>From Research Chat to a Shareable Booklet in Minutes</title>
      <dc:creator>Mw234324324324Booklet AI Writer</dc:creator>
      <pubDate>Fri, 27 Mar 2026 07:51:37 +0000</pubDate>
      <link>https://vibe.forem.com/mw234324324324/from-research-chat-to-a-shareable-booklet-in-minutes-4pha</link>
      <guid>https://vibe.forem.com/mw234324324324/from-research-chat-to-a-shareable-booklet-in-minutes-4pha</guid>
      <description>&lt;p&gt;I've been experimenting with a workflow for turning messy research into something a client or teammate can actually read.&lt;/p&gt;

&lt;p&gt;The result is &lt;strong&gt;Booklet AI&lt;/strong&gt;: &lt;a href="https://bookletai.org" rel="noopener noreferrer"&gt;https://bookletai.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It takes a topic in plain language, searches the web for supporting material, builds a page-by-page outline, and turns the result into a polished A4 booklet you can preview, share, and export.&lt;/p&gt;

&lt;p&gt;What it does well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;asks follow-up questions before generating&lt;/li&gt;
&lt;li&gt;gathers source material from the web&lt;/li&gt;
&lt;li&gt;creates a structured outline first&lt;/li&gt;
&lt;li&gt;generates multi-page visual booklet layouts instead of a long wall of text&lt;/li&gt;
&lt;li&gt;lets you edit one page at a time&lt;/li&gt;
&lt;li&gt;exports to shareable HTML and PDF&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few use cases I think are interesting for builders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;product explainers&lt;/li&gt;
&lt;li&gt;training handbooks&lt;/li&gt;
&lt;li&gt;research summaries&lt;/li&gt;
&lt;li&gt;proposal-style docs for demos or sales&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are building AI products for communication rather than just raw text output, I'd love feedback on the workflow and where this could fit into your stack.&lt;/p&gt;

&lt;p&gt;Try it here: &lt;a href="https://bookletai.org" rel="noopener noreferrer"&gt;https://bookletai.org&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>buildinpublic</category>
      <category>chatgpt</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Create Professional Booklets in Minutes with Booklet AI</title>
      <dc:creator>Mw234324324324Booklet AI Writer</dc:creator>
      <pubDate>Wed, 25 Mar 2026 00:23:19 +0000</pubDate>
      <link>https://vibe.forem.com/mw234324324324/create-professional-booklets-in-minutes-with-booklet-ai-5918</link>
      <guid>https://vibe.forem.com/mw234324324324/create-professional-booklets-in-minutes-with-booklet-ai-5918</guid>
      <description>&lt;p&gt;If you've ever needed to create a professional-looking booklet, brochure, or presentation quickly, you know how time-consuming the design process can be. Between finding the right template, gathering research, writing content, and arranging layouts — it can take hours or even days.That's exactly the problem &lt;a href="https://bookletai.org" rel="noopener noreferrer"&gt;Booklet AI&lt;/a&gt; was built to solve.## What is Booklet AI?&lt;a href="https://bookletai.org" rel="noopener noreferrer"&gt;Booklet AI&lt;/a&gt; is an AI-powered tool that creates professional booklets through conversation. You simply describe what you need, and the AI takes care of everything: research, outline, design, and content generation.## How It Works1. &lt;strong&gt;Describe your topic&lt;/strong&gt; — Just tell the AI what you need in plain language2. &lt;strong&gt;AI confirms requirements&lt;/strong&gt; — It asks about your audience, purpose, and style preferences3. &lt;strong&gt;Automatic research&lt;/strong&gt; — The AI searches the web and scrapes 3-5 high-quality sources4. &lt;strong&gt;Outline preview&lt;/strong&gt; — See the planned structure before generation begins5. &lt;strong&gt;Page-by-page generation&lt;/strong&gt; — Each A4 page is generated with text and images, displayed in real-time6. &lt;strong&gt;Edit and share&lt;/strong&gt; — Fine-tune any page, then share via link or download as HTML/PDF## Key Features- &lt;strong&gt;Fixed A4 layout&lt;/strong&gt; (794×1123 px) with magazine-style formatting- &lt;strong&gt;Real images + AI-generated images&lt;/strong&gt; for each page- &lt;strong&gt;Single-page editing&lt;/strong&gt; — modify one page without affecting others- &lt;strong&gt;Shareable links&lt;/strong&gt; — no login required for viewers- &lt;strong&gt;Export to PDF&lt;/strong&gt; via Playwright rendering## Use Cases- Product brochures for sales teams- Training manuals for HR- Research summaries and industry reports- Pitch decks and proposals- Course materials for educators## Why It's DifferentUnlike regular AI writing tools that output plain text, Booklet AI delivers ready-to-use, print-quality A4 pages with proper layouts. No design skills required — just describe what you want.Check it out at &lt;a href="https://bookletai.org" rel="noopener noreferrer"&gt;bookletai.org&lt;/a&gt; and create your first professional booklet in minutes.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
