Putting a photo on a page when all you have is a URL
A page that loads an image from somebody else’s server is a page with somebody else’s tracking pixel on it.
Why not just accept a URL
Because an image field that takes an address is a hole. Point it at a third-party host and every visitor’s browser announces itself to that host — on a service whose privacy page promises no third-party requests at all. The same field would also flow unescaped into a CSS background, which is its own class of problem.
So image fields accept exactly one shape: a storage key minted by our own upload route. To get one, send the address to the upload endpoint as JSON with a kind of avatar, background or card. The server fetches the file, checks it, re-encodes it and returns a key, which you then save into the page like any other field.
- Upload by URL, receive a key, patch the page with that key. Three steps, or one if you pass the photo URL at creation.
- Only public addresses are fetched: anything resolving to a private or local address is refused, before and after redirects.
- Size caps apply to the source: eight megabytes for avatars and card images, thirty for backgrounds.
- The response also carries the stored size and dimensions, which is useful when you want to report what you did.
What happens to the bytes
- Everything is re-encoded. The file we serve is never the file you sent.
- EXIF is dropped, which matters because phone photographs carry GPS coordinates.
- Dimensions and weight are capped per kind, so a page with six images still opens on mobile data.
- iPhone HEIC files are decoded server-side; you do not need to convert them first.
Anchors, and the mistake to avoid
Templates crop: round for the photo, full-bleed for a background, a strip for a card. Each image field has a companion anchor in percent, and setting it is the difference between a face and a chest. At creation you can pass the anchor with the photo; afterwards it is one more field in an update, and the MCP tool that sets a photo takes it as an argument.
The mistake worth naming: reusing an Instagram CDN address as if it were permanent. Those URLs are signed and expire within days. Copy the bytes across at once — which is exactly what upload-by-URL does — or the avatar breaks quietly a week after you hand the page over.