Introducing blahg
Published by @smokesignal.events on 2025-07-08 02:24 UTC.
Introducing blahg, an open source blog built on top of ATProtocol.
A few days ago I made a silly post:
Lexicon
The lexicon of a blahg post is pretty simple and can be found here: at://did:plc:tgudj2fjm77pzkuawquqhsxm/com.atproto.lexicon.schema/tools.smokesignal.blahg.content.post.
{
"id": "tools.smokesignal.blahg.content.post",
"defs": {
"main": {
"key": "any",
"type": "record",
"record": {
"type": "object",
"properties": {
"langs": {
"type": "array",
"items": {
"type": "string",
"format": "language"
},
"maxLength": 3,
"description": "Indicates human language of text content."
},
"title": {
"type": "string",
"maxLength": 2000,
"maxGraphemes": 200
},
"content": {
"type": "blob",
"accept": [
"text/plain",
"text/html",
"text/markdown"
],
"maxSize": 1000000,
"description": "The content of the post"
},
"attachments": {
"type": "array",
"items": {
"ref": "#attachment",
"type": "ref"
}
},
"publishedAt": {
"type": "string",
"format": "datetime"
}
}
},
"description": "A blagh post"
},
"attachment": {
"type": "object",
"required": [
"content"
],
"properties": {
"alt": {
"type": "string",
"description": "Alt text description of the content, for accessibility."
},
"content": {
"type": "blob",
"accept": [
"image/*"
],
"maxSize": 3000000
}
}
}
},
"$type": "com.atproto.lexicon.schema",
"lexicon": 1
}
There are a few key things that makes it different. First, blog post content is stored as attached blobs. I've never felt good about or heard a compelling argument for storing long-form content directly in records. Moving it to blobs also means that I can reference the content-type of the blob to determine how I want to render it. It really solves a lot of problems for me.
Attachments
Attachments are blobs that are reference inside of the content. For the most part, they are images and blahg will automatically prefix image references that do not have a "https://" or "/" prefix with the path to serve them at render time.
You can see it in action with this post. The image of the screenshot at the top of this post is stored as a blob and the content of the post references the CID.
Backlinks
Blahg is a jetstream consumer and listens to blahg, lexicon community, and bksy.app collections to look for references to posts. When one is encountered, it stores the AT-URI as a reference and displays the collections that have at least one post reference.
Rust Crates
This application was created in about 4 hours and uses the atproto-identity
, atproto-record
, atproto-client
, and atproto-jetstream
crates. Some of the axum scafolding was copied from showcase.
Open Source
Blahg is open source and available on tangled: tangled.sh/@smokesignal.events/blahg