Declaring speakers (and linking sessions) on calendar events

Hey all, thanks for the calendar lexicon :folded_hands: it’s already doing a lot of work for me at Sifa.

Quick context: building Sifa ID, professional identity on atproto and also currently exploring more the event/conference side of someones experience (and from that potentially building a speaker directory, talks directory, personal/org events calendars etc).

The speaker side is now mostly modelled already (a talk, and each delivery of it, currently referencing a community.lexicon.calendar.event).

But what’s I tun into missing on the event side is an event itself declaring/confirming who spoke (or even other types of users like hosts or volunteers etc).

My use-case is a cross-app speaker/talk directory: “who can speak about X, and where have they actually spoken.” and “I’m looking for topics for my conference, what are some well rated/reviewed ones”

For that to work, events need to be able to confirm “these people spoke here”, ideally in the shared lexicon so it isn’t re-invented per app.

So a few things I think are needed for this, and I’d love a sanity check :sweat_smile:

  1. Participant roles beyond RSVP. Attendance today is going/interested/etc. I would also want “person X was (or will be) a speaker / panelist / host / organizer / volunteer at this event” as a first-class role, distinct from a plain attendee. In scope for the community lexicon, or deliberately left to app-specific sidecars?
  2. Sessions vs the top-level event. A conference has many sessions, and a talk is one speaker in one of them. I saw @flo-bit.dev’s parentEvent idea in the kickoff thread. Is a session = a child event with parentEvent the intended model, or is something else planned?
  3. To get to a confirmed speaker in the appview, one of 2 things need to happen:
    • a user adds themself to an event as speaker, event organizer needs to confirm
    • an event adds a user as speaker to an event, the user needs to confirm
  4. Where the data gets entered. I don’t really want to build yet another event-organizer interface, atmo.rsvp and others already do that well. The hope is organizers capture speakers in the tools they already use, and apps like Sifa consume it. Which only works if it lands in the shared lexicon, not a Sifa-only record….

Biggest assumption is #4: imho “events declare their speakers” belongs in community.lexicon.calendar rather than each consumer bolting on its own sidecar (as @ngerakines.me suggested in another thread) ? A sidecar on the Sifa side would allow me to move faster, but then only Sifa would populate it (and again: I don’t necessarily want to build another event interface).

IMHO this will also be super usefull for ATmosphereConf 2027, so would be neat to get this working :smiley:

So… WDYT? Lexicon-worthy or just sidecars (and own event interface) all the way?

3 Likes

I think we can use AtmosphereConf 2027 to prototype this for sure!

I don’t think a lot of what you’ve described lives within calendar events.

We ended up with a custom conference profile for 2026, and I think the attendee status / role also lives within the “conference object”, which is bigger than just one event.

Some of this is badges – attendee, speaker, organizer – aka a verified and accepted two way link. If you squint, this could also be groups, and that probably meshes better with what the conference organizer wants – make certain info only available to attendees, or speakers, or other organizers.

Being an event organizer, I’m happy to build software that helps us organize, market, etc – encouraging speakers to accept and promote their participation on their Sifa.

I think schedules are a super-set of an individual event. Should a conference object exist? Is it just an event with sub-events? aka parentEvent or … is it a group?!

I think we can have a discussion about this starting with what we want to build for AtmosphereConf. I don’t actually see an easy path to rolling this out at scale unless we put it in the hands of speakers (conference organizers will be slower to adopt).

So, on Sifa, an interface where you can search events, select one, pick a role, and point at that event might be most impactful, quickest.

We haven’t had an AtmosphereConf website kick off yet, I’ll be sure to announce that, too!

2 Likes

Just remembered that Lea, a Bluesky client, wants to do things for academic conferences, probably worth looking at

2 Likes

Great write-up @gui.do and thanks for the name check and reminder to elaborate more on why I keep landing on sidecars for this.

The first reason is boring and is all about making sure that you can work quickly and iteratively at your own development pace within your own project. You may be working out what a speaker directory needs to look like and other data model and shape questions, and that shouldn’t be held up if it doesn’t have to be. If the shape turns out to be something other apps want to write to, great, it can move into a community lexicon schema later. If it turns out that it’s mostly applicable to Sifa, then nothing is lost.

The second reason is more structural, and it is the one I would want you to weigh even if you decide sidecars are wrong for everything else. RSVP (community.lexicon.calendar.rsvp) and feed (app.bsky.feed.post) records point at events with strongRefs, which carry both the AT-URI and the CID of the event record. Every time the event record is rewritten, that CID changes, and every existing reference is now pointing at a version that is no longer current. Speaker lineups, session schedules, and social attachments are all fields that churn. Speakers drop, sessions move rooms, a marketing push adds three links in a week, etc. If all of that lives on the event record, every one of those edits ripples out into the RSVPs and the threads hanging off it. Keeping the volatile parts in separate records that reference the event is what lets the event stay stable, and stability is the thing everything else is depending on.

On the “only Sifa would populate it” worry, I get it, but I’m less worried about that because it’s not really a record shape problem. Whether the speaker list lives inside the event or beside it does not change who is willing to type it in. @bmann.ca’s point about putting this in the hands of speakers is where the sidecar model actually helps you, because your point 3 is a two way link. A speaker claiming “I spoke here” is a record in their repo. An organizer confirming it is a record in theirs. Both point at the event. Neither requires the organizer to edit the event record or the speaker to have write access to it, and the appview derives the confirmed state by finding both halves. That is an attestation pattern, and it works across app boundaries as long as the record types are documented, whether or not they sit under community.lexicon on day one.

If there is community lexicon work to do here, I would put it on the reference direction rather than on the event: a well specified record type for “this person had this role at this event” that anybody can write into their own repo. That gets you the cross app directory without the event record turning into a mutable pile of everything a conference wants to say about itself.

3 Likes

It seems to me a speaker would want their talks associated with them (on their PDS) and not the event, as they’ll often do the same talk at multiple events. Then the event would link to the speaker and their talk in some way.

2 Likes

Thanks all! :folded_hands:

@ngerakines.me your standalone “this person had this role at this event” record, sound good. But IDK, the more I wrangle it, the more it seemed like it shouldn’t be a Sifa-namespaced thing: it’s the same primitive as Cartridge’s verification, RSVP-to-attendance, and Lea’s conference speakers all want? So that’s what made me rather co-author it as a community.* lexicon than mint an id.sifa one and fragment the signal

Rough sketch: subject (the person’s DID) + a strongRef to the community.lexicon.calendar.event + a role, written by whoever’s attesting. So indeed still the sidecar your proposed (just strongRefs the event, never touching its core).

@fabricatedtechnobabble.com yeah exactly: the split I use (already live at Sifa): the talk (the reusable content) lives on the speaker’s PDS + a per-occasion “delivery” record pointing at the event. So one talk can give you many deliveries (e.g. same talk at five events = 6 records: one talk + five deliveries). And the “event links back to the speaker and their talk” piece is precisely that role-record above, just authored from the org/event side.

Two things on top:

  • Two halves = confirmed. A single self-written record is a claim. Both the speaker’s own delivery and the org’s role-record existing (pointing at the same event) is the proof. Kills the lie incentive both ways (a speaker “borrowing” a big event’s prestige, or a small event “borrowing” a celebrity’s name).
  • Confirmation-as-seal for tamper-evidence: CID-pin the record it vouched for when there’s one to pin, fall back to a name snapshot for old/unlinked events.

Open Q for me though is what locks a talk after it’s confirmed? Because the editing timeline is split:

  • Before the event you WANT the title/abstract to change and propagate (we all know edits will probably keep happening until the day before the event… :sweat_smile:).
  • After the event, it should stay at what was actually delivered, not change to fake another topic.

But… there’s no write at event-end to seal it. And confirmations could land after the event anyway (backfilling), and of course plenty of talks won’t necessarily link to an atproto calendar event to begin with, so there’s no endsAt, just a self-reported date. Best solution I’ve got so far is that the confirmation IS the seal, and the appview flags any edits it sees after that. :person_shrugging:

@bmann.ca thanks for the @trezy.codes + Lea pointers :folded_hands:. Cartridge’s claim/supersede flow could indeed be the cold-start answer for old/backfilled talks (which I assume is why it was setup that way). @trezy.codes a couple you’ve probably already solved: (1) after a claim, how do you retire the original community record so it’s not a stale duplicate, given you can’t tombstone in someone else’s repo? (2) why did you go manual admin review of organizations on purpose vs auto-verifying on domain-handle control? I was leaning on domain-verified self-claim (where the org’s handle in itself IS the proof, no central approver).

And big +1 on AtmosphereConf 2027 as the guinea pig, and on speaker-first. My gut is sessions want parentEvent and roles/access want the group or conference object.

(fwiw I shipped a first read-only POC version already, sifa.id/speakers + /talks, just to prove that side works with existing Sifa data, the above would be the next layer(s) on top).