social components inlay.at
atproto components sdui
86
fork

Configure Feed

Select the types of activity you want to include in your feed.

README.md

proto#

A prototype Inlay host built with Hono and htmx. It resolves Inlay component trees into HTML and streams the result to the browser.

Live demo: https://inlay-proto.up.railway.app/

Running#

npm install   # from the repo root
npm run dev   # starts on http://localhost:3001

Expects a Redis instance for caching. Set REDIS_URL in .env or .env.local at the repo root (defaults to redis://localhost:6379). Records and DID resolution go through Slingshot.

How it works#

The main route is /at/:did/:collection/:rkey?componentUri=.... It fetches the component record, creates an element ($(componentType, { uri })), and calls @inlay/render in a loop until everything bottoms out in primitives. Each primitive maps to a custom HTML element (org-atsui-stack, org-atsui-text, etc.) styled by two CSS files.

The response is streamed with Hono's renderToReadableStream. Slow XRPC calls don't block the whole page — at.inlay.Loading components use <Suspense> to show a fallback while the rest of the page streams.

Primitives#

This host implements the Atsui primitives. Each primitive is a function in src/primitives.tsx that takes { ctx, props } and returns Hono JSX. A componentMap at the bottom registers them by NSID.

Caching#

Records and XRPC responses are cached in Redis. Cache keys are tagged using the same scheme as @inlay/cachetagRecord for AT URIs, tagLink for backlink patterns. The existing invalidator (a Jetstream firehose listener) can flush entries when records change.

TTLs follow the life values from component responses: seconds (30s), minutes (5m), hours (1h), max (24h).

Infinite scroll#

org.atsui.List renders the first page server-side, then uses htmx to load more pages as the user scrolls. The /htmx/list endpoint handles pagination — it takes a cursor, fetches the next page from the component's XRPC query, renders the items, and returns an HTML fragment with a new sentinel div for the next page.

An IntersectionObserver watches for <a> tags pointing to /at/... routes. When one scrolls into view, it injects a <link rel="prefetch"> so the browser fetches the page before the user clicks.