diff --git a/projects/business/marketing/devto-article.md b/projects/business/marketing/devto-article.md deleted file mode 100644 index d0a4519..0000000 --- a/projects/business/marketing/devto-article.md +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: "I Built an HTML-to-PDF API in a Day — Here's How It Works" -published: false -tags: node, javascript, api, pdf ---- - -Every developer has that one problem they keep solving over and over. For me, it's PDF generation. - -Invoice for a freelance project? PDF. Report for a dashboard? PDF. Receipt for an e-commerce app? PDF. And every time, I'd end up in the same rabbit hole: installing wkhtmltopdf, fighting with Docker images, or configuring Puppeteer from scratch. - -So I built [DocFast](https://docfast.dev) — a simple API that takes HTML or Markdown and returns a PDF. Here's how it works under the hood. - -## The Architecture - -DocFast is straightforward: - -- **Express** handles the API layer -- **Puppeteer** (headless Chromium) does the actual rendering -- A **pool of browser instances** keeps things fast - -The core flow is: - -1. You POST HTML/Markdown + options to the API -2. The server loads it into a pooled Chromium page -3. Chromium renders it and exports to PDF -4. You get the PDF back - -That's it. No queue, no webhook callback, no async polling. Request in, PDF out. - -## Why Puppeteer Over wkhtmltopdf? - -I tried both. wkhtmltopdf is fast but uses an ancient WebKit engine — modern CSS (flexbox, grid, custom properties) breaks in weird ways. Puppeteer uses actual Chromium, so if it looks right in Chrome, it looks right in the PDF. - -The tradeoff is resource usage. Chromium is heavy. That's where the browser pool comes in — instead of launching a new browser per request, I maintain a pool of warm instances. A new page in an existing browser takes ~50ms vs ~2s for a cold start. - -## API Design Choices - -I wanted the API to feel obvious. If you've used any REST API, you already know how to use DocFast. - -### Basic HTML to PDF - -```bash -curl -X POST https://docfast.dev/v1/convert/html \ - -H "Authorization: Bearer YOUR_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{"html": "

Invoice #1042

Amount: $250.00

"}' \ - --output invoice.pdf -``` - -### Markdown to PDF - -```bash -curl -X POST https://docfast.dev/v1/convert/html \ - -H "Authorization: Bearer YOUR_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{"markdown": "# Monthly Report\n\n| Metric | Value |\n|--------|-------|\n| Users | 1,204 |"}' \ - --output report.pdf -``` - -### With Options - -```javascript -const response = await fetch('https://docfast.dev/v1/convert/html', { - method: 'POST', - headers: { - 'Authorization': 'Bearer YOUR_API_KEY', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - html: '

Styled Doc

', - css: 'h1 { color: navy; font-family: Georgia; }', - options: { - format: 'A4', - margin: { top: '20mm', bottom: '20mm' }, - header: '
Page
', - footer: '
Confidential
' - } - }) -}); - -const pdf = await response.blob(); -``` - -A few design decisions I'm happy with: - -- **HTML and Markdown in the same endpoint.** Send `html` or `markdown` — the API figures it out. No separate routes. -- **CSS as a separate field.** Keeps your HTML clean. You can also inline it, obviously. -- **Sensible defaults.** If you send just `{"html": "..."}`, you get an A4 PDF with reasonable margins. No required options. - -## Built-in Templates - -This is the part I'm most excited about. DocFast ships with templates for common document types: - -```javascript -const response = await fetch('https://docfast.dev/v1/convert/html', { - method: 'POST', - headers: { - 'Authorization': 'Bearer YOUR_API_KEY', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - template: 'invoice', - data: { - company: 'Acme Inc.', - items: [ - { description: 'Web Development', quantity: 40, rate: 150 }, - { description: 'Design Review', quantity: 5, rate: 150 } - ], - due_date: '2026-03-01' - } - }) -}); -``` - -You pass structured data, the template handles layout and styling. No HTML authoring needed for standard documents. Currently there are templates for invoices, receipts, and reports — more coming based on what people actually need. - -## Performance - -Some rough numbers from production: - -- Simple HTML (text, basic styling): **~200ms** -- Complex HTML (tables, images, custom fonts): **~800ms** -- Template with data injection: **~400ms** - -Most of the time is Chromium rendering. The API overhead is minimal. For comparison, spinning up Puppeteer yourself (cold start in a Lambda/Cloud Function) typically takes 3-8 seconds. - -## Pricing and Why There's a Free Tier - -Free tier: **100 PDFs/month**, no credit card required. Enough for side projects, prototyping, or low-volume internal tools. - -Pro: **$9/month for 10,000 PDFs**. That's $0.0009 per PDF. - -I wanted the free tier to be actually usable, not a glorified trial. If you're generating fewer than 100 PDFs a month, you never need to pay. If your project takes off and you need more, $9/mo is less than most developers spend on coffee in a week. - -## What I'd Do Differently - -If I rebuilt this from scratch: - -- **I'd start with templates earlier.** The raw HTML→PDF conversion was the obvious MVP, but templates are what people actually get excited about. -- **I'd add a preview endpoint sooner.** Being able to see the PDF in-browser before committing to generation saves a lot of back-and-forth. - -## Try It - -The docs are at [docfast.dev/docs](https://docfast.dev/docs). You can grab an API key in about 30 seconds. - -If you have feedback on the API design, templates you'd want, or bugs — I'm all ears. Building this solo, so every piece of feedback actually gets read. diff --git a/projects/business/marketing/reddit-posts.md b/projects/business/marketing/reddit-posts.md deleted file mode 100644 index 81c4f64..0000000 --- a/projects/business/marketing/reddit-posts.md +++ /dev/null @@ -1,66 +0,0 @@ -# Reddit Posts - ---- - -## r/webdev - -**Title:** Built an HTML-to-PDF API — looking for feedback on the API design - -**Body:** - -Hey r/webdev, - -I've been working on a small API service called [DocFast](https://docfast.dev) that converts HTML or Markdown to PDF. The idea came from rebuilding the same Puppeteer-based PDF pipeline across multiple projects. - -The basic idea: POST your HTML, get a PDF back. It also has built-in templates for common docs like invoices so you can just pass JSON data instead of writing HTML. - -Quick example: - -```javascript -const res = await fetch('https://docfast.dev/v1/convert/html', { - method: 'POST', - headers: { - 'Authorization': 'Bearer YOUR_KEY', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - html: '

Hello

This becomes a PDF.

', - options: { format: 'A4' } - }) -}); -``` - -There's a free tier (100 PDFs/month, no credit card) if anyone wants to try it. - -I'm specifically looking for feedback on: -- The API design — does the interface feel intuitive? -- What templates would be most useful? (Currently have invoice, receipt, report) -- Anything you'd expect from a PDF API that's missing? - -Docs are at https://docfast.dev/docs. Happy to answer any questions about the architecture too (Express + Puppeteer with a browser pool). - ---- - -## r/node - -**Title:** Managing a Puppeteer browser pool for PDF generation — lessons learned - -**Body:** - -I built an API service ([DocFast](https://docfast.dev)) that generates PDFs from HTML using Puppeteer, and wanted to share some things I learned about running Puppeteer in production with Node. - -**The problem:** Launching a new Chromium instance per request is slow (~2-3s). For an API that needs to respond quickly, that's not acceptable. - -**The solution:** A browser pool. I keep a set of warm Chromium instances and create new *pages* (not browsers) per request. New page creation takes ~50ms vs seconds for a cold browser launch. - -Key things I learned: - -1. **Memory management matters.** Each Chromium instance uses 100-300MB. You need to cap your pool size based on available memory and restart instances periodically to avoid leaks. - -2. **Page cleanup is critical.** After each PDF generation, you need to properly close the page and clean up listeners. Forgetting this leads to slow memory leaks that only show up after hours of traffic. - -3. **Graceful degradation.** If all pooled instances are busy, you have two choices: queue the request or spin up a temporary instance. I went with queuing + a small overflow pool. - -4. **Font rendering is OS-dependent.** The same HTML can look different depending on what fonts are installed on the host system. I ended up bundling a standard set of fonts in the Docker image. - -The API is live at https://docfast.dev if anyone wants to poke at it (free tier, 100 PDFs/mo). But mostly curious if others have dealt with similar Puppeteer pooling challenges and what approaches worked for you. diff --git a/projects/business/marketing/show-hn.md b/projects/business/marketing/show-hn.md deleted file mode 100644 index 71be9f7..0000000 --- a/projects/business/marketing/show-hn.md +++ /dev/null @@ -1,25 +0,0 @@ -# Show HN: DocFast – HTML/Markdown to PDF API with built-in templates - -I built a simple API for generating PDFs from HTML or Markdown. It's at https://docfast.dev - -**Why I built it:** Every time I needed to generate invoices, reports, or receipts in a side project, I'd end up wrestling with wkhtmltopdf configs or spinning up a headless browser. I wanted a single API call that just works. - -**What it does:** -- Send HTML or Markdown, get a PDF back -- Built-in templates for common docs (invoices, receipts, reports) -- Supports custom CSS, headers/footers, page sizes -- Fast — most PDFs generate in under 2 seconds - -**Quick example:** - -```bash -curl -X POST https://docfast.dev/v1/convert/html \ - -H "Authorization: Bearer YOUR_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{"html": "

Hello World

Generated with DocFast.

"}' \ - --output hello.pdf -``` - -**Pricing:** Free tier gives you 100 PDFs/month (no credit card). Pro is $9/mo for 10,000 PDFs. - -Built it solo. Would appreciate any feedback on the API design or docs (https://docfast.dev/docs). diff --git a/projects/business/marketing/strategy.md b/projects/business/marketing/strategy.md deleted file mode 100644 index 092309c..0000000 --- a/projects/business/marketing/strategy.md +++ /dev/null @@ -1,98 +0,0 @@ -# DocFast 30-Day Launch Marketing Plan - -**Budget: $0** — organic channels only. - ---- - -## Week 1: Launch (Days 1–7) - -### Day 1 — Launch Day -| Channel | Action | Expected Impact | -|---------|--------|-----------------| -| Hacker News | Post "Show HN" (see show-hn.md) | 50–200 visits if it gains traction; HN is hit-or-miss but high-quality traffic | -| Twitter/X | Tweet #1 (announcement) + #5 (pain point) | Reach depends on existing following; pin the announcement tweet | -| DEV.to | Publish article (see devto-article.md) | Steady long-tail traffic; DEV.to articles rank well on Google | - -### Day 2–3 -| Channel | Action | Expected Impact | -|---------|--------|-----------------| -| Reddit r/webdev | Post feedback request (see reddit-posts.md) | 20–100 visits; genuine feedback | -| Reddit r/node | Post technical discussion (see reddit-posts.md) | Smaller but more targeted audience | -| Indie Hackers | Post in "Show IH" — focus on the solo-builder story, pricing decisions | Community is supportive of solo launches | - -### Day 4–7 -| Channel | Action | Expected Impact | -|---------|--------|-----------------| -| Twitter/X | Tweet #2 (code example) | Code snippets get good engagement from devs | -| DEV.to | Engage with comments on your article | Builds credibility, surfaces article in feeds | -| HN | If Show HN didn't gain traction, resubmit once (allowed by HN rules) | Second attempts sometimes work better | - ---- - -## Week 2: Content (Days 8–14) - -Focus: Create useful content that naturally references DocFast. - -| Day | Channel | Content | -|-----|---------|---------| -| 8 | DEV.to | "5 Ways to Generate PDFs in Node.js (Compared)" — honest comparison including DocFast | -| 10 | Twitter/X | Tweet #3 (comparison) + short thread on PDF generation approaches | -| 12 | Reddit r/webdev | Comment helpfully on any PDF-related questions (don't force it — only if genuinely relevant) | -| 14 | Twitter/X | Tweet #4 (use case — invoices) | - ---- - -## Week 3: Community (Days 15–21) - -Focus: Engage where developers already discuss PDF problems. - -| Action | Where | Notes | -|--------|-------|-------| -| Answer PDF-related questions | Stack Overflow, Reddit | Don't shill. Answer the question, mention DocFast only if it's genuinely the best answer | -| Post on r/SaaS | Reddit | "I launched a developer API at $9/mo — here's what I learned in the first 2 weeks" | -| Share usage stats / lessons | Indie Hackers, Twitter | Transparency builds trust. Share real numbers | -| DEV.to article #2 | DEV.to | "How I Handle 10,000 PDFs/Month with Express + Puppeteer" — technical deep-dive | - ---- - -## Week 4: Iterate (Days 22–30) - -Focus: Double down on what worked, drop what didn't. - -| Action | Details | -|--------|---------| -| Review analytics | Which channel drove the most signups? Most API usage? | -| Write a "1 month in" post | Indie Hackers or DEV.to — share real metrics, lessons, what you'd change | -| Engage repeat visitors | If anyone tweeted about DocFast, reply and thank them | -| Plan month 2 | Based on data: more content? Different subreddits? Guest posts? | - ---- - -## Ongoing (Every Week) - -- **Monitor Reddit/HN/SO** for "pdf generation" discussions — contribute genuinely -- **Tweet 2–3x/week** — mix of product updates, developer tips, and PDF-related content -- **Respond to every piece of feedback** within 24 hours - ---- - -## Channel Summary - -| Channel | Effort | Expected Impact | Best For | -|---------|--------|-----------------|----------| -| Hacker News | Low (1 post) | High variance — could be 10 or 10,000 visits | Launch spike | -| DEV.to | Medium (2–3 articles) | Steady long-tail SEO traffic | Ongoing discovery | -| Twitter/X | Medium (2–3 tweets/week) | Builds over time; compounds | Developer brand | -| Reddit | Low-Medium | Targeted, high-intent traffic | Early feedback | -| Indie Hackers | Low (2 posts) | Small but supportive community | Solo founder story | -| Stack Overflow | Low (answer questions) | Very high intent (people searching for solutions) | Long-tail conversions | - ---- - -## Key Principles - -1. **Be useful first.** Every post should provide value even if DocFast didn't exist. -2. **Don't post and ghost.** Reply to every comment. People remember that. -3. **Share real numbers.** "We got 47 signups in 2 weeks" is more compelling than "growing fast." -4. **One channel at a time.** Don't try to be everywhere on day 1. Stagger posts across the week. -5. **Track everything.** UTM parameters on every link. Know what works. diff --git a/projects/business/marketing/tweets.md b/projects/business/marketing/tweets.md deleted file mode 100644 index fc61cae..0000000 --- a/projects/business/marketing/tweets.md +++ /dev/null @@ -1,57 +0,0 @@ -# DocFast Launch Tweets - -## 1. Announcement - -I built an HTML-to-PDF API because I was tired of configuring Puppeteer for every side project. - -→ Send HTML or Markdown, get a PDF back -→ Built-in templates (invoices, receipts, reports) -→ Free tier: 100 PDFs/mo - -https://docfast.dev - -## 2. Code Example - -Generate a PDF in one curl command: - -``` -curl -X POST https://docfast.dev/v1/convert/html \ - -H "Authorization: Bearer $KEY" \ - -d '{"html": "

Done.

"}' \ - -o doc.pdf -``` - -No config files. No Docker. No Puppeteer setup. - -Free tier: 100 PDFs/mo → https://docfast.dev - -## 3. Comparison to Alternatives - -PDF generation options for developers: - -• wkhtmltopdf — ancient WebKit, breaks on modern CSS -• Self-hosted Puppeteer — works, but you're managing Chromium in prod -• Enterprise APIs — $50+/mo for basic usage - -I built DocFast: modern rendering, simple API, free tier (100/mo), $9/mo for 10K. - -https://docfast.dev - -## 4. Use Case - -If your app generates invoices, you've probably spent more time on PDF layout than on the actual billing logic. - -DocFast has built-in invoice templates. Pass your data as JSON, get a styled PDF back. No HTML required. - -https://docfast.dev/docs - -## 5. Pain Point - -The PDF generation starter pack: -- Install Puppeteer -- Debug Chromium dependencies on Linux -- Figure out why fonts look wrong -- Add 800MB to your Docker image -- Question your career choices - -Or just call an API: https://docfast.dev diff --git a/projects/business/memory/bugs.md b/projects/business/memory/bugs.md index a024ca1..733a33a 100644 --- a/projects/business/memory/bugs.md +++ b/projects/business/memory/bugs.md @@ -2,64 +2,25 @@ ## Open -### BUG-007: Invoice template endpoint not working -- **Found by:** Human (investor) -- **Date:** 2026-02-14 -- **Severity:** HIGH -- **Description:** Invoice template rendering doesn't work. QA failed to test this endpoint. Must test POST /v1/templates/invoice/render with sample data and verify it returns a valid PDF. -- **Status:** Open - -### BUG-008: HTML to PDF has unwanted border -- **Found by:** Human (investor) -- **Date:** 2026-02-14 -- **Severity:** MEDIUM -- **Description:** When converting HTML to PDF, there's a visible border around the content. This should either be removed by default or be an option (e.g. `"border": false` in the request body). -- **Status:** Open - -### BUG-006: Copy button lacks visual feedback +### BUG-004: CSP blocks all inline JavaScript — CRITICAL ROOT CAUSE - **Found by:** Hoid (QA via Playwright) - **Date:** 2026-02-14 -- **Severity:** LOW — cosmetic/UX -- **Description:** After clicking "Click to copy" on the API key, the button text doesn't change to "Copied!" or provide any visual confirmation. The clipboard write itself works without errors (no CSP or JS errors), but the user has no feedback that the copy succeeded. -- **Fix:** Add visual feedback in the copy handler (e.g., change button text to "Copied!" for 2 seconds). +- **Severity:** CRITICAL — blocks ALL frontend functionality +- **Description:** Helmet middleware sets Content-Security-Policy that blocks inline scripts (`script-src 'self'`). The landing page uses inline `