The AI Resume Paradox: Markdown Input, Manual Output
The workflow is familiar to many job seekers today: prompt an AI like ChatGPT, Claude, or Gemini to generate resume bullet points. The AI delivers beautifully structured text. Then comes the slog – forty minutes spent wrestling that output into Microsoft Word or a drag-and-drop resume builder, manually fixing indentation and font sizes. It’s a paradox: AI models speak Markdown fluently, yet nearly every tool forces users to discard that structure and re-enter information into rigid form fields.
This friction sparked the creation of ResumeMD, a tool designed to bridge this gap. It offers a split-pane editor. Paste your Markdown resume on the left, and see a typeset, ready-to-download PDF on the right. Users can select from various templates. The core promise: no signup required, with data stored locally in localStorage by default. However, the development process uncovered significant challenges.

Decision 1: Markdown Rendering and Templating
The first major hurdle was choosing a Markdown rendering engine. Many libraries exist, but few handle complex tables, nested lists, and custom styling gracefully. The goal was to render Markdown that accurately reflected the expected output of LLMs, which often includes elements like bolding for job titles, italics for company names, and bulleted lists for responsibilities. Libraries like marked or markdown-it were considered. markdown-it emerged as the preferred choice due to its extensibility and plugin architecture, allowing for custom handling of specific Markdown syntax that might be prevalent in AI-generated content.
The templating system also presented a significant challenge. LLMs can generate content with varying levels of detail and structure. A robust templating engine is needed to accommodate this variability while producing a consistently professional-looking resume. Options ranged from simple string replacement to more sophisticated templating languages like Handlebars or EJS. The decision was to build a custom, lightweight templating system that could parse Markdown structure (like headings and list items) and map them to predefined visual styles within different templates. This approach aimed for flexibility without the overhead of a full-blown templating library, which might be overkill for the specific needs of resume formatting.
Ensuring cross-browser compatibility for the rendering and templating was also a constant battle. Different browsers interpret CSS and HTML slightly differently, which can lead to variations in how the typeset resume appears. Rigorous testing across Chrome, Firefox, Safari, and Edge was necessary to ensure a consistent user experience. The choice of CSS framework or custom CSS also played a critical role. A minimalist approach, focusing on semantic HTML and well-defined CSS classes, proved more manageable than relying on heavy UI frameworks that might introduce their own rendering quirks.
Decision 2: PDF Generation
Generating a high-quality PDF directly from HTML and CSS is notoriously difficult. Client-side PDF generation libraries like jsPDF or html2pdf.js were evaluated. While these libraries can convert HTML to PDF, they often struggle with complex layouts, specific font embedding, and maintaining precise visual fidelity. The output could sometimes be distorted, with elements overlapping or misaligned, especially when dealing with varied content lengths and complex formatting.
html2pdf.js, which uses jsPDF and html2canvas under the hood, was initially promising. It can take an HTML element and convert it into a PDF. However, the process of getting the rendered HTML from the Markdown editor to look *exactly* like the desired PDF output required extensive CSS workarounds. Achieving pixel-perfect replication of the on-screen preview in the generated PDF became a time sink. This involved debugging CSS that worked for screen rendering but failed in the PDF context, often due to limitations in how PDF generators interpret CSS properties like floats, absolute positioning, or complex flexbox/grid layouts.
The alternative was server-side PDF generation. This would involve sending the final HTML to a server, where a more powerful PDF generation engine (like those used in headless browsers or dedicated PDF services) could process it. However, this approach introduces complexity: it requires a backend infrastructure, adds latency, and potentially raises privacy concerns for users who prefer to keep their resume data entirely client-side. For ResumeMD’s initial goal of a simple, client-side tool, this was an undesirable trade-off. The compromise was to accept that client-side PDF generation might not be *perfectly* pixel-identical to the preview but should be *functionally* accurate and visually acceptable.
Decision 3: User Experience and Local Storage
Designing a user experience that felt intuitive, especially for users accustomed to drag-and-drop editors, was another challenge. The split-pane interface, while efficient for Markdown users, can be unfamiliar to others. Clear visual cues and onboarding were essential. The goal was to make the transition from AI output to a polished resume as seamless as possible, minimizing the learning curve for the Markdown input.
Relying on localStorage for data persistence was a deliberate choice to avoid mandatory signups and keep the tool lightweight and private. However, localStorage has limitations. It has a finite storage capacity (typically 5-10MB per origin), which could be an issue for users with extremely long or complex resumes. More critically, localStorage data is tied to the browser and origin. If a user clears their browser data, switches browsers, or uses a different device, their resume data is lost. This lack of cloud backup is a significant drawback compared to traditional resume builders. Educating users about this limitation and recommending they export their work regularly became a crucial part of the user guidance.
Furthermore, handling errors gracefully was paramount. What happens when a user pastes malformed Markdown? Or when the PDF generation fails unexpectedly? Providing clear, actionable error messages, rather than cryptic technical jargon, is vital. For instance, instead of a generic
