How to implement CoffeeJSON
Two functions: JSON in, your recipe type out, and back again. Required: a title, a dose, and either the water or the ratio. A reader ignores the rest.
The integration guide is the checklist. This page is what you lean on while you work it.
Reference SDKs
| Package | Language | What it covers |
|---|---|---|
@coffeejson/core |
TypeScript | Wire types, the share-link codec, and a total normalize() — an untrusted payload cannot crash a renderer. |
@coffeejson/react |
TypeScript | Renders a document. Frozen class names, replaceable leaves, no styling you cannot override. |
coffeejson-swift |
Swift | Wire types, codec and share-link transport for Apple platforms. Pure Foundation, no dependencies. |
npm install @coffeejson/core
Conformance is something you can run
The transport ships as scan vectors — each a URL exactly as a scanner hands it over, with the document it must yield or the reason to refuse it.
The SDKs run them; so can yours. Rejection names come from the corpus, so two implementations describe the same failure the same way. Document shapes get the same treatment: a fixture corpus, each invalid document naming the rule it breaks.
Documents
- Must accept 50
- action-duration
- addition-unquantified-ice
- additions-milk-temp
- aeropress-mixed-steps
- bag-to-brew
- bean-catalog
- bean-only
- bilingual-bag
- blend-components-unknown
- blend-percentages
- bloom-step
- catalog-with-refs
- credit-roles
- date-published
- espresso-dose-yield
- filter-and-rest
- filter-with-yield
- form-drip-bag
- forward-compat-unknown-fields
- forward-compat-unknown-registry-values
- full-bean-and-recipe
- gear-custom
- gear-variant
- grind-size
- images
- images-empty
- lang-bcp47
- library-export
- minimal
- newer-minor-version
- non-metric-units
- origin-item-varietals
- origin-producers-roles
- origin-supranational-region
- process-multiple
- ranged-quantities
- recipe-description
- recipe-ids
- recipe-ratio-disagrees-with-water
- recipe-ratio-instead-of-water
- recipe-with-author
- tasting-bean-substitution
- tasting-ids-and-lang
- tasting-measured-cup
- tasting-refractometer-only
- tasting-weighed-cup
- typical-pour-over
- valve-and-wait-steps
- vendor-ext
- water-by-volume
- Must refuse 60
- action-duration-negative
- addition-type-empty
- agtron-above-scale
- altitude-missing-unit
- altitude-without-bounds
- author-missing-name
- author-name-empty
- author-role-empty
- author-url-not-uri
- bad-country-code
- bad-lang-tag
- based-on-not-uri
- bean-url-not-uri
- date-published-not-date
- display-unit-symbol
- dose-by-volume
- empty-collections
- espresso-missing-yield
- espresso-with-ratio
- espresso-with-water
- gear-custom-without-label
- gear-id-malformed
- gear-missing-id
- generator-missing-name
- generator-url-not-uri
- grind-size-unknown
- images-single-string
- localizations-bad-locale-key
- localizations-without-lang
- measurement-missing-unit
- measurement-negative-value
- measurement-no-magnitude
- measurement-value-and-window
- measurement-zero-value
- microns-zero
- missing-version
- negative-step-time
- no-collections
- origin-items-empty
- party-type-unknown
- percentage-above-100
- pressure-zero
- ratio-zero
- recipe-id-empty
- recipe-missing-title
- recipe-missing-water
- recipes-element-not-an-object
- roast-date-malformed
- roaster-bare-string
- roaster-missing-name
- tasting-axis-out-of-range
- tasting-id-empty
- tasting-rating-off-scale
- tasting-tds-above-100
- tasting-tds-not-a-percentage
- title-empty
- unknown-method
- version-not-string
- version-prefixed
- version-wrong-major
Every cell is one case in the repository, and a link to it.
Scan vectors
- Must accept 14
- Must refuse 21
Every cell is one case in the repository, and a link to it.
When you have shipped it
An implementation is anything that reads or writes CoffeeJSON — an app, a service, a library, a machine. The two roles are independent.
Open a pull request adding yours to
registries/implementations.json
and it appears on the showcase. No approval step,
nothing to sign.