Skip to content

Configure social preview cards

A preview card is the title, description, and image a social platform may show for a shared page. Crawlers read the Open Graph and Twitter Card tags the page declares; there is no automatic screenshot.

On the admin Settings page, use the Social image field. It PATCHes socialImageUrl; an empty value clears it. Supply either an absolute http or https URL, or a root-relative path that starts with one /.

A root-relative path is made absolute against the application’s configured custom domain, or against the request origin when no custom domain is set. On anonymous, cookie-free server-rendered loads only, og:image and twitter:image are emitted when an image is set; twitter:card then becomes summary_large_image.

Upload a PNG, JPEG, or WebP file with multipart field file. SVG is rejected. The 201 response’s id is the file id.

POST /api/v1/files/upload

There is no admin UI for bindings. Bind files with PATCH /api/v1/applications/{id}, which requires applications:update.

staticAssetBindings is a complete replacement map: an omitted path is unbound, and {} unbinds everything. Use read-merge-write: GET /api/v1/applications/{id}, copy settings.static_asset_bindings, add or replace only the paths you intend to change, then PATCH /api/v1/applications/{id} with the full merged map.

GET /api/v1/applications/{id}
PATCH /api/v1/applications/{id}
{"staticAssetBindings":{"/social-image.png":"<file-id>","/favicon.ico":"<file-id>","/robots.txt":"<file-id>"}}

Keys need a single leading /, with no query, fragment, or percent-encoding. Reserved prefixes /api, /_app, /app, /admin, /login, /register, /forgot-password, /verify-email, and /reset-password are rejected. Every referenced file must exist, belong to the application’s tenant or workspace, and be servable, or the entire PATCH fails with invalid_static_asset_binding.

Set the social image to the root-relative path, such as /social-image.png. The file is served from the site’s own hostname by GET /api/v1/applications/public/by-host/assets/{path}, proxied by the SvelteKit hook for root files and extension paths, with a verified content type, Content-Disposition: inline, and X-Content-Type-Options: nosniff.

The same bind operation serves /favicon.ico when uploaded as image/x-icon and /robots.txt when uploaded as text/plain.

The API-key route PATCH /api/v1/public/applications/{id} accepts the same fields with applications:update at the authoring tier, as does MCP update_application; its upload route POST /api/v1/public/applications/{id}/files/upload needs files:upload and the files_assets capability enabled, otherwise it returns 403 files_capability_disabled (enable it with {"capabilities":{"files_assets":"enabled"}}).

Use a 1200x630 image and keep it legible as a thumbnail, following Open Graph and X Cards platform guidance. The image must be publicly fetchable without authentication from a bound, verified domain of a live, published application, because by-host serving resolves the request host to a routable domain record.

Request the published page without cookies using a crawler User-Agent, then inspect the image response:

curl -s -A 'facebookexternalhit/1.1' https://example.com/ | grep -E 'og:image|twitter:card'
curl -I https://example.com/social-image.png

Expect 200 and the image content type from the second command. Social platforms cache link previews aggressively as platform behavior, so verify before the first share.

  • A 404 Asset not found means the path is not in the current map, perhaps because a later PATCH replaced it; it can also mean the bound file was deleted, quarantined, or retention-expired, the host has no routable domain record, or the application is not live.
  • invalid_static_asset_binding means a key breaks the rules above or a file id is not servable.
  • No og:image in a logged-in browser view is expected because these tags are emitted only on anonymous loads.