Skip to content

Feature: Mastodon-API shim — make JSS work as a backend for Phanpy (and every other Mastodon client) #515

@melvincarvalho

Description

@melvincarvalho

Goal

Make a Solid pod served by JSS speak enough of the Mastodon REST API that a standard Mastodon client — Phanpy as the reference target — can sign in to it, read its timeline, post statuses, and interact.

Phanpy is MIT-licensed, browser-based, single-column, lean — an ideal first target. Every other Mastodon client (Elk, Tusky, Ivory, Ice Cubes, Mona, Pinafore, Toot!, Mastodon's own UI…) speaks the same API, so a shim for Phanpy unlocks the whole ecosystem for free.

Why this matters

Scope

The smallest useful target: a single-pod, single-user Phanpy-can-log-in-and-use-its-own-pod prototype. No federation yet.

Phase 1 — Personal client over your own pod (~2 weeks)

Mastodon REST endpoints needed:

  • OAuth/oauth/authorize, /oauth/token, /api/v1/apps (translate to/from JSS's existing OIDC)
  • Identity/api/v1/accounts/verify_credentials
  • StatusesGET /api/v1/statuses/<id>, POST /api/v1/statuses (back the resource as a JSON-LD schema:Note on the pod)
  • TimelinesGET /api/v1/timelines/home, /public (build from the user's outbox container)
  • Streaming/api/v1/streaming (SSE/WS — JSS already has WebSocket notifications, wrap them in Mastodon's shape)
  • NotificationsGET /api/v1/notifications
  • MediaPOST /api/v1/media (JSS already accepts PUT-to-pod for files; wrap in Mastodon response shape)

Phase 2 — Status interactions (~3–4 weeks)

/api/v1/statuses/<id>/{favourite,reblog,reply,bookmark}, polls, edits, deletes. Multi-user on a shared JSS = a small instance.

Phase 3 — Federation (months — the cliff)

/.well-known/webfinger (#164), HTTP signatures, follower fan-out, outbound Create activities, inbound Follow handling, retry queues. This is where the real difficulty is — federation is genuinely hard.

Architectural choice

Two reasonable shapes:

  1. In JSS — a Mastodon-API module turned on with --mastodon-api (or always on). Tight integration, single binary.
  2. External sidecar — a separate Node process that speaks Mastodon API to clients and JSS LDP to the pod. Loose coupling, evolves independently, can be replaced or removed.

Lean: sidecar for Phase 1 (so the shim can iterate quickly without dragging JSS through churn), fold into JSS only once the shape is stable.

Data mapping (rough)

Mastodon JSS / Solid
Account WebID profile (/profile/card#me)
Status schema:Note JSON-LD at /public/outbox/<id>.jsonld
Outbox LDP container /public/outbox/
Inbox LDP container /inbox/ (already a Solid convention)
Followers Resource /private/followers.jsonld
Streaming event JSS /.notifications WebSocket, reshaped to Mastodon SSE/WS frames

License

Phanpy is MIT. If we want to embed it (ship as a Solid app inside a bundle), MIT is permissive — no copyleft obligation. If we just want to link to it (links.jsonld-style), license doesn't matter.

Success criteria

A user runs jspod, opens Phanpy, types their pod URL as the "server", clicks Sign In, completes OAuth, sees an empty home timeline, posts a status, sees it appear in real time via the streaming endpoint, refreshes, status persists. No federation needed in Phase 1 — single pod, single user.

Notes

  • Done well, this unlocks every Mastodon client at once — that's the leverage. The client surface is the same across Phanpy, Elk, Tusky, Ivory, Ice Cubes, etc.
  • The "tiny Mastodon server in your pod" demo is a much sharper story than "yet another decentralized platform."

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions