Skip to main content
Astro is static-first, so the honest way to describe this integration is not “PixGlory optimises your images at build time” (Astro’s own astro:assets already does that for local files). It’s “PixGlory is your asset host”: build-time or ahead-of-time processed images live in a CDN project, and your site references them by URL instead of shipping the bytes in your own deploy.

Before you start

You need a PixGlory API key and a CDN project. See the Quickstart to create a key, and create a project from your dashboard if you don’t have one yet. Set your key and project id as environment variables for the build:
.env
Find your project’s id with a request against GET /v1/projects:

Serve remote images from PixGlory

Tell Astro’s image service to trust cdn.pixglory.com as a remote source, in astro.config.mjs:
astro.config.mjs
Then use <Image> with an explicit width and height, same as any other remote source. Astro does not re-process a remote image’s pixels, so those two values only reserve layout space; the bytes PixGlory already produced are what ships:

Upload your public/ assets before you deploy

For a static site, the natural integration point is a build-time script rather than a runtime route: walk public/, upload anything that isn’t already in the project, and confirm. Run it in your build pipeline before the deploy step.
scripts/upload-to-pixglory.ts
Run it with node --experimental-strip-types scripts/upload-to-pixglory.ts (or compile it, if your build already has a TypeScript step) as part of your CI pipeline, before the deploy step that publishes your static output. Uploads are idempotent per path: a re-run against files already confirmed skips them rather than erroring.
A single presign request can name several files at once. The script above batches every file under public/images into one call instead of one round trip per file.

Handling errors

A 402 response means the organisation’s storage quota would be exceeded; a 429 means you’ve hit the rate limit and should back off using the Retry-After header. Every error body has the same shape:
Branch on error.code, not error.message, which can change wording without notice. The full list of status codes and error codes is in the API Reference tab.