Some ideas for a checkin record, need input!

Hi Folks,

I’m working on the Anchor app and i’m playing around with some different ideas on what a checkin record should look like. So far i’ve ended up with a core checkin record and an optional post record that i’m still not sure should embed the checkin record (since no other clients will be able to render the embed anytime soon).

My current checkin record looks like this:

{
  "$type": "app.dropanchor.checkin",
  "text": "Great coffee and climbing session!",
  "createdAt": "2025-06-27T10:30:00Z",
  "locations": [
    {
      "$type": "community.lexicon.location.geo",
      "latitude": "40.7128",
      "longitude": "-74.0060"
    },
    {
      "$type": "community.lexicon.location.address", 
      "name": "Brooklyn Boulders",
      "street": "123 Main St",
      "locality": "New York",
      "region": "NY",
      "country": "US",
      "postalCode": "10001"
    }
  ],
  "category": "climbing",
  "categoryGroup": "Sports & Fitness",
  "categoryIcon": "🧗‍♂️"
}

I’ve opted to make a custom record since that will give me much more flexibility in extending the feature set of what my app will do (but do let me know if it’s mad and i should just use a feed post and embed everything in that).

Although that already looks pretty extensive it’s still missing quite a few things:

  • I would like to add the option to add pictures
  • i would like the option to add likes
  • i would like the option to add comments

Since these are all things that already exist for the Post record it could make sense to just re-use that logic so:

  • a picture would be embedded in the checkin record like it would be in a feed post
  • a reply or like would simply use the existing lexicon types but refer to a checkin instead of a post record

Does this makes sense? If i have likes and reply posts on the network that do not reference a feed post but another new type, that most pds servers don’t know about, is that ok or will it mess things up (not sure if there is etiquette involved or if clients and pds servers are just expected to be flexible).

Anyway i would be very happy to receive input from the experts here as i’m only just figuring all of this out.

And then another but related question: when an Anchor user posts their checkin they can optionally also make a feed post that will be created in their home pds. This way something will be visible to people not using Anchor yet which is nice for the user and is of course also a bit of marketing for Anchor. Currently this feed post is a standalone simple post but an earlier design embedded the checkin record in the post. Of course again only Anchor clients would know what to do with that embed so it would just look like an error in other clients. Would be nice to somehow link back to the checkin from the post though… any thoughts on this would also be appreciated.

p.s. we should add some more tags like an atgeo tag for instance…

@seabass.bsky.social considering you are also working on a checkin app i’m very interested to hear your thoughts on this. Even if we end up making completely different product it would be awesome if our apps could read each others checkins… at least i think that would be awesome :smile:

1 Like

In my dream solution there would be a community.lexicon.location.checkin type or something like that btw but i have no idea where to start something like that, except posting about it here..

Yes, 100%. We should be lexicon compatible. I think the first thing to figure out is how to both not duplicate location / venue data and to not break reference if the “location PDS” goes offline. I queried others from the ATGeo group here about it: Discord

This would then be the (optional) record that we would reference our checkin to. WDYT?

Update: I just found your documentation in the Anchor docs - let me read through that and I’ll get back here shortly :slight_smile:

1 Like

Good to hear you are thinking along the same lines. I’m not planning to make a central location store or anything like that, ideally that would be resolved as a community effort at some point. But i do think it’s nice to have the location details as part of the checkin as well since then the client does not have to rely on the location service being up as you say but it also will not have to do another request to get the location details. For a few posts that won’t matter much but when your rendering a whole feed it would be very annoying very fast.

I also don’t mind the duplication much conceptually. You could argue that it makes sense to store the location with the checkin regardless of a central places/location service since places and names change and a checkin to some place that ended up going bankrupt is still nice to have intact as one record even when the places api does not know about this place anymore or deleted it as a closed location.

I’m not in the Discord.. should i be?

I guess aggregating and clustering the locations (e.g. by fsqID) can be done in the AppView as well and I agree that it’s best to have the data available at render time.

However, it still feels wrong to have this record

{
      "$type": "community.lexicon.location.address", 
      "name": "Brooklyn Boulders",
      "street": "123 Main St",
      "locality": "New York",
      "region": "NY",
      "country": "US",
      "postalCode": "10001"
    }

duplicated thousands and thousands of times throughout ATProto.

I’d like to attach locations to regular posts as well in Skeets (like - this post was created “here”). This could also be a regular checkin object. Should we settle on a type like “community.lexicon.location.checkin”?

About Discord: yeah, I think it makes sense, although maybe we’re all moving over here now :slight_smile: Anyway, here’s the invite link: ATProto Touchers

Still though, while i agree it feels wrong, and even if you can fix the performance issues by simply moving that logic to the appview, i still feel duplicating is perhaps the better solution from a world modeling perspective. A checkin represent visiting a certain location at a certain moment in time. Unless you also want to do complicated versioning in a central places db i think it makes sense that the record reflects where you checked in that specific moment in the summer of '28 when you conquered that v3 in Brooklyn Boulders. When in 2030 the gym moved to 567 Central sq, or the new owner remade it into Big Bro’s Lifting i would prefer my checkin from 2028 to still show Brooklyn Boulders… unless of course fsqID’s or whatever a central places db might offer are already made to account for this (e.g. they retain historical locations, and change when the location has significant changes).

I don’t think we should think of records as database entries, as you also mention on Discord. But i’m new here so i might very well be wrong here.

I really think the included location / ATGeo content should be in the form of strong refs to location records. Those records can be sourced from any PDS, not just the xprc service it was produced by.

Apps should be responsible for fetching and hydrating the location as needed.

The fact that it could go away is intentional and by design. Someone could delete the record for privacy or safety reasons.

Hmm ok i had not taking into account privacy/security considerations but that makes sense. So to get this straight:

  • the checkin record contains only a reference to some (yet to be available on at proto) location record
  • the ‘app’ will fetch the record and cache the location so it can be shown in a feed at all times

And the app in this case could then be a custom AppView for the checkin client that creates feeds for users and handles caching/hydration. So the cache of the location could remain for that checkin even if the location is deleted.

Did i get that right?

1 Like

There might not be published location records atm, but the implementation is there to support publishing the record and using a strongref in the anchor record

@western-red-cedar you mean just publishing a standalone record of type community.lexicon.location.address and then in the checkin record include a strongref instead of the record right? that might be make for a good start then, would these standalone records be useful to anyone else without more context though?

Also ideally i’d have both the human readable address and the computer readable geo type in my checkin but publishing standalone community.lexicon.location.geo type records really does not seem like it would have any practical benefit?

Publishing the location records can be useful so that someone can reuse a location and people can check into locations by looking up a name that might already have been “checked into”. Without context I think they are still useful as there would now be a growing list of “places” that exist in the AT ecosystem

A standalone geo record does not make as much sense as a standalone address record and IMO is better embedded.

1 Like

Thanks! I’ll try out that setup in a next revision, and see how that works. Good excuse to make a simple AppView that can handle the merging into something my client can use.

1 Like

I think my brain works better with examples. Let’s say I want to create a checkin in my app. As the app provider I’d like to be able to aggregate and cumulate checkins to find popular places. So I create a UI that - based on the user’s lat/lng - will query the gazetteer to give me places that are close to the user’s location. Let’s say the gazetteer finds and returns the following place for me:

Would this place be:

  1. saved and published in the user’s repo and then referenced by his new checkin?
  2. saved and published in the gazetteer’s repo so that it can then be referenced by the user’s checkin record?

Imho the drawback of 1. is that it will create that record over and over again in every user’s repo that checks into this location. The drawback of 2. seems to be that it will invalidate the references to the location if the gazetteer’s repo goes belly up.

I wonder if there could be a 3rd solution - the place’s data is the same for every “places service” that uses the same base data set. So if I have been using a fsq data provider and the services shuts down I could replace it with another data service. The service I want to use could be saved in the PLC. That way the reference to the location could be something like at://did:web:placed-data-provider/com.foursquare.places/fsqid_123456789 and then I could redirect did:web:placed-data-provider dynamically by replacing the provider in the PLC. Is that possible?

I think in @western-red-cedar’s proposal i would redo my checkin record created by the mobile client into something like this:

{
  "$type": "app.dropanchor.checkin",
  "text": "Meeting Sarah for drinks after work! 🍻",
  "createdAt": "2025-06-29T19:30:00Z",
  "addressRef": {
    "uri": "at://did:plc:venue-database/community.lexicon.location.address/cafe-de-plek-voorburg",
    "cid": "bafyreih5adskjfh2lkh3j4k5l6m7n8o9p0q1r2s3t4u5v6w7x8y9z0a1b2c3"
  },
  "coordinates": {
    "$type": "community.lexicon.location.geo",
    "latitude": "52.0705",
    "longitude": "4.3007"
  }
}

When displaying the check-in, a client would:

  1. Read the check-in record
  2. Extract the strongref
  3. Fetch the address record
  4. Verify content integrity
  5. Display combined data

And when the client is an AppView it would not just do that but also cache the resulting address record. So your mobile client would see the constructed record including the full address served from cache. And it would also still be able to serve the feed when the venue database is gone.

I think this would work and is pretty pragmatic. You could switch to a new venue db when creating records and the AppView would simply continue to cache those as well.

Each mobile app would need it’s own AppView and the cache would essentially duplicate the records. Alternatively you would need to have mirrors of the venue database and then store the mirror strongrefs in the records as well or something like that? Or some sort of unique id (fsqID) and then have a resolver that can query multiple sources. But honestly i’m not sure i like the unique id solution since i kinda of like that you could take any source of place data and just create a new address record without needing to match it to centralized place id…

2 Likes

I was unaware of the Gazeteer working group but that is great to see. I’m sure this is already being discussed on their end, but if they stand up a service with an addLocation endpoint then you could do a fire and forget on location creation, while also storing a copy elsewhere

The drawback of 2. seems to be that it will invalidate the references to the location if the gazetteer’s repo goes belly up

This is a good point and I think we should design for centralized data storage being taken offline.

For point #1, alternatively the location can be published onto the app server’s PDS. I’m not sure if that’s best practice though, since the user doesn’t own that bit of address data.

yeah 100%. I’m also split on this. On the one hand it would be so much more efficient doing the AppView caching approach but at the same time it creates a lot of overhead and stuff you need to setup to get going.

The AppView would be a pretty straightforward cache/proxy if it did not have to hook into the firehose to filter out the records i would be interested in. Ideally i could just pay a few bucks to run a query on some service that is already looking at the firehose to only send my AppView the records i need. That way my ‘infrastucture’ would be super lightweight.

Hmm i think jetstream actually covers that use-case already. I think i’m just gonna try this out and see how far i get with this…

1 Like