Uptoolkit
GitHub

Social Feed

Timeline block that renders an ActivityPub OrderedCollection with a composer.

500
  1. Bergen, Norway

    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

    Hand-drawn coastline contour map with annotated survey markers
    Comparison overlay of the 1984 and current shoreline
    #cartography#openstreetmap
    • Is the 1984 survey digitised anywhere? I would love to run the two through a diff.

    • The hand-drawn linework is beautiful. Are you inking these on vellum?

  2. Rahel Kebede boosted

    What we learned running a mapping co-op for five years

    Five years in, the hardest part was never the software. It was agreeing on what counts as done.

    Full write-up on our site, including the governance docs we wish we had started with.

    #cooperatives
  3. New set of glacier recordings up. Thanks @mira@fediverse.example for the coordinates. #fieldrecording

    Twelve minute glacier field recording
    #fieldrecording
  4. Long typography rant, mild swearing

Installation

npx shadcn@latest add https://ui.uptoolkit.com/r/social-feed.json

Usage

The 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.

Publishing

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.

Pagination

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.

Interactions

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)} />

Structured data

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.