Skip to main content

recipe.exchange lexicons

Your recipes don't live inside Buttery. They live on the open AT Protocol network, in your own account, as portable records under the recipe.exchange namespace. Buttery reads and writes those records — but so can any other app that speaks the same lexicons. Leave Buttery whenever you like and your recipes come with you.

This page is the reference for those record types: what fields exist, what they mean, and — the part worth reading twice — where the published schema and the data you'll actually see on the network diverge.

About this reference

Namespaceexchange.recipe.*
Published bydid:plc:4cx7ts7lqgjtsfquo53qo3sz
Discover itthe _lexicon.recipe.exchange DNS TXT record resolves the publisher
Reflects the schema as of2026-08-01

recipe.exchange is an open, third-party lexicon — Buttery didn't author it and doesn't own it. The tables below describe the schema as published on the network on the date above. Lexicons evolve, so treat this as a snapshot; the network is always the source of truth.

The record types

LexiconKindOne per…Read by Buttery today
exchange.recipe.reciperecordrecipeYes
exchange.recipe.collectionrecordcollectionNot yet
exchange.recipe.profilerecordaccountNot yet
exchange.recipe.defsshared definitionsIndirectly

Three of these are records that live in your account; the fourth is a shared vocabulary the records draw on. Buttery reads recipes today — collections and profiles are part of the schema and coming later.


exchange.recipe.recipe

A single recipe. One record per recipe.

Always present: name, text, ingredients, instructions, createdAt, updatedAt.

FieldTypeRequiredWhat it holds
namestringYesRecipe name, up to 255 characters.
textstringYesDescription, up to 3000 characters.
ingredientsstring[]YesEach item up to 500 characters.
instructionsstring[]YesStep-by-step, each step up to 1000 characters.
createdAtdatetimeYesISO-8601 timestamp.
updatedAtdatetimeYesISO-8601 timestamp.
embed#imagesEmbedUp to 4 photos.
keywordsstring[]Free-form tags, each up to 64 characters.
cookTimestringISO-8601 duration, e.g. "PT30M" (see wire notes).
prepTimestringISO-8601 duration.
totalTimestringISO-8601 duration.
recipeYieldstringServings or yield, free text (e.g. "4 servings").
nutrition#nutritionPer-serving nutrition.
attributionone of attributionWhere the recipe came from.
cookingMethodstringAn open enum — see cookingMethod*.
recipeCuisinestringAn open enum — see cuisine*.
recipeCategorystringAn open enum — see category*.
suitableForDietstring[]Open enum values — see diet*.

Nested shapes

#nutrition

Per-serving nutrition. All fields optional:

FieldTypeNotes
caloriesintegerA whole number.
fatContentstringA decimal carried as text, e.g. "5.0".
proteinContentstringDecimal as text.
carbohydrateContentstringDecimal as text.

#image

What you send when adding a photo:

FieldTypeRequiredNotes
imageblobYesAny image/*, up to 1 MB.
altstringYesAlt text, for accessibility.
aspectRatioapp.bsky.embed.defs#aspectRatioA shared atproto shape.

#imagesEmbed

A set of up to 4 #image uploads — this is what recipe.embed holds.

#viewImage / #view

The hydrated form the network hands back when you read a recipe: each photo comes as a thumb and fullsize URL (served from a CDN) plus alt text and an optional aspect ratio. Worth noting the asymmetry — you upload photos as blobs (#image); you read them back as URLs.


exchange.recipe.collection

A named, ordered list of recipes. One record per collection.

Always present: name, createdAt, updatedAt.

FieldTypeRequiredWhat it holds
namestringYesUp to 100 characters.
createdAtdatetimeYesISO-8601 timestamp.
updatedAtdatetimeYesISO-8601 timestamp.
textstringDescription, up to 1000 characters.
recipesstrongRef[]References (uri + cid) to recipe records.

exchange.recipe.profile

Public profile for a recipe.exchange account. One per account (record key self).

Always present: createdAt, profileType.

FieldTypeRequiredWhat it holds
profileTypestringYesprofileType* — personal or business.
createdAtdatetimeYesISO-8601 timestamp.
updatedAtdatetimeISO-8601 timestamp.
aboutstringBio, up to 2000 characters.
emailstringUp to 255 characters.
phonestringUp to 20 characters.
links#link[]Up to 5 links.
address#addressPostal address.
businessTypestringbusinessType* — for business profiles.

title (up to 100 chars) and url — both required.

#address

Optional city, state, country, street1, street2, postalCode, plus latitude / longitude carried as text (see network notes — the exact encoding is unconfirmed, since no live profiles exist yet).


exchange.recipe.defs

The shared vocabulary the records above draw on: open enums (tokens) and the attribution shapes.

Tokens

These are open enums — a record may carry a value outside the published list, so treat unknown values gracefully:

GroupPrefixRoughlyUsed by
Cuisinescuisine*45 valuesrecipe.recipeCuisine
Categoriescategory*20 valuesrecipe.recipeCategory
Cooking methodscookingMethod*13 valuesrecipe.cookingMethod
Dietsdiet*14 valuesrecipe.suitableForDiet
Licenseslicense*6 valuesattribution
Business typesbusinessType*21 valuesprofile.businessType
Profile typesprofileType*2 valuesprofile.profileType
Publication typespublicationType*2 valuesattribution

Attribution

A recipe's attribution is exactly one of these six shapes, describing where it came from:

ShapeRequiredFor
#attributionOriginallicenseYour own original recipe (with a license*).
#attributionPersonnameSomething a person shared (family, a friend).
#attributionWebsitename, urlA website or blog.
#attributionPublicationtitle, authorA book or magazine (plus isbn, page, publisher).
#attributionShowtitle, networkA TV or streaming show (plus airDate, episode).
#attributionProductbrand, nameA product package or label (plus upc).

The schema vs. the network

The single most useful thing to know if you're reading this data yourself: the published schema and the bytes on the wire don't always agree. A few of these gaps exist because the schema predates today's stricter Lexicon validators. Here's what to actually expect:

  • Durations are text. cookTime, prepTime, and totalTime are ISO-8601 durations ("PT30M"), but they travel as plain strings — parse them yourself.
  • Decimals are text. Every non-whole number rides the wire as a string: nutrition macros ("5.0") and profile latitude/longitude. calories is the only genuine integer.
  • Photos go out as blobs, come back as URLs. You upload an #image blob; a read gives you #viewImage CDN URLs (thumb + fullsize).
  • A handful of fields are looser than they look. Some fields the schema once marked as an email, a date, or a numeric type are, on the network, just strings. Validate defensively.
  • Open enums stay open. Cuisine, category, cooking method, and diet values can legitimately be things not in the published token list. Don't reject a recipe for using one.

How Buttery reads your recipes

Buttery reads your exchange.recipe.recipe records straight from your account's public data — no special access, nothing you have to grant. When it shows a recipe, it validates it against the schema above and reads photos from the URLs the network provides. Because the records are public and portable, the same recipes are readable by any recipe.exchange-aware app — Buttery is just one door into a database you own.

A living document. This reference reflects the recipe.exchange schema as of 2026-08-01. Open lexicons change over time; if something here disagrees with what you see on the network, the network wins.