Spent the week redrawing a 1:25000 coastline by hand. The shoreline has moved 40 metres inland since the 1984 survey.
Every map is a snapshot of a place that has already changed. #cartography #openstreetmap
Timeline block that renders an ActivityPub OrderedCollection with a composer.
npx shadcn@latest add https://ui.uptoolkit.com/r/social-feed.jsonThe timeline. Hand it an OrderedCollection page from an inbox or outbox and it renders each
activity's object, keeping boost attribution intact.
import { SocialFeed } from "@/components/social-feed";
const collection = await fetchInbox(viewer);
<SocialFeed
viewer={viewer}
collection={collection}
showComments
onPublish={(activity) => postToOutbox(viewer, activity)}
onLoadMore={(next) => fetchPage(next)}
/>Create and Announce activities both render; anything without a resolvable object is skipped
rather than rendered as an empty card.
Posts composed in the feed are prepended immediately and kept until you refetch, so the timeline does
not appear to swallow a new post while the request is in flight. onPublish receives the same
Create activity the composer built.
When the collection has a next URL, a "Load older posts" button appears and passes that URL to
onLoadMore. Merge the page into your collection state and pass it back down.
onActivity receives every activity any post emits — Like, EmojiReact, Announce, and the
Undo for each — so a single handler can deliver them all:
<SocialFeed viewer={viewer} onActivity={(activity) => postToOutbox(viewer, activity)} />The block emits one Schema.org CollectionPage wrapping an ItemList of postings, so the timeline
is described once rather than per card.
Without a collection the block renders
social-sample-data so it works the moment it is installed. Pass
hideComposer for a public timeline and a fixed now when rendering on the server.