# proto A prototype Inlay host built with [Hono](https://hono.dev/) and [htmx](https://htmx.org/). It resolves Inlay component trees into HTML and streams the result to the browser. **Live demo:** https://inlay-proto.up.railway.app/ ## Running ```bash 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](https://slingshot.microcosm.blue). ## 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`](../packages/@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 `` to show a fallback while the rest of the page streams. ## Primitives This host implements the [Atsui](https://pdsls.dev/at://did:plc:e4fjueijznwqm2yxvt7q4mba/com.atproto.lexicon.schema) 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/cache` — `tagRecord` for AT URIs, `tagLink` for backlink patterns. The existing [invalidator](../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. ## Link prefetching An `IntersectionObserver` watches for `` tags pointing to `/at/...` routes. When one scrolls into view, it injects a `` so the browser fetches the page before the user clicks.