# atproto-wc — agent reference Framework-agnostic custom elements for rendering ATProto content. 34 elements, ~12KB gzipped, zero runtime dependencies. Works in plain HTML, Astro, Next, Vite, Svelte, Lit, or any environment where custom elements work. This file is self-contained: install, import, the full element catalog with attributes, styling tokens and shadow-part names, programmatic API, framework integration, and the conventions every element shares. If you're an agent writing code against atproto-wc, you should not need to fetch anything else. ## What this library is and isn't - **Is**: a set of `` custom elements that read content directly from the authoring PDS and engagement from the Constellation backlink index. - **Is**: lexicon-agnostic — `` will paginate any collection; `` will list every collection+path linking to a target, including custom lexicons. - **Isn't**: a Bluesky AppView client. Moderation labels, algorithmic feeds, and the denormalized timeline shapes live in the AppView and are out of scope. For a bsky.app-identical embed, use the official widget. - **Isn't**: React components. These are native custom elements that render into Shadow DOM. They work with React (pass attributes as props, mark the importing file as client), but they aren't React components. ## Installation CDN (auto-registers every element): ```html ``` npm: ```sh bun add atproto-wc # or: npm i atproto-wc ``` Package exports: - `atproto-wc` — programmatic API + `registerX` functions + `defineAll()`. Side-effect free. - `atproto-wc/browser` — side-effecting import that registers every `` element. ## Registering elements Three patterns, pick one: ```ts // 1. Auto-register everything (side-effecting import — what the CDN tag does). import "atproto-wc/browser"; // 2. Side-effect-free import, explicit registration call (nicer for tree-shakers). import { defineAll } from "atproto-wc"; defineAll(); // 3. Only the elements you actually render — each has a `register*` function. import { registerPost, registerProfile } from "atproto-wc"; registerPost(); registerProfile(); ``` ## The `src` attribute — three shapes, auto-detected Every element that fetches content takes a `src`: - **AT-URI** — `at://did:plc:abc.../app.bsky.feed.post/3m...` - **bsky.app URL** — `https://bsky.app/profile//post/`, parsed into an AT-URI. - **Handle** — `iammatthias.com`. Resolved via `/.well-known/atproto-did` on the handle's domain. Used by ``, ``, ``, ``, ``, etc. Whichever shape you pass, the element will figure out what to do. For elements that need a repo identity (a profile, a feed, a blob grid), pass a handle or DID. For elements that need a specific record (a post, a thread, a like-count), pass an AT-URI or bsky.app URL. Some elements require a different shape — see the individual entries below. ## Shared behavior — true for every element - Renders a skeleton while loading — no layout shift. - Shows a retry button on transient failures (network, 5xx). Permanent failures (404, bad URI) don't offer retry. - Aborts in-flight fetches when the element disconnects from the DOM. - Deduplicates identical requests within a 10s window. - Attaches clickthrough permalinks to `bsky.app` where appropriate. - Themes via CSS custom properties and `::part()`. - Every Constellation-backed element accepts `constellation="..."` to override the endpoint per element. ## Element catalog Elements are grouped by tier. Required attributes are marked `*`. Unless otherwise noted, the `constellation` attribute is an optional string override. ### Content surfaces #### `` Canonical post embed: author, facets, images, external cards, quote embeds, video, engagement counts. - `src *` (string) — AT-URI or bsky.app post URL. - `compact` (boolean) — trimmed chrome variant for nesting in quote embeds / thread replies. - `no-counts` (boolean) — skip the engagement counts row (saves 4 Constellation calls). - `constellation` (string). #### `` Profile card — avatar, banner, bio, follower/following/post counts. - `src *` (string) — handle, DID, or AT-URI. - `constellation` (string). #### `` Author's posts + reposts, paginated, newest-first. - `src *` (string) — handle or DID. - `collection` (string, default `app.bsky.feed.post`) — which collection to list. - `limit` (number, default `10`). - `include-replies` (boolean) — include the user's own replies (skipped by default). - `no-reposts` (boolean) — skip the parallel `app.bsky.feed.repost` stream. #### `` Full reply tree for a post — ancestors, focal, descendants. - `src *` (string) — any post in the thread; can be mid-thread, ancestors walk up. - `depth` (number, default `2`) — nested reply branches to render. - `constellation` (string). #### `` Threaded replies for a post via Constellation. - `src *` (string) — post AT-URI. - `depth` (number, default `1`) — recursion depth. `depth=0` shows a 'Show replies' button. - `limit` (number, default `10`). - `show-count` (boolean) — render the 'N replies' header. - `constellation` (string). #### `` Browse a repo's every collection. Lazy-expand to records. - `src *` (string) — handle or DID. #### `` Any record, any lexicon, as a JSON tree. - `src *` (string) — AT-URI of any record. #### `` Paginated `listRecords` for an arbitrary collection on an arbitrary repo. Custom lexicons included. - `src *` (string) — handle or DID. - `collection *` (string) — lexicon NSID (e.g. `com.example.myschema`). - `limit` (number, default `10`). #### `` Render an `app.bsky.graph.list` record with its members. - `src *` (string) — AT-URI of the list record. - `limit` (number, default `32`) — members shown. - `constellation` (string). ### Backlink / engagement (Constellation-backed) #### `` Avatar grid of accounts that liked a post. - `src *` (string) — post AT-URI or bsky.app URL. - `limit` (number, default `16`). - `constellation` (string). #### `` Avatar grid of accounts that reposted. - `src *` (string) — post AT-URI or bsky.app URL. - `limit` (number, default `16`). - `constellation` (string). #### `` Posts that quoted the target, rendered as compact cards. - `src *` (string) — post AT-URI or bsky.app URL. - `limit` (number, default `10`). - `constellation` (string). #### `` Avatar grid of followers. - `src *` (string) — subject handle or DID. - `limit` (number, default `16`). - `constellation` (string). #### `` Intersection of two actor sets — who links both `a` and `b` via the same relation. - `a *` (string) — first subject (handle, DID, or AT-URI). - `b *` (string) — second subject, same shape as `a`. - `source` (string, default `follow`) — relation key from `SOURCES`. - `limit` (number, default `16`). - `constellation` (string). #### `` Posts that mention a subject DID. - `src *` (string) — handle or DID. - `limit` (number, default `16`). - `constellation` (string). #### `` Records that cite a target via any `subject` field — e.g. posts that link to a given URL. - `src *` (string) — a URL, AT-URI, or DID. - `limit` (number, default `10`). - `constellation` (string). #### `` Accounts that have blocked a target DID. Public data; use thoughtfully. - `src *` (string) — handle or DID. - `limit` (number, default `16`). - `constellation` (string). #### `` Lists (curated `app.bsky.graph.list` records) that contain a given subject. - `src *` (string) — handle or DID. - `limit` (number, default `10`). - `constellation` (string). #### `` Every collection+path linking to a target, with counts. Lexicon-agnostic — works on any record from any schema. - `src *` (string) — target AT-URI or DID. - `constellation` (string). #### `` Live like count for a post. - `src *` (string) — post AT-URI or bsky.app URL. - `constellation` (string). #### `` Total record count for an arbitrary subject + source pair. The count primitive Constellation returns. - `subject *` (string) — AT-URI, DID, or any backlink target. - `source *` (string) — `collection:path` format (path takes no leading dot). - `label` (string) — suffix label after the count. - `constellation` (string). #### `` Unique-DID count — the "how many people" twin of `generic-count`. - `subject *` (string). - `source *` (string) — same format as `generic-count`. - `label` (string). - `constellation` (string). ### Repo state #### `` Paginated grid of a repo's blob CIDs. Images render inline; non-image MIME types show a badge. - `src *` (string) — handle or DID. - `limit` (number, default `20`). #### `` Repo head — rev + decoded 'last activity' age. - `src *` (string) — handle or DID. - `show-cid` (boolean) — show the commit CID (truncated) alongside the rev. - `hide-age` (boolean) — suppress the decoded timestamp suffix. #### `` Activation state, handle, PDS health (active / deactivated / takendown). - `src *` (string) — handle or DID. #### `` `app.bsky.graph.verification` status for an account — decentralized verification claims against a DID. - `src *` (string) — handle or DID. - `limit` (number, default `16`). - `constellation` (string). #### `` Inline badge for posts with reply/quote limits. - `src *` (string) — post AT-URI or bsky.app URL. - `kind` (string, default `any`) — `any` | `thread` | `post`. - `show-when-absent` (boolean) — render a muted 'open' label when there's no gate. - `constellation` (string). #### `` Inline badge when a post is its author's pinned. - `src *` (string) — post AT-URI or bsky.app URL. - `show-when-not-pinned` (boolean) — render a muted 'not pinned' label instead of nothing. - `constellation` (string). ### Atoms (primitives) Composed by the larger elements. Useful on their own when you want a bare display name without the profile card, or a relative timestamp without the post embed. #### `` - `src *` (string) — handle, DID, or AT-URI. - `size` (string, default `40px`) — `24px` | `40px` | `80px`. - `linked` (boolean) — wrap in anchor pointing at `bsky.app/profile/`. #### `` - `src *` (string) — handle, DID, or AT-URI. - `linked` (boolean). #### `` - `src *` (string) — handle, DID, or AT-URI. - `linked` (boolean). - `bare` (boolean) — skip the leading `@`. #### `` Post text with facet rendering (links, mentions, tags). No network — pure rendering. - `text *` (string) — plain post text. - `facets` (string) — JSON-encoded array of ATProto facets. #### `` `