diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..95b863a40eaf1fbc5aafabdba635e1f7e3601fa8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+config.json
+node_modules
diff --git a/README.md b/README.md
index e9c900df92dff5c2acc34e9f10fa2e99b8e66e51..15dc114d9d303e37dc5ac046ff4c53a5c54620fe 100644
--- a/README.md
+++ b/README.md
@@ -4,3 +4,21 @@ Slash command to record completed tasks as WordPress posts
 
 ## Prerequisites:
 * A WordPress site running version 4.6+ and the JSON Basic Authentication plugin
+* nginx or another proxy to front the app
+
+## Install:
+
+1. `npm install`
+2. Copy `config-sample.json` to `config.json` and update to your needs
+3. `npm start`
+
+## Usage:
+
+1. Make a POST request to `/log` with a POST body that contains the item to record
+
+For example:
+
+```
+curl -X "POST" "http://localhost:9001/log" \
+     -d "I wrote a a thing!"
+```
diff --git a/index.js b/index.js
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..815ac03afd8b556697796dc266d4529bcc26a603 100644
--- a/index.js
+++ b/index.js
@@ -0,0 +1,68 @@
+"use strict";
+
+// Dependencies
+var express    = require( 'express' );
+var bodyParser = require( 'body-parser' );
+var WPAPI      = require( 'wpapi' );
+var striptags  = require( 'striptags' );
+
+var app = express();
+app.use( bodyParser.text() );
+app.use( bodyParser.urlencoded( { extended: true } ) );
+
+// Config
+var config = require( './config.json' );
+
+var wp = new WPAPI( {
+	endpoint: config.wp_endpoint,
+	username: config.wp_username,
+	password: config.wp_password
+} );
+
+// Landing page for status checks
+app.get( '/', function( req, res ) {
+	res.sendStatus( 200 );
+} );
+
+// Parse POST body to create WP post
+app.post( '/log', function( req, res ) {
+	// Don't bother if there's nothing to record
+	if ( 'undefined' === typeof req.body || ! req.body.length ) {
+		return res.sendStatus( 400 );
+	}
+
+	// Massage the title
+	var title = req.body;
+	title = striptags( title, [] );
+
+	if ( title.length > 30 ) {
+		title = 'Did: ' + title.slice( 0, 29 );
+		title += '…';
+	} else {
+		title = 'Did: ' + title;
+	}
+
+	// Decorate the content
+	var content = req.body;
+	content = striptags( content, [ 'a', 'code', 'strong', 'em' ] );
+	content = '<blockquote>' + content + "</blockquote>\n\n#slash-done";
+
+	// Create the post
+	wp.posts().create( {
+		title:   title,
+		content: content,
+		status:  'publish'
+	} ).then( function( resp ) {
+		var response = {
+			"response_type": "ephemeral",
+			"text": "Entry recorded (" + resp.id + ")\n" + resp.title.rendered + "\n\n" + resp.link
+		};
+
+		res.send( response);
+	} );
+} );
+
+//tells Node which port to listen on
+app.listen( config.node_port, config.node_listener, function() {
+	console.log( 'slash-done running on', config.node_listener, 'and port', config.node_port );
+} );
diff --git a/package.json b/package.json
index 675a62acd68c8cf850ba1c9430fa634075c9d3cb..0ce3279b07e63ac1173451eb7422c5ccdc06fb2b 100644
--- a/package.json
+++ b/package.json
@@ -4,10 +4,10 @@
   "description": "Slash command to record completed tasks as WordPress posts",
   "main": "index.js",
   "dependencies": {
-    "body-parser": "*",
     "express": "*",
-    "request": "*",
-    "wpapi": "*"
+    "body-parser": "*",
+    "wpapi": "*",
+    "striptags": "*"
   },
   "devDependencies": {},
   "scripts": {
@@ -19,6 +19,6 @@
     "url": "git+https://ethitter@git.ethitter.com/open-source/slash-done.git"
   },
   "author": "ethitter",
-  "license": "GPLv2",
+  "license": "GPL-2.0+",
   "homepage": "https://git.ethitter.com/open-source/slash-done"
 }