DEV Community

GrabShot
GrabShot

Posted on

How I Built 10 Developer APIs in One Week on a Single VPS

Last week I challenged myself: ship one API product per day, all on the same $10/month VPS. Here's exactly how I did it and what I learned.

The Stack

  • Runtime: Node.js + Express
  • Browser automation: Puppeteer (for screenshots, PDFs, font detection, visual diffs)
  • Image processing: Sharp
  • Database: SQLite (via better-sqlite3)
  • Reverse proxy: Caddy with wildcard SSL (*.grabshot.dev)
  • Process manager: PM2
  • Payments: Stripe

Total infrastructure cost: about $10/month for the VPS + domain.

The Products

Day 1: GrabShot (Screenshot API)

The flagship. Send a URL, get a screenshot.

curl "https://grabshot.dev/v1/screenshot?url=https://news.ycombinator.com&apiKey=YOUR_KEY" -o screenshot.png
Enter fullscreen mode Exit fullscreen mode

Features: full-page capture, custom viewports, dark mode, element selection, retina, format selection (PNG/JPEG/WebP).

The tricky part was handling all the edge cases: cookie banners, lazy-loaded content, sites that require scrolling to render, SPAs that need JS execution time. I ended up with a configurable waitUntil parameter and smart scrolling for lazy content.

Day 2: PDFMagic (HTML to PDF)

Send HTML or a URL, get a professionally formatted PDF.

const res = await fetch('https://pdf.grabshot.dev/v1/pdf', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer YOUR_KEY' },
  body: JSON.stringify({
    html: '<h1>Invoice #1234</h1><p>Amount: $99.00</p>',
    format: 'A4',
    margin: { top: '20mm', bottom: '20mm' }
  })
});
const pdf = await res.arrayBuffer();
Enter fullscreen mode Exit fullscreen mode

Key learning: Puppeteer's page.pdf() returns a Uint8Array, not a Buffer. Wrap it with Buffer.from() or your file writes will silently produce garbage.

Day 3: MetaPeek (Meta Tag Extractor)

Extract Open Graph tags, Twitter Cards, favicons, and all meta tags from any URL. Returns clean JSON.

Useful for: link preview generators, SEO tools, content aggregators.

Day 4: ColorPeek (Color Palette Extractor)

Takes a screenshot, analyzes dominant colors using k-means clustering. Returns hex codes with usage percentages.

Day 5: CronPing (Cron Monitor)

Your cron jobs ping a unique URL. If a ping doesn't arrive on schedule, you get alerted. Dead simple alternative to expensive monitoring services.

Day 6: MailForge (Email Tester)

Renders HTML emails and shows how they look. Email HTML is a nightmare -- this helps you debug it.

Day 7: FontSpy (Font Detector)

Detects which fonts a website actually loads at runtime. Goes beyond CSS inspection -- it hooks into the browser's font loading APIs to see what actually renders.

Days 8-10: LinkCheck, DiffShot, PageAudit

Broken link checker, visual regression diff tool, and a combined SEO/performance/security auditor. Each one is useful on its own, but they also work well together.

Architecture: One VPS, Ten Apps

The key insight: Caddy with wildcard DNS makes this trivial.

*.grabshot.dev {
    @screenshotapi host grabshot.dev
    handle @screenshotapi {
        reverse_proxy localhost:3000
    }

    @pdfmagic host pdf.grabshot.dev
    handle @pdfmagic {
        reverse_proxy localhost:3001
    }

    # ... repeat for each app
}
Enter fullscreen mode Exit fullscreen mode

Each app is a separate Express server running on a different port. PM2 manages all of them. Caddy handles SSL (automatic via Let's Encrypt) and routing.

What I Learned

1. SQLite is perfect for this scale. Zero configuration, zero maintenance, single-file backups. Each app gets its own .db file. At thousands of requests per day, SQLite won't break a sweat.

2. Free tiers should be actually useful. Not 5 requests/month. That's useless. GrabShot's free tier is 25/month -- enough to build a prototype, test an integration, or use in a small side project. The goal is getting people to build something with your API so they need more.

3. Puppeteer is a Swiss Army knife. Screenshots, PDFs, font detection, color extraction, link checking, accessibility auditing -- one browser engine handles all of it. The initial memory cost (~80MB per Chromium instance) is worth it.

4. Ship fast, polish later. Each app started as <500 lines of code. Core endpoint, basic auth, rate limiting, done. Polish comes after you know someone actually wants it.

5. Distribution is harder than building. I can build 10 apps in a week. Getting 10 users takes longer. If I were starting over, I'd spend day 1-3 building one great product and day 4-7 on marketing.

Try It

Everything has a free tier, no credit card required:

npm package: npm install grabshot-sdk

GitHub Action for CI/CD: webgrade-action

What would you build with these? Feedback welcome.

Top comments (0)