Render infrastructure / self-hosted Operational

One render engine. Every file your product ships.

supaserv turns HTML into pixels and into print: PNG, JPEG, WebP and press-ready PDF. One HTTP contract, on infrastructure you control, with no render vendor between you and the output.

Request path HTTPS
  • InHTML plus every asset it needs (JSON, inline base64)
  • AuthBearer token (per-client rate limits)
  • EngineWeasyPrint (PDF) · Chromium (image)
  • Out application/pdfimage/pngimage/jpegimage/webp
The file is the response body. Nothing is stored, nothing is fetched at render time.
InterfaceHTTP · Bearer token
RuntimeChromium, WeasyPrint, FFmpeg
ModelSelf-hosted · no lock-in
01 / The problem

Rendering splits into three separate jobs.

Teams reach for a screenshot service, then discover that print and motion each need a different engine. Stitching three vendors together is how the bill and the blast radius grow.

Runtime Chromium does not run on the edge.

Serverless and edge functions ship without a browser. The moment a product needs a real screenshot, the platform is the wrong shape for it.

Print A PDF is not a screenshot.

Press output needs CMYK, ICC profiles, bleed and trim marks. A browser print dialog silently drops all four.

Motion Video has to be deterministic.

Capture runs as a seek loop. The page is stepped one frame at a time, so the same input produces the same file on every run of the same worker image.

02 / The engine

Two tiers. One contract.

A thin edge gateway handles identity and limits. The work itself happens in a dedicated container. Your application only ever sees one endpoint and one token.

  • 01 Request Your application posts HTML and its assets over HTTPS.
  • 02 Gateway Authentication, routing, per-client rate limits.
  • 03 Worker Chromium, WeasyPrint, FFmpeg and Python on dedicated CPU. Kept warm.
  • 04 Response The finished binary, streamed back to the caller.

Large or long jobs (a body over ~4 MB, such as a print PDF with an embedded ICC profile, or a render that may run past 25 seconds) address the worker directly at https://api.supaserv.io, with the same paths and the same key model, because the edge tier caps the body and closes any connection at 25 seconds.

03 / Capabilities

What the engine returns.

01
Image HTML → PNG / JPEG / WebP

Chromium, one viewport per request, device pixel ratio up to 4, transparent background for PNG and WebP. Every font and image travels inline with the request: POST /v1/image.

02
Document HTML → PDF

WeasyPrint, two profiles: screen for an RGB PDF, print for press: PDF/X-4, DeviceCMYK, an ICC output intent, bleed and crop marks. POST /v1/pdf.

03
Motion HTML → MP4

A deterministic frame loop drives your animation, then FFmpeg encodes it on the worker. /v1/video renders with the scene clock, in one request or as a job; the virtual clock is not built yet.

04
Cutout Image → transparent PNG

u2net segmentation with edge refinement, for product shots that have to sit on any background. The module is in the worker and has no /v1 route yet.

04 / API surface

Two render endpoints. No SDK required.

Every render is a POST with a bearer token. The response is the file.

POST/v1/pdfContract render: screen or print profile
POST/v1/imageContract render: PNG, JPEG or WebP
GET/healthService status, ok or degraded · no auth

Full request and response reference, including every option object, is in the documentation.

05 / Integration

One request, one file.

No client library to install. Synchronous renders answer in one request; only video jobs are polled.

# Render a 1080 x 1350 social asset
curl -X POST https://www.supaserv.io/v1/image \
  -H "Authorization: Bearer $SUPASERV_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "html": "<h1>Q4 results</h1>", "width": 1080, "height": 1350 }' \
  --output asset.png

# HTTP/2 200
# content-type: image/png

Swap the path for /v1/pdf, drop width and height (page geometry comes from @page), and the same markup comes back as a PDF laid out by WeasyPrint.

06 / Operations

The limits, stated up front.

Every number below is the one the code enforces. Rate limits are counted in memory per gateway instance, per client and bucket, in a fixed one-minute window, so they cap each instance rather than guarantee one global count.

Gateway timeout: 25 s Requests through the gateway are cut at 25 seconds. A render that may run longer goes to the worker directly (https://api.supaserv.io, same paths, same key model); on the worker, /v1/image is bounded at 30 seconds.
Rate limits: per client, per bucket /v1/pdf 30 requests per minute, /v1/image 60. Fixed one-minute windows, per edge isolate. Worker-direct calls have no per-client limit.
Payload: ~4 MB through the gateway The gateway caps a /v1 body at 4 MB, just under what the gateway accepts at all. Larger requests go to the worker directly, up to 32 MB.
Capacity: dedicated CPU A warm machine with a recycled browser pool, so there is no cold start and no accumulating memory from long-running Chromium sessions.
Access: one key per client One key per client, configured on the gateway. Each request logs the name of the key it came in with, never the key itself, and a key is withdrawn by removing it from the gateway and redeploying.
07 / Next step

Put it in front of a real job.

Send it the asset you actually need this week, then look at the file that comes back.