Search by

co-infra / image

co-infra

Build img.infra.coop URLs and srcsets. Zero dependencies, framework agnostic.

v0.1.0 2026-08-11 07:17 UTC

This package is not auto-updated.

Last update: 2026-09-23 06:24:08 UTC


README

Build img.infra.coop URLs and srcsets for AT Protocol blobs.


What is this?

img.infra.coop is a free, public image CDN for the AT Protocol. It takes a blob, resizes and reformats it, and serves the result from a durable edge cache, so apps do not have to hand full-resolution originals to browsers.

This package builds the URLs. It does nothing else: no HTTP, no image processing, no configuration to hold. Give it a DID and a blob CID, get a string back.

It is the PHP twin of the @co-infra/image npm package, and produces byte-identical URLs for the same operations.

Why use it?

  • Zero dependencies — PHP 8.3+, nothing else. Drops into any framework, or none.
  • Clamped by construction — computed widths and qualities are pulled into valid ranges instead of producing a URL the CDN will reject.
  • Cache-key safe — params are emitted in a fixed order, so the same transform is always the same URL, and therefore always the same cache entry.
  • Presets and srcsets — named transforms and responsive candidate lists, without hand-writing param strings.

Install

composer require co-infra/image

Quick example

use CoInfra\Image\Image;

$did = 'did:plc:bcgltzqazw5tb6k2g3ttenbj';
$cid = 'bafkreieaezg7ybnl2ax54owmaqi357gvwdo3rn3ui7b3wtu6i4yp6t3lbe';

Image::url($did, $cid, ['width' => 800, 'quality' => 80]);
// https://img.infra.coop/blob/did:plc:.../bafkrei.../w=800,q=80

Image::srcset($did, $cid, [400, 800, 1200]);
// .../w=400 400w, .../w=800 800w, .../w=1200 1200w

Image::placeholder($did, $cid);
// .../w=20,q=30,f=webp,blur=10

Operations

Pass an array, or an Operations object for type safety.

Key Type Range Param
width int 1–4096 w
height int 1–4096 h
size int 1–4096 size
dpr float 1–2 dpr
quality int 1–100 q
format Format|string auto, webp, avif, jpeg, png, gif f
fit Fit|string cover, contain, pad, scale-down fit
gravity string auto, an edge, or a point like 0.5x0.3 g
blur int 1–250 blur
sharpen float 0–10 sharpen
rotate int 90, 180, 270 rotate
background string hex, with or without # bg
preset Preset|string see below p

Out-of-range numbers are clamped. A rotation that is not a right angle, or a background that is not hex, throws InvalidOperationException — there is no sensible nearest value for either.

use CoInfra\Image\{Fit, Format, Operations};

Image::url($did, $cid, new Operations(
    width: 1200,
    height: 630,
    fit: Fit::Cover,
    format: Format::Auto,
));

Presets

Named transforms the CDN resolves server-side.

Preset Shape
Preset::AvatarSmall 128px square, smart-cropped
Preset::Avatar 256px square, smart-cropped
Preset::AvatarLarge 512px square, smart-cropped
Preset::Banner 1500×500, 3:1
Preset::Feed 1000px, scaled down
Preset::Thumb 500px square, smart-cropped
Preset::Card 1200×630 JPEG, 1.91:1
Preset::Blur 20px wide, heavily blurred

A preset is a starting point. Anything you set alongside it wins:

Image::url($did, $cid, ['preset' => Preset::Avatar, 'quality' => 60]);
// .../p=avatar,q=60

The CDN serves its live definitions from /presets and is the source of truth. The enum mirrors it for autocompletion; if the two disagree, the CDN wins.

Private deployments

The public instance is open to everyone, so most apps do not need their own. If you run one, construct a builder with its base URL:

use CoInfra\Image\UrlBuilder;

$images = new UrlBuilder('https://img.example.com');

$images->url($did, $cid, ['width' => 800]);

UrlBuilder is a plain injectable object, so a container can bind it once with the configured base and hand it around.

A note on privacy

Every URL this builds is public. The CDN has no viewer authentication, and com.atproto.sync.getBlob is itself public, so a blob in a repo is readable by anyone who knows the DID and CID. Do not use this for anything that is meant to stay private.

Testing

composer test
composer format

Credits

If you use the public instance, add a small acknowledgement linking to infra.coop somewhere on your site.

License

MIT. See LICENSE.