Lexicon Interoperability in ATProto
Yes, absolutely! This is one of the most powerful features of ATProto - lexicons are open standards that any app can implement. This enables true interoperability between different applications.
How Lexicon Sharing Works
1. Anyone Can Use Any Lexicon
// Your app can write records using BlueSky's lexicons
await agent.com.atproto.repo.createRecord({
repo: userDid,
collection: 'app.bsky.feed.post', // BlueSky's lexicon
record: {
text: 'Hello from my custom app!',
createdAt: new Date().toISOString()
}
})
// Or someone else's custom lexicon
await agent.com.atproto.repo.createRecord({
repo: userDid,
collection: 'com.otherapp.recipe', // Another app's lexicon
record: {
title: 'Chocolate Cake',
ingredients: ['flour', 'sugar', 'cocoa'],
instructions: 'Mix and bake...'
}
})
2. Cross-App Compatibility Example
// App A defines a "book review" lexicon
const bookReviewLexicon = {
"lexicon": 1,
"id": "com.bookapp.review",
"defs": {
"main": {
"type": "record",
"record": {
"type": "object",
"properties": {
"book": {"type": "string"},
"rating": {"type": "integer"},
"review": {"type": "string"}
}
}
}
}
}
// App B can read and write the same lexicon
class BookCompatibleApp {
async publishReview(book: string, rating: number, review: string) {
// Uses App A's lexicon
await this.agent.com.atproto.repo.createRecord({
repo: this.userDid,
collection: 'com.bookapp.review',
record: { book, rating, review }
})
}
async showReviews() {
// Reads reviews from ALL apps using this lexicon
const reviews = await this.agent.com.atproto.repo.listRecords({
repo: this.userDid,
collection: 'com.bookapp.review'
})
return reviews
}
}
Real-World Interoperability Scenarios
3. Social Media Compatibility
// Your specialized app can still participate in the broader social graph
class NicheApp {
async publishPost(content: string) {
// Publish using standard BlueSky lexicon
await this.agent.com.atproto.repo.createRecord({
repo: this.userDid,
collection: 'app.bsky.feed.post',
record: {
text: content,
createdAt: new Date().toISOString()
}
})
// Also publish using your specialized lexicon
await this.agent.com.atproto.repo.createRecord({
repo: this.userDid,
collection: 'com.nicheapp.specialpost',
record: {
content: content,
category: 'technical',
tags: ['programming', 'atproto']
}
})
}
}
4. Building on Existing Ecosystems
// Photography app that's compatible with general social media
class PhotoApp {
async sharePhoto(imageBlob: Blob, caption: string) {
// Upload image first
const imageRef = await this.uploadImage(imageBlob)
// Create standard social media post
await this.agent.com.atproto.repo.createRecord({
repo: this.userDid,
collection: 'app.bsky.feed.post',
record: {
text: caption,
embed: {
$type: 'app.bsky.embed.images',
images: [{ image: imageRef, alt: caption }]
},
createdAt: new Date().toISOString()
}
})
// Also create detailed photo metadata
await this.agent.com.atproto.repo.createRecord({
repo: this.userDid,
collection: 'com.photoapp.photo',
record: {
image: imageRef,
caption,
camera: 'Canon EOS R5',
settings: { iso: 100, aperture: 'f/2.8' },
location: { lat: 40.7128, lng: -74.0060 }
}
})
}
}
Cross-App Discovery
5. Multi-Lexicon App Views
class UniversalFeedApp {
async buildUniversalFeed(userDid: string) {
const follows = await this.getFollows(userDid)
const allContent = []
// Collect content from multiple lexicons
for (const followDid of follows) {
// Standard posts
const posts = await this.getRecords(followDid, 'app.bsky.feed.post')
// Music posts
const musicPosts = await this.getRecords(followDid, 'com.musicapp.track')
// Recipe posts
const recipes = await this.getRecords(followDid, 'com.recipeapp.recipe')
allContent.push(...posts, ...musicPosts, ...recipes)
}
return allContent.sort((a, b) =>
new Date(b.createdAt) - new Date(a.createdAt)
)
}
}
Best Practices for Lexicon Compatibility
6. Multi-Lexicon Publishing Strategy
class CompatibleApp {
async publishContent(content: any) {
const records = []
// Always publish to standard lexicons for broad compatibility
if (content.type === 'text') {
records.push({
collection: 'app.bsky.feed.post',
record: {
text: content.text,
createdAt: new Date().toISOString()
}
})
}
// Also publish to your specialized lexicon
records.push({
collection: 'com.yourapp.content',
record: {
...content,
appVersion: '1.0.0',
metadata: this.generateMetadata(content)
}
})
// Batch create all records
await Promise.all(records.map(r =>
this.agent.com.atproto.repo.createRecord({
repo: this.userDid,
...r
})
))
}
}
7. Lexicon Discovery
// Discover what lexicons a user's repository supports
async function discoverUserCapabilities(userDid: string) {
const collections = await agent.com.atproto.repo.listRecords({
repo: userDid,
limit: 1000
})
const supportedLexicons = new Set()
collections.records.forEach(record => {
supportedLexicons.add(record.uri.split('/')[4]) // Extract collection
})
return Array.from(supportedLexicons)
}
The Power of Open Standards
This interoperability means:
- Users own their data across all apps
- Network effects benefit everyone
- Specialized apps can still participate in the broader ecosystem
- Innovation happens at the application layer, not the protocol layer
So yes, you can absolutely build an app that reads and writes to other apps' lexicons, creating a truly interoperable social ecosystem!