Skip to main content

Portrait

Portrait is Intrasys's self-hosted, Gravatar-style avatar service. One avatar per person, consistent across every Intrasys app (Panes, Presto, Prism, …), keyed by a hash of the person's email.

Everyone gets a deterministic generated avatar by default — no account, nothing stored. Anyone can sign in to Portrait's own console to design their avatar in a full option editor, upload a real photo, or ✨ Ask AI to suggest a designed avatar from a photo. Once saved, that image is what Portrait serves everywhere.

A consuming app does nothing but render an <img>. No SDK, no per-app secret, no schema change.

The problem it solves

Every Intrasys app renders a user avatar — sidebar, member lists, profile. Today each shows initials on a coloured chip. There is no shared, real avatar, and WorkOS can't provide one: its profile_picture_url is read-only and only populated by a social IdP, so magic-auth users (the house login pattern) have none.

Portrait fixes this with three ideas:

  • Email hash as the shared key — an app already knows its user's email, so it computes the key itself and builds the URL. It never calls a Portrait API or holds a Portrait secret. This is what makes adoption free.
  • Always return something — an unknown hash gets a deterministic generated avatar, already better than an initials chip, so an app can adopt Portrait before a single user has an account.
  • The read path never touches the database — a read is one object-store lookup; hit serves, miss generates from the hash. The DB can be down and not a single avatar breaks anywhere in the estate.

Who it's for

Every end-user of every Intrasys app, and every app that renders an avatar. Users manage one face in one place; apps adopt it in one line.

Core concepts

  • Identity keysha256(lower(trim(email))), byte-identical to Gravatar's spec. Public, not a secret, safe in client-side HTML.
  • Three states for any hash — generated (nothing saved), designed (saved option config, incl. ✨ Ask AI output), or uploaded (a real photo).
  • Accounts & claims — an account anchors on a WorkOS user; emails are claims attached to it. One person can claim work + personal addresses and every verified one resolves to the same avatar.

Status

Shipped and live. All four apps run — the public read path (media.*), the session API (api.*), the console (console.*), and the marketing site (portrait.intrasys.ai):

  • Public read path — deterministic generated avatars, sizes, PNG/SVG, caching, metadata.
  • Console — login, avatar designer, photo upload, ✨ Ask AI (photo → suggested design), email claims.
  • Session API — save, reset, from-photo, email-claim management.

An app can adopt Portrait in one line today.

Next steps

  • Getting started — set your avatar, adopt it in an app.
  • Concepts — the identity key, three states, accounts & claims, the read path.
  • App integration — the one-line <img>, fallbacks, caching.
  • API reference — the media.* read API and api.* write API.