diff --git a/.couchapprc b/.couchapprc
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/.couchapprc
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..496ee2ca
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.DS_Store
\ No newline at end of file
diff --git a/app.js b/app.js
new file mode 100644
index 00000000..291a70c7
--- /dev/null
+++ b/app.js
@@ -0,0 +1,102 @@
+var couchapp = require('couchapp')
+ , path = require('path')
+ ;
+
+ddoc =
+ { _id:'_design/removalist'
+ , rewrites :
+ [ {from:"/", to:'pages/index.html'}
+ , {from:"csv", to:'_list/csv/all'}
+ , {from:"headers", to:'_list/urlencode/headers', query: {group: true}}
+ , {from:"/api", to:'../../'}
+ , {from:"/api/*", to:'../../*'}
+ , {from:"/*", to:'*'}
+ ]
+ }
+ ;
+
+ddoc.views = {
+ /**
+ * A simple map function mocking _all, but allows usage with lists etc.
+ */
+ all: {
+ map: function(doc) {
+ emit(doc.id, doc);
+ }
+ },
+ headers: {
+ map: function(doc) {
+ var keys = [];
+ for (var key in doc) {
+ emit(key, 1);
+ }
+ },
+ reduce: "_sum"
+ }
+};
+
+ddoc.lists = {
+ /**
+ * Generates a CSV from all the rows in the view.
+ *
+ * Takes in a url encoded array of headers as an argument. You can
+ * generate this by querying /_list/urlencode/headers. Pass it in
+ * as the headers get parameter, e.g.: ?headers=%5B%22_id%22%2C%22_rev%5D
+ *
+ * @author Max Ogden
+ */
+ csv: function(head, req) {
+ if ('headers' in req.query) {
+ var headers = JSON.parse(unescape(req.query.headers))[0];
+ var row, sep = '\n', headerSent = false, startedOutput = false;
+
+ start({"headers":{"Content-Type" : "text/csv; charset=utf-8"}});
+ send('"' + headers.join('","') + '"\n');
+ while (row = getRow()) {
+ for (var header in headers) {
+ if (row.value[headers[header]]) {
+ if (startedOutput) send(",");
+ var value = row.value[headers[header]];
+ if (typeof(value) == "object") value = JSON.stringify(value);
+ if (typeof(value) == "string") value = value.replace(/\"/g, '""');
+ send("\"" + value + "\"");
+ } else {
+ if (startedOutput) send(",");
+ }
+ startedOutput = true;
+ }
+ startedOutput = false;
+ send('\n');
+ }
+ } else {
+ send("You must pass in the urlencoded headers you wish to build the CSV from. Query /_list/urlencode/headers");
+ }
+ },
+ /**
+ * Returns the urlencoded version of the view's keys
+ *
+ * @author Max Ogden
+ */
+ urlencode: function(head, req) {
+ start({"headers":{"Content-Type" : "application/json"}});
+ if ('callback' in req.query) send(req.query['callback'] + "(");
+
+ var headers = [];
+ while (row = getRow()) {
+ headers.push(row.key);
+ }
+ send(escape(JSON.stringify(headers)));
+
+ if ('callback' in req.query) send(")");
+ }
+}
+
+ddoc.validate_doc_update = function (newDoc, oldDoc, userCtx) {
+ if (newDoc._deleted === true && userCtx.roles.indexOf('_admin') === -1) {
+ throw "Only admin can delete documents on this database.";
+ }
+};
+
+couchapp.loadAttachments(ddoc, path.join(__dirname, 'attachments'));
+
+module.exports = ddoc;
\ No newline at end of file
diff --git a/_attachments/images/bg_gradient.gif b/attachments/images/bg_gradient.gif
similarity index 100%
rename from _attachments/images/bg_gradient.gif
rename to attachments/images/bg_gradient.gif
diff --git a/_attachments/images/css3buttons_backgrounds.png b/attachments/images/css3buttons_backgrounds.png
similarity index 100%
rename from _attachments/images/css3buttons_backgrounds.png
rename to attachments/images/css3buttons_backgrounds.png
diff --git a/_attachments/images/css3buttons_icons.png b/attachments/images/css3buttons_icons.png
similarity index 100%
rename from _attachments/images/css3buttons_icons.png
rename to attachments/images/css3buttons_icons.png
diff --git a/_attachments/images/loader-blue.gif b/attachments/images/loader-blue.gif
similarity index 100%
rename from _attachments/images/loader-blue.gif
rename to attachments/images/loader-blue.gif
diff --git a/_attachments/images/loader.gif b/attachments/images/loader.gif
similarity index 100%
rename from _attachments/images/loader.gif
rename to attachments/images/loader.gif
diff --git a/_attachments/pages/index.html b/attachments/pages/index.html
similarity index 100%
rename from _attachments/pages/index.html
rename to attachments/pages/index.html
diff --git a/_attachments/script/jquery-1.5.min.js b/attachments/script/jquery-1.5.min.js
similarity index 100%
rename from _attachments/script/jquery-1.5.min.js
rename to attachments/script/jquery-1.5.min.js
diff --git a/_attachments/script/jquery.mustache.js b/attachments/script/jquery.mustache.js
similarity index 100%
rename from _attachments/script/jquery.mustache.js
rename to attachments/script/jquery.mustache.js
diff --git a/_attachments/style/css3buttons.css b/attachments/style/css3buttons.css
similarity index 100%
rename from _attachments/style/css3buttons.css
rename to attachments/style/css3buttons.css
diff --git a/_attachments/style/demo.css b/attachments/style/demo.css
similarity index 100%
rename from _attachments/style/demo.css
rename to attachments/style/demo.css
diff --git a/_attachments/style/reset.css b/attachments/style/reset.css
similarity index 100%
rename from _attachments/style/reset.css
rename to attachments/style/reset.css
diff --git a/lists/csv.js b/lists/csv.js
deleted file mode 100644
index e3d99df5..00000000
--- a/lists/csv.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Generates a CSV from all the rows in the view.
- *
- * Takes in a url encoded array of headers as an argument. You can
- * generate this by querying /_list/urlencode/headers. Pass it in
- * as the headers get parameter, e.g.: ?headers=%5B%22_id%22%2C%22_rev%5D
- *
- * @author Max Ogden
- */
-function(head, req) {
- if ('headers' in req.query) {
- var headers = JSON.parse(unescape(req.query.headers))[0];
- var row, sep = '\n', headerSent = false, startedOutput = false;
-
- start({"headers":{"Content-Type" : "text/csv; charset=utf-8"}});
- send('"' + headers.join('","') + '"\n');
- while (row = getRow()) {
- for (var header in headers) {
- if (row.value[headers[header]]) {
- if (startedOutput) send(",");
- var value = row.value[headers[header]];
- if (typeof(value) == "object") value = JSON.stringify(value);
- send("\"" + value.replace(/\"/g, '""') + "\"");
- } else {
- if (startedOutput) send(",");
- }
- startedOutput = true;
- }
- startedOutput = false;
- send('\n');
- }
- } else {
- send("You must pass in the urlencoded headers you wish to build the CSV from. Query /_list/urlencode/headers");
- }
-};
diff --git a/lists/json.js b/lists/json.js
deleted file mode 100644
index 26416681..00000000
--- a/lists/json.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Generates a simple array of json objects representing each doc in the db
- * @author Max Ogden
- */
- function(head, req) {
- var row, out, sep = '\n';
-
- start({"headers":{"Content-Type" : "application/json"}});
-
- if ('callback' in req.query) send(req.query['callback'] + "(");
-
- send('[');
- while (row = getRow()) {
- for (var header in row.value) {
- if (row.value[header]) {
- var value = row.value[header];
- if (typeof(value) == "object") {
- row.value[header] = "\"" + JSON.stringify(value) + "\"";
- }
- }
- }
- send(sep + JSON.stringify(row.value));
- sep = ',\n';
- }
- send("]");
- if ('callback' in req.query) send(")");
-
- };
\ No newline at end of file
diff --git a/lists/refine.js b/lists/refine.js
deleted file mode 100644
index b9293456..00000000
--- a/lists/refine.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Generates a simple array of json objects representing each doc in the db
- * @author Max Ogden
- */
- function(head, req) {
- var row, out, sep = '\n';
-
- start({"headers":{"Content-Type" : "application/json"}});
-
- if ('callback' in req.query) send(req.query['callback'] + "(");
-
- send('{');
- while ((row = getRow())) {
- for (var header in row.value) {
- if (row.value[header]) {
- var value = row.value[header];
- if (typeof(value) == "object") {
- row.value[header] = "\"" + JSON.stringify(value) + "\"";
- }
- }
- }
- send(sep + '"":' + JSON.stringify(row.value));
- sep = ',\n';
- }
- send("]");
- if ('callback' in req.query) send(")");
-
- };
\ No newline at end of file
diff --git a/lists/urlencode.js b/lists/urlencode.js
deleted file mode 100644
index 908a4a15..00000000
--- a/lists/urlencode.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Returns the urlencoded version of the view value
- *
- * @author Max Ogden
- */
-function(head, req) {
- // Send the same Content-Type as CouchDB would
- if (req.headers.Accept.indexOf('application/json')!=-1)
- start({"headers":{"Content-Type" : "application/json"}});
- else
- start({"headers":{"Content-Type" : "text/plain"}});
-
- if ('callback' in req.query) send(req.query['callback'] + "(");
-
- var rows = []
- while (row = getRow()) {
- rows.push(row.value)
- }
- send(escape(JSON.stringify(rows)));
-
- if ('callback' in req.query) send(")");
-};
diff --git a/readme.md b/readme.md
index 73357123..06505450 100644
--- a/readme.md
+++ b/readme.md
@@ -25,6 +25,4 @@ After you install it, visit this link to open Removalist:
You'll have to get yourself a couch. The easiest way is from [the instructions on this page](http://couchone.com/get). Once it's going, open up `http://YOURCOUCH/_utils` and create a new database to store your data.
-You can either replicate the couchapp from my couch [max.couchone.com/apps/_design/removalist](http://max.couchone.com/apps/_design/removalist) (quickest option) or, if you want to hack on the removalist source code first, you'll need to install the [CouchApp command line utility](http://couchapp.org/page/installing) and check out this repo.
-
-If you want to hack on removalist, once you have the couchapp utility working, git clone this repo and go into this folder and execute couchapp init. To upload removalist into your couch just run couchapp push http://YOURCOUCH/DATABASENAME. Otherwise see the Quick install section above.
\ No newline at end of file
+You can either replicate the couchapp from my couch [max.couchone.com/apps/_design/removalist](http://max.couchone.com/apps/_design/removalist) (quickest option) or, if you want to hack on the removalist source code first, you'll need to install `mikeal/node.couchapp.js` and clone this repo.
\ No newline at end of file
diff --git a/rewrites.json b/rewrites.json
deleted file mode 100644
index 69c2b60d..00000000
--- a/rewrites.json
+++ /dev/null
@@ -1,50 +0,0 @@
-[
- {
- "to": "style/*",
- "from": "style/*"
- },
- {
- "to": "script/*",
- "from": "script/*"
- },
- {
- "to": "pages/*",
- "from": "pages/*"
- },
- {
- "to": "images/*",
- "from": "images/*"
- },
- {
- "to": "pages/index.html",
- "from": ""
- },
- {
- "to": "_list/csv/all",
- "from": "csv"
- },
- {
- "to": "_list/urlencode/headers",
- "from": "headers"
- },
- {
- "to": "./",
- "from": "ddoc"
- },
- {
- "to": "./",
- "from": "api/_design/ddoc"
- },
- {
- "to": "./*",
- "from": "api/_design/ddoc/*"
- },
- {
- "to": "../../",
- "from": "api"
- },
- {
- "to": "../../*",
- "from": "api/*"
- }
-]
\ No newline at end of file
diff --git a/views/all/map.js b/views/all/map.js
deleted file mode 100644
index 81ba003b..00000000
--- a/views/all/map.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * A simple map function mocking _all, but allows usage with lists etc.
- *
- */
-function(doc) {
- emit(doc.id, doc);
-}
diff --git a/views/headers/map.js b/views/headers/map.js
deleted file mode 100644
index fb17672f..00000000
--- a/views/headers/map.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * Returns an array of all of the keys in the document.
- *
- * @author Max Ogden
- */
-function(doc) {
- var keys = [];
- for (var key in doc) {
- keys.push(key);
- }
- emit(doc, keys);
-}
diff --git a/views/headers/reduce.js b/views/headers/reduce.js
deleted file mode 100644
index 17e4e5df..00000000
--- a/views/headers/reduce.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Reduces the passed in view headers to a list of unique object key attributes
- *
- * @author Max Ogden
- */
-function(keys, values, rereduce) {
-
- function include(arr, obj) {
- return (arr.indexOf(obj) != -1);
- }
-
- var headers = [];
- for (var doc in values) {
- for (var header in values[doc]) {
- if(!include(headers, values[doc][header])) {
- headers.push(values[doc][header]);
- }
- }
- }
-
- return headers;
-}
\ No newline at end of file