We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
In the previous post, we learned the basics of posting to Bluesky.
Today, we are taking it a step further by adding tags to the post.
You might think that it's as easy as just adding tags as text prepended with a #
sign, but it is a little more complicated than that unfortunately.
If you add the tags as plain text, you'll see that they are represented that way in Bluesky and that you are unable to click on them.
To add real tags in your Bluesky post, we need to use a concept called "facets". Facets can be multiple things such as tags, mentions and clickable links.
Let's see how they work.
Step 1: Get the list of tag facets from the text
We will start with creating a helper function which can extract the tags from the text and return the proper data structure as expected by Bluesky:
defmodule BlueskyHelpers do
def get_tags_as_facets(text) do
Regex.scan(~r/#\S+/, text, return: :index)
|> Enum.map(fn [{start, length}] -> tag_to_facet(text, start, length) end)
end
def tag_to_facet(text, start, length) do
tag =
text
|> String.slice(start, length)
|> String.trim_leading("#")
%{
index: %{
byteStart: start,
byteEnd: start + length
},
features: [
%{
"$type": "app.bsky.richtext.facet#tag",
tag: tag
}
]
}
end
end
What this code does is:
- It will use a regular expression to extract the tags from the text
- It will then tranform each tag into the proper facet data structure
The helper function for turning the tag into a facet does:
- It will use the start index and the length to get the actual tag text
- It will then create a map with the index containing the byte start and end of the tag (including the
#
sign) - It will use the type
app.bsky.richtext.facet#tag
to indicate that this is a tag facet - It will specify the actual tag for the facet (without the
#
sign)
Step 2: Creating the post record
This is again the same structure as in the previous post, but with one change.
We now added the list of facets:
# Create the current timestamp in ISO format with a trailing Z
created_at = DateTime.utc_now() |> DateTime.to_iso8601()
# The text to post
text = "Hello from Elixir #MyElixir #example"
# Get the list of facets
facets = BlueskyHelpers.get_tags_as_facets(text)
# Create the post record
record =
%{
text: text,
createdAt: created_at,
"$type": "app.bsky.feed.post",
langs: ["en-US"],
facets: facets # Add the list of facets
}
Step 3: Post to Bluesky
We can now use the same code from the previous post to publish the record:
%{"commit" => %{"rev" => rev}} =
Req.post!(
"https://bsky.social/xrpc/com.atproto.repo.createRecord",
auth: {:bearer, token},
json: %{
repo: did, # The did value from step 1
collection: "app.bsky.feed.post", # We want to post to our timeline
record: record # The record we want to post to our timeline
}
).body
If all goes well, the tags should show up in the post as clickable items.
Next time, we'll continue with facets to enable mentioning other users.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.