diff --git a/0.21.0/examples/code/apply.function.n.times.json b/0.21.0/examples/code/apply.function.n.times.json
new file mode 100644
index 00000000..edc8f868
--- /dev/null
+++ b/0.21.0/examples/code/apply.function.n.times.json
@@ -0,0 +1 @@
+{"title":"Apply a given function N times","name":"Apply function N times","description":null,"source":"let R = require('ramda');\n\n// applyN :: (a -> a) -> Number -> (a -> a)\nconst applyN = R.compose(R.reduceRight(R.compose, R.identity), R.repeat);\n\napplyN(x => x * x, 4)(2); //=> 65536 (2 -> 4 -> 16 -> 256 -> 65536)\n\nconst isOdd = n => n % 2 == 1;\nconst collatz = n => isOdd(n) ? (3 * n + 1) : (n / 2);\n\napplyN(collatz, 5)(27);\n"}
diff --git a/0.21.0/examples/code/convert.list.to.object.json b/0.21.0/examples/code/convert.list.to.object.json
new file mode 100644
index 00000000..ae36b6cb
--- /dev/null
+++ b/0.21.0/examples/code/convert.list.to.object.json
@@ -0,0 +1 @@
+{"title":"Convert a list of property-lists (with header) into a list of objects","name":"Convert List to Object","description":null,"source":"let R = require('ramda');\n\nconst tsv = [\n ['name', 'age', 'drink'], \n ['john', 23, 'wine'], \n ['maggie', 45, 'water']\n];\nR.compose(R.apply(R.lift(R.zipObj)), R.splitAt(1))(tsv);\n"}
diff --git a/0.21.0/examples/code/convert.object.to.array.json b/0.21.0/examples/code/convert.object.to.array.json
new file mode 100644
index 00000000..aa643dec
--- /dev/null
+++ b/0.21.0/examples/code/convert.object.to.array.json
@@ -0,0 +1 @@
+{"title":"Convert object to array","name":"Convert object to array","description":null,"source":"let R = require('ramda');\n\n// convert :: {a} -> [{ word :: String, count :: a }]\nconst convert = R.compose(R.map(R.zipObj(['word', 'count'])), R.toPairs);\n\nconvert({I: 2, it: 4, that: 1});\n"}
diff --git a/0.21.0/examples/code/create.list.json b/0.21.0/examples/code/create.list.json
new file mode 100644
index 00000000..54bcb949
--- /dev/null
+++ b/0.21.0/examples/code/create.list.json
@@ -0,0 +1 @@
+{"title":"Create a list","name":"Create a list","description":"This snippet will create a new list with the specified values. Check out https://clojuredocs.org/clojure.core/list.","source":"let R = require('ramda');\n\n// list :: a... -> [a...]\nvar list = R.unapply(R.identity);\nlist(1, 2, 3);\n"}
diff --git a/0.21.0/examples/code/diff.objects.json b/0.21.0/examples/code/diff.objects.json
new file mode 100644
index 00000000..89e823b4
--- /dev/null
+++ b/0.21.0/examples/code/diff.objects.json
@@ -0,0 +1 @@
+{"title":"diffing objects","name":"Diff Objects","description":"similar to Guava's Maps Difference","source":"let R = require('ramda');\n\nvar groupObjBy = R.curry(R.pipe(\n // Call groupBy with the object as pairs, passing only the value to the key function\n R.useWith(R.groupBy, [R.useWith(__, [R.last]), R.toPairs]),\n R.map(R.fromPairs)\n))\n\nvar diffObjs = R.pipe(\n R.useWith(R.mergeWith(R.merge), [R.map(R.objOf(\"leftValue\")), R.map(R.objOf(\"rightValue\"))]),\n R.groupObjBy(R.cond([\n [\n R.both(R.has(\"leftValue\"), R.has(\"rightValue\")),\n R.pipe(R.values, R.ifElse(R.apply(equals), R.always(\"common\"), R.always(\"difference\")))\n ],\n [R.has(\"leftValue\"), R.always(\"onlyOnLeft\")],\n [R.has(\"rightValue\"), R.always(\"onlyOnRight\")],\n ])),\n R.evolve({\n common: R.map(R.prop(\"leftValue\")),\n onlyOnLeft: R.map(R.prop(\"leftValue\")),\n onlyOnRight: R.map(R.prop(\"rightValue\"))\n })\n);\n\ndiffObjs({a: 1, c: 5, d: 4 }, {a: 1, b: 2, d: 7});\n"}
diff --git a/0.21.0/examples/code/do.any.strings.appear.json b/0.21.0/examples/code/do.any.strings.appear.json
new file mode 100644
index 00000000..49fa9571
--- /dev/null
+++ b/0.21.0/examples/code/do.any.strings.appear.json
@@ -0,0 +1 @@
+{"title":"Do any of these strings appear in another list?","name":"Any Duplicate Strings","description":null,"source":"let R = require('ramda');\n// overlaps :: [a] -> [a] -> Boolean\nconst overlaps = R.pipe(R.intersection, R.complement(R.isEmpty));\nprocess.argv // ['node', 'script.js', '-v']\noverlaps(['-v', '--verbose'], process.argv)\n"}
diff --git a/0.21.0/examples/code/filter.using.keys.and.values.json b/0.21.0/examples/code/filter.using.keys.and.values.json
new file mode 100644
index 00000000..6657d85c
--- /dev/null
+++ b/0.21.0/examples/code/filter.using.keys.and.values.json
@@ -0,0 +1 @@
+{"title":"Filter an object using keys as well as values","name":"Filter w/ Keys & Vals","description":null,"source":"let R = require('ramda');\n\nconst filterWithKeys = (pred, obj) => R.pipe(\n R.toPairs, \n R.filter(R.apply(pred)), \n R.fromPairs\n)(obj);\n\nfilterWithKeys(\n (key, val) => key.length === val, \n {red: 3, blue: 5, green: 5, yellow: 2}\n);\n"}
diff --git a/0.21.0/examples/code/get.object.by.id.json b/0.21.0/examples/code/get.object.by.id.json
new file mode 100644
index 00000000..b6a326b3
--- /dev/null
+++ b/0.21.0/examples/code/get.object.by.id.json
@@ -0,0 +1 @@
+{"title":"Get object by id","name":"Get object by id","description":null,"source":"let R = require('ramda');\n\n// findById :: String -> Array -> Object\nconst findById = R.converge(\n R.find,\n [R.pipe(R.nthArg(0), R.propEq(\"id\")), R.nthArg(1)]\n);\n"}
diff --git a/0.21.0/examples/code/get.objects.methods.json b/0.21.0/examples/code/get.objects.methods.json
new file mode 100644
index 00000000..cc88e298
--- /dev/null
+++ b/0.21.0/examples/code/get.objects.methods.json
@@ -0,0 +1 @@
+{"title":"Get an object's method names","name":"Get method names","description":null,"source":"let R = require('ramda');\n\n// methodNames :: Object -> [String]\nvar methodNames = R.compose(R.keys, R.pickBy(R.is(Function)));\n\nvar obj = {\n foo: true,\n bar: function() {},\n baz: function() {},\n};\n\nmethodNames(obj);\n"}
diff --git a/0.21.0/examples/code/increment.with.step.json b/0.21.0/examples/code/increment.with.step.json
new file mode 100644
index 00000000..de519692
--- /dev/null
+++ b/0.21.0/examples/code/increment.with.step.json
@@ -0,0 +1 @@
+{"title":"Create an incrementing or decrementing range of numbers with a step","name":"Increment with step","description":null,"source":"let R = require('ramda');\n\nconst rangeStep = (start, step, stop) => R.map(\n n => start + step * n,\n R.range(0, (1 + (stop - start) / step) >>> 0)\n);\n\nconsole.log(rangeStep(1, 1, 4)); // [1, 2, 3, 4]\nconsole.log(rangeStep(2, 2, 8)); // [2, 4, 6, 8]\nconsole.log(rangeStep(0, 3, 10)); // [0, 3, 6, 9]\nconsole.log(rangeStep(3, -2, -3)); // [3, 1, -1, -3]\n"}
diff --git a/0.21.0/examples/code/make.objects.out.of.keys.json b/0.21.0/examples/code/make.objects.out.of.keys.json
new file mode 100644
index 00000000..331475a2
--- /dev/null
+++ b/0.21.0/examples/code/make.objects.out.of.keys.json
@@ -0,0 +1 @@
+{"title":"Make an object out of keys, with values derived from them","name":"Make object from keys","description":null,"source":"let R = require('ramda');\nlet fs = require('fs');\n\n// objFromKeys :: (String -> a) -> [String] -> {String: a}\nconst objFromKeys = R.curry((fn, keys) =>\n R.zipObj(keys, R.map(fn, keys)));\nconst files = ['diary.txt', 'shopping.txt'];\nobjFromKeys(fs.readFileSync, files);\n"}
diff --git a/0.21.0/examples/code/map.keys.of.object.json b/0.21.0/examples/code/map.keys.of.object.json
new file mode 100644
index 00000000..528cb1a6
--- /dev/null
+++ b/0.21.0/examples/code/map.keys.of.object.json
@@ -0,0 +1 @@
+{"title":"Map keys of an object","description":null,"source":"let R = require('ramda');\n\n// mapKeys :: (String -> String) -> Object -> Object\nconst mapKeys = R.curry((fn, obj) =>\n R.fromPairs(R.map(R.adjust(fn, 0), R.toPairs(obj))));\nmapKeys(R.toUpper, { a: 1, b: 2, c: 3 });\n"}
diff --git a/0.21.0/examples/code/map.keys.to.objects.json b/0.21.0/examples/code/map.keys.to.objects.json
new file mode 100644
index 00000000..cb55a10b
--- /dev/null
+++ b/0.21.0/examples/code/map.keys.to.objects.json
@@ -0,0 +1 @@
+{"title":"Map Keys To Objects","name":"Map keys to objects","description":null,"source":"let R = require('ramda');\n\nconst mapKeys = R.curry((fn, obj) =>\n R.fromPairs(R.map(R.adjust(fn, 0), R.toPairs(obj))));\n mapKeys(R.toUpper, { a: 1, b: 2, c: 3 });\n"}
diff --git a/0.21.0/examples/code/map.value.at.end.of.path.json b/0.21.0/examples/code/map.value.at.end.of.path.json
new file mode 100644
index 00000000..d84b42b1
--- /dev/null
+++ b/0.21.0/examples/code/map.value.at.end.of.path.json
@@ -0,0 +1 @@
+{"title":"Map over the value at the end of a path","name":"Map val at end of path","description":null,"source":"let R = require('ramda');\n\n// :: [String] -> (a -> b) -> {k: a} -> {k: b}\nconst mapPath = R.curry((path, f, obj) =>\n R.assocPath(path, f(R.path(path, obj)), obj)\n);\n\nmapPath(['a', 'b', 'c'], R.inc, {a: {b: {c: 3}}});\n"}
diff --git a/0.21.0/examples/code/mess.with.dom.json b/0.21.0/examples/code/mess.with.dom.json
new file mode 100644
index 00000000..0b6e7c9c
--- /dev/null
+++ b/0.21.0/examples/code/mess.with.dom.json
@@ -0,0 +1 @@
+{"title":"Mess with the DOM","name":"Mess with DOM","description":"This example shows how to set styles so that all paragraphs are red.","source":"let R = require('ramda');\n\n// Get all descendants that match selector\n// Note: NodeList is array-like so you can run ramda list functions on it.\n// cssQuery :: String -> Node -> NodeList\nvar cssQuery = R.invoker(1, 'querySelectorAll');\n\n// Mutate style properties on an element\n// setStyle :: String -> String -> Element -> Element\nvar setStyle = R.assoc('style');\n\n// Make all paragraphs and anchors red\nR.pipe(\n cssQuery('a, p'),\n R.map(setStyle('color', 'red'))\n)(document)\n"}
diff --git a/0.21.0/examples/code/n.function.calls.json b/0.21.0/examples/code/n.function.calls.json
new file mode 100644
index 00000000..300e769a
--- /dev/null
+++ b/0.21.0/examples/code/n.function.calls.json
@@ -0,0 +1 @@
+{"title":"Get n function calls as a list","name":"Get n function calls","description":null,"source":"let R = require('ramda');\n\nR.map(R.call, R.repeat(Math.random, 5));\n"}
diff --git a/0.21.0/examples/code/object.size.json b/0.21.0/examples/code/object.size.json
new file mode 100644
index 00000000..8f659aa1
--- /dev/null
+++ b/0.21.0/examples/code/object.size.json
@@ -0,0 +1 @@
+{"title":"Get Object Size","name":"Object Size","description":null,"source":"let R = require('ramda');\n\n// objSize :: Object -> Number\nconst objSize = R.nAry(1, R.pipe(\n R.when(R.is(Object), R.keys),\n R.when(R.is(Boolean), R.cond([[R.equals(false), R.always(null)], [R.T, R.always(1)]])),\n R.when(R.is(Number), R.toString),\n R.ifElse(R.isNil, R.always(0), R.length)\n));\nconsole.log(objSize()); // 0\nconsole.log(objSize(undefined)); // 0\nconsole.log(objSize(null)); // 0\nconsole.log(objSize(false)); // 0\nconsole.log(objSize(true)); // 1\nconsole.log(objSize('')); // 0\nconsole.log(objSize('foo')); // 3\nconsole.log(objSize(0)); // 1\nconsole.log(objSize(13)); // 2\nconsole.log(objSize(101)); // 3\nconsole.log(objSize(0.01)); // 4\nconsole.log(objSize({})); // 0\nconsole.log(objSize({foo:undefined, bar:undefined})); // 2\nconsole.log(objSize([])); // 0\nconsole.log(objSize([undefined, undefined])); // 2\n"}
diff --git a/0.21.0/examples/code/pick-list.json b/0.21.0/examples/code/pick-list.json
new file mode 100644
index 00000000..217f93b4
--- /dev/null
+++ b/0.21.0/examples/code/pick-list.json
@@ -0,0 +1 @@
+{"title":"Pick List Values by Index","name":"Pick List by Index","description":"This example shows you how to specify multiple indexes of an array to retrieve multiple values from the array.","source":"let R = require('ramda');\n\n// :: [Number] -> [a] -> [a]\nvar pickIndexes = R.compose(R.values, R.pickAll);\npickIndexes([0, 2], ['a', 'b', 'c']);\n"}
diff --git a/0.21.0/examples/code/r.props.deep.fields.json b/0.21.0/examples/code/r.props.deep.fields.json
new file mode 100644
index 00000000..d605c27a
--- /dev/null
+++ b/0.21.0/examples/code/r.props.deep.fields.json
@@ -0,0 +1 @@
+{"title":"Derivative of R.props for deep fields","name":"R.props for deep fields","description":null,"source":"let R = require('ramda');\n\nvar dotPath = R.useWith(R.path, R.split('.'));\nvar propsDotPath = R.useWith(R.ap, R.map(dotPath), R.of);\nvar obj = {\n a: { b: { c: 1 } },\n x: 2\n};\n\npropsDotPath(['a.b.c', 'x'], obj);\n"}
diff --git a/0.21.0/examples/code/ramda.fantasy.ajax.json b/0.21.0/examples/code/ramda.fantasy.ajax.json
new file mode 100644
index 00000000..37068fc1
--- /dev/null
+++ b/0.21.0/examples/code/ramda.fantasy.ajax.json
@@ -0,0 +1 @@
+{"title":"Use ramda-fantasy Future to wrap AJAX","name":"ramda-fantasy wrap AJAX","description":null,"source":"var Future = require('ramda-fantasy').Future;\n// Wrap ajax in a future\n// fetch :: String -> Future String\nvar fetch = function(url) {\n return new Future(function(rej, res) {\n var oReq = new XMLHttpRequest();\n oReq.addEventListener('load', res, false);\n oReq.addEventListener('error', rej, false);\n oReq.addEventListener('abort', rej, false);\n oReq.open('get', url, true);\n oReq.send();\n });\n};\n\n// Could use Either instead of Future but they work about the same.\n// parseJSON :: String -> Future Object\nvar parseJSON = function(str) {\n return new Future(function(rej, res) {\n try {\n res(JSON.parse(str));\n } catch (err) {\n rej({ error: 'json parse error' });\n }\n });\n};\n\n// We have\n// String -> Future String\n// And\n// String -> Future Object\n// So we can .chain() them together\nvar fetchJSON = fetch.chain(parseJSON);\n\n// Get the items out of it?\n// fetchItems :: Future Object -> Future []\nvar fetchItems = fetchJSON.map(R.prop('items'));\n\n// BTW at this point in the code the request still hasn't been sent\n\n// Filter the response?\n// Have to map first to get at the contents of the future then filter\n// fetchNewItems :: Future [Object] -> Future [Object]\nvar fetchNewItems = fetchItems.map(R.filter(R.prop('new')));\n\n// Just get the titles of the items\n// getNewTitles :: Future [Object] -> Future [String]\nvar getNewTitles = fetchNewItems.map(R.map('title'));\n\n// Finally do something\ngetNewTitles('/products.json').fork(console.error, console.log);\n// Now the AJAX req is sent and will log success or failure to console.\n\n// Bonus: Make one ajax request dependent on another\nfetchDependent = fetchJSON.map(R.prop('url')).chain(fetch);\nfetchDependent('urls.json').fork(console.error, console.log);\n"}
diff --git a/0.21.0/examples/code/rename.keys.of.object.json b/0.21.0/examples/code/rename.keys.of.object.json
new file mode 100644
index 00000000..7a986132
--- /dev/null
+++ b/0.21.0/examples/code/rename.keys.of.object.json
@@ -0,0 +1 @@
+{"title":"Rename keys of an object","name":"Rename keys","description":null,"source":"let R = require('ramda');\n\n/**\n* Creates a new object with the own properties of the provided object, but the\n* keys renamed according to the keysMap object as `{oldKey: newKey}`.\n* When some key is not found in the keysMap, then it's passed as-is.\n*\n* Keep in mind that in the case of keys conflict is behaviour undefined and\n* the result may vary between various JS engines!\n*\n* @sig {a: b} -> {a: *} -> {b: *}\n*/\nconst renameKeys = R.curry((keysMap, obj) => {\n return R.reduce((acc, key) => {\n acc[keysMap[key] || key] = obj[key];\n return acc;\n }, {}, R.keys(obj));\n});\n\nconst input = { firstName: 'Elisia', age: 22, type: 'human' }\n\nrenameKeys({ firstName: 'name', type: 'kind', foo: 'bar' })(input)\n"}
diff --git a/0.21.0/examples/code/set.properties.if.dont.exist.json b/0.21.0/examples/code/set.properties.if.dont.exist.json
new file mode 100644
index 00000000..217d0d2f
--- /dev/null
+++ b/0.21.0/examples/code/set.properties.if.dont.exist.json
@@ -0,0 +1 @@
+{"title":"Set properties only if they don't exist","name":"Set non-existent properties","description":"Useful for passing defaults, similar to lodash's _.defaults.","source":"let R = require('ramda');\n\n// defaults :: Object -> Object -> Object\nvar defaults = R.flip(R.merge);\n\n// process.env.SECRET overwrites deadbeef if it exists\ndefaults(process.env, {\n SECRET: 'deadbeef'\n});\n"}
diff --git a/0.21.0/examples/code/specific.order.json b/0.21.0/examples/code/specific.order.json
new file mode 100644
index 00000000..c38fb0cd
--- /dev/null
+++ b/0.21.0/examples/code/specific.order.json
@@ -0,0 +1 @@
+{"title":"Apply a list of functions in a specific order into a list of values","name":"Functions in order","description":null,"source":"let R = require('ramda');\n\nconst {red, green, blue} = require('chalk');\nconst disco = R.pipe(R.zipWith(R.call, [ red, green, blue ]), R.join(' '));\nconsole.log(disco([ 'foo', 'bar', 'xyz' ]));\n"}
diff --git a/0.21.0/examples/index.html b/0.21.0/examples/index.html
new file mode 100644
index 00000000..970f16f1
--- /dev/null
+++ b/0.21.0/examples/index.html
@@ -0,0 +1,97 @@
+
+
+
+
+
+ Ramda Cookbook
+
+
+
+
+
+
+
+