<?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>DEV Community: EbookForge</title>
    <description>The latest articles on DEV Community by EbookForge (@mxprs).</description>
    <link>https://dev.to/mxprs</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3649724%2Fa46f2501-5909-4e23-9edd-ab3f408630dd.webp</url>
      <title>DEV Community: EbookForge</title>
      <link>https://dev.to/mxprs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mxprs"/>
    <language>en</language>
    <item>
      <title>Why relying on a raw LLM to build structured PDFs is a nightmare (and how I fixed it)</title>
      <dc:creator>EbookForge</dc:creator>
      <pubDate>Sun, 26 Jul 2026 14:02:03 +0000</pubDate>
      <link>https://dev.to/mxprs/why-relying-on-a-raw-llm-to-build-structured-pdfs-is-a-nightmare-and-how-i-fixed-it-f73</link>
      <guid>https://dev.to/mxprs/why-relying-on-a-raw-llm-to-build-structured-pdfs-is-a-nightmare-and-how-i-fixed-it-f73</guid>
      <description>&lt;p&gt;If you’ve ever tried to generate a polished, production-ready PDF directly from an LLM, you already know the pain.&lt;/p&gt;

&lt;p&gt;You ask for a clean layout, maybe some headers and a specific margin, and the model confidently spits back an unformatted wall of markdown. Or worse, you try to pipe its output directly into a PDF library like ReportLab or PDFKit, and the layout breaks completely. The fonts are wrong, the page breaks happen in the middle of sentences, and any structured data you had is now a chaotic mess.&lt;/p&gt;

&lt;p&gt;Here's why raw LLMs fail at structured PDF generation, and the pipeline I built to fix it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem: LLMs are writers, not designers
&lt;/h3&gt;

&lt;p&gt;Large Language Models are incredible at generating text, summarizing data, and even reasoning through logic. But they have zero spatial awareness. When an LLM generates a document, it doesn't "see" a 8.5x11 inch page. It sees a continuous stream of tokens.&lt;/p&gt;

&lt;p&gt;Trying to get an LLM to reliably output precise spacing, page breaks, or complex tables that fit perfectly on a printed page is like asking a novelist to typeset their own book while blindfolded.&lt;/p&gt;

&lt;p&gt;The typical naive approach looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prompt the LLM to generate content.&lt;/li&gt;
&lt;li&gt;Tell it to output HTML.&lt;/li&gt;
&lt;li&gt;Pass the HTML to a PDF generator.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This breaks because LLMs hallucinate HTML tags, forget closing tags, and completely ignore pagination logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution: A Decoupled Architecture
&lt;/h3&gt;

&lt;p&gt;To fix this, I stopped treating the LLM as a designer and started treating it strictly as a content engine. The solution was a decoupled pipeline:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Structured Data Generation (JSON/Markdown)&lt;/strong&gt;&lt;br&gt;
Instead of asking the LLM for HTML or layout instructions, I prompt it to return strictly structured JSON or clean Markdown. I use function calling (or structured outputs) to enforce a strict schema. The LLM's only job is to provide the content (titles, paragraphs, data points).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Templating Engine (HTML/CSS)&lt;/strong&gt;&lt;br&gt;
I created a robust templating layer (using Jinja2/Handlebars) that holds the actual design. This layer knows exactly how to handle margins, fonts, and headers. It takes the structured JSON from the LLM and maps it to predefined, heavily tested HTML components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The PDF Rendering Engine&lt;/strong&gt;&lt;br&gt;
Finally, the rendered HTML is passed to a headless browser (like Puppeteer/Playwright) or a dedicated rendering engine (like WeasyPrint) that actually understands CSS paged media. This handles the page breaks, headers, and footers flawlessly.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Result
&lt;/h3&gt;

&lt;p&gt;By decoupling the content generation from the layout rendering, the nightmare stopped. The LLM focuses on what it does best (writing and structuring data), and the rendering engine handles the visual layout. No more broken tables, no more mid-sentence page breaks.&lt;/p&gt;

&lt;p&gt;If you are building an AI-powered document generator, stop trying to make the LLM do everything. Build a pipeline.&lt;/p&gt;




&lt;h3&gt;
  
  
  Further Reading from EbookForge
&lt;/h3&gt;

&lt;p&gt;If you're building document generation pipelines or working with AI-generated content, check out these related posts from our blog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://ebookforge.app/blog/from-prompt-to-print" rel="noopener noreferrer"&gt;From Prompt to Print: Mastering CSS Paged Media for Automated PDFs&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Dive deeper into how we use tools like WeasyPrint and CSS &lt;code&gt;@page&lt;/code&gt; rules to ensure perfect page breaks, custom margins, and dynamic headers/footers when converting HTML to PDF. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://ebookforge.app/blog/stop-parsing-markdown" rel="noopener noreferrer"&gt;Stop Parsing Markdown: Enforcing JSON Schemas with LLM Function Calling&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A technical guide on how to guarantee your LLM outputs strictly typed JSON data. Learn how to use OpenAI's structured outputs and function calling to eliminate broken tags and missing fields in your document pipelines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://ebookforge.app/blog/puppeteer-vs-weasyprint" rel="noopener noreferrer"&gt;The Puppeteer vs. WeasyPrint Showdown for Document Generation&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Should you use a headless browser or a dedicated CSS rendering engine? We break down the performance, scalability, and layout accuracy of both approaches when generating thousands of documents at scale.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://ebookforge.app/blog/handling-hallucinations" rel="noopener noreferrer"&gt;Handling Hallucinations in Automated Reporting&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
How to build robust validation layers and fallback mechanisms when your AI content engine goes off-script. Learn how to sanitize LLM data before it ever hits your Jinja templates. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Ready to automate your document creation without the layout headaches? Try &lt;a href="https://ebookforge.app" rel="noopener noreferrer"&gt;EbookForge.app&lt;/a&gt; today and let us handle the rendering pipeline for you.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>webdev</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>I built a book generator that runs entirely in your browser — no server, no account, no backend</title>
      <dc:creator>EbookForge</dc:creator>
      <pubDate>Sat, 21 Mar 2026 14:02:23 +0000</pubDate>
      <link>https://dev.to/mxprs/i-built-a-book-generator-that-runs-entirely-in-your-browser-no-server-no-account-no-backend-3llc</link>
      <guid>https://dev.to/mxprs/i-built-a-book-generator-that-runs-entirely-in-your-browser-no-server-no-account-no-backend-3llc</guid>
      <description>&lt;p&gt;A few months ago I posted here about EbookForge — a JSON-to-PDF engine I built because formatting ebooks was driving me insane.&lt;/p&gt;

&lt;p&gt;That post got zero comments. Fair enough. The product was rough, the pitch was confusing, and honestly — asking people to write books as JSON was a hard sell.&lt;/p&gt;

&lt;p&gt;But the formatting problem was real. So I kept building. And the project got completely out of hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  What started as a formatter became something else
&lt;/h2&gt;

&lt;p&gt;The original pain: I had structured content and no clean way to turn it into a typeset PDF with a cover page, justified text, embedded fonts, and a table of contents with actual page numbers. Everything I tried required a server, looked terrible, or both.&lt;br&gt;
So I built a client-side PDF engine. That worked. But then I realized: the formatting was the easy part. The hard part was making the input worth formatting.&lt;/p&gt;

&lt;p&gt;So I kept going.&lt;/p&gt;

&lt;h2&gt;
  
  
  EbookForge today
&lt;/h2&gt;

&lt;p&gt;EbookForge now generates complete books from scratch — entirely in your browser.&lt;/p&gt;

&lt;p&gt;You describe your taste:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pick up to 3 genres&lt;/li&gt;
&lt;li&gt;Place a dot on a 2D emotional axis (comforted ↔ disturbed, devastated ↔ euphoric)&lt;/li&gt;
&lt;li&gt;Describe your protagonist in one sentence&lt;/li&gt;
&lt;li&gt;Drop in a "wildcard seed" — a sensory image, a memory, a vibe&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The AI then architects a full book blueprint (title, plot, chapter arcs, themes, trigger warnings), generates a painterly cover illustration, and writes the first chapter. You read it, then forge the next chapters one by one.&lt;/p&gt;

&lt;p&gt;The twist: between chapters, you can inject "Director's Notes" — creative instructions like "a sudden betrayal" or "the rain stops and the silence becomes deafening." The system rewrites the remaining chapter plan to stay coherent with your intervention.&lt;/p&gt;

&lt;p&gt;Then you download the whole thing as a typeset PDF with embedded fonts, cover art, synopsis page, and numbered table of contents.&lt;/p&gt;

&lt;p&gt;No server. No account. No database. Your Gemini API key lives in sessionStorage and dies when you close the tab. There's a full demo book you can browse without any key.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;p&gt;Zero backend. Zero dependencies beyond the browser and a Gemini key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting AI to generate images without text.
&lt;/h2&gt;

&lt;p&gt;I needed painterly cover illustrations with zero typography. Image models desperately want to put words on images. The prompt has to be adversarial — "ABSOLUTELY NO TEXT, NO LETTERS, NO WORDS" — and it still fails maybe 20% of the time. This single problem took more iterations than the rest of the app combined.&lt;/p&gt;

&lt;p&gt;Multi-chapter coherence with human interventions. When you inject a Director's Note that contradicts the planned story arc, every downstream chapter summary needs to adapt. The system sends the generated chapter text + the user's note back to the AI and asks it to rewrite the remaining chapter metadata. It works surprisingly well. When it doesn't, the prose still adapts through context because each chapter prompt includes the tail end of the previous chapter.&lt;/p&gt;

&lt;p&gt;Two-pass PDF rendering. The table of contents needs page numbers, but you don't know the page numbers until you've rendered all the chapters. So: first pass renders everything and tracks where each chapter lands, second pass goes back to the TOC page and fills in the numbers. Justified text is done via manual word-spacing calculation — split each line into words, measure the leftover space, distribute it evenly.&lt;/p&gt;

&lt;p&gt;Persistence without a backend. Cover images are multi-megabyte base64 strings that blow up localStorage. Solution: metadata goes to localStorage, covers go to IndexedDB, and the library view stitches them back together on load. Delete a book and both stores get cleaned up.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it's NOT
&lt;/h2&gt;

&lt;p&gt;It's not a publishing pipeline. It's not meant to flood Amazon with AI novels. It's a creative toy — closer to AI Dungeon for long-form fiction than a KDP tool.&lt;/p&gt;

&lt;p&gt;The question I was chasing: can a human and an AI co-direct a narrative across multiple chapters, with the human's choices propagating forward coherently?&lt;/p&gt;

&lt;p&gt;The answer is "sometimes, and it's genuinely fascinating when it works."&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it &lt;code&gt;ebookforge.app&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;You can browse the full demo book (English or French) without entering any API key. Bring your own Gemini key to forge one from scratch.&lt;br&gt;
Bilingual EN/FR. &lt;/p&gt;

&lt;p&gt;The whole thing is a solo side project that started as a formatting script and turned into whatever this is. If you've ever fought with PDF generation in the browser, or tried to make AI-generated text stay coherent across 10+ chapters — I'd love to hear how you approached it.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>ai</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I built a JSON to PDF Ebook engine because formatting ebooks was driving me insane</title>
      <dc:creator>EbookForge</dc:creator>
      <pubDate>Sun, 07 Dec 2025 00:40:23 +0000</pubDate>
      <link>https://dev.to/mxprs/i-built-a-json-to-pdf-ebook-engine-because-formatting-ebooks-was-driving-me-insane-3mcn</link>
      <guid>https://dev.to/mxprs/i-built-a-json-to-pdf-ebook-engine-because-formatting-ebooks-was-driving-me-insane-3mcn</guid>
      <description>&lt;p&gt;Hey everyone 👋&lt;/p&gt;

&lt;p&gt;I’m Sam — a solo builder who spends way too much time writing long-form content: guides, frameworks, SOPs, ebooks…&lt;br&gt;
And weirdly, the writing was never the hard part.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The hard part was turning that content into something clean, structured, and publishable without spending hours in Google Docs, Notion, or—worse—InDesign.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I built EbookForge:&lt;br&gt;
👉 a fast, deterministic JSON → PDF Ebook engine for developers and creators. Website: &lt;a href="https://ebookforge.app" rel="noopener noreferrer"&gt;EbookForge&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9sq8off5b64y223upq2q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9sq8off5b64y223upq2q.png" alt=" " width="800" height="662"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you write long-form content, you probably know the pain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fighting with margins and spacing&lt;/li&gt;
&lt;li&gt;Random line breaks&lt;/li&gt;
&lt;li&gt;Tables that jump around&lt;/li&gt;
&lt;li&gt;PDFs that look different every time you export&lt;/li&gt;
&lt;li&gt;Manual formatting that kills your flow&lt;/li&gt;
&lt;li&gt;Templates that solve nothing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I always thought “why isn’t there a simple, deterministic way to generate a clean ebook from structured content?”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There wasn’t. So I built one.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What EbookForge does
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;EbookForge takes a strict JSON schema and turns it into a clean, professional PDF ebook.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Titles / subtitles&lt;/li&gt;
&lt;li&gt;Headings&lt;/li&gt;
&lt;li&gt;Paragraphs&lt;/li&gt;
&lt;li&gt;Lists&lt;/li&gt;
&lt;li&gt;Page layout rules&lt;/li&gt;
&lt;li&gt;Consistent typography&lt;/li&gt;
&lt;li&gt;Automatic spacing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;*&lt;em&gt;No WYSIWYG. No template hell. Just structure → output. *&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why JSON?
&lt;/h2&gt;

&lt;p&gt;Because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;t’s predictable&lt;/li&gt;
&lt;li&gt;It’s scriptable&lt;/li&gt;
&lt;li&gt;It’s versionable&lt;/li&gt;
&lt;li&gt;It works with LLMs&lt;/li&gt;
&lt;li&gt;It integrates with any backend&lt;/li&gt;
&lt;li&gt;Developers already understand it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’ve ever built internal docs, tutorials, online courses, ebooks, or technical PDFs… JSON is the perfect middle layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this is for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Developers generating PDFs programmatically&lt;/li&gt;
&lt;li&gt;SaaS founders shipping guides or documentation&lt;/li&gt;
&lt;li&gt;Indie hackers building content products&lt;/li&gt;
&lt;li&gt;Writers who want full control over structure&lt;/li&gt;
&lt;li&gt;Anyone automating content workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I built EbookForge for myself first, but I realized others might find it useful too.&lt;/p&gt;

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

&lt;p&gt;It’s live here &lt;a href="https://ebookforge.app" rel="noopener noreferrer"&gt;EbookForge&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You paste a JSON example, hit “&lt;strong&gt;Generate&lt;/strong&gt;”, and get a clean PDF instantly.&lt;/p&gt;

&lt;p&gt;Still early, still improving — feedback is super welcome.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback appreciated
&lt;/h2&gt;

&lt;p&gt;If you’ve ever struggled with PDF/ebook generation, I’d love to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What formats do you use?&lt;/li&gt;
&lt;li&gt;What pain points do you hit the most?&lt;/li&gt;
&lt;li&gt;What features would make this 10× more useful?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy to share code snippets or JSON examples too.&lt;/p&gt;

&lt;p&gt;Thanks for reading! 🙌&lt;br&gt;
Sam&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>javascript</category>
      <category>writing</category>
    </item>
  </channel>
</rss>
