Skip to main content
Glama
README.md
# RenderPing

**Website screenshots and PDFs from any URL — one REST call.**

RenderPing renders any public URL with real headless Chromium and returns a signed URL to a PNG,
JPEG, WebP or PDF. Full-page or custom viewport, element capture, hide-selector cleanup, cookies
and headers for authenticated pages, sync or async rendering with webhooks. Ships with an MCP
server so AI agents can render pages as tools.

- **Live API:** https://renderping.theking.qzz.io
- **Docs:** https://renderping.theking.qzz.io/docs/
- **OpenAPI 3.1 spec:** https://renderping.theking.qzz.io/openapi.json
- **Dashboard:** https://renderping.theking.qzz.io/app/

## Quickstart

```bash
# Sign up (returns your JWT + full API key, shown once)
curl -X POST https://renderping.theking.qzz.io/api/auth/signup \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"a-long-password"}'

# First capture
curl -X POST https://renderping.theking.qzz.io/api/v1/captures \
  -H "X-API-Key: rp_live_..." -H "Content-Type: application/json" \
  -d '{"url":"https://example.com","format":"png","full_page":true}'
```

The response contains `result_url` — an HMAC-signed, expiring link to the rendered file.
Free plan: 50 successful renders/month.

## Monorepo layout

| Path | What it is |
|---|---|
| `apps/server` | Fastify API: auth, API keys, captures queue, quota metering, signed file delivery, Paddle + Gumroad billing rails |
| `apps/worker` | Playwright/Chromium render worker with PG-backed job queue (`FOR UPDATE SKIP LOCKED`, concurrency-limited) and SSRF protection |
| `apps/mcp` | MCP server (stdio) exposing `render_screenshot`, `render_pdf`, `check_changes`, `get_usage` to AI agents |
| `apps/dashboard` | Vanilla-JS SPA: keys, playground, usage meter, license redemption |
| `apps/marketing` | Landing page + deterministic pSEO generator (~250 pages + sitemap + robots) |
| `apps/docs` | Developer documentation site |
| `packages/shared` | Plans, types, SSRF guard (`assertPublicUrl`) |
| `packages/design` | Shared design system (tokens + components, no framework) |

## Notable engineering details

- **SSRF-safe rendering**: every target URL is DNS-resolved and checked against private/reserved
  ranges (loopback, RFC1918, link-local/cloud metadata, ULA, IPv4-mapped v6) before navigation;
  blocked literal hosts are also aborted per-request for redirects/subresources
  (`packages/shared/src/net.ts`).
- **Byte-faithful webhook verification**: Paddle signatures are verified over the raw request bytes
  via a scoped content-type parser — not a re-serialization of parsed JSON
  (`scripts/verify-paddle-webhook.js` proves it end-to-end).
- **Deterministic pSEO**: two generator runs produce byte-identical output; the verifier enforces
  canonical/h1/meta/internal-link invariants per page plus sitemap completeness.
- **Verification harnesses for everything**: `scripts/verify-{dashboard,marketing,docs,mcp,paddle-webhook,gumroad-redeem}.js`
  run against the live server on `localhost:8080`.

## Self-hosting

```bash
npm install
cp .env.example .env          # fill DATABASE_URL, JWT_SECRET, FILE_SIGN_SECRET
node scripts/migrate.js       # applies migrations/*.sql
npm run build
npm start                     # or systemd units under infra/
```

Requirements: Node 20+, PostgreSQL 12+, Chromium (installed via `npx playwright install chromium`).

## Billing

Paid plans are monthly memberships sold on Gumroad with instant license-key redemption
(`POST /api/billing/gumroad/redeem`). A Paddle Merchant-of-Rail checkout path is implemented behind
feature flags (`PADDLE_MODE=sandbox|live`) and verified by its own harness.

## License

© 2026 RenderPing. All rights reserved. Public repository published for transparency; reuse of the
code requires permission.