Cosmik Labs

Lab Notes #005: Semble <-> Margin Interop

Details on how we interoperate with Margin data

February 04, 2026

a bee flying from the Margin logo to the Semble logo

Today is a big day for Semble because we took a big step towards a more interoperable social web — one of the main reasons most of us build on atproto in the first place! put it best:

Tynan Purdy's avatar
Tynan Purdy
1mo

The killer app of atproto is interop

We've just shipped our side of a collaboration with . Less than two weeks ago we agreed on a complimentary and straightforward form of interop without sharing lexicons. Here are the details of how that works, what it looks like, what's missing, and where things can go moving forward.

How it works

There are nine types of records in Margin, and three of them map perfectly to existing concepts in Semble: bookmarks, collections and collection items (to indicate that something is in a collection). In Semble, these are: cards, collections and collection links.

We've designed our internal representations of these concepts to not depend on specific ATProto details. This approach is part of our layered architecture, something which we will outline in a future post.

What this means is that Cards and Collections are represented as separate entities from their corresponding ATProto records, which are referenced via their StrongRef (aturi + CID). It looks a bit like this:

a diagram showing a card with a strongRef property pointing to an atproto record

In fact, our AppView (are we still calling them this??)

All votes are public

...doesn't care what exactly the atproto record looks like, so long as there is a way to map it from the record to the card (basically, does it represent a URL in some way?). This is intentional so that things can evolve and change at the protocol / infrastructure layer without causing upstream breaking changes to our inner layers (especially the domain layer, again, more on this in a future post). It also means that a card can point to records of differing lexicons, like at.margin.bookmark. Making it look a bit more like this:

a diagram showing a card with a strongRef property pointing to an atproto record with cosmik.network.card NSID and another with at.margin.bookmark NSID

As long as we can map at.margin.bookmark to a Card, at.margin.collection to a Collection and at.margin.collectionItem to a Card within a Collection, we can ingest them from the firehose just like we do with network.cosmik.card, network.cosmik.collection and network.cosmik.collectionLink record events, the only difference being the mapping step.

a diagram showing how at.margin.bookmark and network.cosmik.card firehose events get mapped to cards in Semble

The same idea works for Collections, and adding Cards to Collections. After the mapping step, everything else works the same way as it normally would (e.g. the library count will reflect the total number of accounts from both Margin and Semble).

Lastly, Semble also backfills Margin data, so any of your Margin bookmarks or collection made prior to today will also show up in Semble (we perform a lazy sync, so it only gets triggered once you either save a card in Semble or create a bookmark in Margin).

What it looks like

Margin bookmarks will appear the same as Semble cards, with a margin logo present (linking to a view of it on margin). The explore feed can also be filtered by source, making it easy to discover content being shared in either or both apps.

a screenshot of the semble explore feed filtered by content coming from Margin

Collection pages also include the Margin logo, which links to Margin.

a screenshot of a collection page in Semble showing the Margin logo by the title, with hover text "View on Margin"

You can add Cards from Semble or Margin to Collections from Semble or Margin. Likewise, you will see your Semble Cards and Collections in Margin. Cross-pollinate as you see fit!

A screenshot of the add card to collection modal in Semble, showing a list of collections, one of them has the Margin logo beside it indicating it's from Margin

What's missing?

Margin has two other record types relevant to Semble: highlights and annotations. Since these concepts don't yet exist in Semble, we currently ignore them. Eventually this will change, but for now, you won't see your Margin highlights or annotations in Semble.

What's next?

In the near term, we want to include highlights and annotations within Semble by including them on the Semble Page and as a separate activity type:

a mock up of a Semble feed activity showing that a user annotated a link, including the highlighted snippet plus a comment

In the mid term, we want to support Semble highlights and annotations directly as a card type, not just an activity type, which means they could be added to collections directly.

In the long term, we would love to align on shared lexicons for annotations, bookmarks, collections and any other pattern that is commonly shared across apps (not just Semble and Margin). We are inspired by and see a similar initiative as a pathway towards longer term interoperability.

The best part about this all is that it shows how the Atmosphere has no walled gardens.

Happy cross-pollinating y'all 🐝

Subscribe to Cosmik Labs
to get updates in Reader, RSS, or via Bluesky Feed
Lab Notes #006: Open Collections and Community Stewardship
Lab Notes #004: Semble Updates - Notifications, Provenance and Indie Integrations