If you’re building a an Atmospheric (AT Protocol) app you may have designed your own lexicon for storing you app’s data.
When I first started out I found it tricky to publish them “properly”, even to know what spec-compliant publishing was.
This is a quick explainer & guide for publishing your lexicon, as a one-off or setting it up in your repo’s CI so you never have to think about it again.
Why would you want this? Once your lexicon is published it'll appear on sites like lexicon.garden, can be found on PDS.ls and similar, and PDS validation will work when your records are written!
The process
Recently I published the me.byjp.emojify.suggestEmoji lexicon; to publish it I had to:
- 1.
Put a
com.atproto.lexicon.schemaatproto record in my account, holding the lexicon schema- 1.
I published to my @byjp.me account, but the account handle doesn’t need to match the NSID (Bluesky’s don’t!)
- 2.
Have a DNS TXT record, on the domain matching the lexicon, pointing to that atproto account's DID
- 1.
It must be “all but the last segment” of the lexicon,
me.byjp.emojifyfor me, reversed and with_lexicon.in front—so I had to create aTXTrecord at_lexicon.emojify.byjp.me(see it here) - 2.
The record has to be the DID of the account. For me that's
did=did:plc:ephkzpinhaqcabtkugtbzrwu— my account (I look it up on PDS.ls). You can't use your handle - 3.
Note: a record on
_lexicon.byjp.me(ie. 'one level up') won’t work. If your app has categories of lexicon (eg.app.bsky.actor.profile+app.bsky.feed.post) you need multiple DNS entries (eg._lexicon.actor.bsky.app,_lexicon.feed.bsky.app)
It's only those two steps!
Tools
Goat for publishing lexicons to your PDS, at-SDP for publishing your lexicons to a static website that acts as a PDS thanks to the power of .
Both of these tools need you to have set up your _lexicon DNS record; naturally that's super easy on , the atmospheric domain registrar!
Goat
goat (github) is a superb CLI tool for managing atproto things, and it can publish lexicon files to your atproto account:
# Publish the lexicon JSON files to your atproto account
goat lex publish \
--username byjp.me \
--password $ACCOUNT_APP_PASSWORD \
./lexicons/me/byjp/emojify/*.jsonIt will:
Tell you if your DNS record isn't in place
Check the validity of your lexicons
Tell you if you're going to change a lexicon
The last may seem counter intuitive, but lexicons aren't meant to change once published. The assumption being that once you've published the lexicon it's likely that someone will publish records that fit that schema, if you change the schema then their record becomes invalid.
So by default goat will stop you from publishing updates. If your update is forward and backward compatible (or if you know no-one has used your lexicon yet) you can use the -u flag to update.
at-SDP
at-sdp (tangled) is my own project; it builds a Statically Defined PDS out of your lexicons (and other JSON atproto records), including all that's needed for a did:web:<your-domain> as your account.
This is a great fit for a side-project where you don't expect to interactively use the atproto account that publishes the lexicons, and for "fire and forget" CI workflows.
With at-SDP you don't need an account on a PDS, a password, or anythng beyond your site deployed with wisp.place.
To set things up you initialize your account with at-sdp init --domain <your-domain>. This makes an at-sdp.json (which you should keep in your repo, if you're planning on doing this in CI).
Then, when you're ready to publish your website (eg. in ./public) with wisp-cli:
# Build a PDS from lexicons & optionally any other records
# and add the files to your existing site in ./public
at-sdp build \
--out ./public \
./lexicons/me/byjp/emojify \
./atproto/bluesky/profile.json
# Publish your site with wisp.place
wisp-cli deploy emojify.byjp.me \
--path ./public \
--site emojify \
--password "$ACCOUNT_APP_PASSWORD" \
--yes
# Wait for your PDS to be live
at-sdp check --site emojify.byjp.me
# Notify the relays (bluesky and blacksky by default)
# that new records have been published
at-sdp notifyI want to make building on atproto as easy as possible for folks, so if you have questions, please on Bluesky and I'll see if I can help.