posting delay; homebrew recipes and the semantic web

Sorry for the long delay in posting. A few months ago, the girlfriend and I bought a sinkhole of time and materials generally referred to as a house. This one was particularly large in that it needed some serious internal rennovation before being habitable. Between that and a desire to focus this less on just talking and more on talking about production, I’ve not had much time or much to write about…

For the past couple of years, I’ve been pretty interested in the semantic web technologies, and in RDF. I came to the space looking for rigor about how to use XML to model data. What I found was really what I was looking for: both the recognition of XML’s true nature as well as a better way to actually do the data-modeling I was seeking… or so I thought.

Like many others, I feel into the trap of “RDF for everything!”, neglecting to remember that it is the (web) Resource Description Format. While many things are, or can be (and should be), Resources, the framwork is setup more for the wide-scale exchange of information about those resources, not as a general-purpose “small-scale” data-modeling framework. However, many things can be resources…

One project I started just about a year ago, when I started homebrewing, was keeping my homebrewing journal in a file. I knew that I wanted to keep notes in a good bit of structured detail, but I didn’t want the pain associated with authoring them in XML. I decided to author them in RDF, in N3, along a loose ontology that I would create and extend as I authored.

The main aspects to record in such a journal are the following:

  • the recipe itself
  • grains, adjuncts, hop-schedule, and notes
  • instances of brewing the recipe
  • deviations from the recipe
  • notes about the brewing process (e.g., tempatures reached, times of boiling, &c.)
  • readings of the specific gravity of the wort at the beginning and end of the fermentation.

As such, I ended up with notes that look like:

<#maplePorter> a hb:Recipe ; rdf:label “Maple Porter” ; dc:created “2005-04-02-05:00″^^xsd:date ; foaf:maker <#jsled> ; hb:ingredient [ a hb:Grain; hb:amt [ rdf:value 4.75; hb:units hb:lb ]; rdf:label “pale extract” ]

,[ a hb:Adjunct; hb:amt [ rdf:value 2.5; hb:units hb:lb ] ,[ rdf:value 43; hb:units hb:oz ]; rdf:label “Vermont maple syrup; unblended @ 20 min remaining” ] ,[ a hb:Hop; hb:amt [ rdf:value 2.0; hb:units hb:oz ]; rdf:label “Goldings”; hb:hopTime [ rdf:value 60; hb:units hb:min ] ]

. <#aprMaplePorter> a hb:BrewInstance ; hb:recipe <#maplePorter> ; dc:created “2005-04-18-05:00″^^xsd:date ; foaf:maker <#jsled> ; hb:journal [ a hb:OriginalGravityReading; dc:created “2005-04-18-05:00″^^xsd:date; rdf:value 1.042; hb:temp [ rdf:value 60; hb:units hb:F ]] ,[ dc:created “2005-04-18-05:00″^^xsd:date; rdf:label “Used Wyeast 1318 (London Ale Yeast III), cultured Feb 15 2005, incubated for 2 days” ]


For quite a while I’ve been hoping to publish the collection of data, autogenerated from the RDF into HTML. I finally set down and have done it. contains both.

The pipeline is the “standard” one: cwm plus a bit of inference into XML, then XSLT into HTML. contains a bit of the detail. It’d be nicer to use a RDF-specific path/templating/transformation language, but xsltproc is widely available and simple.

A major part of the process was cleaning up and making-consistent the journal data. In doing this a couple of issues with the ad-hoc formating I’d naturally done in the RDF were made much more clear:

  1. The relation between a recipe and an ingredient should really be made quite regular through the use of a URI for the ingredient, rather than simple a value string. While true in recipes generally, this is particularly true in beer recipes, which draw from a small, fixed set of ingredients and vary primarily in the n-ary relations of those ingredients to the recipe.

  2. What are currently n3-file-local fragments should really be first-order resources at<filename>. One thing that RDF makes particularly painful is the seamless transition from a very informal organization into a concrete one.