Put the recipe next to the coffee

Paste four lines into a product page or a blog post, and your readers get the dose, the water and every timed pour as a card they can brew from. No plugin, no account, nothing to host.

  1. Pick a coffee, or build your own.
  2. Copy the four lines.
  3. Paste them anywhere your site takes HTML: a theme's custom-code section, a page builder's HTML block, a post's source view.

For a recipe on its own, this gives search engines the steps. Leave it off for a bag on a shop page whose theme already describes the product.

<script type="module" src="https://cdn.jsdelivr.net/npm/@coffeejson/core@1.2.0/dist/element/auto.js"></script>
<coffee-json d="eyJjb2ZmZWVqc29uIjoiMS4xIiwiYmVhbnMiOlt7Im5hbWUiOiJTZXJtb24iLCJyb2FzdGVyIjp7Im5hbWUiOiJWZXJ2ZSBDb2ZmZWUiLCJ1cmwiOiJodHRwczovL3d3dy52ZXJ2ZWNvZmZlZS5jb20iLCJ0eXBlIjoib3JnYW5pemF0aW9uIn0sInVybCI6Imh0dHBzOi8vd3d3LnZlcnZlY29mZmVlLmNvbS9wcm9kdWN0cy9zZXJtb24iLCJvcmlnaW4iOnsidHlwZSI6ImJsZW5kIiwiaXRlbXMiOlt7ImNvdW50cnkiOiJDTyIsInByb2Nlc3MiOlsid2FzaGVkIl19LHsicmVnaW9uIjoiRWFzdCBBZnJpY2EiLCJwcm9jZXNzIjpbIm5hdHVyYWwiXX1dfSwicm9hc3RfbGV2ZWwiOiJtZWRpdW0iLCJmb3JtIjoiYmVhbiIsInJvYXN0ZXJfbm90ZXMiOlsiQmx1ZWJlcnJ5IFBpZSIsIkNvY29hIiwiQ2FuZGllZCBQZWNhbiJdLCJkZXNjcmlwdGlvbiI6IkZydWl0LWZvcndhcmQgYW5kIGZ1bGwtYm9kaWVkLCBTZXJtb24gaXMgcGxheWZ1bCBhbmQgYXBwcm9hY2hhYmxlIGJyZXdlZCBvciBhcyBlc3ByZXNzby4gVGhpcyBlYXN5LWRyaW5raW5nIGJsZW5kIGlzIGJ1aWx0IGZyb20gdGhvdWdodGZ1bGx5IGNob3NlbiBuYXR1cmFsbHktcHJvY2Vzc2VkIGNvZmZlZXMgZnJvbSBFYXN0IEFmcmljYSB0aGF0IGNvbnRyaWJ1dGUgZGVlcCBzd2VldG5lc3MgYW5kIGJlcnJ5IG5vdGVzIGFuZCBhIHdhc2hlZCBDb2xvbWJpYW4gY29tcG9uZW50IHRoYXQgcHJvdmlkZXMgc3RydWN0dXJlIGFuZCBiYWxhbmNlLiBCZWhvbGQsIHlvdXIgcGVyZmVjdCBtb3JuaW5nLiIsImxhbmciOiJlbiJ9XSwicmVjaXBlcyI6W3sidGl0bGUiOiJWZXJ2ZSBTZXJtb24gRHdlbGwiLCJkZXNjcmlwdGlvbiI6IlZlcnZlJ3MgRHdlbGwgRHJpcHBlciBzdWdnZXN0aW9uIGZvciBTZXJtb246IDIwIGcgdG8gMzAwIGcgYXQgMToxNSBvbiBhIG1lZGl1bSBncmluZCwgZHJhd24gZG93biBhdCAyOjIxLiIsIm1ldGhvZCI6InBvdXJfb3ZlciIsInJlY29tbWVuZGVkIjp0cnVlLCJicmV3ZXIiOnsiaWQiOiJ2ZXJ2ZS1kd2VsbCJ9LCJjb2ZmZWUiOnsidmFsdWUiOjIwLCJ1bml0IjoiZ3JhbSJ9LCJ3YXRlciI6eyJ2YWx1ZSI6MzAwLCJ1bml0IjoiZ3JhbSJ9LCJyYXRpbyI6MTUsImdyaW5kIjp7InNpemUiOiJtZWRpdW0ifSwiZmluaXNoX3MiOjE0MSwibGFuZyI6ImVuIiwiYXV0aG9yIjp7Im5hbWUiOiJWZXJ2ZSBDb2ZmZWUiLCJ1cmwiOiJodHRwczovL3d3dy52ZXJ2ZWNvZmZlZS5jb20iLCJ0eXBlIjoib3JnYW5pemF0aW9uIn0sImJhc2VkX29uIjoiaHR0cHM6Ly93d3cudmVydmVjb2ZmZWUuY29tL3Byb2R1Y3RzL3Nlcm1vbiJ9LHsidGl0bGUiOiJWZXJ2ZSBTZXJtb24gRnJlbmNoIFByZXNzIiwiZGVzY3JpcHRpb24iOiJWZXJ2ZSdzIEZyZW5jaCBwcmVzcyBzdWdnZXN0aW9uIGZvciBTZXJtb246IDM1IGcgdG8gNTAwIGcgb24gYSBjb2Fyc2UgZ3JpbmQsIGZpdmUgbWludXRlcy4iLCJtZXRob2QiOiJmcmVuY2hfcHJlc3MiLCJyZWNvbW1lbmRlZCI6dHJ1ZSwiYnJld2VyIjp7ImlkIjoiZnJlbmNoLXByZXNzIn0sImNvZmZlZSI6eyJ2YWx1ZSI6MzUsInVuaXQiOiJncmFtIn0sIndhdGVyIjp7InZhbHVlIjo1MDAsInVuaXQiOiJncmFtIn0sImdyaW5kIjp7InNpemUiOiJjb2Fyc2UifSwiZmluaXNoX3MiOjMwMCwibGFuZyI6ImVuIiwiYXV0aG9yIjp7Im5hbWUiOiJWZXJ2ZSBDb2ZmZWUiLCJ1cmwiOiJodHRwczovL3d3dy52ZXJ2ZWNvZmZlZS5jb20iLCJ0eXBlIjoib3JnYW5pemF0aW9uIn0sImJhc2VkX29uIjoiaHR0cHM6Ly93d3cudmVydmVjb2ZmZWUuY29tL3Byb2R1Y3RzL3Nlcm1vbiJ9XX0" viewer="https://coffeejson.org/r/" viewer-label="Open">
  <a href="https://coffeejson.org/r/?d=eyJjb2ZmZWVqc29uIjoiMS4xIiwiYmVhbnMiOlt7Im5hbWUiOiJTZXJtb24iLCJyb2FzdGVyIjp7Im5hbWUiOiJWZXJ2ZSBDb2ZmZWUiLCJ1cmwiOiJodHRwczovL3d3dy52ZXJ2ZWNvZmZlZS5jb20iLCJ0eXBlIjoib3JnYW5pemF0aW9uIn0sInVybCI6Imh0dHBzOi8vd3d3LnZlcnZlY29mZmVlLmNvbS9wcm9kdWN0cy9zZXJtb24iLCJvcmlnaW4iOnsidHlwZSI6ImJsZW5kIiwiaXRlbXMiOlt7ImNvdW50cnkiOiJDTyIsInByb2Nlc3MiOlsid2FzaGVkIl19LHsicmVnaW9uIjoiRWFzdCBBZnJpY2EiLCJwcm9jZXNzIjpbIm5hdHVyYWwiXX1dfSwicm9hc3RfbGV2ZWwiOiJtZWRpdW0iLCJmb3JtIjoiYmVhbiIsInJvYXN0ZXJfbm90ZXMiOlsiQmx1ZWJlcnJ5IFBpZSIsIkNvY29hIiwiQ2FuZGllZCBQZWNhbiJdLCJkZXNjcmlwdGlvbiI6IkZydWl0LWZvcndhcmQgYW5kIGZ1bGwtYm9kaWVkLCBTZXJtb24gaXMgcGxheWZ1bCBhbmQgYXBwcm9hY2hhYmxlIGJyZXdlZCBvciBhcyBlc3ByZXNzby4gVGhpcyBlYXN5LWRyaW5raW5nIGJsZW5kIGlzIGJ1aWx0IGZyb20gdGhvdWdodGZ1bGx5IGNob3NlbiBuYXR1cmFsbHktcHJvY2Vzc2VkIGNvZmZlZXMgZnJvbSBFYXN0IEFmcmljYSB0aGF0IGNvbnRyaWJ1dGUgZGVlcCBzd2VldG5lc3MgYW5kIGJlcnJ5IG5vdGVzIGFuZCBhIHdhc2hlZCBDb2xvbWJpYW4gY29tcG9uZW50IHRoYXQgcHJvdmlkZXMgc3RydWN0dXJlIGFuZCBiYWxhbmNlLiBCZWhvbGQsIHlvdXIgcGVyZmVjdCBtb3JuaW5nLiIsImxhbmciOiJlbiJ9XSwicmVjaXBlcyI6W3sidGl0bGUiOiJWZXJ2ZSBTZXJtb24gRHdlbGwiLCJkZXNjcmlwdGlvbiI6IlZlcnZlJ3MgRHdlbGwgRHJpcHBlciBzdWdnZXN0aW9uIGZvciBTZXJtb246IDIwIGcgdG8gMzAwIGcgYXQgMToxNSBvbiBhIG1lZGl1bSBncmluZCwgZHJhd24gZG93biBhdCAyOjIxLiIsIm1ldGhvZCI6InBvdXJfb3ZlciIsInJlY29tbWVuZGVkIjp0cnVlLCJicmV3ZXIiOnsiaWQiOiJ2ZXJ2ZS1kd2VsbCJ9LCJjb2ZmZWUiOnsidmFsdWUiOjIwLCJ1bml0IjoiZ3JhbSJ9LCJ3YXRlciI6eyJ2YWx1ZSI6MzAwLCJ1bml0IjoiZ3JhbSJ9LCJyYXRpbyI6MTUsImdyaW5kIjp7InNpemUiOiJtZWRpdW0ifSwiZmluaXNoX3MiOjE0MSwibGFuZyI6ImVuIiwiYXV0aG9yIjp7Im5hbWUiOiJWZXJ2ZSBDb2ZmZWUiLCJ1cmwiOiJodHRwczovL3d3dy52ZXJ2ZWNvZmZlZS5jb20iLCJ0eXBlIjoib3JnYW5pemF0aW9uIn0sImJhc2VkX29uIjoiaHR0cHM6Ly93d3cudmVydmVjb2ZmZWUuY29tL3Byb2R1Y3RzL3Nlcm1vbiJ9LHsidGl0bGUiOiJWZXJ2ZSBTZXJtb24gRnJlbmNoIFByZXNzIiwiZGVzY3JpcHRpb24iOiJWZXJ2ZSdzIEZyZW5jaCBwcmVzcyBzdWdnZXN0aW9uIGZvciBTZXJtb246IDM1IGcgdG8gNTAwIGcgb24gYSBjb2Fyc2UgZ3JpbmQsIGZpdmUgbWludXRlcy4iLCJtZXRob2QiOiJmcmVuY2hfcHJlc3MiLCJyZWNvbW1lbmRlZCI6dHJ1ZSwiYnJld2VyIjp7ImlkIjoiZnJlbmNoLXByZXNzIn0sImNvZmZlZSI6eyJ2YWx1ZSI6MzUsInVuaXQiOiJncmFtIn0sIndhdGVyIjp7InZhbHVlIjo1MDAsInVuaXQiOiJncmFtIn0sImdyaW5kIjp7InNpemUiOiJjb2Fyc2UifSwiZmluaXNoX3MiOjMwMCwibGFuZyI6ImVuIiwiYXV0aG9yIjp7Im5hbWUiOiJWZXJ2ZSBDb2ZmZWUiLCJ1cmwiOiJodHRwczovL3d3dy52ZXJ2ZWNvZmZlZS5jb20iLCJ0eXBlIjoib3JnYW5pemF0aW9uIn0sImJhc2VkX29uIjoiaHR0cHM6Ly93d3cudmVydmVjb2ZmZWUuY29tL3Byb2R1Y3RzL3Nlcm1vbiJ9XX0">Sermon, as CoffeeJSON</a>
</coffee-json>

Where it earns its place

Why four lines are enough

Attributes

AttributeWhat it does
srcA URL that serves the document. Fetched, then checked like any decoded document.
dA payload, the same string a share link carries after ?d=. Wins over src. Padding is accepted, so a template filter that emits padded URL-safe Base64 produces a valid value.
unitsmetric, imperial or as-authored (the default).
langA BCP-47 tag for the digits, for example de for a decimal comma.
viewerA viewer's URL, absolute or a path on your site, http or https only. Adds an "Open" link to it with the payload as ?d=. Without it there is no such link, because the package picks no host for you.
viewer-labelThe text of that link, in your page's words and language. The default is "Open". The value is shown as text, never as markup. Without viewer it does nothing.
labelsCaptions in your page's words, as JSON: a PartialLabels object, merged over the English defaults the way the React cards' config.labels is, so you name only what changes. actions.download is the Download button. A value that is not a JSON object keeps the defaults; the element still renders and reports nothing, because the document is fine. Every label is shown as text, never as markup.
jsonldWhen present, the element adds the document's schema.org JSON-LD to the page's <head>, and removes it when the element goes. When absent, it adds nothing, because your page may already describe the same product.

A page with script can set labels as an object on the element's property instead. The element fires coffeejson-load and coffeejson-error, and both bubble. Theme it with the --cj-* custom properties and ::part(). The package README has the rest.

Make a card for your coffee Browse the recipes

Every card on this page is drawn by the script the snippet loads, at version 1.2.0, from the npm CDN. This site is demonstrating the element, not listing who uses it: the showcase says what has shipped.