<?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: jom hou</title>
    <description>The latest articles on DEV Community by jom hou (@jom_hou_f89f9d6df6d688c0a).</description>
    <link>https://dev.to/jom_hou_f89f9d6df6d688c0a</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%2F4070760%2F7ded75fc-5f1a-43ee-9599-bb3f74422696.png</url>
      <title>DEV Community: jom hou</title>
      <link>https://dev.to/jom_hou_f89f9d6df6d688c0a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jom_hou_f89f9d6df6d688c0a"/>
    <language>en</language>
    <item>
      <title>How I built a Markdown-to-PDF export tool with Next.js (and what I learned)</title>
      <dc:creator>jom hou</dc:creator>
      <pubDate>Mon, 10 Aug 2026 12:18:53 +0000</pubDate>
      <link>https://dev.to/jom_hou_f89f9d6df6d688c0a/how-i-built-a-markdown-to-pdf-export-tool-with-nextjs-and-what-i-learned-25gl</link>
      <guid>https://dev.to/jom_hou_f89f9d6df6d688c0a/how-i-built-a-markdown-to-pdf-export-tool-with-nextjs-and-what-i-learned-25gl</guid>
      <description>&lt;h1&gt;
  
  
  How I built a Markdown-to-PDF export tool with Next.js (and what I learned)
&lt;/h1&gt;

&lt;p&gt;I've been building side projects for a while, but &lt;strong&gt;Markdownary&lt;/strong&gt; is the first one I actually shipped and put in front of real users.&lt;/p&gt;

&lt;p&gt;The core feature sounds simple: write Markdown, export to PDF. But getting it to work &lt;em&gt;well&lt;/em&gt; turned out to be surprisingly tricky.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with browser-based PDF export
&lt;/h2&gt;

&lt;p&gt;Most Markdown-to-PDF tools use one of two approaches:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;window.print()&lt;/code&gt;&lt;/strong&gt; — quick and dirty, but the output looks like a printed webpage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Puppeteer/headless Chrome&lt;/strong&gt; — accurate, but heavy, slow to cold-start, and expensive to host&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I wanted something that produced clean, typographically correct PDFs without spinning up a full browser instance on every request.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution: server-side rendering with a Skia-based engine
&lt;/h2&gt;

&lt;p&gt;I ended up using a server-side Markdown rendering engine built on &lt;strong&gt;Skia Canvas&lt;/strong&gt; — the same graphics library that powers Chrome's rendering. It processes Markdown on the server and produces vector-quality output without needing a headless browser.&lt;/p&gt;

&lt;p&gt;The result: PDFs that look like they were designed, not printed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 15&lt;/strong&gt; (App Router) — API routes handle all export logic server-side&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt; throughout&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS 4&lt;/strong&gt; for the editor UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;react-markdown + remark-gfm&lt;/strong&gt; for live preview&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PM2 cluster mode&lt;/strong&gt; for production deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What the app does
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Markdownary&lt;/strong&gt; is a clean, distraction-free Markdown editor with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Export to &lt;strong&gt;PDF, Word (.docx), PNG, and HTML&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;6 themes&lt;/strong&gt; with live preview (light, dark, warm, bamboo, ocean, rose)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No login required&lt;/strong&gt; — open and start writing&lt;/li&gt;
&lt;li&gt;Import &lt;code&gt;.md&lt;/code&gt;, &lt;code&gt;.docx&lt;/code&gt;, &lt;code&gt;.txt&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;Synchronized scroll between editor and preview&lt;/li&gt;
&lt;li&gt;Mobile-friendly toolbar&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lessons learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. PDF quality is a UX differentiator&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Users notice immediately when PDF output looks bad. Investing in a proper rendering engine made the biggest difference in early feedback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. "No login" is a feature&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Removing the signup wall increased the conversion from "landing page visitor" to "actual user" dramatically. People just want to try it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Character limits matter&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Without a content size limit on the export API, a single large document can spike memory usage and affect all users. I added a 300k character cap with a clear error message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Mobile is non-negotiable&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even for a "desktop" tool like a Markdown editor, ~30% of initial visits came from mobile. A collapsed toolbar with the most-used actions (bold, italic, heading, list) surfaced made a huge difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Google AdSense integration (currently in review)&lt;/li&gt;
&lt;li&gt;More export themes&lt;/li&gt;
&lt;li&gt;Collaborative editing (maybe)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you're into Markdown, writing tools, or just want to try it out:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://markdownary.com" rel="noopener noreferrer"&gt;https://markdownary.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Would love feedback — especially on the PDF output quality and anything that feels broken on mobile.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>markdown</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
