Private media delivery — draft images stay gated until you publish
Uploads now return canonical /api/media paths instead of world-readable Supabase URLs. Aveiro signs at read time for live visitors, gated draft previews, and social platform fetch — unpublishing or deleting an asset revokes access.
Site and org media no longer rely on world-readable Supabase URLs. Content stores canonical /api/media paths; Aveiro signs them at read time so draft images stay private, unpublishing revokes visitor access, and social platforms fetch through revocable share grants.
What changed
Previously, every upload returned a Supabase public URL and that absolute link was persisted into MDX, settings, ads, and social drafts. Anyone holding the URL could fetch the bytes — including images on sites that were never published.Media now flows through /api/media/<key> with authorization carried in the URL:
Published pages sign media for visitors while the site is live; unpublish revokes standing access.
Draft previews sign only for org members who already have site access — otherwise references stay bare and resolve to 404.
Social publishing mints a per-asset share grant so Instagram, LinkedIn, and similar platforms can fetch server-side without a session; deleting the file revokes the grant.
Stored values stay unsigned so one reference works for visitors on a custom domain and for members in the editor. Legacy Supabase URLs in older content are still recognised — no migration required.
For agents and API callers
Upload responses (POST …/media/upload, social direct upload) now return a canonical publicUrl like /api/media/site-media/{siteId}/…. Persist that path in <Media src> or page metadata — not the signed displayUrl from list responses.Details: Site media API, Social media API. Dashboard behaviour: Media library.
Also in this release
Email campaigns rewrite media to absolute share-grant URLs at send time. Stored HTML keeps canonical /api/media paths; inbox fetches never rely on a browser session.
Campaign previews use session cookies on bare paths instead — the iframe is on our origin and cannot sign HTML composed on the client.
Site settings and collection listings now sign logo, favicon, default OG cover, and folder thumbnails on read.
Dashboard editor and settings sign page MDX, metadata, site settings, and site-list covers on read so images no longer break in the editor; saves canonicalize grants back to bare paths before storing.
Newsletter editor and social thumbnails use the same read-sign / write-canonicalize round-trip — member-facing surfaces that still stored bare /api/media paths.
API and form validators accept canonical /api/media paths alongside https:// URLs, so attaching a library image to a social post no longer fails with "Invalid url".
Member preview URLs quantize expiry windows so media-library thumbnails cache correctly in next/image.
Template gallery sites — visitor media access is gated by whether your site is still published, not by who uploaded the file. Cloning copies MDX and settings verbatim, including /api/media/… paths that may still point at the template source; those images load on your live site and stop when you unpublish.
Dashboard home and showcase gallery — Recent Sites cover thumbnails and public showcase cards sign on read with member or visitor grants; showcase covers stay root-relative on the platform origin.
Shop product images — attach from the media library (canonical /api/media paths, not only https:// URLs) and sign on every read: product editor hydration, live product pages, the Products block, and Product Showcase blocks grounded on the site being viewed (visitor grant on a published site; member grant in draft preview).
Frametic failed renders can be dismissed per browser; the assets grid reserves placeholder slots so finished renders do not jump the layout on load.