{"@context":{"rdf":"http://www.w3.org/1999/02/22-rdf-syntax-ns#","rdfs":"http://www.w3.org/2000/01/rdf-schema#","owl":"http://www.w3.org/2002/07/owl#","foaf":"http://xmlns.com/foaf/0.1/","dc":"http://purl.org/dc/elements/1.1/","dct":"http://purl.org/dc/terms/","sioc":"http://rdfs.org/sioc/types#","blog":"http://vocab.amy.so/blog#","as":"https://www.w3.org/ns/activitystreams#","mf2":"http://microformats.org/profile/","ldp":"http://www.w3.org/ns/ldp#","solid":"http://www.w3.org/ns/solid#","view":"https://terms.rhiaro.co.uk/view#","asext":"https://terms.rhiaro.co.uk/as#","dbp":"http://dbpedia.org/property/","geo":"http://www.w3.org/2003/01/geo/wgs84_pos#","doap":"http://usefulinc.com/ns/doap#","time":"http://www.w3.org/2006/time#"},"@graph":[{"@id":"https://rhiaro.co.uk/2017/08/","@type":["as:Collection","ldp:Container"],"ldp:contains":[{"@id":"https://rhiaro.co.uk/2017/08/when-cut"},{"@id":"https://rhiaro.co.uk/2017/08/last-night"},{"@id":"https://rhiaro.co.uk/2017/08/59844e7e9d58c"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo"},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review"},{"@id":"https://rhiaro.co.uk/2017/08/598b55e4a96a6"},{"@id":"https://rhiaro.co.uk/2017/08/photos-uk"},{"@id":"https://rhiaro.co.uk/2017/08/598efd32d0fef"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-2"},{"@id":"https://rhiaro.co.uk/2017/08/diy-ldn"},{"@id":"https://rhiaro.co.uk/2017/08/599346c4ed1f5"},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review-2"},{"@id":"https://rhiaro.co.uk/2017/08/summer"},{"@id":"https://rhiaro.co.uk/2017/08/yak"},{"@id":"https://rhiaro.co.uk/2017/08/pizza-mousse"},{"@id":"https://rhiaro.co.uk/2017/08/duolingo"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-4"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-3"},{"@id":"https://rhiaro.co.uk/2017/08/59a31bc2a6143"},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review-3"},{"@id":"https://rhiaro.co.uk/2017/08/59a31d9187914"},{"@id":"https://rhiaro.co.uk/2017/08/59a31e68d8d2d"},{"@id":"https://rhiaro.co.uk/2017/08/59a31ee60d122"},{"@id":"https://rhiaro.co.uk/2017/08/59a31f5eb9f64"},{"@id":"https://rhiaro.co.uk/2017/08/59adba9882010"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-5"},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review-4"},{"@id":"https://rhiaro.co.uk/2017/08/59adbae9aaeab"},{"@id":"https://rhiaro.co.uk/2017/09/59adbb27b6cc5"},{"@id":"https://rhiaro.co.uk/2017/09/59adbb65e6aed"}],"as:name":"Posts between 2017/08 and 2017/09","as:totalItems":{"@type":"http://www.w3.org/2001/XMLSchema#nonNegativeInteger","@value":"30"}},{"@id":"https://rhiaro.co.uk/2017/08/59844e7e9d58c","@type":"as:Add","as:content":"
'Mince' made with finely chopped cauliflower, chilli tofu, mushrooms, tomato, soy sauce.
\r\nPizza with a base of chickpea flower and flaxseed (fried on the stovetop to solidify before baking to make it crispy) with Tesco jalapeno not-chedder cubed (super melty) and Violife not-parmesan grated (only the bits not directly exposed to the grill melted, the top went dry/crispy) on top.
\r\nGrilled not-cheese, with the Tesco jalapeno chedder. Did I mention this melts super well?
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170731_214956.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170802_221556.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170803_190546.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-04T12:37:44+02:00"},"as:summary":"Amy added 3 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/08/598b55e4a96a6","@type":"as:Add","as:content":"Food I made when I was home.
\r\nMum sent me to Gram's with instructions to make lunch from whatever I could find. There wasn't a lot in the cupboards, but I managed to rustle up tomato and mixed peppers soup.
\r\nI made curry and chapati for Mum, Dave and J too. Also featured: blue not-cheese (coconut oil based) on toast.
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170806_130701.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170806_200423.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170806_200427.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170807_101015.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170807_101220.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-09T20:35:09+02:00"},"as:summary":"Amy added 5 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/08/598efd32d0fef","@type":"as:Add","as:content":"Pasta with not-cheese.. and a chocolate coconut fudge cake.
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170811_204654.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170811_211804.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170811_215554.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170811_220057.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170811_220736.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170812_140938.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170812_140944.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-11T21:05:48+02:00"},"as:summary":"Amy added 7 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/08/599346c4ed1f5","@type":"as:Add","as:content":"Pasties stuffed with potatoes, herbs, spices, and not-cheese. Entirely spelt flour pastry, which is pretty dense, but works out.
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170813_204052.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170813_204107.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170813_204627.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170813_213747.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-13T20:08:46+02:00"},"as:summary":"Amy added 4 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/08/59a31bc2a6143","@type":"as:Add","as:content":"I coated soy chunks (twice) in a wet batter (soy sauce, sambal, flax egg, oat cream and various spices) and dry (wheat flour, corn flour, nutritional yeast, spices), then deep fried in coconut oil for a few seconds. I covered potato chunks in dry batter and fried those too. It was good with onion and mushroom gravy, and the next day cold with salad and sambal to dip.
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170820_144837.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170820_145741.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170820_162303.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170820_162837.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170820_162842.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170820_162957.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170820_163236.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170820_163243.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170820_163328.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170820_163344.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170820_163350.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170820_163529.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170820_190951.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-20T20:21:31+02:00"},"as:summary":"Amy added 13 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/08/59a31d9187914","@type":"as:Add","as:content":"Cookies! Wheat flour, spelt flour, baking soda, white sugar, coconut oil, dark chocolate chunks, 8 minutes low oven. Equal parts oil and sugar, 2x flour, take out of the oven whilst still soft. Good texture, but brown sugar will be better.
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170822_183224.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170822_183229.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-22T20:29:14+02:00"},"as:summary":"Amy added 2 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/08/59a31e68d8d2d","@type":"as:Add","as:content":"Chilli. Good with homemade chips, good in cevapi bread, good by the spoon. Mixed beans, leftover mushroom gravy, lentils, sweetcorn, soya mince, tomato puree, sambal, various spices.
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170822_185106.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170822_185112.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170825_174759.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170825_174804.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-25T20:32:50+02:00"},"as:summary":"Amy added 4 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/08/59a31ee60d122","@type":"as:Add","as:content":"Chocolate hazelnut cookies. Equal parts coconut oil and sugar; 2x that of flour (spelt and wheat); baking soda; cocoa; flaxseed; dark chocolate chunks and hazelnut halves. Smaller and flatter than the last batch, improved the texture, but I still need to ditch the white sugar. The coconut oil makes them so creamy. Best after refrigeration.
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170825_184208.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170825_184218.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170825_184224.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170825_184248.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-25T20:34:54+02:00"},"as:summary":"Amy added 4 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/08/59a31f5eb9f64","@type":"as:Add","as:content":"Omelette made from chickpea flour with a sprinkling of flaxseed, vegetable stock, turmeric, basil; topped with cherry tomatoes, lightly grilled mushrooms, and coconut oil not-cheese.
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170826_104641.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170826_105204.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170826_105209.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170827_150546.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-27T17:36:55+02:00"},"as:summary":"Amy added 4 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/08/59adba9882010","@type":"as:Add","as:content":"An approximation of quesadillas
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170827_192237.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170827_192508.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170827_193458.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170827_193504.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170827_194145.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170827_194900.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-27T20:41:54+02:00"},"as:summary":"Amy added 6 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/08/59adbae9aaeab","@type":"as:Add","as:content":"Curry, salad, veggie burger and chips.
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170828_220120.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170828_222228.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170828_222238.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170828_231423.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170828_231451.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170828_231456.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170828_232116.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170829_195139.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170829_195404.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-29T20:43:16+02:00"},"as:summary":"Amy added 9 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/08/?before=https://rhiaro.co.uk/2017/08/when-cut&limit=16","@type":["as:CollectionPage","ldp:Container"],"ldp:contains":[{"@id":"https://rhiaro.co.uk/2017/08/when-cut"},{"@id":"https://rhiaro.co.uk/2017/08/last-night"},{"@id":"https://rhiaro.co.uk/2017/08/59844e7e9d58c"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo"},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review"},{"@id":"https://rhiaro.co.uk/2017/08/598b55e4a96a6"},{"@id":"https://rhiaro.co.uk/2017/08/photos-uk"},{"@id":"https://rhiaro.co.uk/2017/08/598efd32d0fef"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-2"},{"@id":"https://rhiaro.co.uk/2017/08/diy-ldn"},{"@id":"https://rhiaro.co.uk/2017/08/599346c4ed1f5"},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review-2"},{"@id":"https://rhiaro.co.uk/2017/08/summer"},{"@id":"https://rhiaro.co.uk/2017/08/yak"},{"@id":"https://rhiaro.co.uk/2017/08/pizza-mousse"},{"@id":"https://rhiaro.co.uk/2017/08/duolingo"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-4"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-3"},{"@id":"https://rhiaro.co.uk/2017/08/59a31bc2a6143"},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review-3"},{"@id":"https://rhiaro.co.uk/2017/08/59a31d9187914"},{"@id":"https://rhiaro.co.uk/2017/08/59a31e68d8d2d"},{"@id":"https://rhiaro.co.uk/2017/08/59a31ee60d122"},{"@id":"https://rhiaro.co.uk/2017/08/59a31f5eb9f64"},{"@id":"https://rhiaro.co.uk/2017/08/59adba9882010"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-5"},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review-4"},{"@id":"https://rhiaro.co.uk/2017/08/59adbae9aaeab"},{"@id":"https://rhiaro.co.uk/2017/09/59adbb27b6cc5"},{"@id":"https://rhiaro.co.uk/2017/09/59adbb65e6aed"}],"as:items":[{"@id":"https://rhiaro.co.uk/2017/08/when-cut"},{"@id":"https://rhiaro.co.uk/2017/08/last-night"},{"@id":"https://rhiaro.co.uk/2017/08/59844e7e9d58c"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo"},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review"},{"@id":"https://rhiaro.co.uk/2017/08/598b55e4a96a6"},{"@id":"https://rhiaro.co.uk/2017/08/photos-uk"},{"@id":"https://rhiaro.co.uk/2017/08/598efd32d0fef"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-2"},{"@id":"https://rhiaro.co.uk/2017/08/diy-ldn"},{"@id":"https://rhiaro.co.uk/2017/08/599346c4ed1f5"},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review-2"},{"@id":"https://rhiaro.co.uk/2017/08/summer"},{"@id":"https://rhiaro.co.uk/2017/08/yak"},{"@id":"https://rhiaro.co.uk/2017/08/pizza-mousse"},{"@id":"https://rhiaro.co.uk/2017/08/duolingo"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-4"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-3"},{"@id":"https://rhiaro.co.uk/2017/08/59a31bc2a6143"},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review-3"},{"@id":"https://rhiaro.co.uk/2017/08/59a31d9187914"},{"@id":"https://rhiaro.co.uk/2017/08/59a31e68d8d2d"},{"@id":"https://rhiaro.co.uk/2017/08/59a31ee60d122"},{"@id":"https://rhiaro.co.uk/2017/08/59a31f5eb9f64"},{"@id":"https://rhiaro.co.uk/2017/08/59adba9882010"},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-5"},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review-4"},{"@id":"https://rhiaro.co.uk/2017/08/59adbae9aaeab"},{"@id":"https://rhiaro.co.uk/2017/09/59adbb27b6cc5"},{"@id":"https://rhiaro.co.uk/2017/09/59adbb65e6aed"}],"as:name":"Posts between 2017/08 and 2017/09","as:next":{"@id":"https://rhiaro.co.uk/2017/09/"},"as:partOf":{"@id":"https://rhiaro.co.uk/2017/08/"},"as:prev":{"@id":"https://rhiaro.co.uk/2017/07/"}},{"@id":"https://rhiaro.co.uk/2017/08/diy-ldn","@type":"as:Article","as:content":"Linked Data Notifications is a protocol to facilitate sharing and reuse of notifications between different Web applications. It's a W3C Recommendation from the Social Web Working Group, and part of a push to help people own their data and re-decentralise the Web, particularly the Social Web. You can read more about why you might want to care about this here.
\r\n\r\nFor this post, I'm going to jump straight into implementation. I've chosen PHP, without any frameworks, because if you already have a (local or remote) server it should be quick for you to get going with, without needing to set up or configure anything. The \"Linked Data\" in the name implies involvement of RDF; in fact LDN uses JSON-LD, but I don't presume any existing understanding of these things for this post, I'll just try to introduce the minimum that you need as we go along. (For a nice intro to JSON-LD see Manu's YouTube video JSON-LD Basics.) I am assuming though you have a basic understanding of JSON, and what HTTP Headers are.
\r\n\r\nLDN is a three part protocol. We expect front-end applications as well as servers to play the roles of senders and consumers of notifications. The third part is receiving. As the human in the mix, you need to tell the applications you use where to send notifications that are meant for you (or your software to pick up), as well as where applications can read them from (in order to display them back to you, or to process them and trigger other tasks to run). This 'where' is your Inbox. Applications might, for example, discover it from your homepage or a social media profile. You should host your Inobx somewhere you trust. Just like with email, some people might want to rent space from a provider, or maybe your workplace or school supplies one to you. At the moment the market for this is.. pretty small. This Web-data-owernship thing is in its early days.
\r\n\r\nSo for the pioneering developers among us, we can write our own, using around 50 lines of quick and dirty PHP.
\r\n\r\nFor convenience, we're going to set some variables for URL paths we will use regularly:
\r\n\r\n\r\n $base = \"https://\".$_SERVER['HTTP_HOST']; // Your domain\r\n $inboxpath = \"inbox\"; // The directory where your notification files are stored.\r\n\r\n\r\n
First, your script needs to accept HTTP POST
requests containing JSON-LD blobs. We get the data from the php://input
path. We also get the request headers. LDN receivers need to support as a bare minimum application/ld+json
payloads, so we'll send a 415
if the Content-Type
header doesn't match this. We're also going to check the payload parses as JSON since that's an easy way to throw out (with a 400 Bad Request
) invalid JSON-LD. If you have a JSON-LD parser handy, you can validate it against that too. I haven't included one here because.. quick and dirty.
Aside: If you do have an RDF parser around, you can accept other RDF serialisations like text/turtle
. If you do, you should advertise this with an Accept-Post
HTTP header on your Inbox. I use EasyRdf for all of my RDF stuff. If you don't want to include a library there are a few services with APIs you can call, like rdf-translator.
\r\n $input = file_get_contents('php://input');\r\n $headers = apache_request_headers();\r\n $data = json_decode($input, true);\r\n\r\n if(strpos($headers[\"Content-Type\"], \"application/ld+json\") === false){\r\n header(\"HTTP/1.1 415 Unsupported Media Type\");\r\n }elseif(!$data){\r\n header(\"HTTP/1.1 400 Bad Request\");\r\n echo \"Invalid payload.\";\r\n }else{\r\n\r\n // Write notification contents to a file \r\n\r\n }\r\n\r\n\r\n
The LDN specification says that even if you only accept JSON-LD serialized notifications, you should set the Accept-Post
header anyway. You can do this in PHP with header(\"Accept-Post: application/ld+json\");
or an .htaccess file with Header set Accept-Post \"application/ld+json\"
.
Once we've determined the payload contents are valid, we should store the notification. This is where you might want to do any or all of the following:
\r\n@type
, or other specific property-value (predicate-object) combinations.But for now, all we're going to do is dump the contents into a file, update the notification's @id
to point to the location we're storing it, and set the HTTP response headers:
\r\n // Write notification contents to a file \r\n\r\n $filename = $inboxpath.\"/\".date(\"ymd-His\").\"_\".uniqid().\".json\";\r\n $data[\"@id\"] = $base.\"/\".$filename;\r\n $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);\r\n\r\n $h = fopen(\"../\".$filename, 'w');\r\n fwrite($h, $json);\r\n fclose($h);\r\n\r\n header(\"HTTP/1.1 201 Created\");\r\n header(\"Location: \".$base.\"/\".$filename);\r\n\r\n\r\n
Aside: This implementation is super simplistic. The notification may come with an @id
already set, or even contain several distinct subjects, pointing to resources somewhere else on the Web. Checking that referenced resources makes the same statements as the notification you received could be good practice for verifying the truth of the notification contents. It may also be set to \"@id\": \"\"
, which is relative to request; it basically means 'this'. You don't need to add your own absolute @id
if it's already set; you can consider the URL at which you store the data as a graph URI, which contains statements about other things, but not about itself. Alternatively, you could wrap the notification data in @graph
and apply your own @id
on the top level.
Since we're storing the notifications as JSON files, you probably want to tell your server to return JSON files with Content-Type: application/ld+json
. You can do this by putting the following in a .htaccess file: AddType application/ld+json .json
.\r\n\r\n
In order to make your notifications reusable by other applications, you need to expose them to GET
requests. Specifically, your Inbox needs to return a blob of JSON-LD which points to a list of the URLs from which the individual notifications can be retrieved. You probably want to put this behind some kind of access control, so that only applications with which you have authenticated can read your notifications. I use IndieAuth as a service.
In this case, the URLs in the list are the files we stored the notification data in. The JSON-LD for an Inbox listing should look like:
\r\n\r\n\r\n {\r\n \"@context\": \"http://www.w3.org/ns/ldp#\",\r\n \"@id\": \"\",\r\n \"@type\": \"ldp:Container\",\r\n \"contains\": [\r\n {\r\n \"@id\": \"https://example.org/notification1\"\r\n },\r\n {\r\n \"@id\": \"https://example.org/notification2\"\r\n }\r\n ]\r\n}\r\n\r\n\r\n
The listing doesn't need to look identical to this, but it needs to be an equivalent JSON-LD representation. Since there are several ways of presenting the same thing in JSON-LD, you might find you use a serializer that outputs something slightly different. For example, you might see the contains part shortened to: \"contains\": [\"https://example.org/notification1\", \"https://example.org/notification2\"]
. You're also likely see the @context
appear differently, and prefixes for the properties (keys) might be used. The JSON-LD Playground is a good place to look at different possibilities.
Aside: The \"@type\": \"ldp:Container\"
is optional for LDN, but it helps other LDP clients understand that they might be able to use your data too.
You could store the Inbox listing in a flat file, and update it every time you receive (or delete) a notification. However, for this implementation we're going to generate it dynamically from the JSON files in our \"inbox\" directory. (You can take either approach if your notifications are stored in a database, too).
\r\n\r\n\r\n $files = scandir(\"../\".$inboxpath); \r\n $notifications = array();\r\n foreach($files as $file){\r\n if(!is_dir($file) && substr($file, -5) == \".json\"){\r\n $notifications[] = array(\"@id\" => $base.\"/\".$inboxpath.\"/\".$file);\r\n }\r\n }\r\n $inbox = array( \"@context\" => \"http://www.w3.org/ns/ldp#\"\r\n ,\"@id\" => \"\"\r\n ,\"@type\" => \"ldp:Container\"\r\n ,\"contains\" => $notifications\r\n );\r\n $inboxjson = json_encode($inbox, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);\r\n \r\n header(\"Content-Type: application/ld+json\");\r\n echo $inboxjson;\r\n\r\n\r\n
If you want to restrict access to your notifications, this is a good place to check the request against the authentication method of your choice (eg. a token in the Authentication
header, or a signature of some kind).
Now that's all done, you can put your script on a server and check it works with the LDN Receiver test suite. If it does, submit an implementation report!
\r\n\r\nIn order to be useful, you need to make your Inbox discoverable by sender and consumer applications. You can do this by modifying any resource on the Web which you control (like a blog post or your website homepage) to link to the Inbox with the ldp:inbox
relation. This can be with an HTTP header:
\r\n Link: <https://example.org/inbox.php>; rel=\"http://www.w3.org/ns/ldp#inbox\"\r\n\r\n \r\n
or RDF link, eg. JSON-LD:
\r\n\r\n\r\n {\r\n \"@context\": \"http://www.w3.org/ns/ldp\",\r\n \"@id\": \"https://example.org/profile\",\r\n \"inbox\": \"https://example.org/inbox.php\"\r\n }\r\n\r\n\r\n
eg. RDFa:
\r\n\r\n\r\n <link href=\"https://example.org/inbox.php\" rel=\"http://www.w3.org/ns/ldp#inbox\" />\r\n\r\n\r\n
And that's all there is to it! The complete script is available here, for your copy-pasting pleasure (Apache 2.0 licensed).
\r\n\r\nIf you don't fancy writing your own script to handle LDN receiving, there are few existing implementations you could self-host on your own server. Plus Linked Data Platform servers work out of the box as LDN receivers, so maybe you want to set one of those up.
","as:name":"DIY LDN Inbox","as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-13T17:03:00+02:00"},"as:tag":[{"@id":"https://rhiaro.co.uk/tags/hacking"},{"@id":"https://rhiaro.co.uk/tags/php"},{"@id":"https://rhiaro.co.uk/tags/tutorial"},{"@id":"https://rhiaro.co.uk/tags/linked+data+notifications"},{"@id":"https://rhiaro.co.uk/tags/ldn"},{"@id":"https://rhiaro.co.uk/tags/standards"}]},{"@id":"https://rhiaro.co.uk/2017/08/duolingo","@type":"as:Note","as:content":"Why does duolingo have High Valarian but not Bosanski?
","as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-15T21:54:00+02:00"},"as:tag":[{"@id":"https://rhiaro.co.uk/tags/language"},{"@id":"https://rhiaro.co.uk/tags/bosnian"}]},{"@id":"https://rhiaro.co.uk/2017/08/last-night","@type":"as:Note","as:content":"Last night, in a seamless blending of the current state of my professional and personal lives, I dreamt that Putin and Chief O'Brien held me hostage in a secret underground luxury hotel.
","as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-03T19:29:00+02:00"},"as:tag":[{"@id":"https://rhiaro.co.uk/tags/dream"},{"@id":"https://rhiaro.co.uk/tags/life"},{"@id":"https://rhiaro.co.uk/tags/star+trek"}]},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo","@type":"as:Add","as:content":"I left my window open today and a cat came in. She chased a fly, hung out, took a nap, left the way she came in. I call her Ishka because she as an independent woman who does what she wants.
","as:object":[{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_191422.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_191507.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_191601.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_191623.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_192312.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_192400.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_192413.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_192511.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_192519.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_192625.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_192630.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_192635.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_192718.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_192729.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_193121.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_193128.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_193305.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_193330.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_193338.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170804_193350.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-04T23:06:52+02:00"},"as:summary":"Amy added 20 photos to https://i.amy.gy/2017-sarajevo/","as:target":{"@id":"https://i.amy.gy/2017-sarajevo/"}},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-2","@type":"as:Add","as:content":"A hike to Skakavac waterfall (just north of Sarajevo). GPS trace. The good photos are by Edin.
","as:object":[{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_093325.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_094704.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_100813.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_101215.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_102213.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_102854.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_102857.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_102917_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_102924.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_102930_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_102940_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_103019_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_103025_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_103054_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_103342.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_103349_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_103612.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_103620_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_103632_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_103807_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_103814.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_103823.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_104708_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_104713_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_104747.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_104929.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_104938.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_105227_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_105234.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_105333.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_105624_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_105632_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_105803.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_110050_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_110658.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_111642_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_111657.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_111706.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_111852_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_111901.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_111909_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_112219.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_112228.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_112337_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_112345.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_112352_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_122025.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_122100_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_122414_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_122426_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_122543_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_122751.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_123406.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_123551.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_123644.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_123655.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_131328.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_131638.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_143612.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_145018.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_145051.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_145133.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_145212.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170812_145253.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-12T15:15:46+02:00"},"as:summary":"Amy added 64 photos to https://i.amy.gy/2017-sarajevo/","as:target":{"@id":"https://i.amy.gy/2017-sarajevo/"}},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-3","@type":"as:Add","as:content":"Road trip to Sutjeska valley, the site of one of the biggest battles of WWII, which now features a somewhat neglected but nonetheless impressive memorial sculpture. We took the scenic route, winding through the mountains, with a stop in Gorazde for lunch, and drove for about five hours.
\r\nAfter a swim in the 'lake', the more direct return journey took about an hour and a half, but also took us through some impressive sheer cliff faces and through tunnels bored into the mountains.
","as:object":[{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_125736.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_125756.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_125818.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_125832.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_131208.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_131217.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_133332.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_133337.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_133408.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_133455.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_134457.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_134501.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_141337.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_143328.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_160623.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_160818.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161031.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161229.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161233.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161236.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161423.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161429.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161434.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161436_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161447_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161508.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161540.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161555.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161643_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161710.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161713.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161718.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161745.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161810.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161914.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_161955.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_162032.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_164207.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_164519.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_164527.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_164530.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_164926.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_165901.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_165906.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_170005.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_170145.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_170330.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_170333.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_174717.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170819_174722.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-19T23:13:53+02:00"},"as:summary":"Amy added 50 photos to https://i.amy.gy/2017-sarajevo/","as:target":{"@id":"https://i.amy.gy/2017-sarajevo/"}},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-4","@type":"as:Add","as:content":"Film Festival; Karuzo food
","as:object":[{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170816_202736.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170816_203442.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170816_205413.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170816_205502.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170816_205523.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170817_205656.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170817_205719.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170817_205824.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-17T22:18:27+02:00"},"as:summary":"Amy added 8 photos to https://i.amy.gy/2017-sarajevo/","as:target":{"@id":"https://i.amy.gy/2017-sarajevo/"}},{"@id":"https://rhiaro.co.uk/2017/08/photos-sarajevo-5","@type":"as:Add","as:content":"Misc Sarajevo, Karuzo.
\r\nTrebevic during Eko-fest, hammock time with Boudicca and Renee.
\r\nSunset from the Yellow Fort.
","as:object":[{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170822_195423.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170822_195858.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170823_190546.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170823_190705.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170823_210139.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170823_223105.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_122833.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_122837.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123334.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123445.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123446.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123447.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123448.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123449.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123450.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123451.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123452.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123453.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123455.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123456.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123504.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_123509.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_124625.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_133159.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_133204.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_133206.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_133329.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_133332.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_133335.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_144501.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_144743.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_144850.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_144940.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_144943.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_151105.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_151106.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_172857.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_172900.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_173149.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_173153.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_174034.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_175024_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_184531.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_184532.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_184533.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_184533_1.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_184534.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190322.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190323.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190324.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190325.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190326.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190327.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190328.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190329.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190330.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190331.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190332.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190339.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_190825.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_191805.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_192513.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_192514.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_192515.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_192516.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_192517.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_195513.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_195514.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_195516.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_202348.jpg"},{"@id":"https://i.amy.gy/2017-sarajevo/IMG_20170826_210156.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-27T21:04:28+02:00"},"as:summary":"Amy added 71 photos to https://i.amy.gy/2017-sarajevo/","as:target":{"@id":"https://i.amy.gy/2017-sarajevo/"}},{"@id":"https://rhiaro.co.uk/2017/08/photos-uk","@type":"as:Add","as:content":"I went to the UK for a long weekend cos Dave and J were visiting from Tokyo. I flew in and out of Tuzla and Luton. The WizzAir minibus from Sarajevo to Tuzla takes about 2.5 hours and winds through the mountains. The train between Luton and King's Cross takes just under an hour. On the way out my flight was early and I ultimately gained 2 hours at KGX before my train to Newark. Time for Nando's. On my way back the flight was delayed 45 minutes, but the airport transfer waited and I got back to Sarajevo around 2.30am.
\r\nSunday: Dave and J went airsofting. J looks like an action hero. I went to Gram's and made lunch.
\r\nMonday: We went for a leisurely stroll around Woodhall Spa, and to the Kinema in the Woods.
\r\nTuesday: A day out in London. Lunch at Camden market, coffee in the Sky Garden, a walk along the river to Westminster and Buckingham Palace, and then I left them to fly back.
","as:object":[{"@id":"https://i.amy.gy/201708-uk/IMG_20170805_164053.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170805_164112.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170805_195749.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170805_195914.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170805_201342.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170805_213927.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170806_090659.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170806_090720.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170806_110429.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170806_121557.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170806_130701.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170806_195032.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170806_195929.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170806_200423.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170806_200427.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170806_200435.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170807_101015.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170807_101220.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170807_132225.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170807_135337.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170807_155533.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170807_163650.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170807_204546.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_102138.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_130126.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_130647.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_131753.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_131822.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_133245.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_133747.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_140842.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_142503.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_142521.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_142523.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_143718.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_144144.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_154124.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_154136.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_154143.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_154145.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_155512.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_224118.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_20170808_224127.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_7878.JPG"},{"@id":"https://i.amy.gy/201708-uk/IMG_7879.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_7880.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_7881.jpg"},{"@id":"https://i.amy.gy/201708-uk/IMG_7882.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-09T20:38:03+02:00"},"as:summary":"Amy added 48 photos to https://i.amy.gy/201708-uk/","as:target":{"@id":"https://i.amy.gy/201708-uk/"}},{"@id":"https://rhiaro.co.uk/2017/08/pizza-mousse","@type":"as:Add","as:content":"During today's Social Web WG call I made the best pizza I've ever made. It was helped by four kinds of vegan cheese, three of which were part of the new (to me) Tesco range. I stuffed the crust with Violife, and on top put chunks of Tesco blue cheese and chedder, and covered it liberally with grated mozzarella. Somewhere underneath were red onions, yellow bell pepper and courgette. The base sauce was chilli paste and tomato. The dough is a mix of spelt and wheat flour, and water.
\r\nLast week I made a cake, and recalled that I'd put leftover frosting in the back of my fridge in a cup. This is an unknown ratio (because who measure things) of date paste, coconut oil and cocoa, and it is a perfect chocolate mousse!
\r\nWhat a glorious evening.
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170815_195404.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170815_195411.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170815_195641.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170815_201109.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170815_202432.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170815_203532.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170815_203544.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-15T21:04:53+02:00"},"as:summary":"Amy added 7 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/08/summer","@type":"as:Note","as:content":"Summer in Sarajevo peaked yesterday, and now my coconut oil is back to being solid at room temperature.
","as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-13T23:35:00+02:00"},"as:tag":{"@id":"https://rhiaro.co.uk/tags/weather"}},{"@id":"https://rhiaro.co.uk/2017/08/week-in-review","@type":"as:Article","as:content":"When people lightly cut their hands on TV to drip blood onto something for like a pact or a ritual or for some dark magic thing, part of my mind was always slightly skeptical about the amount that just pours out. Having previously had no experience of hand-slicing, and comparing it to when I've cut my arms or legs on something, it seemed like you'd have to try harder to get that much free-flowing blood from a skin-deep cut.
\r\nAnyway I cut my finger making dinner this evening and it immediately generated more than enough to participate in any Klingon ritual you can think of. And it's so bright red!
\r\nI have never been queasy at the sight of blood before, but today I guess I was feeling generally off all day, and hadn't eaten much. After a few seconds of staring as it pooled up in my hand and thinking about TV hand-cutting rituals I almost blacked out. Anyway I'm fine now. Back to the pizza.
","as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-02T22:07:00+02:00"},"as:tag":{"@id":"https://rhiaro.co.uk/tags/life"}},{"@id":"https://rhiaro.co.uk/2017/08/yak","@type":"as:Note","as:content":"Current status:
\r\n\r\n \r\n \r\n
","as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-15T12:22:00+02:00"},"as:tag":{"@id":"https://rhiaro.co.uk/tags/hacking"}},{"@id":"https://rhiaro.co.uk/2017/09/59adbb27b6cc5","@type":"as:Add","as:content":"Pear and blackberry tart, made with gluten free flour and not quite enough coconut oil. The pastry was not flaky, but the fruit carried it. I ate one slice, and OCCRP wiped out the rest.
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170830_231652.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170830_232610.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170831_083351.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170831_083358.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170831_083645.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-31T09:00:18+02:00"},"as:summary":"Amy added 5 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}},{"@id":"https://rhiaro.co.uk/2017/09/59adbb65e6aed","@type":"as:Add","as:content":"I made spicy battered tofu for Elizabeth. Inspired by kung-pao style. The batter was equal parts gluten free flour, cornflour, and water; coated the tofu then deep fried in coconut oil for less than a minute. Turned out fantastic. The sauce is chillis, leek, garlic, ginger, carrots, peppers, peanuts and soya sauce. Spicy. Served with brown rice noodles, and blackberry lemonade.
","as:object":[{"@id":"https://i.amy.gy/madefood/IMG_20170831_203135.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170831_203139.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170831_205319.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170831_205330.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170831_211228.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170831_211236.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170831_211239.jpg"},{"@id":"https://i.amy.gy/madefood/IMG_20170831_211702.jpg"}],"as:published":{"@type":"http://www.w3.org/2001/XMLSchema#dateTime","@value":"2017-08-31T21:45:20+02:00"},"as:summary":"Amy added 8 photos to https://i.amy.gy/madefood/","as:target":{"@id":"https://i.amy.gy/madefood/"}}]}