content surface · pds + constellation
<atproto-profile>
Profile card with banner, avatar, bio, follower / following / post counts.
Live
<atproto-profile src="pfrazee.com"></atproto-profile>
<atproto-profile src="did:plc:..."></atproto-profile>
<atproto-profile src="at://did:plc:..."></atproto-profile> Attributes
| Name | Type | Default | Description |
|---|---|---|---|
src * | string | — | Handle, DID, or AT-URI. |
constellation | string | — | Override the Constellation endpoint. |
Parts
External CSS can target these via atproto-profile::part(<name>) { ... }.
| Part | What it is |
|---|---|
article | Outer card. |
banner / banner-image | Banner strip and inner img. |
head | Avatar + names cluster. |
avatar / avatar-image | Avatar circle and inner img. |
names / display-name / handle | Name + handle stack. |
description | Profile bio paragraph. |
stats / stat | Followers / following / posts row. |
What it does
Renders a full profile card — banner, avatar, display name, handle, bio,
and three count stats. Content comes from the subject's own PDS (their
app.bsky.actor.profile/self record); the follower count comes
from Constellation; following and post counts are derived by paginating
listRecords on the subject's own repo, capped at 500.
Why following/post counts show "500+"
There's no cheap count endpoint for a repo's own records. The component
paginates listRecords up to 500 items and caps display there —
real numbers above that show as 500+. That's a deliberate
tradeoff: an accurate count on a 10,000-follow account would cost 100
sequential PDS calls, and the exact number rarely matters to readers. If
you need more, override the cap in source (countOwnRecords
in atproto-profile.ts) — it's a one-line change.
When to use this vs alternatives
<atproto-profile>— full card. Default choice.- Compose atomics (
<atproto-avatar>+<atproto-display-name>+<atproto-handle>) — when you want a smaller inline presence (author line in a comment, sidebar byline) without the banner/bio/stats chrome. <atproto-lexicon-viewer src="at://did/app.bsky.actor.profile/self">— when you want to see the raw profile record (debugging).
Styling
All color / typography / radius tokens apply. Parts let you target specific pieces — a common tweak is squaring the avatar or hiding stats:
atproto-profile::part(avatar) { border-radius: 4px; }
atproto-profile::part(stats) { display: none; }
atproto-profile::part(banner) { height: 200px; }