You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ctakes.apache.org by jo...@apache.org on 2023/06/07 15:48:35 UTC

[ctakes-website] 01/01: first commit

This is an automated email from the ASF dual-hosted git repository.

johnsd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ctakes-website.git

commit b08712dd4d6af02b165e9960e192cc206a4810d1
Author: Johnsd11 <34...@users.noreply.github.com>
AuthorDate: Wed Jun 7 11:48:24 2023 -0400

    first commit
---
 .gitignore                                         |   1 +
 .idea/.gitignore                                   |   3 +
 .idea/jpa-buddy.xml                                |   6 +
 .idea/misc.xml                                     |   9 +
 .idea/modules.xml                                  |   8 +
 .idea/monkeysnatchbanana.com.iml                   |   9 +
 .idea/vcs.xml                                      |   6 +
 Gemfile                                            |   5 +
 Gemfile.lock                                       |  14 +
 README.md                                          |   1 +
 _site/README.md                                    |   1 +
 _site/archetypes/default.md                        |   9 +
 _site/config.toml                                  |  59 ++
 _site/content/intro.md                             |  23 +
 .../post/adventures-in-documentation-building.md   |  23 +
 _site/content/post/adventures-in-pthreading.md     |  10 +
 _site/content/post/an-acceptable-tool.md           |  21 +
 _site/content/post/code-management-wishlist.md     | 156 +++++
 .../content/post/codemeshio-how-did-i-get-here.md  |  51 ++
 .../post/deconstructing-a-pony-echo-server.md      | 229 ++++++++
 .../post/faking-a-https-client-for-glass.md        |  79 +++
 _site/content/post/inside-the-pony-tcp-stack.md    | 644 +++++++++++++++++++++
 _site/content/post/interview-exchange.md           |  10 +
 _site/content/post/interview-with-lobste-rs.md     |  12 +
 _site/content/post/learning-from-ada.md            |  20 +
 .../post/nyc-python-scale-agnostic-python.md       |  16 +
 _site/content/post/of-debt-and-decisions.md        |  32 +
 _site/content/post/of-me-and-be.md                 |  13 +
 _site/content/post/on-becoming-a-better-teacher.md |  40 ++
 _site/content/post/pony-patterns-waiting.md        |  86 +++
 _site/content/post/qcon-how-did-i-get-here.md      |  51 ++
 _site/content/post/qcon-ny-17-pony.md              |  31 +
 _site/content/post/redline-the-journey-so-far.md   |  10 +
 .../post/reverse-proxying-to-seaside-with-nginx.md | 156 +++++
 _site/content/post/role-not-title.md               |  10 +
 ...tting-up-a-monticello-repository-using-nginx.md | 130 +++++
 _site/content/post/sidestepping-technical-debt.md  |  10 +
 .../post/storm-applied-behind-the-scenes.md        |  33 ++
 .../post/using-fastcgi-with-nginx-and-seaside.md   | 119 ++++
 _site/content/post/varnish-in-five-acts.md         | 393 +++++++++++++
 _site/content/post/why-pony-polyconf-17.md         |  13 +
 _site/content/post/why-pony.md                     |  39 ++
 _site/static/CNAME                                 |   1 +
 _site/static/img/avatar.png                        | Bin 0 -> 7654 bytes
 _site/static/img/ctakes_logo.jpg                   | Bin 0 -> 14182 bytes
 _site/static/img/logo.png                          | Bin 0 -> 7654 bytes
 .../img/post/interview-with-lobste-rs/IMG_3648.jpg | Bin 0 -> 601320 bytes
 .../Definition-of-web-scale-from-Storm-Applied.png | Bin 0 -> 84195 bytes
 .../Screenshot-2016-01-18-16-51-54.png             | Bin 0 -> 13457 bytes
 .../storm-applied.jpg                              | Bin 0 -> 48600 bytes
 .../img/post/varnish-in-five-acts/before-after.png | Bin 0 -> 187353 bytes
 .../varnish-all-the-things.jpg                     | Bin 0 -> 77466 bytes
 .../img/post/varnish-in-five-acts/varnish-flow.png | Bin 0 -> 38570 bytes
 _site/themes/sean-steam/CHANGELOG.md               |  15 +
 _site/themes/sean-steam/LICENSE.md                 |  22 +
 _site/themes/sean-steam/README.md                  |  76 +++
 _site/themes/sean-steam/archetypes/default.md      |   4 +
 _site/themes/sean-steam/exampleSite/config.toml    |  45 ++
 .../themes/sean-steam/exampleSite/content/about.md |  20 +
 .../exampleSite/content/post/goisforlovers.md      | 343 +++++++++++
 .../exampleSite/content/post/hugoisforlovers.md    |  88 +++
 _site/themes/sean-steam/images/screenshot.png      | Bin 0 -> 77960 bytes
 _site/themes/sean-steam/images/tn.png              | Bin 0 -> 35771 bytes
 _site/themes/sean-steam/layouts/404.html           |   7 +
 _site/themes/sean-steam/layouts/index.html         |  10 +
 .../themes/sean-steam/layouts/partials/author.html |   6 +
 .../themes/sean-steam/layouts/partials/footer.html |   7 +
 _site/themes/sean-steam/layouts/partials/head.html |  40 ++
 .../themes/sean-steam/layouts/partials/header.html |   6 +
 _site/themes/sean-steam/layouts/partials/js.html   |  19 +
 .../sean-steam/layouts/partials/navigation.html    |  11 +
 .../sean-steam/layouts/partials/pagination.html    |  13 +
 .../themes/sean-steam/layouts/partials/share.html  |  16 +
 .../themes/sean-steam/layouts/partials/social.html |  29 +
 .../layouts/partials/themes/blue-theme.html        |   8 +
 .../layouts/partials/themes/custom-theme.html      |   8 +
 .../layouts/partials/themes/green-theme.html       |   8 +
 .../layouts/partials/themes/orange-theme.html      |   8 +
 .../layouts/partials/themes/red-theme.html         |   8 +
 _site/themes/sean-steam/static/css/github.css      | 127 ++++
 _site/themes/sean-steam/static/css/screen.css      | 521 +++++++++++++++++
 _site/themes/sean-steam/static/favicon.ico         | Bin 0 -> 1150 bytes
 _site/themes/sean-steam/static/fonts/icons.eot     | Bin 0 -> 2252 bytes
 _site/themes/sean-steam/static/fonts/icons.svg     |  41 ++
 _site/themes/sean-steam/static/fonts/icons.ttf     | Bin 0 -> 2096 bytes
 _site/themes/sean-steam/static/fonts/icons.woff    | Bin 0 -> 2656 bytes
 .../sean-steam/static/img/appletouchicon.png       | Bin 0 -> 7351 bytes
 _site/themes/sean-steam/static/img/avatar.jpg      | Bin 0 -> 4359 bytes
 _site/themes/sean-steam/static/img/favicon.ico     | Bin 0 -> 1150 bytes
 _site/themes/sean-steam/static/js/index.js         |  18 +
 .../sean-steam/static/js/smooth-scroll.min.js      |   2 +
 _site/themes/sean-steam/theme.toml                 |  24 +
 archetypes/default.md                              |   9 +
 config.toml                                        |  59 ++
 content/intro.md                                   |  23 +
 .../post/adventures-in-documentation-building.md   |  23 +
 content/post/adventures-in-pthreading.md           |  10 +
 content/post/an-acceptable-tool.md                 |  21 +
 content/post/code-management-wishlist.md           | 156 +++++
 content/post/codemeshio-how-did-i-get-here.md      |  51 ++
 content/post/deconstructing-a-pony-echo-server.md  | 229 ++++++++
 content/post/faking-a-https-client-for-glass.md    |  79 +++
 content/post/inside-the-pony-tcp-stack.md          | 644 +++++++++++++++++++++
 content/post/interview-exchange.md                 |  10 +
 content/post/interview-with-lobste-rs.md           |  12 +
 content/post/learning-from-ada.md                  |  20 +
 content/post/nyc-python-scale-agnostic-python.md   |  16 +
 content/post/of-debt-and-decisions.md              |  32 +
 content/post/of-me-and-be.md                       |  13 +
 content/post/on-becoming-a-better-teacher.md       |  40 ++
 content/post/pony-patterns-waiting.md              |  86 +++
 content/post/qcon-how-did-i-get-here.md            |  51 ++
 content/post/qcon-ny-17-pony.md                    |  31 +
 content/post/redline-the-journey-so-far.md         |  10 +
 .../post/reverse-proxying-to-seaside-with-nginx.md | 156 +++++
 content/post/role-not-title.md                     |  10 +
 ...tting-up-a-monticello-repository-using-nginx.md | 130 +++++
 content/post/sidestepping-technical-debt.md        |  10 +
 content/post/storm-applied-behind-the-scenes.md    |  33 ++
 .../post/using-fastcgi-with-nginx-and-seaside.md   | 119 ++++
 content/post/varnish-in-five-acts.md               | 393 +++++++++++++
 content/post/why-pony-polyconf-17.md               |  13 +
 content/post/why-pony.md                           |  39 ++
 static/CNAME                                       |   1 +
 static/img/avatar.png                              | Bin 0 -> 7654 bytes
 static/img/ctakes_logo.jpg                         | Bin 0 -> 14182 bytes
 static/img/logo.png                                | Bin 0 -> 7654 bytes
 .../img/post/interview-with-lobste-rs/IMG_3648.jpg | Bin 0 -> 601320 bytes
 .../Definition-of-web-scale-from-Storm-Applied.png | Bin 0 -> 84195 bytes
 .../Screenshot-2016-01-18-16-51-54.png             | Bin 0 -> 13457 bytes
 .../storm-applied.jpg                              | Bin 0 -> 48600 bytes
 .../img/post/varnish-in-five-acts/before-after.png | Bin 0 -> 187353 bytes
 .../varnish-all-the-things.jpg                     | Bin 0 -> 77466 bytes
 .../img/post/varnish-in-five-acts/varnish-flow.png | Bin 0 -> 38570 bytes
 themes/sean-steam/CHANGELOG.md                     |  15 +
 themes/sean-steam/LICENSE.md                       |  22 +
 themes/sean-steam/README.md                        |  76 +++
 themes/sean-steam/archetypes/default.md            |   4 +
 themes/sean-steam/exampleSite/.gitignore           |   2 +
 themes/sean-steam/exampleSite/config.toml          |  45 ++
 themes/sean-steam/exampleSite/content/about.md     |  20 +
 .../exampleSite/content/post/goisforlovers.md      | 343 +++++++++++
 .../exampleSite/content/post/hugoisforlovers.md    |  88 +++
 themes/sean-steam/exampleSite/static/.gitkeep      |   0
 themes/sean-steam/images/screenshot.png            | Bin 0 -> 77960 bytes
 themes/sean-steam/images/tn.png                    | Bin 0 -> 35771 bytes
 themes/sean-steam/layouts/404.html                 |   7 +
 themes/sean-steam/layouts/_default/baseof.html     |  13 +
 themes/sean-steam/layouts/_default/list.html       |   7 +
 themes/sean-steam/layouts/_default/single.html     |  35 ++
 themes/sean-steam/layouts/_default/summary.html    |  14 +
 themes/sean-steam/layouts/_default/terms.html      |  11 +
 themes/sean-steam/layouts/index.html               |  10 +
 themes/sean-steam/layouts/partials/author.html     |   6 +
 themes/sean-steam/layouts/partials/footer.html     |   7 +
 themes/sean-steam/layouts/partials/head.html       |  40 ++
 themes/sean-steam/layouts/partials/header.html     |   6 +
 themes/sean-steam/layouts/partials/js.html         |  19 +
 themes/sean-steam/layouts/partials/navigation.html |  11 +
 themes/sean-steam/layouts/partials/pagination.html |  13 +
 themes/sean-steam/layouts/partials/share.html      |  16 +
 themes/sean-steam/layouts/partials/social.html     |  29 +
 .../layouts/partials/themes/blue-theme.html        |   8 +
 .../layouts/partials/themes/custom-theme.html      |   8 +
 .../layouts/partials/themes/green-theme.html       |   8 +
 .../layouts/partials/themes/orange-theme.html      |   8 +
 .../layouts/partials/themes/red-theme.html         |   8 +
 themes/sean-steam/static/css/github.css            | 127 ++++
 themes/sean-steam/static/css/screen.css            | 521 +++++++++++++++++
 themes/sean-steam/static/favicon.ico               | Bin 0 -> 1150 bytes
 themes/sean-steam/static/fonts/icons.eot           | Bin 0 -> 2252 bytes
 themes/sean-steam/static/fonts/icons.svg           |  41 ++
 themes/sean-steam/static/fonts/icons.ttf           | Bin 0 -> 2096 bytes
 themes/sean-steam/static/fonts/icons.woff          | Bin 0 -> 2656 bytes
 themes/sean-steam/static/img/appletouchicon.png    | Bin 0 -> 7351 bytes
 themes/sean-steam/static/img/avatar.jpg            | Bin 0 -> 4359 bytes
 themes/sean-steam/static/img/favicon.ico           | Bin 0 -> 1150 bytes
 themes/sean-steam/static/js/index.js               |  18 +
 themes/sean-steam/static/js/smooth-scroll.min.js   |   2 +
 themes/sean-steam/theme.toml                       |  24 +
 180 files changed, 8303 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a48cf0d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+public
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/jpa-buddy.xml b/.idea/jpa-buddy.xml
new file mode 100644
index 0000000..966d5f5
--- /dev/null
+++ b/.idea/jpa-buddy.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JpaBuddyIdeaProjectConfig">
+    <option name="renamerInitialized" value="true" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..d79bd4e
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="jpab" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c5c9677
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/monkeysnatchbanana.com.iml" filepath="$PROJECT_DIR$/.idea/monkeysnatchbanana.com.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/monkeysnatchbanana.com.iml b/.idea/monkeysnatchbanana.com.iml
new file mode 100644
index 0000000..d6ebd48
--- /dev/null
+++ b/.idea/monkeysnatchbanana.com.iml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..d2403f1
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+# gem "rails"
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..7cf5dbd
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,14 @@
+GEM
+  remote: https://rubygems.org/
+  source "https://rubygems.org"
+  specs:
+
+PLATFORMS
+  x64-mingw-ucrt
+
+DEPENDENCIES
+gem "jekyll"
+gem "jekyll-paginate"
+
+BUNDLED WITH
+   2.4.13
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..39cd0bc
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+Move along...
diff --git a/_site/README.md b/_site/README.md
new file mode 100644
index 0000000..39cd0bc
--- /dev/null
+++ b/_site/README.md
@@ -0,0 +1 @@
+Move along...
diff --git a/_site/archetypes/default.md b/_site/archetypes/default.md
new file mode 100644
index 0000000..f90fe3b
--- /dev/null
+++ b/_site/archetypes/default.md
@@ -0,0 +1,9 @@
++++
+draft = true
+slug = "post-url-name"
+author = "Sean T. Allen"
+tags = [
+    "tag 1",
+    "tag 2",
+]
++++
diff --git a/_site/config.toml b/_site/config.toml
new file mode 100644
index 0000000..e1061ff
--- /dev/null
+++ b/_site/config.toml
@@ -0,0 +1,59 @@
+baseurl = "https://www.monkeysnatchbanana.com"
+languageCode = "en-us"
+title = "Apache cTAKES Website"
+theme = "sean-steam"
+# Enable Google Analytics be inserting your tracking code
+# Number of posts per page
+paginate = 5
+
+[permalinks]
+  post = "/:year/:month/:day/:title/"
+
+[params]
+  title = "Apache cTAKES Website"
+  copyright = ""
+
+  # You can choose between green, orange, red and blue.
+  themecolor = "blue"
+
+  # Link custom assets relative to /static
+  favicon   = "favicon.ico"
+  customCSS = []
+  customJS  = []
+
+  # To provide some metadata for search engines and the about section in the footer
+  # feel free to add a few information about you and your website.
+  name = "Sean T Allen"
+  bio = "Co-author of [Storm Applied: Strategies for real-time event processing](http://manning.com/sallen/?a_aid=sallen)"
+  description = ""
+
+  # Link your social networks (optional)
+  location = ""
+  twitter = ""
+  linkedin = ""
+  googleplus = ""
+  facebook = ""
+  instagram = ""
+  github = ""
+  gitlab = ""
+  bitbucket = ""
+
+  # Customize or translate the strings
+  keepReadingStr = "READ THIS ARTICLE"
+  backtotopStr = "Back to top"
+  shareStr = "Share"
+  pageNotFoundTitle = "404 - Page not found"
+  useSummaryIfNoDescription = true
+
+[[menu.main]]
+    name = "Introduction"
+    weight = -110
+    url = "/about/"
+[[menu.main]]
+    name = "Wikipedia"
+    weight = -100
+    url = "http://manning.com/sallen/?a_aid=sallen"
+[[menu.main]]
+    name = "Downloads"
+    weight = -90
+    url = "/index.xml"
diff --git a/_site/content/intro.md b/_site/content/intro.md
new file mode 100644
index 0000000..9d03b2c
--- /dev/null
+++ b/_site/content/intro.md
@@ -0,0 +1,23 @@
++++
+title = "Introduction"
++++
+
+The Apache™ clinical Text Analysis and Knowledge Extraction System (cTAKES™) focuses on extracting knowledge from clinical text through Natural Language Processing (NLP) techniques.
+
+cTAKES is engineered in a modular fashion and employs leading-edge rule-based and machine learning methods.
+
+cTAKES has standard features for biomedical text processing software, including the ability to extract concepts such as symptoms, procedures, diagnoses, medications and anatomy with attributes and standard codes.
+
+More powerful components can perform tasks as complex as identifying temporal events, dates and times – resulting in placement of events in a patient timeline.
+
+Components are trained on gold standards from the biomedical as well as the general domain. This affords usability across different types of clinical narrative (e.g. radiology reports, clinical notes, discharge summaries) in various institution formats as well as other types of health-related narrative (e.g. twitter feeds), using multiple data standards (e.g. Health Level 7 (HL7), Clinical Document Architecture (CDA), Fast Healthcare Interoperability Resources (FHIR), SNOMED-CT, RxNORM).
+
+cTAKES is the NLP platform for many initiatives across the world covering a variety of research purposes and large datasets. Contributors include professionals at medical and commercial institutions, NLP and Machine Learning researchers, Medical Doctors, and students of many disciplines and levels. We encourage people from all backgrounds to get involved! (link)
+
+---
+
+### Elsewhere...
+
+* [Email](mailto:dennis.johns@childrens.harvard.edu)
+* [GitHub](https://github.com/apache/ctakes)
+
diff --git a/_site/content/post/adventures-in-documentation-building.md b/_site/content/post/adventures-in-documentation-building.md
new file mode 100644
index 0000000..0cb61c8
--- /dev/null
+++ b/_site/content/post/adventures-in-documentation-building.md
@@ -0,0 +1,23 @@
++++
+draft = true
+date = "2017-02-18T09:22:51-05:00"
+title = "Adventures in Documentation Building"
+tags = ["tag 1","tag 2"]
+author = "Sean T. Allen"
+slug = "adventures-in-documentation-building"
+
++++
+
+Does your project use [TravisCI](https://travis-ci.org)? Create it's documentation using [Mkdocs](http://www.mkdocs.org)? Awesome. Let me show you how to 
+
+```
+after_success:
+  - if [[ $TRAVIS_BRANCH == 'master' && $TRAVIS_PULL_REQUEST == 'false' ]]; then
+      git remote add gh-token "https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}";
+      git fetch gh-token && git fetch gh-token gh-pages:gh-pages;
+      build/release/ponyc packages/stdlib --docs;
+      cd stdlib-docs;
+      sudo -H pip install mkdocs;
+      mkdocs gh-deploy -v --clean --remote-name gh-token;
+    fi;
+```
diff --git a/_site/content/post/adventures-in-pthreading.md b/_site/content/post/adventures-in-pthreading.md
new file mode 100644
index 0000000..fa9eeca
--- /dev/null
+++ b/_site/content/post/adventures-in-pthreading.md
@@ -0,0 +1,10 @@
++++
+slug = "post-url-name"
+draft = true
+date = "2017-02-18T09:29:19-05:00"
+title = "adventures in pthreading"
+tags = ["tag 1","tag 2"]
+author = "Sean T. Allen"
+
++++
+
diff --git a/_site/content/post/an-acceptable-tool.md b/_site/content/post/an-acceptable-tool.md
new file mode 100644
index 0000000..530b4bc
--- /dev/null
+++ b/_site/content/post/an-acceptable-tool.md
@@ -0,0 +1,21 @@
++++
+title = "An Acceptable Tool"
+tags = ["software architecture"]
+author = "Sean T. Allen"
+slug = "an-acceptable-tool"
+draft = false
+date = "2015-02-24T11:31:27-05:00"
+
++++
+
+Imagine for a moment that you are on a small development team tasked with core operations at a moderate sized startup. You're responsible for the development, operations and maintenance of various production systems. Your day is filled with all the fun of programming combined with the joys of running a distributed system. You've just entered a room with the rest of your teammates to discuss what tools you'll be using to build your latest system. 
+
+You're fairly far along in the process; down to an Erlang based solution and a JVM based one. The Erlang solution is very alluring. Erlang's OTP library handles a ton of concerns for you that you will otherwise have to handle yourself with the JVM solution. Erlang is "the right tool for the job". However, you are going in to the room to argue for the JVM solution. Why? Because you don't need the right tool, you just need "an acceptable tool".
+
+You don't run any Erlang based systems in production. You have no experience with monitoring Erlang, collecting metrics or all the other things that go into running a stable system. The JVM on the other hand, you have tons of experience with. You and your team mates are proficient at tuning the garbage collector to minimize latency. You have extensive Java profiling experiencing. You have battle tested metrics collecting and other libraries that you've been running in production without issue. 
+
+The JVM might not be the right tool, but it isn't the wrong one either. It's acceptable. It will get the job done and most importantly you know how to get the job done with it. Operational knowledge is hard won. Far harder to win than understanding the syntax and semantics of a new programming language. 
+
+In the first few weeks after your new project is released into production, you'll be thankful you picked the merely acceptable tool because you spend less time learning how to fight the inevitable fires and more time sleeping peacefully at night.
+
+What's the difference between the right tool and an acceptable one? It's a matter of context and costs. Every tool comes with a cost that varies based on the context in which it's used. In a production environment, operational experience should factor heavily into that cost analysis. Picking an acceptable tool is hard. It requires research and understanding. Its easy to fall into the trap of thinking you are picking an acceptable tool when really you're just picking the tool at hand.
diff --git a/_site/content/post/code-management-wishlist.md b/_site/content/post/code-management-wishlist.md
new file mode 100644
index 0000000..0369f4a
--- /dev/null
+++ b/_site/content/post/code-management-wishlist.md
@@ -0,0 +1,156 @@
++++
+title = "Things I'd like in my code management tool"
+author = "Sean T. Allen"
+slug = "code-management-wishlist"
+draft = false
+date = "2018-12-26T13:31:27-05:00"
++++
+This morning, I was reading a [blog post from Joe Armstrong](https://joearms.github.io/#2018-12-26%20Fun%20with%20the%20TiddlyWiki)  about how he got a [Chandler](https://en.wikipedia.org/wiki/Chandler_(software)) like [Triage system](https://en.wikipedia.org/wiki/Triage) working in [Tiddly-Wiki](https://tiddlywiki.com/). A Triage system is one of the things I'd like to see GitHub add. That got me thinking, what are some of the other things I'd like to see in a GitHub. What follows is fa [...]
+
+Most of what is on this list is in the area of "project management"; after all, code management is more than just about managing the code. It's about managing the project around the code.
+
+## Multi-level issues
+
+Most tools at best give me two levels. There's a project, and there are issues. Only having two levels can be hard to work with if you are interested in organizing work in a way that leads to better ["ambient awareness"](https://en.wikipedia.org/wiki/Ambient_awareness) of what is going on in a project. Having only two levels also makes a lot of the other "project management" features I mention later less attractive as well.
+
+Ideally what I want is to start from something like "We are going to do X" and then break X down into issues and perhaps those issues into other issues.
+
+At any time, I want to be able to look at any level and understand what is going on. Be it at the top level of the project or at any individual issue which might itself be a collection of issues.
+
+Image an issue for example that is made up of 3 other issues. Each of those issues is assigned to different team members. When I look at my higher-level issue, I can see that 3 people are working on it. I can see there are 3 sub-issues that I can drill into. 
+
+## Triage system
+    
+You can fake this with tags in something like GitHub, but it's a pain. For every issue, I want to be able to say it is for "now, later, or done." An issue can move from any state to any other state. See [https://en.wikipedia.org/wiki/Triage](https://en.wikipedia.org/wiki/Triage) for more information.
+
+When something is marked as "later," I should be prompted in the future to reconsider it. "You said later for X, is it later yet? Should that become a now?"
+    
+## "Threaded" comments
+
+ A popular GitHub issue is about as useful as a really popular IRC channel. Eventually, it devolves into several different conversations related to a general topic at once. It becomes increasingly hard to follow different threads of conversation. "Threading" is far from perfect but it's better than the "all in one long vertical bucket" that most tools supply.
+        
+## Dependencies between issues
+
+Some tasks can't be started until others are finished. I want to be able to see and visualize this easily.
+
+## Dependencies for issues
+
+Sometimes some dependencies are outside the issue system itself. For example, only Alice is qualified to do this work at this time. We need Alice to be available. Alternatively, even, "either Alice or Bob could do this"
+
+## Estimation of issues
+
+Really, there are two styles of estimation that I'd like my tools to support. 
+
+### High-level estimation
+I want to be able to give quick, high-level estimates of things. For example- tiny, small, medium, large, huge that are a quick "we think it will take handwave amount of time." These are useful for getting a really rough idea of the amount of effort something would involve.
+
+### Fine-grained estimation
+
+I want to be able to apply estimates to that switch from a handwave amount of time to a granular estimate that is measured in days (it would be nice because some tasks are small to be able to measure in hours as well, but in the end, I could do without this).
+
+## Attach "risk" to issues
+
+Sometimes when we estimate an issue, we know with high certainty that our estimate is right. Other times, we know there's a great deal of possible variation. 
+
+I address this by asking everyone to give a best case, worst case, and most likely case estimate for work. The wider the range between those estimates, the more risk there is and the less confidence we can have that the work won't end up derailing our project. Capturing this information on issues is valuable.
+
+## Burndown charts
+
+I want burndown charts that take into account dependencies and estimations. Burndown charts are a powerful way of visualizing if a project is on track or behind. 
+
+In a burndown chart, I want to be able to run simulations as well. "What happens to this project if X work falls behind. What happens if Bob gets sick?"
+
+You can do all the math yourself, but it's a hell of a lot nicer to have a computer do it for you (even if it can't account for nuance that you as a human can)
+
+## Cumulative Flow Charts
+
+I don't use them often, but they can be convenient from time to time for being able to visualize problems that might be ready to arise easily.
+
+See [https://kanbantool.com/cumulative-flow-diagram](https://kanbantool.com/cumulative-flow-diagram) to learn more if you aren't familiar with them.
+
+## Milestones 
+
+I want milestones that are made up of various issues which will then be explicitly represented in burndown charts. I want a tool that can do the math I currently have to do to determine if something is "on track" or not. 
+
+## Time tracking
+
+Estimating is hard. We get it wrong all the time. However, we can't get it right if we aren't reflective on it. One way to do that is to record our original estimates for tasks and then record how much work we did on the item. Seeing that we thought something would take 8 hours of work but we spent 24 is incredibly valuable. We can revisit our assumptions we made when estimating see where we got it wrong. Then, we can try and account for it next time. Yes, estimating is hard but its also [...]
+
+## Ability to re-estimate
+
+Look, sometimes we get those estimates wrong. Leaving the original estimate in place doesn't help. Then our dependencies and burndown charts are going to be wrong. I want the ability to change an estimate from 1 day to 10 days, and if work has already started, I want to be able to get access to earlier estimates and have the new estimate accounted for when determining if things are "on track", that means the new estimate should be reflected in milestones and burndown charts and every oth [...]
+
+## Estimate groups
+
+Look, let's face it. If you have 3 different people and a single issue, it's quite likely that the amount of time it will take to complete that issue will vary based on who is doing it; sometimes it will vary greatly. 
+
+You need to capture that information. It's essential for planning if it will take Alice 2 days to do something but 10 if Bob does it.
+
+Estimation groups go back to an idea I expressed in "dependencies for issues." Sometimes, you have a limited number of people who can conceivably work on a particular problem.
+
+## Due dates for "everything"
+
+It's nice to be able to look at a thing and know "oh, this has to be done by Thursday for us to stay on track." 
+
+## Kanban style board that is tied to changes in issue status
+
+I want to be able to move things through a lifecycle that is displayed in a visual kanban style without doing a lot of manual moving of issues from one column to another.
+
+## Issue status that is tied to Kanban style board
+
+If I move an issue into an "in-progress" column in a board, that change should be reflected on the issue as well.
+
+## Tie issues to "external" documents and vice-versa
+
+When I estimate larger projects, I invariably end up working collaboratively with others in a GoogleDoc to come up with a project plan. A ton of information is captured in that doc:
+
+- timelines
+- dependencies
+- assumptions
+- in-depth detail
+
+A lot of that information can be captured in other items I've put on my wishlist here, however, capturing the original information and tying it to the project is essential. I want to have a bidirectional link from a project and its issues to supporting documentation (there could be multiple documents). 
+
+I want to be able to both edit those documents offline and in a collaborative fashion online.
+
+I want to be able to comment on specific aspects of those docs as well and carry conversations in those comments.
+
+## "Configurable" kanban board definition
+
+Kanban boards are a great way to visualize things, but if I have to add everything to a board manually, it gets old fast. One of the great things about kanban boards is that they provide a visualization of information for a specific context. However, that context can vary. 
+
+The ability to derive boards from a central pool of information would be great. In addition to "more traditional" boards, I might want to see on a per assignee basis, by estimate or god knows what. 
+
+Even if I have only 1 board, not having to set everything up by hand would a godsend.
+
+## Confidential "issues"
+
+Some information shouldn't be made public. Perhaps it contains information about a security flaw or confidential information for a specific group that we are working it.
+
+## Integrated "CI"
+
+I love that GitHub has an API that allows me to hook up to tools like TravisCI, CircleCI, Code Climate, and what-not but, in the end, what I want is the ability to run arbitrary code at any point in a life cycle. That might be event-driven like, "on pull request, run these tasks," or it might be time-based "run fault injection tests daily with 50 random interleavings". Either way, I want that to be fully integrated into my "code management" tool. 
+
+In the end, this is far more than just "CI." I want to be able to run "my code in my environment" on demand based on lifecycle events. Further, "my environment" probably means something more like "my containers" because I don't want to manage the infrastructure for all this.
+
+[GitHub actions](https://github.com/features/actions) look intriguing and like a step in this direction. Perhaps they give me everything I would want but, I haven't played with them yet, so ¯\_(ツ)_/¯.
+
+## File storage
+
+I want to be able to store files of all sorts with my project — for example, dependencies like specific versions of a compiler. Alternatively, perhaps created artifacts and what not.
+
+## Ability to "clone" everything
+
+It's fantastic that tools like GitHub and Gitlab allow me to clone the code and work with it offline, but I want to be able to clone everything. Issues, project boards, wikis, everything! 
+
+## Conclusion
+
+Welp, that's where I got to with this morning's list. Now that I'm here, I realize there's a ton more for me dig into. For example, when I was putting this list together, I realized that I  need to do one that  is "what I want in an integrated CI system." There's a ton to dig into in just that topic. Moreover, there are a variety of others as well. For example, I gave zero thought to code review and that unto itself is yet another massive area. 
+
+I think I'm going to start making lists for different areas like code management, code review, integrated CI and what not and slowly build up my list of "what I want in my code management tool" for real. I feel happy with this as a first pass.
+
+Looking around, even though I'm a heavy [GitHub user](https://github.com/seantallen/), it looks like [Gitlab is the currently tool that would most likely end up fulfilling my desires](https://about.gitlab.com/features/). 
+
+Got thoughts on things you'd like to see in a "GitHub like" tool? I'd love to hear them. Feel free to ping me on [Twitter](https://twitter.com/seantallen).
+
+
diff --git a/_site/content/post/codemeshio-how-did-i-get-here.md b/_site/content/post/codemeshio-how-did-i-get-here.md
new file mode 100644
index 0000000..b30ddea
--- /dev/null
+++ b/_site/content/post/codemeshio-how-did-i-get-here.md
@@ -0,0 +1,51 @@
++++
+draft = false
+date = "2016-11-22T09:56:56-05:00"
+title = "CodeMeshIO: How Did I Get Here?"
+tags = ["talks","testing", "distributed systems", "stream processing", "video", "slides"]
+description = "Post with link my CodeMesh.io talk \"How Did I Get Here? Building Confidence in a Distributed Stream Processor\" and associated content."
+author = "Sean T. Allen"
+slug = "codemeshio-how-did-i-get-here"
++++
+
+## Building Confidence in a Distributed Stream Processor
+
+Video of my CodeMeshIO talk: ["How Did I Get Here? Building Confidence in a Distributed Stream Processor"](https://www.youtube.com/watch?v=6MsPDtpe2tg&index=3&list=PLWbHc_FXPo2hGJHXhpgqDU-P4BArpCdh6) is now available. 
+
+---
+
+There's a number of links at the end of the talk for additional material you can check out. To make life easier on everyone I'm recreating it here.
+
+### Peter Alvaro
+
+* [Peter Alvaro's twitter](https://twitter.com/palvaro)
+* [Lineage-driven Fault Injection](http://www.cs.berkeley.edu/~palvaro/molly.pdf)
+* [Outwards from the Middle of the Maze](https://www.youtube.com/watch?v=ggCffvKEJmQ)
+
+### Kyle Kingsbury
+
+* [Kyle Kingsbury's twitter](https://twitter.com/aphyr)
+* [Jepsen](https://aphyr.com/tags/Jepsen)
+
+### Will Wilson
+
+* [Testing Distributed Systems w/ Deterministic Simulation](https://www.youtube.com/watch?v=4fFDFbi3toc)
+
+### Catie McCaffrey
+
+* [Catie McCaffrey's twitter](https://twitter.com/caitie)
+* [The Verification of a Distributed System:
+A practitioner's guide to increasing confidence in system correctness](http://queue.acm.org/detail.cfm?ref=rss&id=2889274)
+* [The Verification of a Distributed System](https://www.infoq.com/presentations/distributed-systems-verification)
+
+### Inés Sombra
+
+* [Inés Sombra twitter](https://twitter.com/randommood)
+* [Testing in a Distributed World](https://www.youtube.com/watch?v=KSdNYi55kjg)
+
+### Chaos Engineering
+
+* [Principles of Chaos Engineering](http://principlesofchaos.org)
+
+---
+If you are interested, I've made the [slides available on Speakerdeck](https://speakerdeck.com/seantallen/how-did-i-get-here-building-confidence-in-a-distributed-stream-processor-1). Like most of my talks, the slides aren't particularly good at standing on their own without the talk itself.
diff --git a/_site/content/post/deconstructing-a-pony-echo-server.md b/_site/content/post/deconstructing-a-pony-echo-server.md
new file mode 100644
index 0000000..71d9e6b
--- /dev/null
+++ b/_site/content/post/deconstructing-a-pony-echo-server.md
@@ -0,0 +1,229 @@
++++
+tags = ["pony"]
+author = "Sean T. Allen"
+date = "2015-12-13T10:56:41-05:00"
+title = "Deconstructing a Pony echo server"
+slug = "deconstructing-a-pony-echo-server"
+draft = false
++++
+
+Lately I've been diving into learning [Pony](http://ponylang.org) in a more organized fashion. As part of that, I've decided to share the experience along the way. If you aren't familiar with Pony then you probably won't get much from this post. If you are interested in a high performance, safe, actor based programming language, then I'd suggest you check out the [Pony tutorial](http://tutorial.ponylang.org) then venture back. All that said, I'll do my best to provide links to relevant P [...]
+
+This morning's exercise was to write an echo server and see what bits of Pony I'd learn along the way. What follows is the complete original source code for my Pony echo server and then some discussion of what I learned as I was writing it.
+
+If you want to get started writing any network services with Pony, I'd suggest by started by reading the ["net" example](https://github.com/ponylang/ponyc/tree/master/examples/net). My echo server borrows heavily from the example code. My basic process was to steal bits from the example code until I had a working echo server and then set about figuring out how it all actually worked. 
+
+Hopefully, you find this useful. I'm going to start by dropping all the code on you at once, don't worry about absorbing it all. We'll walk through the important parts together. Without further ado, _echo.pony_: 
+
+```
+use "net"
+
+actor Main
+  new create(env: Env) =>
+    TCPListener.ip4(recover Listener(env) end)
+
+class Listener is TCPListenNotify
+  let _env: Env
+  var _host: String = ""
+  var _service: String = ""
+
+  new create(env: Env) =>
+    _env = env
+
+  fun ref listening(listen: TCPListener ref) =>
+    try
+      (_host, _service) = listen.local_address().name()
+      _env.out.print("listening on " + _host + ":" + _service)
+    else
+      _env.out.print("couldn't get local address")
+      listen.close()
+    end
+
+  fun ref not_listening(listen: TCPListener ref) =>
+    _env.out.print("couldn't listen")
+    listen.close()
+
+  fun ref connected(listen: TCPListener ref) : TCPConnectionNotify iso^ =>
+    Server(_env)
+
+class Server is TCPConnectionNotify
+  let _env: Env
+
+  new iso create(env: Env) =>
+    _env = env
+
+  fun ref accepted(conn: TCPConnection ref) =>
+    _env.out.print("connection accepted")
+
+  fun ref received(conn: TCPConnection ref, data: Array[U8] iso) =>
+    _env.out.print("data received, looping it back")
+    conn.write("server says: ")
+    conn.write(consume data)
+
+  fun ref closed(conn: TCPConnection ref) =>
+    _env.out.print("server closed")
+```
+
+First important thing to note is that none of this will work without some classes from the [Pony standard networking library](https://github.com/ponylang/ponyc/tree/master/packages/net). We include those classes we might need with the _use_ expression:
+
+```
+use "net"
+```
+
+Every Pony program has a _Main_ actor that acts as its entry point. You can get more details about special significance of _Main_ in the ["hello-world" section of the Pony tutorial](http://tutorial.ponylang.org/getting-started/hello-world.html).
+
+Let's take a look at our echo server's _Main_ actor:
+
+```
+actor Main
+  new create(env: Env) =>
+    TCPListener.ip4(recover Listener(env) end)
+```
+
+There's quite a bit going on here for a newbie to absorb. It took me a while with the examples and the standard library to understand how to get started with network programming in Pony. Let's unpack the important bits.
+
+```
+01: TCPListener.ip4(
+02:   recover
+03:     Listener(env)
+04:   end
+05: )
+```
+
+We start by creating a TCPListener that only handles ip version 4. _TCPListener_ is an actor [defined in the standard library](https://github.com/ponylang/ponyc/blob/master/packages/net/tcplistener.pony). To create an ipv4 TCPListener, we have to provide one thing: a class that implements [_TCPListenNotify_](https://github.com/ponylang/ponyc/blob/master/packages/net/tcpnotify.pony#L61). That object will be notified by the TCPListener actor we are creating anytime a new connection comes in. 
+
+Here's our _Listener_ from the echo server:
+
+```
+class Listener is TCPListenNotify
+  let _env: Env
+  var _host: String = ""
+  var _service: String = ""
+
+  new create(env: Env) =>
+    _env = env
+
+  fun ref listening(listen: TCPListener ref) =>
+    try
+      (_host, _service) = listen.local_address().name()
+      _env.out.print("listening on " + _host + ":" + _service)
+    else
+      _env.out.print("couldn't get local address")
+      listen.close()
+    end
+
+  fun ref not_listening(listen: TCPListener ref) =>
+    _env.out.print("couldn't listen")
+    listen.close()
+
+  fun ref connected(listen: TCPListener ref) : TCPConnectionNotify iso^ =>
+    Server(_env)
+```
+
+Basically, you can sum up what it does by saying:
+
+* When it starts up, it prints out the host and port it's listening on
+* When a new connection is established, it creates a new instance of _Server_ to handle the incoming connection
+
+Our Server class implements the [_TCPConnectionNotify_ interface](https://github.com/ponylang/ponyc/blob/master/packages/net/tcpnotify.pony#L1) as required by _TCPListenNotify_.
+
+```
+class Server is TCPConnectionNotify
+  let _env: Env
+
+  new iso create(env: Env) =>
+    _env = env
+
+  fun ref accepted(conn: TCPConnection ref) =>
+    _env.out.print("connection accepted")
+
+  fun ref received(conn: TCPConnection ref, data: Array[U8] iso) =>
+    _env.out.print("data received, looping it back")
+    conn.write("server says: ")
+    conn.write(consume data)
+
+  fun ref closed(conn: TCPConnection ref) =>
+    _env.out.print("server closed")
+``` 
+
+We can sum up what _Server_ is doing with:
+
+* Outputs a message to standard out any time it accepts a connection.
+* When it receives data, it sends it back to the sender with an additional _"server says: "_ message.
+
+There's one interesting bit of Pony in our Server class:
+
+```
+  fun ref received(conn: TCPConnection ref, data: Array[U8] iso) =>
+    _env.out.print("data received, looping it back")
+    conn.write("server says: ")
+    conn.write(consume data)
+```
+
+What's up with that _consume data_ that is being passed to _conn.write_? It's part of [Pony's reference capabilities](http://tutorial.ponylang.org/capabilities/reference-capabilities.html). Reference capabilities are one of Pony's killer features. As programmers, we can mark data with different capabilities allowing us, with the support of the compiler, to safely use shared mutable state. If you aren't familiar with Pony's reference capabilities, I suggest you [review them](http://tutori [...]
+
+Right now, the two capabilities that we care about are _isolated_ and _value_. They are defined in the Pony tutorial as:
+
+> Isolated, written iso. This is for references to isolated data structures. If you have an iso variable then you know that there are no other variables that can access that data. So you can change it however you like and give it to another actor.
+
+> Value, written val. This is for references to immutable data structures. If you have a val variable then you know that no-one can change the data. So you can read it and share it with other actors.
+
+The type signature for TCPConnection write is:
+
+```
+be write(data: ByteSeq)
+```
+
+write takes a ByteSeq _value_. However, our data variable is tagged as being an _isolated_ capability. If we were to try and pass our _iso data_ to our _val write_, we'd get the following compiler error:
+
+```
+echo.pony:43:16: argument not a subtype of parameter
+    conn.write(data)
+               ^
+packages/net/tcpconnection.pony:75:12: parameter type: ByteSeq val
+  be write(data: ByteSeq) =>
+           ^
+echo.pony:43:16: argument type: Array[U8 val] iso!
+    conn.write(data)
+```
+
+We need to turn our iso into a val. By doing that, we are widening the access to it. Pretty dangerous stuff. When you need to expand capabilities in that fashion, Pony provides the [consume keyword](http://tutorial.ponylang.org/capabilities/consume-and-destructive-read.html#consuming-a-variable). When we consume our iso data, we are creating a new variable that is a val and declaring that from this point forward, no one can use the original data variable. If we were to try to access the  [...]
+
+We've covered a lot of ground and ended up stumbling around in [Pony's reference capabilities](http://tutorial.ponylang.org/capabilities/reference-capabilities.html) which are one of the hardest parts of the language to get a handle on. There's still one bit of our echo server that we haven't tackled yet. Earlier, when discussing our _Main_ actor, we had this code:
+
+```
+01: TCPListener.ip4(
+02:   recover
+03:     Listener(env)
+04:   end
+05: )
+```
+
+We never discussed what was going on with lines 02 and 04. What up with that recover? Again, the answer lines in [Pony's reference capabilities](http://tutorial.ponylang.org/capabilities/reference-capabilities.html). The method signature for TCPListener.ip4 says that the notify handler we supply has to be an iso reference. However, our Listener is a reference. _recover_ in this case takes our ref and returns an iso. I won't dig into the details as the Pony tutorial has a good [section on [...]
+
+Lastly, I'll add that I realized as I was writing this post, that I didn't need to use recover at all. I was using it because I took it from the ["net" example code](https://github.com/ponylang/ponyc/tree/master/examples/net). If we were to change our _Listener_ classes constructor from returning a ref:
+
+```
+  new create(env: Env) =>
+    _env = env
+```
+
+to returning an iso:
+
+```
+  new iso create(env: Env) =>
+    _env = env
+```
+
+then our _Main_ actor can become the far more straightforward:
+
+```
+actor Main
+  new create(env: Env) =>
+    let listener = TCPListener.ip4(Listener(env))
+```
+
+The final code is currently available on [GitHub](https://github.com/SeanTAllen/pony-echo-server) and will be making it into the official Pony examples. Hopefully you've learned a little something. I know I learned a quite bit having to explain what I did this morning. Check back soon, there will be plenty more learning Pony content coming.
+
+_12/14/15 update: the echo server is now available as part of the [official ponyc examples](https://github.com/ponylang/ponyc/blob/master/examples/echo/echo.pony)._
+
diff --git a/_site/content/post/faking-a-https-client-for-glass.md b/_site/content/post/faking-a-https-client-for-glass.md
new file mode 100644
index 0000000..2dc368c
--- /dev/null
+++ b/_site/content/post/faking-a-https-client-for-glass.md
@@ -0,0 +1,79 @@
++++
+date = "2010-06-22T08:59:50-05:00"
+title = "Faking a https client for GLASS"
+slug = "faking-a-https-client-for-glass"
+draft = false
+tags = ["GLASS","nginx","smalltalk","seaside"]
+author = "Sean T. Allen"
+
++++
+
+So, you are humming along developing your GLASS hosted Seaside application. If you are following the proscribed development path, your application is running in Pharo and you've started porting it to GLASS when a problem arises:
+
+Your application needs to make calls out to a secure web service (merchant processor etc) but, GLASS doesn't have a native https client. The Pharo [cryptography package](http://www.squeaksource.com/Cryptography.html) implements an https client which you could port to Gemstone, but the process model it uses doesn't map nicely and you have better things to do with your time. You could wrap up the [C OpenSSL library](http://www.openssl.org/) and access it from Smalltalk-- also a large amoun [...]
+
+## Http to Https Proxying
+
+A [proxy server](http://en.wikipedia.org/wiki/Proxy_server) is *a server (a computer system or an application program) that acts as an intermediary for requests from clients seeking resources from other servers.* In our current scenario, our Seaside application will make an http connection to a local proxy that will in turn open a https connection to a remote server passing our info along in the process. In order to accomplish this, we will give a hostname to our proxy and connect to it  [...]
+
+```
+127.0.0.1   secure_service
+```
+
+From our smalltalk code instead of opening a connection to *https://api.secure_service.com/apiLocation*, we will open a connection to *http://secure_service/apiLocation*. With this simple code change out of the way, we can move on to setting up the proxy. There are two primary options for doing http to https proxying. Using [stunnel](http://stunnel.mirt.net/) or a proxying web server:
+
+### Stunnel
+
+I'm not going to give an in depth coverage to setting up stunnel as a means of doing outgoing https connections from  GLASS. Why? For any production GLASS system, we are probably going to be running a web server in front of the swazoo, hyper or fastcgi adapter that is serving your Seaside content; that web server is all you need. If we use stunnel to as a proxy for our http to https connections, we are just adding another point of failure to our setup. By using our existing web server as [...]
+
+### Proxying Web Server
+
+We could use [apache](http://httpd.apache.org/docs/2.0/mod/mod_proxy.html), [lighttpd](http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModProxy) or any other proxying web server to implement the following solution. I'll use [Nginx](http://www.nginx.org)[^n] as it is the server I'm most comfortable with. We already added a name for our */etc/hosts* and now it is time to add an additional server entry to our *nginx.conf* file[^n].
+
+```
+server
+{
+  server_name secure_service;
+  
+  location /
+  {
+    proxy_pass https://api.secure_service.com;
+  }
+}
+```
+
+Restart Nginx and we are good to go.
+
+## Using test resources
+
+If we use a build system and the remote service offers production and testing versions, we can get an added bonus from the proxy setup: easy switching at build time between production and testing services.
+
+Let's assume that *secure_service* is a merchant processing provider that provides a test interface where no billing is actually done as well as a production system where transactions are charged to the consumer. Instead of having testing and production objects that change the url we are using, we can have a build system insert the correct url in our *nginx.conf file*. If we are using a [standard c preprocessor](http://gcc.gnu.org/onlinedocs/cpp/index.html)[^n], the following setup and s [...]
+
+```
+#ifdef PRODUCTION
+#define SECURE_SERVICE_URL  production-api.secure_service.com
+#else
+#define SECURE_SERVICE_URL  testing-api.secure_service.com
+#endif
+```
+
+```
+server
+{
+  server_name secure_service;
+  
+  location /
+  {
+    proxy_pass https://SECURE_SERVICE_URL;
+  }
+}
+```
+
+[^n]: If we need to access your proxy from multiple machines, using real dns entries for our domain will make maintenance much easier.
+
+[^n]: You need to configure Nginx at build time to include https support.
+
+[^n]: Normally located in /etc/nginx.conf
+
+[^n]: Any preprocessor would do.
diff --git a/_site/content/post/inside-the-pony-tcp-stack.md b/_site/content/post/inside-the-pony-tcp-stack.md
new file mode 100644
index 0000000..7a5471d
--- /dev/null
+++ b/_site/content/post/inside-the-pony-tcp-stack.md
@@ -0,0 +1,644 @@
++++
+draft = false
+tags = ["pony"]
+date = "2015-12-19T10:52:43-05:00"
+title = "Inside the Pony TCP Stack"
+author = "Sean T. Allen"
+slug = "inside-the-pony-tcp-stack"
+
++++
+
+In this post, we are going to take a look at how [Pony](http://www.ponylang.org/) implements its TCP stack. The API for Pony's networking stack is callback and event driven. I've previously written about [network programming in Pony](http://www.monkeysnatchbanana.com/2015/12/13/deconstructing-a-pony-echo-server/) and showed how to implement a simple echo server. We didn't, however, dive too deeply into the Pony TCP stack. In this post, we'll move down a level of abstraction and see how P [...]
+
+* Review the two interfaces that we previously used to implement an echo server
+* Give a quick overview of how server side TCP programming works
+* Recap the important TCP related bits from our echo server
+* Show how Pony's [standard library networking code](https://github.com/ponylang/ponyc/tree/master/packages/net) implements standard TCP programming patterns
+* Give a quick overview of Pony's [C FFI](http://tutorial.ponylang.org/c-ffi/calling-c/)
+* Touch briefly on Pony's internal event system
+
+This post features a lot of Pony code as well as a lot of C code. In order to follow along, you'll need to have some familiarity with each. If you are unfamiliar with Pony, I suggest you do a review of Pony's basic semantics by reviewing the [Pony Tutorial](http://tutorial.ponylang.org). Most of the code examples are simplified versions of actual Pony code. Where possible, I have removed platform specific code as well as code that - while important to overall functionality - has little t [...]
+
+Let's get started...
+
+## A Skeleton for a Pony TCP server
+
+<img src="https://videos.hasbro.com/img/694893024001/201502/1058/694893024001_4070167773001_MLP-MV-ThePerfectStallion-SingAlong-FINAL-720H264-vs.jpg?pubId=694893024001" align="center">
+
+Our echo server is built around a two classes that implement interfaces that are part of the Pony network stack. Each method in the interfaces corresponds to an event that can happen while interacting with or attempting to interact with a network resource. The particulars aren't that important right now, what is important is recognizing the callback driven nature of network programming with Pony. Pony handles the details of networking programming while users of the API are responsible fo [...]
+
+```
+interface TCPListenNotify
+  """
+  Notifications for TCP listeners.
+  """
+  fun ref listening(listen: TCPListener ref) =>
+    """
+    Called when the listener has been bound to an address.
+    """
+    None
+
+  fun ref not_listening(listen: TCPListener ref) =>
+    """
+    Called if it wasn't possible to bind the listener to an address.
+    """
+    None
+
+  fun ref closed(listen: TCPListener ref) =>
+    """
+    Called when the listener is closed.
+    """
+    None
+
+  fun ref connected(listen: TCPListener ref): TCPConnectionNotify iso^ ?
+    """
+    Create a new TCPConnectionNotify to attach to a new TCPConnection for a
+    newly established connection to the server.
+    """
+```
+
+As you might notice in the _TCPListenNotify_ code above, the return type for the ```connected``` method is a ```TCPConnectionNotify``` instance. ```TCPConnectionNotify``` is our second interface that we need to implement. 
+
+```
+interface TCPConnectionNotify
+  """
+  Notifications for TCP connections.
+  """
+  fun ref accepted(conn: TCPConnection ref) =>
+    """
+    Called when a TCPConnection is accepted by a TCPListener.
+    """
+    None
+
+  fun ref connecting(conn: TCPConnection ref, count: U32) =>
+    """
+    Called if name resolution succeeded for a TCPConnection and we are now waiting for a connection to the server to succeed. The count is the number of connections we're trying. The notifier will be informed each time the count changes, until a connection is made or connect_failed() is called.
+    """
+    None
+
+  fun ref connected(conn: TCPConnection ref) =>
+    """
+    Called when we have successfully connected to the server.
+    """
+    None
+
+  fun ref connect_failed(conn: TCPConnection ref) =>
+    """
+    Called when we have failed to connect to all possible addresses for the server. At this point, the connection will never be established.
+    """
+    None
+
+  fun ref auth_failed(conn: TCPConnection ref) =>
+    """
+    A raw TCPConnection has no authentication mechanism. However, when protocols are wrapped in other protocols, this can be used to report an authentication failure in a lower level protocol (eg. SSL).
+    """
+    None
+
+  fun ref sent(conn: TCPConnection ref, data: ByteSeq): ByteSeq ? =>
+    """
+    Called when data is sent on the connection. This gives the notifier an opportunity to modify sent data before it is written. The notifier can raise an error if the data is swallowed entirely.
+    """
+    data
+
+  fun ref received(conn: TCPConnection ref, data: Array[U8] iso) =>
+    """
+    Called when new data is received on the connection.
+    """
+    None
+
+  fun ref closed(conn: TCPConnection ref) =>
+    """
+    Called when the connection is closed.
+    """
+    None
+```
+
+If you read the documentation strings attached to _TCPConnectionNotify_'s methods, you can see that they are related to servicing individual connections. 
+
+You might want to take the time now to check out [Deconstructing a Pony echo server](http://www.monkeysnatchbanana.com/2015/12/13/deconstructing-a-pony-echo-server/) to see _TCPListenNotify_ and _TCPConnectionNotify_ in action. It's not a required read but can add color and background that you might find helpful. Next, we are going to cover the basics of TCP/IP server programming which will set the table for our exploration of our main method in our echo server and our trip through the P [...]
+
+## TCP/IP server basics
+
+<img src="https://upload.wikimedia.org/wikipedia/en/5/55/Bsd_daemon.jpg" align="right">
+
+In order to understand Pony's approach to network programming, it's important to understand the basics of the BSD socket API. According to Wikipedia:
+
+>Berkeley sockets is an application programming interface (API) for Internet sockets and Unix domain sockets, used for inter-process communication (IPC). It is commonly implemented as a library of linkable modules.
+
+>The API evolved with little modification from a de facto standard into a component of the POSIX specification. Therefore, the term POSIX sockets is essentially synonymous with Berkeley sockets. They are also known as BSD sockets, acknowledging the first implementation in the Berkeley Software Distribution.
+
+The FreeBSD Developers' Handbook has an [excellent overview](https://www.freebsd.org/doc/en/books/developers-handbook/sockets-essential-functions.html) of the basics of BSD socket programming. I highly advise reading it if you aren't familiar with socket programming. You can however make it through this post while knowing only a subset of the information in the Developers' Handbook. 
+
+Let's go step by step through the basics of creating a TCP/IP server using the BSD socket API:
+
+**Create a socket**: It's basically ephemeral and attached to nothing. The only thing we know about are basic info such as its domain, protocol, and type. As of yet, our socket has no address and can't accept any incoming connections. The C function signature is: 
+
+`int socket(int domain, int type, int protocol)`
+
+**Bind**: We bind our new socket to an address and port pair. For example, if we wanted to bind to the standard HTTP port on localhost, we would bind to 127.0.0.1 on port 80. 
+
+`int bind(int s, const struct sockaddr *addr, socklen_t addrlen)`
+
+**Listen**: Once our socket is associated with an address, we can start listening for incoming connections. 
+
+`int listen(int s, int backlog)`
+
+**Accept**: When we receive a new connection, accept is called to create a new socket to handle that connection. Our original socket continues listening for more incoming connections while our new socket handles talking to our remote client.
+
+`int accept(int s, struct sockaddr *addr, socklen_t *addrlen)`
+
+To put this together, when writing a server using the BSD socket interface we:
+
+* Create a new socket
+* Bind it to an address/port combo
+* Start listening for incoming connections
+* Spawn new socket on demand to handle each incoming connection as they arrive
+
+Go ahead and review those steps until you feel comfortable with them. If you are struggling to remember them, write them down so you can refer to them as we work through Pony's TCP stack code. Those basic steps will help keep you oriented as we progress.
+
+## An echo server redux
+
+<img src="https://www.cs.northwestern.edu/~agupta/_projects/networking/TCPClientServer/cs.gif" align="right">
+
+Recapping our echo server code from last time, we are going to dive in from:
+
+```
+actor Main  
+  new create(env: Env) =>
+    TCPListener.ip4(recover Listener(env) end)
+```
+
+I previously described this code as:
+
+>We start by creating a TCPListener that only handles ip version 4. TCPListener is an actor defined in the standard library. To create an ipv4 TCPListener, we have to provide one thing: a class that implements TCPListenNotify. That object will be notified by the TCPListener actor we are creating anytime a new connection comes in.
+
+In that post, we didn't go into _TCPListener_ to see how it's implemented. Let's pull back that veil and move down another layer of abstraction.
+
+## A little bit of TCP/IP in Pony
+
+The Pony TCP stack is a powered by combination of callback objects and events. As we move through the code, this will become more and more clear. Let's take a look at the _TCPListener ipv4_ constructor that we called from our _Main_ actor in our echo server:
+
+```
+actor TCPListener
+
+  new ip4(notify: TCPListenNotify iso, host: String = "",
+    service: String = "0", limit: USize = 0)
+  =>
+    """
+    Listens for IPv4 connections.
+    """
+    _limit = limit
+    _notify = consume notify
+    _event = @os_listen_tcp4[AsioEventID](this, host.cstring(), service.cstring())
+    _fd = @asio_event_fd(_event)
+    _notify_listening()
+```
+
+The first line we want to focus on is:
+
+```
+_event = @os_listen_tcp4[AsioEventID](this, host.cstring(), service.cstring())
+```
+
+Let's start with that ```@os_listen_tcp4[AsioEventID]```. What's going on there? It appears to be some kind of function call but it's unlike any we have previously seen. The _@_ indicates that the function ```os_listen_tcp4``` is implemented in C. The ```[AsioEventID]``` indicates that our return type is of the type ```AsioEventID```. That's as much as you need to know about Pony's C FFI to get through the rest of this post. If you are interested in learning more, check out the [calling  [...]
+
+Let's check out what is going on in the C function ```os_listen_tcp4``` that we are calling:
+
+```
+asio_event_t* os_listen_tcp4(pony_actor_t* owner, const char* host,
+  const char* service)
+{
+  return os_socket_listen(owner, host, service, AF_INET, SOCK_STREAM,
+    IPPROTO_TCP);
+}
+```
+
+That's pretty straight forward. It is just calling another C function ```os_socket_listen```. What's important to note and to keep an eye on as we work through this, is the ```pony_actor_t* owner```. Don't lose track of it. It's a pointer to _TCPListener_ actor and will be very important later. Anyway, continuing on, ```os_socket_listen```:
+```
+static asio_event_t* os_socket_listen(pony_actor_t* owner, const char* host,
+  const char* service, int family, int socktype, int proto)
+{
+  struct addrinfo* result = os_addrinfo_intern(family, socktype, proto, host,
+    service, true);
+
+  struct addrinfo* p = result;
+
+  while(p != NULL)
+  {
+    int fd = socket_from_addrinfo(p, true);
+
+    if(fd != -1)
+    {
+      asio_event_t* ev = os_listen(owner, fd, p, proto);
+      freeaddrinfo(result);
+      return ev;
+    }
+
+    p = p->ai_next;
+  }
+
+  freeaddrinfo(result);
+  return NULL;
+}
+```
+
+The lines to focus on are:
+
+```
+asio_event_t* ev = os_listen(owner, fd, p, proto);
+...
+return ev;
+```
+
+Where we call ```os_listen``` and get an ```asio_event_id*``` back that will unwind its way back up the stack all the way to the Pony code in _TCPListener_ and be assigned to the ```_event``` variable:
+
+```
+_event = @os_listen_tcp4[AsioEventID](this, host.cstring(), service.cstring())
+```
+
+Before returning to _TCPListener_, we have more C code to follow. What's going on in ```os_listen```?
+
+```
+static asio_event_t* os_listen(pony_actor_t* owner, int fd,
+  struct addrinfo *p, int proto)
+{
+  if(bind((SOCKET)fd, p->ai_addr, (int)p->ai_addrlen) != 0)
+  {
+    os_closesocket(fd);
+    return NULL;
+  }
+
+  if(p->ai_socktype == SOCK_STREAM)
+  {
+    if(listen((SOCKET)fd, SOMAXCONN) != 0)
+    {
+      os_closesocket(fd);
+      return NULL;
+    }
+  }
+
+  // Create an event and subscribe it.
+  asio_event_t* ev = asio_event_create(owner, fd, ASIO_READ, 0, true);
+
+  (void)proto;
+
+  return ev;
+}
+```
+
+There we go! In all that C code, I see some BSD socket code:
+
+```
+if(bind((SOCKET)fd, p->ai_addr, (int)p->ai_addrlen) != 0)
+```
+
+where we bind our socket and 
+
+```
+if(listen((SOCKET)fd, SOMAXCONN) != 0)
+```
+
+where we start listening on that socket.
+
+If you remember our BSD socket creation steps earlier we had:
+
+**socket -> bind -> listen** -> accept
+
+Now that we are listening, how do we end up accepting incoming connections? The key lies in Pony's internal event system. Looking at the end of ```os_listen```, you'll see:
+
+```
+// Create an event and subscribe it.
+asio_event_t* ev = asio_event_create(owner, fd, ASIO_READ, 0, true);
+```
+
+Let's check out what is going on in ```asio_event_create```. N.B. that our first parameter is the ```pony_actor_t* owner``` that is a pointer to our _TCPListener_ actor that has been weaving its way down through the code.
+
+```
+asio_event_t* asio_event_create(pony_actor_t* owner, int fd, uint32_t flags, uint64_t nsec, bool noisy)
+{
+  if((flags == ASIO_DISPOSABLE) || (flags == ASIO_DESTROYED))
+    return NULL;
+
+  pony_type_t* type = *(pony_type_t**)owner;
+  uint32_t msg_id = type->event_notify;
+
+  if(msg_id == (uint32_t)-1)
+    return NULL;
+
+  asio_event_t* ev = POOL_ALLOC(asio_event_t);
+
+  ev->magic = ev;
+  ev->owner = owner;
+  ev->msg_id = msg_id;
+  ev->fd = fd;
+  ev->flags = flags;
+  ev->noisy = noisy;
+  ev->nsec = nsec;
+
+  // The event is effectively being sent to another thread, so mark it here.
+  pony_ctx_t* ctx = pony_ctx();
+  pony_gc_send(ctx);
+  pony_traceactor(ctx, owner);
+  pony_send_done(ctx);
+
+  asio_event_subscribe(ev);
+  return ev;
+}
+```
+
+The important take away from ```asio_event_create``` is that it creates a new event for ```ASIO_READ``` and passes that event to ```asio_event_subscribe```. We won't go any further into Pony's event system at this time, suffice it to say that ```asio_event_subscribe``` is the entry into events being sent on Pony and has several different implementations based on the asio backing implementation. The current options are platform specific and one of epoll, kqueue, iocp.
+
+Great! Now we are bound and listening and are ready to receive events related to our socket.
+
+## Back to our echo server
+
+<img src="https://t07.deviantart.net/JyMOqvGHj7ZX4s7XelqnI86rk8g=/300x200/filters:fixed_height(100,100):origin()/pre03/3fd6/th/pre/i/2013/265/e/1/night_watch_the_bat_pony_2_by_zee66-d6nfuuc.png" align="right">
+
+So we have a socket bound and listening. What now? Let's take a look again inside _TCPListener's ip4_ constructor and see how it triggers our first callback ```listening``` on our _TCPListenNotify_ implementor.
+
+```
+actor Main  
+  new create(env: Env) =>
+    TCPListener.ip4(recover Listener(env) end)
+
+actor TCPListener
+  new ip4(notify: TCPListenNotify iso, host: String = "",
+    service: String = "0", limit: USize = 0)
+  =>
+    """
+    Listens for IPv4 connections.
+    """
+    _limit = limit
+    _notify = consume notify
+    _event = @os_listen_tcp4[AsioEventID](this, host.cstring(),
+      service.cstring())
+    _fd = @asio_event_fd(_event)
+    _notify_listening()
+```
+
+Note the last line in the _ip4_ constructor:
+
+```
+_notify_listening()
+```
+
+And its corresponding implementation later in _TCPListener_:
+
+```
+  fun ref _notify_listening() =>
+    """
+    Inform the notifier that we're listening.
+    """
+    if not _event.is_null() then
+      _notify.listening(this)
+    else
+      _closed = true
+      _notify.not_listening(this)
+    end
+```
+
+The ```_notify.listening``` method calls ```listening``` on our callback object ```_notify```. Over in our echo server, we have the rather uninteresting:
+
+```
+  fun ref listening(listen: TCPListener ref) =>
+    try
+      (_host, _service) = listen.local_address().name()
+      _env.out.print("listening on " + _host + ":" + _service)
+    else
+      _env.out.print("couldn't get local address")
+      listen.close()
+    end
+```
+
+But hey, we're now listening on our socket and we've printed out a log message. Exciting? Maybe. So we've gone from *Socket* to *Bind* to *Listen* and all that is left is accepting and handling incoming connections.
+
+## Accepting a connection
+
+<img src="https://img04.deviantart.net/d968/i/2014/078/7/f/vampire_pony_sisters_by_magister39-d7au3ef.png" width="200" align="right">
+
+You might remember from earlier that in ```os_listen``` we used ```asio_event_subscribe``` to register that our _TCPListener_ instance was interested in knowing about ```ASIO_READ``` events on our socket. Whenever an event is generated, it will be delivered to our actor by calling its ```_event_notify``` behavior.
+
+```
+  be _event_notify(event: AsioEventID, flags: U32, arg: U32) =>
+    """
+    When we are readable, we accept new connections until none remain.
+    """
+    ...
+
+    if AsioEvent.readable(flags) then
+      _accept(arg)
+    end
+
+    ...
+```
+
+You can see that if our event is readable, we'll call the ```_accept``` method on our actor:
+
+```
+    if AsioEvent.readable(flags) then
+      _accept(arg)
+    end
+```
+
+Let's check out what is going on in ```_accept```:
+
+```
+  fun ref _accept(ns: U32 = 0) =>
+    """
+    Accept connections as long as we have spawned fewer than our limit.
+    """
+    ...
+
+    while (_limit == 0) or (_count < _limit) do
+      var fd = @os_accept[U32](_event)
+
+      match fd
+      | -1 =>
+        // Something other than EWOULDBLOCK, try again.
+        None
+      | 0 =>
+        // EWOULDBLOCK, don't try again.
+        return
+      else
+        _spawn(fd)
+      end
+    end
+
+    _paused = true
+```
+
+The important line to focus on is where we make another C FFI call, this time to ```@os_accept[U32]```. Returning back to the C code in the Pony runtime library, we see that ```os_accept``` is defined as:
+
+```
+int os_accept(asio_event_t* ev)
+{
+  int ns = accept(ev->fd, NULL, NULL);
+
+  ...
+
+  return (int)ns;
+}
+```
+
+And there, we see another BSD socket call:
+
+```
+int ns = accept(ev->fd, NULL, NULL);
+```
+
+Which means that we are pretty close to completing our chain **Socket -> Bind -> Listen -> Accept**.
+
+Once the connection is accepted, we return to ```_accept``` where we verify that everything is kosher with our new connection and then call ```_spawn```:
+```
+    while (_limit == 0) or (_count < _limit) do
+      var fd = @os_accept[U32](_event)
+
+      match fd
+      | -1 =>
+        // Something other than EWOULDBLOCK, try again.
+        None
+      | 0 =>
+        // EWOULDBLOCK, don't try again.
+        return
+      else
+        _spawn(fd)
+      end
+    end
+```
+
+Let's check out what is going on in Spawn.
+```
+  fun ref _spawn(ns: U32) =>
+    """
+    Spawn a new connection.
+    """
+    try
+      TCPConnection._accept(this, _notify.connected(this), ns)
+      _count = _count + 1
+    else
+      @os_closesocket[None](ns)
+    end
+```
+
+The important line to focus on is:
+
+```
+TCPConnection._accept(this, _notify.connected(this), ns)
+```
+
+There's actually a lot going on in that one line so let's take a moment to walk through it. First, we call the ```connected``` method on our ```_notify``` callback object. In our current context, ```_notify``` is our listener callback object:
+
+```
+  fun ref connected(listen: TCPListener ref) : TCPConnectionNotify iso^ =>
+    Server(_env)
+```
+
+Here, we are creating a Server object that implements _TCPConnectionNotify_ and will handle connections to our echo server. This notifier is in turn passed into the _TCPConnection_ actor's ```_accept``` constructor back in our ```_spawn``` method:
+
+```
+TCPConnection._accept(this, _notify.connected(this), ns)
+```
+
+Let's check out _TCPConnection_'s ```_accept``` constructor:
+
+```
+actor TCPConnection
+
+  new _accept(listen: TCPListener, notify: TCPConnectionNotify iso, fd: U32) =>
+    """
+    A new connection accepted on a server.
+    """
+    _listen = listen
+    _notify = consume notify
+    _connect_count = 0
+    _fd = fd
+    _event = @asio_event_create(this, fd, AsioEvent.read_write(), 0, true)
+    _connected = true
+
+    _notify.accepted(this)
+```
+
+You can see we set up an event via a C FFI call to ```@asio_event_create``` and finally, call the ```_accepted``` method on our _Server_ callback object.
+
+Our accepted callback gives us a chance to do interesting things upon accepting a new connection, in our case, "interesting" means logging an informational message:
+
+```
+class Server is TCPConnectionNotify  
+
+  fun ref accepted(conn: TCPConnection ref) =>
+    _env.out.print("connection accepted")
+```
+
+And handling connection input? Again, it comes from the depths of the event system. Our actor is notified of an event via the ```_event_notify``` behavior. 
+
+```
+  be _event_notify(event: AsioEventID, flags: U32, arg: U32) =>
+    """
+    Handle socket events.
+    """
+    ...
+
+    if AsioEvent.readable(flags) then
+      _readable = true
+      _complete_reads(arg)
+      _pending_reads()
+    end
+
+    ...
+  end
+```
+
+I've stripped out a lot of code from ```_event_notify``` to draw your attention more easily to the one line we really care about, the call to the private method `_pending_reads`.
+
+```
+  fun ref _pending_reads() =>
+    """
+    Read while data is available, guessing the next packet length as we go. If
+    we read 4 kb of data, send ourself a resume message and stop reading, to
+    avoid starving other actors.
+    """
+    try
+      var sum: USize = 0
+
+      while _readable and not _shutdown_peer do
+        // Read as much data as possible.
+        let len = @os_recv[USize](_event, _read_buf.cstring(), _read_buf.space()) ?
+
+        var next = _read_buf.space()
+
+        ...
+
+        let data = _read_buf = recover Array[U8].undefined(next) end
+        data.truncate(len)
+        _notify.received(this, consume data)
+
+        ...
+      end
+    ...
+```
+
+Again there's a lot of work going on in this method, there's a lot of book keeping, a call to the C function that gets data from the socket (```@os_recv```) and most importantly, the invocation of the ```received``` method on our Server callback:
+
+```
+_notify.received(this, consume data)
+```
+
+Which means, we've finally arrived at the ```received``` method on our Server class where we take the data our echo server has received and send it back out to the client:
+
+```
+fun ref received(conn: TCPConnection ref, data: Array[U8] iso) =>
+    _env.out.print("data received, looping it back")
+    conn.write("server says: ")
+    conn.write(consume data)
+```
+
+## Wrapping up
+
+We've made our way though a lot of Pony and C code to get to this point where we can see how our simple echo server works.
+I hope by now you feel like you have a grasp on how BSD socket programming works and nice event based abstractions that Pony provides for working with it. If you are interested in learning more about TCP/IP programming, I highly recommend you pick up all 3 volumes of W. Richard Steven's classic _TCP/IP Illustrated_ series:
+
+* [TCP/IP Illustrated, Volume 1: The Protocols](http://www.amazon.com/TCP-Illustrated-Protocols-Addison-Wesley-Professional/dp/0321336313/ref=sr_1_1?ie=UTF8&qid=1450229478&sr=8-1&keywords=tcp+ip+illustrated) 
+* [TCP/IP Illustrated: The Implementation, Vol. 2](http://www.amazon.com/TCP-IP-Illustrated-Implementation-Vol/dp/020163354X/ref=sr_1_3?ie=UTF8&qid=1450229478&sr=8-3&keywords=tcp+ip+illustrated)
+* [TCP/IP Illustrated, Vol. 3: TCP for Transactions, HTTP, NNTP, and the UNIX Domain Protocols](http://www.amazon.com/TCP-Illustrated-Vol-Transactions-Protocols/dp/0201634953/ref=sr_1_4?ie=UTF8&qid=1450229478&sr=8-4&keywords=tcp+ip+illustrated)
+
+Next time, we'll dig into Pony's event system and explore what's going on inside ```asio_event_subscribe```.
diff --git a/_site/content/post/interview-exchange.md b/_site/content/post/interview-exchange.md
new file mode 100644
index 0000000..f1b4dfe
--- /dev/null
+++ b/_site/content/post/interview-exchange.md
@@ -0,0 +1,10 @@
++++
+draft = true
+tags = ["tag 1","tag 2"]
+author = "Sean T. Allen"
+date = "2017-02-18T09:29:51-05:00"
+title = "interview exchange"
+slug = "post-url-name"
+
++++
+
diff --git a/_site/content/post/interview-with-lobste-rs.md b/_site/content/post/interview-with-lobste-rs.md
new file mode 100644
index 0000000..ce1232e
--- /dev/null
+++ b/_site/content/post/interview-with-lobste-rs.md
@@ -0,0 +1,12 @@
++++
+date = "2014-03-06T11:35:28-05:00"
+title = "Interview with Lobste.rs"
+author = "Sean T. Allen"
+slug = "interview-with-lobste-rs"
+draft = false
+
++++
+
+![Roger](/img/post/interview-with-lobste-rs/IMG_3648.jpg)
+
+I recently did an [interview](https://lobste.rs/s/gheyhy/lobsters_interview_with_sean_t_allen) with the news aggregator site [lobste.rs](http://www.lobste.rs/). It covers some of what I've been up to in my role as [Principal Architect at TheLadders](http://dev.theladders.com/), as well as some info about my forthcoming book [Storm Applied](http://www.manning.com/sallen).
diff --git a/_site/content/post/learning-from-ada.md b/_site/content/post/learning-from-ada.md
new file mode 100644
index 0000000..fabd4d4
--- /dev/null
+++ b/_site/content/post/learning-from-ada.md
@@ -0,0 +1,20 @@
++++
+author = "Sean T. Allen"
+slug = "learning-from-ada"
+draft = false
+tags = ["c","ada"]
+date = "2016-02-22T10:42:22-05:00"
+title = "Learning From Ada"
++++
+
+This is a cautionary tale. One of youth and a lesson I eventually learned but still often don't heed. About how sometimes, the tool that is easiest to get started with isn’t the tool that will make your job the easiest.
+
+When I was getting started as a professional programmer, I was devouring languages left and right, trying them out for a few days before moving on to others. From this, I stuck with a few. My first "professional" languages were Perl, Pascal, UserLand Frontier, and AppleScript. During my first couple of years programming, I either released some little bit of open source software or got paid to write something using one of them. Pascal was my favorite. It had the best performance and it wa [...]
+
+Ada's reputation, or at least what had filtered down to me, was pretty cool. It was built for safety. It was used at the Department of Defense and to do all sorts of awesome cool-sounding stuff, but given my level of experience, most of its features meant little to me. I set about trying to learn Ada. Over the course of two weeks, I slowly grew more and more frustrated with Ada. It took me forever to get any of my programs to compile. I was being asked to think more than I had with other [...]
+
+I quickly fell in love with C. It felt much simpler than Ada. It was much easier to get my code to compile. There were more books, the community seemed larger and I knew that Apple was moving the Macintosh APIs from Pascal to C. So many things lined up to rationalize using C. In the end though, there was one factor that I know was more important than any other. The C compiler made me feel adequate. Unlike Ada, I regularly got my programs to compile. And so, I made my choice and went with C.
+
+With that decision of C over Ada, a large portion of my development as a programmer was decided. I spent a ton of time in C dealing with code that segfaulted. The power and freedom that C gave me with pointers came back to bite me all the time. Sure, my code compiled but man, did it also crash a lot. I spent years with C and C++ learning patterns for sharing memory, for immutable objects, for concurrency via threading that I still use to this day; patterns to avoid dangerous code that th [...]
+
+When I look back now at my Ada/C decision. I do so with some regret. I took the easy path. I let frustration get the best of me. And now whenever I encounter a difficult moment learning new languages like Haskell or Pony, I try to remember my Ada/C decision and stick will the language whose compiler is trying to tell me I'm doing it wrong. 
diff --git a/_site/content/post/nyc-python-scale-agnostic-python.md b/_site/content/post/nyc-python-scale-agnostic-python.md
new file mode 100644
index 0000000..cb5cf1f
--- /dev/null
+++ b/_site/content/post/nyc-python-scale-agnostic-python.md
@@ -0,0 +1,16 @@
++++
+draft = false
+date = "2017-08-19T11:56:56-04:00"
+title = "NYC Python: Scale Agnostic Python"
+tags = ["talks","python", "distributed systems", "slides", "wallaroo", "scale agnostic"]
+description = "Post with information about my August 17, 2017 NYC Python talk \"Scale Agnostic Python? How to scale your Python application without any code changes\"."
+author = "Sean T. Allen"
+slug = "nyc-python-aug-17-scale-agnostic-python"
++++
+
+## Scale Agnostic Python: How to scale your Python application without any code changes*
+
+Unfortunately, there is no video of this talk. I am, however, planning on putting a record together of the topic. Slides are available. A full half of the presentation was a code walkthrough and a demo of a bit of the power that you can get from using a scale agnostic platform. If you are interested in the topic, I strongly advise you check out the Pat Helland paper below.
+
+- ["Scale Agnostic Python" slides](https://speakerdeck.com/seantallen/scale-agnostic-python) 
+- ["Life Beyond Distributed Transactions: An apostate's opinion"](https://queue.acm.org/detail.cfm?id=3025012)
diff --git a/_site/content/post/of-debt-and-decisions.md b/_site/content/post/of-debt-and-decisions.md
new file mode 100644
index 0000000..45b00a1
--- /dev/null
+++ b/_site/content/post/of-debt-and-decisions.md
@@ -0,0 +1,32 @@
++++
+draft = false
+date = "2015-04-19T11:09:15-05:00"
+title = "Of Debt and Decisions"
+tags = ["technical debt","war story"]
+author = "Sean T. Allen"
+slug = "of-debt-and-decisions"
++++
+
+Back in the salad days of the 1990's, I was working at a company that was building the hot product of the day: an intranet. Every company wanted an intranet. We'd built several for different client before deciding to create a white labelable intranet that would be the delight of all our customers. Give us some money and we'd give you a themed intranet with calendaring, project tracking, task management and more.
+
+We didn't offer a hosted service instead, we would ship a computer to you with all the software installed that you could run on your network. In addition to being white lableable, you got to pick which you would be most comfortable supporting: a Linux or Windows NT based install. The Linux version came with RedHat Linux, Apache and MySQL. The NT, in addition to Windows, came with IIS and SQL Server. This post is the story of engineering decisions, both good and bad, that went into the cr [...]
+
+A tale of two languages
+One of the first questions most engineers will ask of you when discussing a project is what language you used. Our intranet-in-a-box used 2: Perl and Java. Our primary language for doing client projects before we got into software was Perl. In the beginning, the intranet-in-a-box was the work of a single developer. It wasn't a primary focus of the company. The vast majority of time was spent doing client work. While intranet-in-a-box development slowly progressed on the side, that single [...]
+
+Most communication between the different modules was done by using a database as a pool of mutable shared state. If module A and B needed to talk to one another, they could just modify and read from the same tables.The vast majority of sharing could be handled this way, there was just one problem: the further we got into the project, the more shared base code that we were porting from Java to Perl or Perl to Java. Further, that shared code was getting out of sync. If you had a utility ro [...]
+
+I don't know what anyone else would have done given that task and constraint but I know what I did: I created a cross language bridge that allowed the two sides of the codebase to talk to one another. The bridge involved serializing data on one side of a socket and deserializing it on the other. CORBA and various RPC tools like it were quite popular at the time. I had been learning a lot about them and so, our own little monster was created. I might cringe about it now, but it worked. It [...]
+
+The other way to be "database agnostic"
+The time came when we were going to start selling our intranet-in-a-box to our first customers. We installed RedHat Linux, Apache, MySQL and our mixed Perl and Java codebase onto a box and shipped them off to a customer. Before long, we had another customer but their IT staff was comfortable with NT and not Linux so we set about getting everything running on NT with IIS as the webserver. Getting Perl running on Windows NT with IIS was a bit of a pain but it was a known, solved problem. O [...]
+
+We barely had any source control, we had no automated testing and all work was done on and tested against individual developer machines. Some like mine were Linux, others Windows. Somehow along the way we ended with code in one of the modules that had been written against SQLServer while being developed. It relied on SQLServer syntax that didn't exist in MySQL. For the life of me, I don't remember what the syntax was, I just remember that we had hit a point where we needed to run differe [...]
+
+What's a few more patches between friends
+Somewhere along the line, we got a couple complaints about the software not being fast enough. Given our stack and lack of sophisticated tooling, we had no way to address the issue easily. We didn't have any fancy profiling tools and most code paths from web request to database and back were going to be fairly short. Optimizing the code was going to be problematic and might not result in much of a gain. Moving the Perl portion of the codebase to Java would have helped with performance in [...]
+
+I started searching the Internet for ways we could speed up Linux and MySQL. I came across a couple of kernel changes you could make that would in theory provide a speed boost. I patched the Linux source, created a new build and tried it out. Primitive quantitative testing and qualitative testing both pointed to the changes having a real impact. I was already interested in operating systems, network stacks and had been doing quite a bit of reading and exploring both the Linux and NetBSD  [...]
+
+The horror story that wasn’t
+Hopefully you are horrified by all things we didn't do that are now considered best practices. No reproducible builds, lack of automated testing, creating and then repeatedly sidestepping technical debt. For a long time, that is how I told these stories: as horror stories that came complete with hand gesticulations to emphasize the "can you believe I had to do that?" nature of it all. Here's the thing though: we were making money. We were growing and supporting ourselves. We were continu [...]
diff --git a/_site/content/post/of-me-and-be.md b/_site/content/post/of-me-and-be.md
new file mode 100644
index 0000000..bc2947c
--- /dev/null
+++ b/_site/content/post/of-me-and-be.md
@@ -0,0 +1,13 @@
++++
+date = "2017-02-18T09:26:34-05:00"
+title = "Of Me and Be"
+tags = ["tag 1","tag 2"]
+author = "Sean T. Allen"
+slug = "of-me-and-be"
+draft = true
+
++++
+
+<iframe width="420" height="315" src="https://www.youtube.com/embed/BsVydyC8ZGQ" frameborder="0" allowfullscreen></iframe>
+
+"a system that makes programming fun again"
diff --git a/_site/content/post/on-becoming-a-better-teacher.md b/_site/content/post/on-becoming-a-better-teacher.md
new file mode 100644
index 0000000..432417c
--- /dev/null
+++ b/_site/content/post/on-becoming-a-better-teacher.md
@@ -0,0 +1,40 @@
++++
+author = "Sean T. Allen"
+slug = "on-becoming-a-better-teacher"
+draft = false
+date = "2015-04-12T11:24:38-05:00"
+title = "On Becoming a Better Teacher"
+
++++
+
+Sometime in early 2013, I was really struggling with writing [Storm Applied](http://manning.com/sallen/?a_aid=sallen). I felt stymied at every turn by the requests of our editor. He was always asking us to explain simple topics more deeply. I almost lost my mind when a request to explain “web-scale” came up. It all felt like Manning was having us dumb the book down. Here we were trying to write an “advanced” book and we were running around explaining obvious, simple topics. In short, I w [...]
+
+![Definition of web-scale from Storm Applied](/img/post/on-becoming-a-better-teacher/Definition-of-web-scale-from-Storm-Applied.png)
+
+I'll admit to a certain level of elitism that I carry through my life. As an example, there's a series of books designed to teach various aspects of being a programmer called [Head First](http://shop.oreilly.com/category/series/head-first.do). I'd always looked down on them. They weren't books for “real programmers”. In my mind, they were written for lazy people who weren't willing to invest thought into teaching themselves new topics. And here was our editor at Manning, asking us to do  [...]
+
+What Kathy taught me was something that had been staring me in the face the entire time. I do a lot of mentoring and teaching as part of my job. This is almost always in person, often to a group of people rather than one on one. When I'm teaching something, I can tell who is understanding an explanation and who isn't just by looking at people's faces. When I see someone not understanding what I'm explaining, I always stop and try explaining it another way; often asking them questions to  [...]
+
+We were introducing a couple of new developers on our team at TheLadders to Storm and it became clear they had very little idea how to use the Storm UI. I was very versed in the UI and considered it extremely simple. It was always my first stop when diagnosing problems in our production Storm cluster. I started teaching people how to use the Storm UI to do what I did and it hit me: Here was a topic I was going to have to teach in Storm Applied and I was doing the “explain it many differe [...]
+
+I started in on Storm Applied again with renewed vigor. I was no longer considering dropping out of the project because it was being “dumbed down”. I started approaching every topic with the question “what is obvious to me that won't be to someone just learning this”. It's really hard to do. One of the hardest things I've had to do. To drill down, through all my professional experience and say “what do I know that others don't that I'm assuming they will know”. Those conversations with K [...]
+
+A couple of examples of how this played out:
+
+* Chapter 8 in Storm Applied is about diving below the basic abstractions that Storm provides you as a programmer and looking at how they are implemented. Before I wrote that chapter, I taught 5 different groups of people the same material, each time taking the questions they asked and building it into how I taught it the next time. 
+
+* Chapter 5 includes a 12 page review of the Storm UI. It's very straight-forward. Lots of screenshots calling out and highlighting certain parts of different screens saying ”and this important bit is…”. 
+
+![Example Storm UI screenshot from Storm Applied](/content/images/2015/04/Storm-UI-Figure-from-Storm-Applied.png)
+
+For some people, this might be redundant and seem pointless. An otherwise glowing review of [Storm Applied on Amazon](http://www.amazon.com/Storm-Applied-Strategies-real-time-processing/dp/1617291897/ref=sr_1_1) includes the following:
+
+> What I didn't love:
+>
+> There only minor issue that I have with the book is that section on the Storm UI seemed like "filler". The UI is not very complex, and it is very self-explanatory once you know the basic Storm concepts and terminology. The numerous screenshots and descriptions in the book could have easily been left out with no real detriment to the reader. I would recommend skimming or skipping these sections.
+
+I understand that comment quite well. I said something similar to Matt and Peter when we were discussing how much we should cover the UI when we were first planning the book. I said in my [previous post about Storm Applied](http://www.monkeysnatchbanana.com/2015/04/04/storm-applied/):
+
+> I don't remember now what I envisioned the book being when we first signed the contract. I know that Storm Applied isn't that book but I'm quite happy with it nonetheless.
+
+That “advanced book” I was planning on writing? It's a distant memory now. I can still sort of remember what it would have been like but that book wouldn't have been as good as Storm Applied is. And so, I'm quite happy with reviews that call out “filler” and repetition because I know why its there. And now you do as well.
diff --git a/_site/content/post/pony-patterns-waiting.md b/_site/content/post/pony-patterns-waiting.md
new file mode 100644
index 0000000..c63a9c5
--- /dev/null
+++ b/_site/content/post/pony-patterns-waiting.md
@@ -0,0 +1,86 @@
++++
+title = "Pony Patterns: Waiting"
+tags = ["pony"]
+author = "Sean T. Allen"
+slug = "pony-patterns-waiting"
+draft = false
+date = "2016-01-16T10:46:33-05:00"
+
++++
+
+> I am a patient boy. I wait, I wait, I wait, I wait. My time is water down a drain
+> 
+> Everybody's moving. Everybody's moving.
+> Everything is moving, moving, moving, moving
+> 
+> Please don't leave me to remain.
+> In the waiting room
+>
+> --- Ian MacKaye
+
+How do you wait when you can't wait? No, that isn't a riddle; it's a question I recently faced while writing some [Pony](http://www.ponylang.org) code for [work](https://www.wallaroolabs.com). 
+
+Here's the problem: I'm writing a black box testing application that will verify the correctness of our system under test. My black box tester sends information into the box via UDP and gets data back via the same means and verifies that the data is valid. That system under test is currently a prototype written in Python. All things considered, it performs well. The problem is Pony performs better. 
+
+When I first fired up my tester, it quickly swamped the prototype. We haven't implemented any sort of backpressure yet so, I knew I needed to slow my application down via more "manual" means. I needed to limit the rate it was supplying data to the system under test. But how? 
+
+In a language with blocking operations, I could just call sleep and be done with it. It might not be the most elegant solution but it would work. Pony, however, isn't such a language. One of Pony's key features is there are no blocking operations. So, back to our original question: how do you wait when you can't wait? 
+
+After a bit of digging around, we came across the [Timer](https://github.com/CausalityLtd/ponyc/blob/master/packages/time/timer.pony) class. A timer allows you to execute code at set intervals. I'm going to walk you through how to use a timer using a simple application that prints out a number to the console every 5 seconds until someone terminates the program:
+
+```
+use "time"
+
+actor Main
+  new create(env: Env) =>
+    let timers = Timers
+    let timer = Timer(NumberGenerator(env), 0, 5_000_000_000)
+    timers(consume timer)
+
+class NumberGenerator is TimerNotify
+  let _env: Env
+  var _counter: U64
+
+  new iso create(env: Env) =>
+    _counter = 0
+    _env = env
+
+  fun ref _next(): String =>
+    _counter = _counter + 1
+    _counter.string()
+
+  fun ref apply(timer: Timer, count: U64): Bool =>
+    _env.out.print(_next())
+    true
+```
+
+Zooming in on the key bits, we first set up our timers, create one and add it to our set of timers:
+
+```
+    let timers = Timers
+    let timer = Timer(NumberGenerator(env), 0, 5_000_000_000)
+    timers(consume timer)
+```
+
+The Timer constructor takes 3 arguments, the class to notify, how long until our timer expires and how often to fire. In our example code an instance of NumberGenerator will be called every 5 billion nanoseconds i.e. every 5 seconds until the program is killed.
+
+Here's our method in NumberGenerator that gets executed:
+
+```
+  fun ref apply(timer: Timer, count: U64): Bool =>
+    _env.out.print(_next())
+    true
+```
+
+If we were to compile and run our application, we'd end up with some output like:
+
+![program output](/img/post/pony-patterns-waiting/Screenshot-2016-01-18-16-51-54.png)
+
+It's not the most exciting output in the world but, it's a pattern that I expect many Pony users will need: '[how to wait without waiting](https://www.youtube.com/watch?v=cMOAXm94VWo)'.
+
+---
+
+_If you are interested in what is going on with the `consume` in the `timers(consume timer)`, check out my previous post [Deconstructing a Pony echo server](http://www.monkeysnatchbanana.com/2015/12/13/deconstructing-a-pony-echo-server/) where I cover the semantics of consume._
+
+
+
diff --git a/_site/content/post/qcon-how-did-i-get-here.md b/_site/content/post/qcon-how-did-i-get-here.md
new file mode 100644
index 0000000..2ee7d71
--- /dev/null
+++ b/_site/content/post/qcon-how-did-i-get-here.md
@@ -0,0 +1,51 @@
++++
+title = "QCon: How Did I Get Here?"
+tags = ["talks","testing", "distributed systems", "stream processing", "video", "slides"]
+description = "Post with link my 2016 QCon New York talk \"How Did I Get Here? Building Confidence in a Distributed Stream Processor\" and associated content."
+author = "Sean T. Allen"
+slug = "qcon-how-did-i-get-here"
+draft = false
+date = "2016-10-06T10:20:46-05:00"
+
++++
+
+## Building Confidence in a Distributed Stream Processor
+
+Video of my QCon New York talk: ["How Did I Get Here? Building Confidence in a Distributed Stream Processor"](https://www.infoq.com/presentations/trust-distributed-systems) is now available. 
+
+---
+
+There's a number of links at the end of the talk for additional material you can check out. To make life easier on everyone I'm recreating it here.
+
+### Peter Alvaro
+
+* [Peter Alvaro's twitter](https://twitter.com/palvaro)
+* [Lineage-driven Fault Injection](http://www.cs.berkeley.edu/~palvaro/molly.pdf)
+* [Outwards from the Middle of the Maze](https://www.youtube.com/watch?v=ggCffvKEJmQ)
+
+### Kyle Kingsbury
+
+* [Kyle Kingsbury's twitter](https://twitter.com/aphyr)
+* [Jepsen](https://aphyr.com/tags/Jepsen)
+
+### Will Wilson
+
+* [Testing Distributed Systems w/ Deterministic Simulation](https://www.youtube.com/watch?v=4fFDFbi3toc)
+
+### Catie McCaffrey
+
+* [Catie McCaffrey's twitter](https://twitter.com/caitie)
+* [The Verification of a Distributed System:
+A practitioner's guide to increasing confidence in system correctness](http://queue.acm.org/detail.cfm?ref=rss&id=2889274)
+
+### Inés Sombra
+
+* [Inés Sombra twitter](https://twitter.com/randommood)
+* [Testing in a Distributed World](https://www.youtube.com/watch?v=KSdNYi55kjg)
+
+### Chaos Engineering
+
+* [Principles of Chaos Engineering](http://principlesofchaos.org)
+
+---
+If you are interested, I've made the [slides available on Speakerdeck](https://speakerdeck.com/seantallen/how-did-i-get-here-building-confidence-in-a-distributed-stream-processor). Like most of my talks, the slides aren't particularly good at standing on their own without the talk itself.
diff --git a/_site/content/post/qcon-ny-17-pony.md b/_site/content/post/qcon-ny-17-pony.md
new file mode 100644
index 0000000..f7a035c
--- /dev/null
+++ b/_site/content/post/qcon-ny-17-pony.md
@@ -0,0 +1,31 @@
++++
+title = "QCon NY: Pony"
+tags = ["talks", "pony", "stream processing", "video", "slides"]
+description = "Post with link to my 2017 QCon New York talk \"Pony: How I learned to stop worrying and embrace an unproven technology\" and associated content."
+author = "Sean T. Allen"
+slug = "qcon-ny-17-pony"
+draft = false
+date = "2017-09-02T10:20:46-05:00"
+
++++
+
+## Pony: How I learned to stop worrying and embrace an unproven technology
+
+Video of my QCon New York talk: ["Pony- How I learned to stop worrying and embrace an unproven technology"](https://www.infoq.com/presentations/pony-wallaroo) is now available. 
+
+The talk details my experiences thus far in using [Pony](https://www.ponylang.org) at [Wallaroo Labs](https://twitter.com/wallaroolabs) to build Wallaroo, a high-performance stream processing system. The talk was part of a FinTech track so there's a slight Fintech bent to some of the content that probably wouldn't have been in the talk otherwise.
+
+---
+
+There's a couple of links at the end of the talk for the additional material you can check out. To make life easier on everyone I'm recreating it here.
+
+### Trash Day: Coordinating Garbage Collection in Distributed Systems
+
+["Trash Day"](https://www.usenix.org/system/files/conference/hotos15/hotos15-paper-maas.pdf) is an awesome paper on how coordinating garbage collection pauses in Apache Spark, and Apache Cassandra clusters improved performance.
+
+### Ownership and Reference Counting based Garbage Collection in the Actor World
+
+More commonly known as the ["ORCA paper"](https://www.ponylang.org/media/papers/OGC.pdf). This article by Sylvan Clebsch et al. dives into the inner-workers of the Pony garbage collector.
+
+---
+If you are interested, I've made the [slides available on Speakerdeck](https://speakerdeck.com/seantallen/pony-how-i-learned-to-stop-worrying-and-embrace-an-unproven-technology). Like most of my talks, the slides aren't particularly good at standing on their own without the talk itself.
diff --git a/_site/content/post/redline-the-journey-so-far.md b/_site/content/post/redline-the-journey-so-far.md
new file mode 100644
index 0000000..1ed251a
--- /dev/null
+++ b/_site/content/post/redline-the-journey-so-far.md
@@ -0,0 +1,10 @@
++++
+title = "Redline Smalltalk: The Journey So Far"
+slug = "redline-smalltalk-the-journey-so-far"
+draft = false
+tags = ["smalltalk","redline", "video", "talks"]
+author = "Sean T. Allen"
+date = "2011-04-11T08:42:24-05:00"
++++
+
+Video of [James](https://twitter.com/jamesladd) and my [talk at Smalltalk Solutions](https://vimeo.com/22084832) on where we are currently with [Redline Smalltalk](http://www.redline.st) has been posted.
diff --git a/_site/content/post/reverse-proxying-to-seaside-with-nginx.md b/_site/content/post/reverse-proxying-to-seaside-with-nginx.md
new file mode 100644
index 0000000..5cb7505
--- /dev/null
+++ b/_site/content/post/reverse-proxying-to-seaside-with-nginx.md
@@ -0,0 +1,156 @@
++++
+author = "Sean T. Allen"
+slug = "reverse-proxying-to-seaside-with-nginx"
+draft = false
+date = "2010-06-24T08:56:43-05:00"
+title = "Reverse Proxying to Seaside with Nginx"
+tags = ["nginx","smalltalk","seaside"]
+
++++
+
+## Why Reverse Proxy a.k.a Why Not FastCGI?
+
+Transparency.
+
+FastCGI setups are opaque. You can't easily test all aspects of it. Unless you write your own FastCGI client, debugging configuration problems can be very difficult. Lets imagine for a moment that are trying to debug a problem with your application-- the issue might be in the front end server or it might be in the Seaside application server. When you are using FastCGI, all your interactions with your application server are routed through the front end server which acts as a client for yo [...]
+
+## Reverse Proxying to Seaside Options
+
+Now that you have decided that you want to use reverse proxying to your Seaside application, you need to decide between a couple of basic setup options. You can either setup each application on its own subdomain of your domain or you can run multiple applications off the same domain.
+
+### One Application Per Subdomain
+
+Our first example, shows a basic setup for running the counter and multicounter example applications off their own subdomains. With this configuration, you would be able to access the counter example via the uri `http://counter.example.com/` and the multicounter example via `http://multicounter.example.com/`.
+
+```
+01: server
+02: {
+03:   server_name counter.example.com;
+04:  
+05:   rewrite ^/$ /examples/counter;
+06:   proxy_redirect /examples/counter /;
+07:
+08:   location /examples/counter
+09:   {
+10:     proxy_pass http://127.0.0.1:8080;
+11:   }
+12: }
+13:
+14: server
+15: {
+16:   server_name multicounter.example.com;
+17:  
+18:   proxy_redirect /examples/multicounter /;
+19:   rewrite ^/$ /examples/multicounter;
+20:
+21:   location /examples/multicounter
+22:   {
+23:     proxy_pass http://127.0.0.1:8080;
+24:   }
+25: }
+```
+
+If you've never seen a nginx configuration file before that might be quite a bit to absorb, so lets break it down: 
+
+* We setup two virtual servers, one for each application. This is done via the server {} directives that start on lines 1 and 14. Each virtual server is almost identical except counter appears in one and multicounter in the other.
+* Line 3 tells our first server to respond to requests for the host `counter.example.com`.
+* Line 5 rewrites `http://counter.example.com/` to `http://counter.example.com/examples/counter`. _This change in URI isn't seen by the client browser_.
+* Line 6 removes `/examples/counter` from URIs being returned by the counter application.
+* Line 8 sets up an nginx location. It passes the URI `/examples/counter` to a our application server listening on port 8080 of localhost.
+
+### Multiple Applications Per Domain 
+
+For our multiple applications per domain example, we are going to setup example.com to server any of the example Seaside applications. All the example Seaside applications start with their URI path with `/examples`-- a nicety we will take advantage of.
+
+```
+1: server
+2: {
+3:   server_name example.com;
+4:
+5:   location /examples
+6:   {
+7:     proxy_pass http://127.0.0.1:8080/examples;
+8:   }
+9: }
+```
+
+The nginx location we setup on line 5, routes anything under `/examples` to the same path on our application server. Under this setup, we could access the counter application at `http://example.com/examples/counter` and multi counter application at `http://example.com/examples/multicounter`.
+
+## Complete Nginx Reverse Proxy Server Configuration[^n]
+
+Building on the 'One Application Per Subdomain' setup above, lets setup the serving a hypothetical To Do application. Our application will be responsible for serving the site's homepage. Nginx will serve any static assets ( css files, images etc ).
+
+```
+01: server
+02: {
+03:   server_name todo.example.com;
+04:  
+05:   root /var/www/todo.example.com/;
+06:   
+07:   location /
+08:   {
+09:     try_files $uri $uri/;
+10:   }
+11:   
+12:   proxy_redirect /todo /;
+13:   rewrite ^/$ /todo;
+14: 
+15:   location /todo
+16:   {
+17:     proxy_pass http://127.0.0.1:8080;
+18:   }
+19: }
+```
+
+A quick breakdown of the new elements we've introduced:
+
+* Line 5 tells nginx that any static attributes should be located by looking in `/var/www/todo.example.com/` This is equivalent to Apache's DocumentRoot directive.
+* The location directive that starts on line 7 defines how nginx should locate static assets[^n]. The try\_files directive on line 9 tells nginx to try to means to satisfy a URI. If our incoming request has a path of `/about` then, nginx will first look for a file called `about` in the server root. If that isn't found nginx will look for a directory `about/` in the server root. If neither rule can be satisfied, nginx will return a 404 error. 
+* Line 15 defines a location rule that is more specific than the one on line 7.  It will only be triggered if the URI path is `/todo`. This is the same setup that we saw in both of our previous examples.
+
+## Putting It All Together
+
+Now all we have to do is drop our reverse proxy server configuration into our nginx configuration and we end up with something like[^n]...
+
+```
+worker_processes 1;
+
+events
+{
+  worker_connections  1024;
+}
+
+http
+{
+  include       mime.types;
+  default_type  application/octet-stream;
+      
+  server
+  {
+    server_name todo.example.com;
+ 
+    root /var/www/todo.example.com/;
+  
+    location /
+    {
+      try_files $uri $uri/;
+    }
+  
+    proxy_redirect /todo /;
+    rewrite ^/$ /todo;
+
+    location /todo
+    {
+      proxy_pass http://127.0.0.1:8080;
+    }
+  }
+}
+```
+
+<div class="footnotes"><ol><li class="footnote" id="fn:1"><p>Or any other http client; one of my favorites is <a href="http://github.com/cloudhead/http-console">http console</a>. <a href="#fnref:1" title="return to article">↩</a></p></li>
+
+<li class="footnote" id="fn:2"><p>See <a href="http://wiki.nginx.org/NginxHttpProxyModule">Nginx wiki</a> for complete Nginx proxy module documentation. If you are running multiple Seaside application instances (on GLASS for instance), you should also check out the <a href="http://wiki.nginx.org/NginxHttpUpstreamModule">upstream</a>, <a href="http://wiki.nginx.org/NginxHttpUpstreamFairModule">fair upstream</a> and <a href="http://wiki.nginx.org/NginxHttpUpstreamRequestHashModule">upstrea [...]
+
+<li class="footnote" id="fn:3"><p>Location / is the most general location rule possible with nginx. It will used if a more specific location can't be found. <a href="#fnref:3" title="return to article">↩</a></p></li>
+
+<li class="footnote" id="fn:4"><p>Yours may look radically different. This is just a basic example of a full nginx configuration file. <a href="#fnref:4" title="return to article">↩</a></p></li></ol></div>
diff --git a/_site/content/post/role-not-title.md b/_site/content/post/role-not-title.md
new file mode 100644
index 0000000..9fda419
--- /dev/null
+++ b/_site/content/post/role-not-title.md
@@ -0,0 +1,10 @@
++++
+author = "Sean T. Allen"
+slug = "post-url-name"
+draft = true
+date = "2017-02-18T09:30:24-05:00"
+title = "role not title"
+tags = ["tag 1","tag 2"]
+
++++
+
diff --git a/_site/content/post/setting-up-a-monticello-repository-using-nginx.md b/_site/content/post/setting-up-a-monticello-repository-using-nginx.md
new file mode 100644
index 0000000..43ffb03
--- /dev/null
+++ b/_site/content/post/setting-up-a-monticello-repository-using-nginx.md
@@ -0,0 +1,130 @@
++++
+slug = "setting-up-a-monticello-repository-using-nginx"
+date = "2010-10-05T08:46:14-05:00"
+title = "Setting up a Monticello repository using Nginx"
+draft = false
+tags = ["nginx","smalltalk"]
+author = "Sean T. Allen"
+
++++
+## How Hard Could It Be?
+
+Not very hard; this little monkey who is more interested in bananas did it in no time flat. Setting up and running your own private Monticello repository is something almost any Smalltalker should be able to accomplish; as long as your aren't completely command line and systems administration phobic, you should be done with my directions within half an hour.
+
+## Installing Nginx with WebDAV Support
+
+Most prepackaged binary version of Nginx don't support WebDAV. If this is the case with yours, [download the latest stable version](http://nginx.org/) and build following the included instructions. You will need to change the standard configure step to one of the following:
+
+### Basic configuration
+
+```
+./configure --with-http_dav_module
+```
+
+### Advanced configuration to match the standard Debian/Ubuntu packages
+
+```
+./configure --prefix=/var/lib/nginx --conf-path=/etc/nginx/nginx.conf \ 
+  --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/error.log \
+  --http-log-path=/var/log/nginx/access.log --lock-path=/var/run/nginx.lock \
+  --user=www-data --group=www-data --sbin-path=/usr/sbin/nginx --with-http_dav_module
+```
+
+## Our Bare Bones Nginx Monticello Server Configuration
+
+```
+01: worker_processes 1;
+02: 
+03: events
+04: {
+05:   worker_connections  1024;
+06: }
+07: 
+08: http
+09: {
+10:   include       mime.types;
+11:   default_type  application/octet-stream;
+12:   
+13:   server
+14:   {
+15:     listen monticello.example.com;
+16:     server_name monticello.example.com;
+17: 
+18:     location / 
+19:     {
+20:       auth_basic "Monticello access restricted";
+21:       auth_basic_user_file /PATH_TO_OUR_PASSWORD_FILE;
+22: 
+23:       autoindex on;
+24: 
+25:       root /PATH_TO_OUR_MONTICELLO_REPOSITORY;
+26: 
+27:       dav_methods          PUT;
+28:       create_full_put_path on;
+29:       dav_access           group:rw  all:r;
+30:     } 
+31:   }
+32: }
+```
+
+The preceeding bit of code is a mostly bare bones Nginx Monticello server configuration. There isn't a whole lot to it, so I will quickly hit the points of interest:
+
+### Lines 15-16
+
+```
+listen monticello.example.com;
+server_name monticello.example.com;
+```
+
+Setup the name of our Monticello server and address it should be listening on.
+
+### Lines 18-19 & 30
+
+```
+location /
+{
+}
+```
+
+Define a location handler[^n] that encompasses everything that matches '/'. Any standard uri will match against this location so, you can consider it to be "global" in scope. Everything we want our Monticello server to do is handled by this one location handler.
+
+### Lines 20-21
+
+```
+auth_basic "Monticello access restricted";
+auth_basic_user_file /PATH_TO_OUR_PASSWORD_FILE;
+```
+
+Protects our Monticello repository from anonymous access using HTTP Basic Authentication. */PATH_TO_OUR_PASSWORD_FILE* should be replaced with the location of your password file. Your password file can be generated either using Apache's htpasswd application or using [this python script](http://wiki.nginx.org/NginxFaq#How_do_I_generate_an_httpasswd_file_without_having_Apache_tools_installed). N.B. Your password file has to be readable by the user that Nginx is running as. When installing  [...]
+
+### Line 23
+
+```
+autoindex on;
+```
+
+Is required for WebDAV to function properly- without directory indexing on, you will run into access denied errors.
+
+### Line 25
+
+```
+root /PATH_TO_OUR_MONTICELLO_REPOSITORY;
+```
+
+Defines the root of our WebDAV server. */PATH_TO_OUR_MONTICELLO_REPOSITORY* should be replaced with the directory that you are storing Monticello packages in. The directory has to be readable and writable by the user that Nginx is running as.
+
+### Lines 27-29
+
+```
+dav_methods          PUT;
+create_full_put_path on;
+dav_access           group:rw  all:r;
+```
+
+Define the rest of our WebDAV server setup. Instead of rehashing the [Nginx WebDAV documentation](http://wiki.nginx.org/HttpDavModule) I suggest you check the preceeding link as it covers this section of our setup in about as much time as it would take for me to detail it.
+
+## Are We Done?
+
+Indeed, but there is plenty more configuration that can be added to this basic Nginx WebDAV/Monticello setup. I would suggest visiting the [Nginx wiki](http://wiki.nginx.org/) to learn about Nginx so you can flesh out your configuration.
+
+<div class="footnotes"><ol><li class="footnote" id="fn:1"><p>See the <a href="http://wiki.nginx.org/NginxHttpCoreModule#location">Nginx wiki</a> for more information on the location directive. <a href="#fnref:1" title="return to article">↩</a></p></li></ol></div>
diff --git a/_site/content/post/sidestepping-technical-debt.md b/_site/content/post/sidestepping-technical-debt.md
new file mode 100644
index 0000000..c705a84
--- /dev/null
+++ b/_site/content/post/sidestepping-technical-debt.md
@@ -0,0 +1,10 @@
++++
+date = "2017-02-18T09:28:35-05:00"
+title = "sidestepping technical debt"
+tags = ["tag 1","tag 2"]
+author = "Sean T. Allen"
+slug = "post-url-name"
+draft = true
+
++++
+
diff --git a/_site/content/post/storm-applied-behind-the-scenes.md b/_site/content/post/storm-applied-behind-the-scenes.md
new file mode 100644
index 0000000..c0cfbea
--- /dev/null
+++ b/_site/content/post/storm-applied-behind-the-scenes.md
@@ -0,0 +1,33 @@
++++
+author = "Sean T. Allen"
+date = "2015-04-04T11:28:12-05:00"
+title = "Storm Applied: Behind the Scenes"
+slug = "storm-applied"
+draft = false
+tags = ["storm","storm applied"]
+
++++
+
+Almost two years ago, I embarked on a project that I had no idea the immensity of. And today, it has finally led to this:
+
+![Storm Applied](/img/post/storm-applied-behind-the-scenes/storm-applied.jpg)
+
+It started with my bugging [Matt Jankowski](https://twitter.com/mattjanks16) to write a ["mea culpa" blog post](http://dev.theladders.com/2013/03/riders-on-the-storm-take-a-long-holiday-let-your-children-play/) about our problems getting going with Storm at TheLadders. The idea was to start with a "boy we didn't know what we were doing" post and continue on with a series of posts about running Storm in a production. The first post happened, the rest never did. Instead, Manning reached ou [...]
+
+I don't remember now what I envisioned the book being when we first signed the contract. I know that Storm Applied isn't that book but I'm quite happy with it nonetheless. There's a lot of hard earned lessons packed into the latter half of the book that I think will help a lot of people trying to run Storm in production. Hopefully our pain can benefit a lot of people. There's a ton of stories I could tell about writing the book, some good, some bad but I think I'll just leave you with a  [...]
+
+* We really wanted to call the book _Thinking in Storm_ but there is already a _Thinking in ..._ series of books.
+* I wanted to subtitle the book "I wanna go fast" but that got rejected. Still, [it sort of worked out.](http://manning.com/sallen/excerpt_contents.html)
+* We intended to write "an advanced book" but ended up writing a book that starts as an intro and ends really advanced because there were no good intro Storm books in print.
+* I spent WAY TOO MUCH TIME trying to work lines from [this scene](https://www.youtube.com/watch?v=5A0-u85aAYg) into the book.
+* Manning googled an Eleanor Roosevelt quote and made us change the attribution to "misquoted".
+
+![Pretty sure Eleanor Roosevelt did say this](/content/images/2015/04/misquoted.png)
+
+* Most of the content I wrote was written using [Write Room](http://www.hogbaysoftware.com/products/writeroom). Full screen; no distractions = Awesome. Then Matt turned it into a "Manning usable" format because...
+* Manning uses MS Word for manuscripts. I managed to get through the entire book without really knowing how to use Word thanks to Matt.
+* The [source code for Chapter 6](https://github.com/Storm-Applied/C6-Flash-sale-recommender) got messed up and after the book had gone to press, I was working on recreating miss parts from what was in the chapter and memory.
+* Whenever our editor mentioned "the publisher", it always sounded very mysterious; much like someone talking about Charlie from Charlie's Angels. 
+* While writing Storm Applied, I [scientifically determined](https://www.youtube.com/watch?v=5ipGhzrIi3s&spfreload=10) that [The Jam](https://www.youtube.com/watch?v=GOK_vqtXgbk) is the [best band](https://www.youtube.com/watch?v=AE1ct5yEuVY) to [listen](https://www.youtube.com/watch?v=m-H0uIH5HHQ) to while [writing a book.](https://www.youtube.com/watch?v=hf4EFDGP4yg)
+
+O and...  [BUY MY BOOK!](http://manning.com/sallen/?a_aid=sallen)
diff --git a/_site/content/post/using-fastcgi-with-nginx-and-seaside.md b/_site/content/post/using-fastcgi-with-nginx-and-seaside.md
new file mode 100644
index 0000000..e314fd6
--- /dev/null
+++ b/_site/content/post/using-fastcgi-with-nginx-and-seaside.md
@@ -0,0 +1,119 @@
++++
+date = "2010-08-18T08:51:50-05:00"
+title = "Using FastCGI with Nginx and Seaside"
+tags = ["GLASS","nginx","smalltalk","seaside"]
+author = "Sean T. Allen"
+slug = "using-fastcgi-with-nginx-and-seaside"
+draft = false
+
++++
+
+## Why FastCGI a.k.a Why Not Reverse Proxy?
+
+I've [previously written](/2010/06/24/reverse-proxying-to-seaside-with-nginx/) about why I prefer reverse proxying to FastCGI. I still believe all those points, however there are certain Seaside deployment situations where FastCGI is currently preferable to reverse proxying. If you are deploying your Seaside application to run on Gemstone's [GLASS](http://seaside.gemstone.com/) then you should give FastCGI serious consideration. The current swazoo adapter that you use when proxying to GL [...]
+
+## Our Bare Bones Nginx FastCGI Configuration
+
+```
+worker_processes 1;
+
+events
+{
+  worker_connections  1024;
+}
+
+http
+{
+  include       mime.types;
+  default_type  application/octet-stream;
+  
+  upstream seaside 
+  {
+    server localhost:9001;
+    server localhost:9002;
+    server localhost:9003;
+  }
+
+  server
+  {
+    root /var/www/glass/;
+
+    location /
+    { 
+      error_page 403 404 = @seaside;
+    }
+    
+    location @seaside
+    {
+      include fastcgi_params;
+      fastcgi_pass seaside;
+    }
+  }
+}
+```
+
+The preceeding bit of code is a mostly bare bones Nginx to GLASS FastCGI configuration. There isn't a whole lot to it, so I will quickly hit the points of interest:
+
+### Lines 13-18
+
+```
+upstream seaside 
+{
+  server localhost:9001;
+  server localhost:9002;
+  server localhost:9003;
+}
+```
+
+Define a named upstream pool called _seaside_. The default GLASS installation sets up 3 FastCGI listeners on ports 9001 to 9003. You would just add more server entries in the upstream block to have Nginx start using any additional FastCGI listeners that you might setup in GLASS.
+
+### Line 22
+
+```
+root /var/www/glass/;
+```
+
+Defines where our static assets like images, css and html are served from. You need to change the definition to a directory you create or create _/var/www/glass/_ and populate it with your various assets.
+
+### Lines 24-27
+
+```
+location /
+{ 
+  error_page 403 404 = @seaside;
+}
+```
+
+Define a location handler[^n] that encompasses everything that matches '/'. Any standard uri will match against this location so, you can consider it to be "global" in scope. Line 26 states that any uri request that would result in an http 403 or 404 response code should be routed to the named location _@seaside_. N.B. This named location is not the same as our upstream block. Nginx will process a request as follows:
+
+1. Check to see if a static asset for the uri exists. If it does, return it.
+2. If a static asset doesn't exist then either a 403 or 404 error will be generated resulting in handing the uri off to the @seaside location.
+
+This could also be done as:
+
+```
+location /
+{ 
+  try_files $uri @seaside;
+}
+```
+
+Getting into the details of why you would prefer _try\_files_ or _error\_page_ is the subject for another post.
+
+### Lines 29-33
+
+```
+location @seaside
+{
+  include fastcgi_params;
+  fastcgi_pass seaside;
+}
+```
+
+Define our named @seaside location that is responsible for handling FastCGI. The _include fastcgi\_params_ directive has Nginx include its standard FastCGI protocol definitions that are installed at _/etc/nginx/fastcgi\_params_. The _fastcgi\_pass_ directive simply says: 'pass all uris from this to the servers defined in the _seaside_ upstream block'.
+
+## Are We Done?
+
+Yes. Yes we are. There is plenty more configuration that can be added to make the FastCGI handling more robust ( failovers, timeouts etc ), but that is all you need to get started. I would suggest visiting the [Nginx wiki](http://wiki.nginx.org/) to learn about Nginx so you can flesh out your configuration. If you run into issues or need any help, feel free to drop me an email or catch up with me on [Twitter](http://www.twitter.com/SeanTAllen).
+
+<div class="footnotes"><ol><li class="footnote" id="fn:1"><p>See the <a href="http://wiki.nginx.org/NginxHttpCoreModule#location">Nginx wiki</a> for more information on the location directive. <a href="#fnref:1" title="return to article">↩</a></p></li></ol></div>
diff --git a/_site/content/post/varnish-in-five-acts.md b/_site/content/post/varnish-in-five-acts.md
new file mode 100644
index 0000000..dc44f36
--- /dev/null
+++ b/_site/content/post/varnish-in-five-acts.md
@@ -0,0 +1,393 @@
++++
+date = "2013-05-03T13:21:47-05:00"
+title = "Varnish in Five Acts"
+draft = true
+tags = ["varnish","scaling"]
+author = "Sean T. Allen"
+slug = "varnish-in-five-acts"
+
++++
+
+
+> “Take a load off Annie. Take a load for free. Take a load off Annie. And you put the load right on me.” -- Robbie Robertson
+
+## Act I: The Players
+
+At my current employer, we have a number of entity services that clients access via HTTP. Some examples are the job service, the job application service and the topic of this post: the job seeker service. Each service manages the lifecycle of a core entity in our domain. On each request, the service gathers data from multiple data sources to build a complete entity and then serializes that entity to JSON. This is done for every request and is incredibly wasteful when you consider that mo [...]
+
+All this repeated, unnecessary entity object assembly and JSON serialization created scaling problems. Making matters worse, we periodically have batch processes that can increase service load by an order of magnitude. Caching is an easy win here. The question is how.
+
+Initial attempts to cache these entities were done inside the service JVMs, using familiar and popular JVM based caches like EHcache and calls out to memcache. Unfortunately, this left us operating at JVM speeds and the caches were competing with the service logic for memory and threads.
+
+In addition, our service code was muddled with messy caching logic.  Making the code harder to reuse, and more annoyingly, changes just affecting caching forced us to re-release the entire service.  We didn’t like this mixing of concerns.
+
+We thought we could do better if we used external read through caches. It's easy to slide them between existing clients and services. With caching outside the service, it get released only when their logic changes not because we’re tuning caching.
+
+For reasons too numerous to cover in this post we chose [Varnish](https://www.varnish-cache.org/about) as our read through cache.
+
+****
+
+## Act II: The Architecture
+
+When we introduced Varnish to our architecture, we wanted to make sure we were not adding a single point of failure. Simply put, if the cache layer goes down, our infrastructure should continue running. Performance might be degraded, but we should continue to be able to serve content to clients.
+
+The diagram below shows a typical setup. In a normal scenario, a client accesses Varnish via a load balancer. Varnish in turn farms out the work in round robin fashion to one of four job seeker service nodes. Should Varnish become unavailable, the load balancer stops sending traffic to Varnish and reroutes it to the four job seeker service nodes.
+
+![](/img/post/varnish-in-five-acts/varnish-flow.png)
+
+Of all our entity services, the job seeker services carries the highest median load. The graph below is the 1 minute request rate on 4 service nodes over the 36 hour period before and after Varnish was turned on.
+
+![](/img/post/varnish-in-five-acts/before-after.png)
+
+****
+
+## Act III: Cache Invalidation
+
+Cache invalidation is one of the 2 hard problems in computer science along with naming things and off by one errors.
+
+We cache job seeker entity representations until some point in the “far future”, which is great until something about that job seeker changes, then we must invalidate the cached entry. So, how do we do that?
+
+Two ways.
+
+### Via Header:
+
+All requests that change the state of a job seeker that are made via the service attach a header in the response called "x-invalidates" that looks something like:
+
+```
+x-invalidates: /jobseeker/123
+```
+
+Varnish, when it sees this header, turns the value into a content expiring regular expression. My team mate [@johnconnolly](http://twitter.com/johnconnolly) learned about this general technique from [Kevin Burns Jr.](https://twitter.com/kevburnsjr) at [http://restfest.org](RESTFest) 2012.  I used Kevin’s post on the [subject](http://blog.kevburnsjr.com/tagged-cache-invalidation) as a jumping off point for our implementation.
+
+### Via Magic:
+
+Once upon a time, we had a database administrator named Gennady. Gennady wrote a [PHP script that reads MySQL’s binary logs](http://www.dinodigusa.com/images/Magic1.gif), looking for changes to a set of predefined tables. When it sees an update, it finds the primary key for the row and fires off an invalidation request. In our case, a purge of the cached entity url in Varnish. This allows us to invalidate cached job seeker entities even when the update was performed via legacy code that  [...]
+
+If you were to do this manually, it would look something like:
+
+```
+curl -X PURGE varnish-jobseeker/jobseeker/123
+```
+
+****
+
+## Act IV: Configuration Spelunking
+
+So, how did we do it? I’m going to break down our configuration into its parts and cover the general role each part plays. From here on out, I’m assuming you understand the basics of how Varnish works and how you configure it. Also, there is some repetition in our configuration that isn’t required, it just makes it easier for our configuration management tool, puppet, to create the final output.
+
+### Load Balancing
+
+We have four service servers behind varnish so we create four backend entries and then set up a director to round robin between them. Then in vcl_recv, we set our director named 'nodes' to be the backend that we will use to fetch content.
+
+``` bash
+backend JS1 {
+  .host  = "JS1";
+  .port  = "8080";
+
+  ...
+}
+
+backend JS2 {
+  .host  = "JS2";
+  .port  = "8080";
+
+  ...
+}
+
+backend JS3 {
+  .host  = "JS3";
+  .port  = "8080";
+
+  ...
+}
+
+backend JS4 {
+  .host  = "JS4";
+  .port  = "8080";
+
+  ...
+}
+
+director nodes round-robin {
+  { .backend = JS1 ; }
+  { .backend = JS2 ; }
+  { .backend = JS3 ; }
+  { .backend = JS4 ; }
+}
+
+sub vcl_recv {
+  set req.backend = nodes;
+}
+
+# store in cache only by url, not backend host
+sub vcl_hash {
+  hash_data(req.url);
+  return (hash);
+}
+```
+
+### Degraded
+
+Each backend is setup with a probe url that we use to check its health. If the probe url doesn't return at least one HTTP 200 response within a fifteen second period, we mark that backend as unhealthy.
+
+``` bash
+backend ... {
+   ...
+
+  .probe = {
+    .url = "/donjohnson/pulse";
+    .interval = 5s;
+    .timeout = 250ms;
+    .window = 3;
+    .threshold = 2;
+  }
+}
+```
+
+Varnish has the concept of a grace period, wherein, we can keep content alive in our cache past the TTL based on the health status of our backends. In our case, when the all backends are down, we keep cached items alive for an extra hour. During this time, we operate in a degraded status. Read requests for cached items will be handled while write requests will fail because there is no backend service to handle them.
+
+``` bash
+sub vcl_fetch {
+  # max time to keep an item in the cache past its ttl
+  # used in conjunction with code in vcl_recv to
+  # deal with 'sick' backends
+  set beresp.grace = 1h;
+
+  ...
+}
+
+sub vcl_recv {
+  ...
+
+  # extra ttl for cached objects based on backend health
+  if (!req.backend.healthy) {
+    set req.grace = 1h;
+  } else {
+    set req.grace = 15s;
+  }
+}
+```
+
+### Invalidation
+
+We do two types of invalidation:
+
+* invalidation based on the 'x-invalidates' header that comes back with a response
+* 'manual' invalidation based on sending the HTTP PURGE verb to a url in the Varnish cache.
+
+The ability to do a manual purge is limited to a small set of IP addresses that we validate against when a purge request is received.
+
+``` bash
+acl purge {
+  "localhost";
+  "10.10.10.10";
+}
+
+sub vcl_recv {
+  ...
+
+  # 'manual' purge
+  if (req.request == "PURGE") {
+    if (client.ip ~ purge) {
+       return(lookup);
+    }
+
+    error 405 "Not allowed.";
+  }
+
+  ...
+}
+```
+
+The actual mechanics of doing the purge are fairly simple. If the url attempted to be purged exists, purge it and return a 200.
+
+``` bash
+sub vcl_hit {
+  # 'manual' purge
+  if (req.request == "PURGE") {
+    purge;
+    error 200 "Purged.";
+  }
+}
+```
+
+If it doesn't, return a 404 response code:
+
+``` bash
+sub vcl_miss {
+  # 'manual' purge
+  if (req.request == "PURGE") {
+    purge;
+    error 404 "Not in cache.";
+  }
+}
+```
+
+Update requests include invalidation-related headers. Every request we fetch has, inside of Varnish, its request url stored in a special x-url header. This will be used as the url to check the x-invalidates header against. As this header is purely for our internal use, we remove it before delivering items to a client:
+
+``` bash
+sub vcl_fetch {
+  ...
+
+  set beresp.http.x-url = req.url;
+
+  ...
+}
+
+sub vcl_deliver {
+  # clear internal cache invalidation header before sending to client
+  unset resp.http.x-url;
+}
+```
+
+Any 'successful' PUT, POST, DELETE or PATCH response will have its x-invalidates header used as a regular expression to invalidate existing content whose x-url header matches the x-invalidates regex.
+
+```
+sub vcl_fetch {
+  ...
+
+  # cache invalidation
+  set beresp.http.x-url = req.url;
+  if (req.request == "PUT" || req.request == "POST" || req.request == "DELETE" || req.request == "PATCH") {
+    if  (beresp.status >= 200 && beresp.status < 400) {
+     ban("obj.http.x-url ~ " + beresp.http.x-invalidates);
+    }
+  }
+}
+```
+****
+
+## Act V: The final product
+
+And finally, we put it all together into a complete file (note, we use Varnish 3, the semantics around ban/purge changed from v2 to v3):
+
+``` bash
+backend JS1 {
+  .host  = "JS1";
+  .port  = "8080";
+  .probe = {
+    .url = "/donjohnson/pulse";
+    .interval = 5s;
+    .timeout = 250ms;
+    .window = 3;
+    .threshold = 2;
+  }
+}
+
+backend JS2 {
+  .host  = "JS2";
+  .port  = "8080";
+  .probe = {
+    .url = "/donjohnson/pulse";
+    .interval = 5s;
+    .timeout = 250ms;
+    .window = 3;
+    .threshold = 2;
+  }
+}
+
+backend JS3 {
+  .host  = "JS3";
+  .port  = "8080";
+  .probe = {
+    .url = "/donjohnson/pulse";
+    .interval = 5s;
+    .timeout = 250ms;
+    .window = 3;
+    .threshold = 2;
+  }
+}
+
+backend JS4 {
+  .host  = "JS4";
+  .port  = "8080";
+  .probe = {
+    .url = "/donjohnson/pulse";
+    .interval = 5s;
+    .timeout = 250ms;
+    .window = 3;
+    .threshold = 2;
+  }
+}
+
+director nodes round-robin {
+  { .backend = JS1 ; }
+  { .backend = JS2 ; }
+  { .backend = JS3 ; }
+  { .backend = JS4 ; }
+}
+
+# what machines can institute a 'manual' purge
+acl purge {
+  "localhost";
+  "192.1.1.4";
+}
+
+# store in cache only by url, not backend host
+sub vcl_hash {
+  hash_data(req.url);
+  return (hash);
+}
+
+sub vcl_fetch {
+  # max time to keep an item in the cache past its ttl
+  # used in conjunction with code in vcl_recv to
+  # deal with 'sick' backends
+  set beresp.grace = 1h;
+
+  # cache invalidation
+  set beresp.http.x-url = req.url;
+  if (req.request == "PUT" || req.request == "POST" || req.request == "DELETE" || req.request == "PATCH") {
+    if  (beresp.status >= 200 && beresp.status < 400) {
+     ban("obj.http.x-url ~ " + beresp.http.x-invalidates);
+    }
+  }
+}
+
+sub vcl_recv {
+  set req.backend = nodes;
+
+  # 'manual' purge
+  if (req.request == "PURGE") {
+    if (client.ip ~ purge) {
+       return(lookup);
+    }
+
+    error 405 "Not allowed.";
+  }
+
+  # extra ttl for cached objects based on backend health
+  if (!req.backend.healthy) {
+    set req.grace = 1h;
+  } else {
+    set req.grace = 15s;
+  }
+}
+
+sub vcl_deliver {
+  # clear internal cache invalidation header before sending to client
+  unset resp.http.x-url;
+}
+
+sub vcl_hit {
+  # 'manual' purge
+  if (req.request == "PURGE") {
+    purge;
+    error 200 "Purged.";
+  }
+}
+
+sub vcl_miss {
+  # 'manual' purge
+  if (req.request == "PURGE") {
+    purge;
+    error 404 "Not in cache.";
+  }
+}
+```
+
+## Hidden Track Bonus Act:
+
+![](/img/post/varnish-in-five-acts/varnish-all-the-things.jpg)
+
+Join the discussion over at [Hacker News](https://news.ycombinator.com/item?id=5651874).
diff --git a/_site/content/post/why-pony-polyconf-17.md b/_site/content/post/why-pony-polyconf-17.md
new file mode 100644
index 0000000..fd4febb
--- /dev/null
+++ b/_site/content/post/why-pony-polyconf-17.md
@@ -0,0 +1,13 @@
++++
+draft = false
+date = "2017-08-19T09:56:56-05:00"
+title = "Polyconf'17: Why Pony?"
+tags = ["talks","pony", "video", "slides"]
+description = "Post with link my Polyconf'17 talk \"Why Pony? Bleeding edge technology for your concurrency woes\"."
+author = "Sean T. Allen"
+slug = "polyconf-17-why-pony"
++++
+
+## Why Pony? Bleeding edge technology for your concurrency woes
+
+Video of my [Polyconf'17](https://polyconf.com/) talk ["Why Pony? Bleeding edge technology for your concurrency woes"](https://www.youtube.com/watch?v=0XFhTrtOGK4) is now available. The slides are available [here](https://speakerdeck.com/seantallen/why-pony).
diff --git a/_site/content/post/why-pony.md b/_site/content/post/why-pony.md
new file mode 100644
index 0000000..179d8c9
--- /dev/null
+++ b/_site/content/post/why-pony.md
@@ -0,0 +1,39 @@
++++
+date = "2017-02-18T09:24:45-05:00"
+title = "Why Pony?"
+tags = ["pony","erlang","c"]
+author = "Sean T. Allen"
+slug = "why-pony"
+draft = true
+
++++
+
+Early in 2015, [Pony](http://www.ponylang.org) a high performance actor based language caught my eye. Pony's feature set excites me quite a bit, however, the language is very immature. Making the decision to base a production application on new, immature technology is fraught with uncertainty. I've spent a lot of time thinking about where it might be appropriate to leverage Pony. 
+
+[The Pony philosophy](https://github.com/CausalityLtd/ponyc/wiki/Philosophy):
+
+> Correctness. Incorrectness is simply not allowed. It's pointless to try to get stuff done if you can't guarantee the result is correct.
+
+> Performance. Runtime speed is more important than everything except correctness. If performance must be sacrificed for correctness, try to come up with a new way to do things. The faster the program can get stuff done, the better. This is more important than anything except a correct result.
+
+> Simplicity. Simplicity can be sacrificed for performance. It is more important for the interface to be simple than the implementation. The faster the programmer can get stuff done, the better. It's ok to make things a bit harder on the programmer to improve performance, but it's more important to make things easier on the programmer than it is to make things easier on the language/runtime.
+
+> Consistency. Consistency can be sacrificed for simplicity or performance. Don't let excessive consistency get in the way of getting stuff done.
+
+> Completeness. It's nice to cover as many things as possible, but completeness can be sacrificed for anything else. It's better to get some stuff done now than wait until everything can get done later. 
+
+
+## The case of Pony v Erlang
+
+People often compare Pony to Erlang because they are both actor based. It's a natural comparison to want to make. A lot of the people I see getting interested in Pony are coming from an Erlang background. While it's appropriate to compare the goals of the language, you shouldn't be formulating questions like- 'Should I use Erlang or should I use Pony?' Erlang is a very mature language that has been in existence for over 20 years. Pony is less than 5 years old. Extensive native tooling ex [...]
+
+## The case of Pony v C
+
+If writing your application in C is something you are seriously considering, then there is a case for Pony. Pony started its life as an actor library that was callable from C and you can still [use Pony in that fashion](http://bluishcoder.co.nz/2015/12/16/c-linkable-libraries-with-pony.html). Pony and C integration is excellent. At this point in its life, I consider Pony to an excellent complement to C. You can use existing C tooling with Pony while leveraging Pony's type system and conc [...]
+
+If you are looking at a C project and think:
+
+* The Actor model would be a good concurrency model for your project 
+* You'd like the compiler support to verify you are sharing memory safely
+
+then Pony might be right for you. The right way to think of Pony is as a better C that provides an excellent high performance, safe concurrent programming model based on actors.
diff --git a/_site/static/CNAME b/_site/static/CNAME
new file mode 100644
index 0000000..1bc9fad
--- /dev/null
+++ b/_site/static/CNAME
@@ -0,0 +1 @@
+www.monkeysnatchbanana.com
diff --git a/_site/static/img/avatar.png b/_site/static/img/avatar.png
new file mode 100644
index 0000000..0791eb6
Binary files /dev/null and b/_site/static/img/avatar.png differ
diff --git a/_site/static/img/ctakes_logo.jpg b/_site/static/img/ctakes_logo.jpg
new file mode 100644
index 0000000..4089c34
Binary files /dev/null and b/_site/static/img/ctakes_logo.jpg differ
diff --git a/_site/static/img/logo.png b/_site/static/img/logo.png
new file mode 100644
index 0000000..0791eb6
Binary files /dev/null and b/_site/static/img/logo.png differ
diff --git a/_site/static/img/post/interview-with-lobste-rs/IMG_3648.jpg b/_site/static/img/post/interview-with-lobste-rs/IMG_3648.jpg
new file mode 100644
index 0000000..2863c69
Binary files /dev/null and b/_site/static/img/post/interview-with-lobste-rs/IMG_3648.jpg differ
diff --git a/_site/static/img/post/on-becoming-a-better-teacher/Definition-of-web-scale-from-Storm-Applied.png b/_site/static/img/post/on-becoming-a-better-teacher/Definition-of-web-scale-from-Storm-Applied.png
new file mode 100644
index 0000000..0d684da
Binary files /dev/null and b/_site/static/img/post/on-becoming-a-better-teacher/Definition-of-web-scale-from-Storm-Applied.png differ
diff --git a/_site/static/img/post/pony-patterns-waiting/Screenshot-2016-01-18-16-51-54.png b/_site/static/img/post/pony-patterns-waiting/Screenshot-2016-01-18-16-51-54.png
new file mode 100644
index 0000000..20c894c
Binary files /dev/null and b/_site/static/img/post/pony-patterns-waiting/Screenshot-2016-01-18-16-51-54.png differ
diff --git a/_site/static/img/post/storm-applied-behind-the-scenes/storm-applied.jpg b/_site/static/img/post/storm-applied-behind-the-scenes/storm-applied.jpg
new file mode 100644
index 0000000..ec953ec
Binary files /dev/null and b/_site/static/img/post/storm-applied-behind-the-scenes/storm-applied.jpg differ
diff --git a/_site/static/img/post/varnish-in-five-acts/before-after.png b/_site/static/img/post/varnish-in-five-acts/before-after.png
new file mode 100644
index 0000000..e807679
Binary files /dev/null and b/_site/static/img/post/varnish-in-five-acts/before-after.png differ
diff --git a/_site/static/img/post/varnish-in-five-acts/varnish-all-the-things.jpg b/_site/static/img/post/varnish-in-five-acts/varnish-all-the-things.jpg
new file mode 100644
index 0000000..ba61ef5
Binary files /dev/null and b/_site/static/img/post/varnish-in-five-acts/varnish-all-the-things.jpg differ
diff --git a/_site/static/img/post/varnish-in-five-acts/varnish-flow.png b/_site/static/img/post/varnish-in-five-acts/varnish-flow.png
new file mode 100644
index 0000000..126575c
Binary files /dev/null and b/_site/static/img/post/varnish-in-five-acts/varnish-flow.png differ
diff --git a/_site/themes/sean-steam/CHANGELOG.md b/_site/themes/sean-steam/CHANGELOG.md
new file mode 100644
index 0000000..46c52a4
--- /dev/null
+++ b/_site/themes/sean-steam/CHANGELOG.md
@@ -0,0 +1,15 @@
+# Changelog
+
+### 27th November 2016
+
+- `favicon` allows you to link a custom favicon by adding a path relative to the `static` folder
+- with `customCSS` and `customJS` you can link your own stylesheets and scripts. The files have to be link relative to `static` as well.
+
+### 26th November 2016
+
+Some of the new features of Hugo v0.17 were now introduced in this theme. Since some changes are not backwards compatible you have to update to Hugo v0.17 or newer versions.
+
+- Steam now uses the Google Analytics template that is shipped with Hugo. Just move the `googleAnaltics` variable outside the `params` block. Have a look at the [example config file](https://github.com/digitalcraftsman/hugo-steam-theme/blob/master/exampleSite/config.toml).
+- The support for Google Plus comments in now deprecated.
+- Formerly, it was only possible to show pages of `type` post on the homepage. Now, all types of pages are shown. You can hide single pages by adding `hide = true` to the (TOML) frontmatter.
+- External dependencies like Highlight.js have been updated to the latest version.
diff --git a/_site/themes/sean-steam/LICENSE.md b/_site/themes/sean-steam/LICENSE.md
new file mode 100644
index 0000000..9667d69
--- /dev/null
+++ b/_site/themes/sean-steam/LICENSE.md
@@ -0,0 +1,22 @@
+Copyright (c) 2015 Digitalcraftsman - Released under The MIT License.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/_site/themes/sean-steam/README.md b/_site/themes/sean-steam/README.md
new file mode 100644
index 0000000..022e5dd
--- /dev/null
+++ b/_site/themes/sean-steam/README.md
@@ -0,0 +1,76 @@
+# Steam
+
+Steam is a minimal and customizable theme for bloggers and was developed by [Tommaso Barbato](//github.com/epistrephein). He created it as a slightly adapted version of the [Vapor](//github.com/sethlilly/Vapor) Ghost theme by [Seth Lilly](//github.com/sethlilly). Noteworthy features of this Hugo port are the integration of a comment-system powered by Disqus, the customizable appearance by changing theme colors, support for RSS feeds, syntax highlighting via Highlight.js for source code a [...]
+
+![Screenshot](https://raw.githubusercontent.com/digitalcraftsman/hugo-steam-theme/dev/images/screenshot.png)
+
+
+## Installation
+
+Inside the folder of your Hugo site run:
+
+    $ cd themes
+    $ git clone https://github.com/digitalcraftsman/hugo-steam-theme.git
+
+For more information read the official [setup guide](//gohugo.io/overview/installing/) of Hugo.
+
+### The config file
+
+Take a look inside the [`exampleSite`](//github.com/digitalcraftsman/hugo-steam-theme/blob/dev/exampleSite/) folder of this theme. You'll find a file called [`config.toml`](//github.com/digitalcraftsman/hugo-steam-theme/blob/dev/exampleSite/config.toml).
+
+To use it, copy the [`config.toml`](//github.com/digitalcraftsman/hugo-steam-theme/blob/dev/exampleSite/config.toml) in the root folder of your Hugo site. Feel free to change strings as you like to customize your website.
+
+## Add links to the navigation
+
+You can add custom pages like this by adding `menu = "main"` in the frontmatter:
+
+```toml
++++
+date  = "2015-08-22"
+title = "About me"
+menu  = "main"
++++
+```
+
+If no document contains menu = "main" in the frontmatter than the navigation will not be shown
+
+
+## Customize theme colors
+
+This theme features four different theme colors (green as default, blue, red and orange) that change the appearance of you Hugo site slightly. Just set the `themeColor` variable to the color you like.
+
+Furthermore you can create your own theme. Under [`layouts/partials/themes`](//github.com/digitalcraftsman/hugo-steam-theme/tree/dev/layouts/partials/themes) you'll find a stylesheet template called [`custom-theme.html`](//github.com/digitalcraftsman/hugo-steam-theme/blob/dev/layouts/partials/themes/custom-theme.html). Customize the colors as you like and save the new theme with the schema `<myNewColor>-theme.html` within the same folder. As you can see, the color is the prefix of the st [...]
+
+## Comments
+
+This theme features a comment system powered by Disqus. To enable it you have to add your Disqus shortname to the `disqusShortname` variable in the config file.
+
+## Nearly finished
+
+In order to see your site in action, run Hugo's built-in local server. 
+
+    $ hugo server
+
+Now enter [`localhost:1313`](http://localhost:1313) in the address bar of your browser.
+
+## Changelog
+
+You can find the latest changes and improvements of this theme in the [CHANGELOG.md](https://github.com/digitalcraftsman/hugo-steam-theme/blob/master/CHANGELOG.md)
+
+
+## Contributing
+
+Did you found a bug or got an idea for a new feature? Feel free to use the [issue tracker](//github.com/digitalcraftsman/hugo-steam-theme/issues) to let me know. Or make directly a [pull request](//github.com/digitalcraftsman/hugo-steam-theme/pulls).
+
+
+## License
+
+This theme is released under the MIT license. For more information read the [License](//github.com/digitalcraftsman/hugo-steam-theme/blob/master/LICENSE.md).
+
+
+## Annotations
+
+Thanks to 
+
+- [Steve Francia](//github.com/spf13) for creating Hugo and the awesome community around the project.
+- [Seth Lilly](//github.com/sethlilly) and [Tommaso Barbato](//github.com/epistrephein) for developing the original version(s) of this theme
diff --git a/_site/themes/sean-steam/archetypes/default.md b/_site/themes/sean-steam/archetypes/default.md
new file mode 100644
index 0000000..0ac3054
--- /dev/null
+++ b/_site/themes/sean-steam/archetypes/default.md
@@ -0,0 +1,4 @@
++++
+
++++
+
diff --git a/_site/themes/sean-steam/exampleSite/config.toml b/_site/themes/sean-steam/exampleSite/config.toml
new file mode 100644
index 0000000..a77808a
--- /dev/null
+++ b/_site/themes/sean-steam/exampleSite/config.toml
@@ -0,0 +1,45 @@
+baseurl = "https://example.org/"
+languageCode = "en-us"
+title = "Steam - a minimal theme for Hugo"
+theme = "hugo-steam-theme"
+disqusShortname = "spf13"
+# Enable Google Analytics be inserting your tracking code
+googleAnalytics = ""
+# Number of posts per page
+paginate = 10
+
+[params]
+	title = "Steam"
+	subtitle = "a minimal theme for ~~Ghost~~ Hugo"
+	copyright = "Released under the MIT license."
+
+	# You can choose between green, orange, red and blue.
+	themecolor = "green"
+
+	# Link custom assets relative to /static
+	favicon   = "favicon.ico"
+	customCSS = []
+	customJS  = []
+
+	# To provide some metadata for search engines and the about section in the footer
+	# feel free to add a few information about you and your website.
+	name = "John Doe"
+	bio = "programmer - blogger - coffee aficionado"
+	description = "Your description of the blog"
+	
+	# Link your social networks (optional)
+	location = ""
+	twitter = "spf13"
+	linkedin = ""
+	googleplus = ""
+	facebook = ""
+	instagram = ""
+	github = "spf13"
+	gitlab = ""
+	bitbucket = ""
+
+	# Customize or translate the strings
+	keepReadingStr = "Keep reading"
+	backtotopStr = "Back to top"
+	shareStr = "Share"
+	pageNotFoundTitle = "404 - Page not found"
diff --git a/_site/themes/sean-steam/exampleSite/content/about.md b/_site/themes/sean-steam/exampleSite/content/about.md
new file mode 100644
index 0000000..ef6f5bd
--- /dev/null
+++ b/_site/themes/sean-steam/exampleSite/content/about.md
@@ -0,0 +1,20 @@
++++
+date  = "2015-08-22"
+title = "Link custom pages"
+menu  = "main"
+url = "about/"
+hide = "true"
++++
+
+You can add custom pages like this by adding `menu = "main"` in the frontmatter:
+
+```toml
++++
+date  = "2015-08-22"
+title = "About me"
+menu  = "main"
+url = "about/"
++++
+```
+
+This site is just a usual document. Create a new file, e.g. `about.md` in the `content` content directory. The `url` variable in the frontmatter allows you to define the final url of the about page.
\ No newline at end of file
diff --git a/_site/themes/sean-steam/exampleSite/content/post/goisforlovers.md b/_site/themes/sean-steam/exampleSite/content/post/goisforlovers.md
new file mode 100644
index 0000000..4087031
--- /dev/null
+++ b/_site/themes/sean-steam/exampleSite/content/post/goisforlovers.md
@@ -0,0 +1,343 @@
++++
+title = "(Hu)go Template Primer"
+tags = [
+    "go",
+    "golang",
+    "templates",
+    "themes",
+    "development",
+]
+date = "2014-04-02"
+categories = [
+    "Development",
+    "golang",
+]
+description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Earum similique, ipsum officia amet blanditiis provident ratione nihil ipsam dolorem repellat."
++++
+
+Hugo uses the excellent [go][] [html/template][gohtmltemplate] library for
+its template engine. It is an extremely lightweight engine that provides a very
+small amount of logic. In our experience that it is just the right amount of
+logic to be able to create a good static website. If you have used other
+template systems from different languages or frameworks you will find a lot of
+similarities in go templates.
+
+This document is a brief primer on using go templates. The [go docs][gohtmltemplate]
+provide more details.
+
+## Introduction to Go Templates
+
+Go templates provide an extremely simple template language. It adheres to the
+belief that only the most basic of logic belongs in the template or view layer.
+One consequence of this simplicity is that go templates parse very quickly.
+
+A unique characteristic of go templates is they are content aware. Variables and
+content will be sanitized depending on the context of where they are used. More
+details can be found in the [go docs][gohtmltemplate].
+
+## Basic Syntax
+
+Go lang templates are html files with the addition of variables and
+functions. 
+
+**Go variables and functions are accessible within {{ }}**
+
+Accessing a predefined variable "foo":
+
+    {{ foo }}
+
+**Parameters are separated using spaces**
+
+Calling the add function with input of 1, 2:
+
+    {{ add 1 2 }}
+
+**Methods and fields are accessed via dot notation**
+
+Accessing the Page Parameter "bar"
+
+    {{ .Params.bar }}
+
+**Parentheses can be used to group items together**
+
+    {{ if or (isset .Params "alt") (isset .Params "caption") }} Caption {{ end }}
+
+
+## Variables
+
+Each go template has a struct (object) made available to it. In hugo each
+template is passed either a page or a node struct depending on which type of
+page you are rendering. More details are available on the
+[variables](/layout/variables) page.
+
+A variable is accessed by referencing the variable name.
+
+    <title>{{ .Title }}</title>
+
+Variables can also be defined and referenced.
+
+    {{ $address := "123 Main St."}}
+    {{ $address }}
+
+
+## Functions
+
+Go template ship with a few functions which provide basic functionality. The go
+template system also provides a mechanism for applications to extend the
+available functions with their own. [Hugo template
+functions](/layout/functions) provide some additional functionality we believe
+are useful for building websites. Functions are called by using their name
+followed by the required parameters separated by spaces. Template
+functions cannot be added without recompiling hugo.
+
+**Example:**
+
+    {{ add 1 2 }}
+
+## Includes
+
+When including another template you will pass to it the data it will be
+able to access. To pass along the current context please remember to
+include a trailing dot. The templates location will always be starting at
+the /layout/ directory within Hugo.
+
+**Example:**
+
+    {{ template "chrome/header.html" . }}
+
+
+## Logic
+
+Go templates provide the most basic iteration and conditional logic.
+
+### Iteration 
+
+Just like in go, the go templates make heavy use of range to iterate over
+a map, array or slice. The following are different examples of how to use
+range.
+
+**Example 1: Using Context**
+
+    {{ range array }} 
+        {{ . }}
+    {{ end }}
+
+**Example 2: Declaring value variable name**
+
+    {{range $element := array}} 
+        {{ $element }} 
+    {{ end }}
+
+**Example 2: Declaring key and value variable name**
+
+    {{range $index, $element := array}}
+        {{ $index }} 
+        {{ $element }} 
+    {{ end }}
+
+### Conditionals 
+
+If, else, with, or, & and provide the framework for handling conditional
+logic in Go Templates. Like range, each statement is closed with `end`.
+
+
+Go Templates treat the following values as false: 
+
+* false
+* 0 
+* any array, slice, map, or string of length zero
+
+**Example 1: If**
+
+    {{ if isset .Params "title" }}<h4>{{ index .Params "title" }}</h4>{{ end }}
+
+**Example 2: If -> Else** 
+
+    {{ if isset .Params "alt" }} 
+        {{ index .Params "alt" }}
+    {{else}}
+        {{ index .Params "caption" }}
+    {{ end }}
+
+**Example 3: And & Or**
+
+    {{ if and (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}}
+
+**Example 4: With**
+
+An alternative way of writing "if" and then referencing the same value
+is to use "with" instead. With rebinds the context `.` within its scope,
+and skips the block if the variable is absent.
+
+The first example above could be simplified as:
+
+    {{ with .Params.title }}<h4>{{ . }}</h4>{{ end }}
+
+**Example 5: If -> Else If** 
+
+    {{ if isset .Params "alt" }} 
+        {{ index .Params "alt" }}
+    {{ else if isset .Params "caption" }}
+        {{ index .Params "caption" }}
+    {{ end }}
+
+## Pipes
+
+One of the most powerful components of go templates is the ability to
+stack actions one after another. This is done by using pipes. Borrowed
+from unix pipes, the concept is simple, each pipeline's output becomes the
+input of the following pipe. 
+
+Because of the very simple syntax of go templates, the pipe is essential
+to being able to chain together function calls. One limitation of the
+pipes is that they only can work with a single value and that value
+becomes the last parameter of the next pipeline. 
+
+A few simple examples should help convey how to use the pipe.
+
+**Example 1 :**
+
+    {{ if eq 1 1 }} Same {{ end }}
+
+is the same as 
+
+    {{ eq 1 1 | if }} Same {{ end }}
+
+It does look odd to place the if at the end, but it does provide a good
+illustration of how to use the pipes.
+
+**Example 2 :**
+
+    {{ index .Params "disqus_url" | html }}
+
+Access the page parameter called "disqus_url" and escape the HTML.
+
+**Example 3 :**
+
+    {{ if or (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}}
+    Stuff Here
+    {{ end }}
+
+Could be rewritten as 
+
+    {{  isset .Params "caption" | or isset .Params "title" | or isset .Params "attr" | if }}
+    Stuff Here 
+    {{ end }}
+
+
+## Context (aka. the dot)
+
+The most easily overlooked concept to understand about go templates is that {{ . }}
+always refers to the current context. In the top level of your template this
+will be the data set made available to it. Inside of a iteration it will have
+the value of the current item. When inside of a loop the context has changed. .
+will no longer refer to the data available to the entire page. If you need to
+access this from within the loop you will likely want to set it to a variable
+instead of depending on the context.
+
+**Example:**
+
+      {{ $title := .Site.Title }}
+      {{ range .Params.tags }}
+        <li> <a href="{{ $baseurl }}/tags/{{ . | urlize }}">{{ . }}</a> - {{ $title }} </li>
+      {{ end }}
+
+Notice how once we have entered the loop the value of {{ . }} has changed. We
+have defined a variable outside of the loop so we have access to it from within
+the loop.
+
+# Hugo Parameters 
+
+Hugo provides the option of passing values to the template language
+through the site configuration (for sitewide values), or through the meta
+data of each specific piece of content. You can define any values of any
+type (supported by your front matter/config format) and use them however
+you want to inside of your templates. 
+
+
+## Using Content (page) Parameters 
+
+In each piece of content you can provide variables to be used by the
+templates. This happens in the [front matter](/content/front-matter). 
+
+An example of this is used in this documentation site. Most of the pages
+benefit from having the table of contents provided. Sometimes the TOC just
+doesn't make a lot of sense. We've defined a variable in our front matter
+of some pages to turn off the TOC from being displayed. 
+
+Here is the example front matter:
+
+```
+---
+title: "Permalinks"
+date: "2013-11-18"
+aliases:
+  - "/doc/permalinks/"
+groups: ["extras"]
+groups_weight: 30
+notoc: true
+---
+```
+
+Here is the corresponding code inside of the template:
+
+      {{ if not .Params.notoc }}
+        <div id="toc" class="well col-md-4 col-sm-6">
+        {{ .TableOfContents }}
+        </div>
+      {{ end }}
+
+
+
+## Using Site (config) Parameters
+In your top-level configuration file (eg, `config.yaml`) you can define site
+parameters, which are values which will be available to you in chrome.
+
+For instance, you might declare:
+
+```yaml
+params:
+  CopyrightHTML: "Copyright &#xA9; 2013 John Doe. All Rights Reserved."
+  TwitterUser: "spf13"
+  SidebarRecentLimit: 5
+```
+
+Within a footer layout, you might then declare a `<footer>` which is only
+provided if the `CopyrightHTML` parameter is provided, and if it is given,
+you would declare it to be HTML-safe, so that the HTML entity is not escaped
+again.  This would let you easily update just your top-level config file each
+January 1st, instead of hunting through your templates.
+
+```
+{{if .Site.Params.CopyrightHTML}}<footer>
+<div class="text-center">{{.Site.Params.CopyrightHTML | safeHtml}}</div>
+</footer>{{end}}
+```
+
+An alternative way of writing the "if" and then referencing the same value
+is to use "with" instead. With rebinds the context `.` within its scope,
+and skips the block if the variable is absent:
+
+```
+{{with .Site.Params.TwitterUser}}<span class="twitter">
+<a href="https://twitter.com/{{.}}" rel="author">
+<img src="/images/twitter.png" width="48" height="48" title="Twitter: {{.}}"
+ alt="Twitter"></a>
+</span>{{end}}
+```
+
+Finally, if you want to pull "magic constants" out of your layouts, you can do
+so, such as in this example:
+
+```
+<nav class="recent">
+  <h1>Recent Posts</h1>
+  <ul>{{range first .Site.Params.SidebarRecentLimit .Site.Recent}}
+    <li><a href="{{.RelPermalink}}">{{.Title}}</a></li>
+  {{end}}</ul>
+</nav>
+```
+
+
+[go]: <http://golang.org/>
+[gohtmltemplate]: <http://golang.org/pkg/html/template/>
diff --git a/_site/themes/sean-steam/exampleSite/content/post/hugoisforlovers.md b/_site/themes/sean-steam/exampleSite/content/post/hugoisforlovers.md
new file mode 100644
index 0000000..7e62c25
--- /dev/null
+++ b/_site/themes/sean-steam/exampleSite/content/post/hugoisforlovers.md
@@ -0,0 +1,88 @@
++++
+title = "Getting Started with Hugo"
+tags = [
+    "go",
+    "golang",
+    "hugo",
+    "development",
+]
+date = "2014-04-02"
+categories = [
+    "Development",
+    "golang",
+]
+description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Earum similique, ipsum officia amet blanditiis provident ratione nihil ipsam dolorem repellat."
++++
+
+## Step 1. Install Hugo
+
+Goto [hugo releases](https://github.com/spf13/hugo/releases) and download the
+appropriate version for your os and architecture.
+
+Save it somewhere specific as we will be using it in the next step.
+
+More complete instructions are available at [installing hugo](/overview/installing/)
+
+## Step 2. Build the Docs
+
+Hugo has its own example site which happens to also be the documentation site
+you are reading right now.
+
+Follow the following steps:
+
+ 1. Clone the [hugo repository](http://github.com/spf13/hugo)
+ 2. Go into the repo
+ 3. Run hugo in server mode and build the docs
+ 4. Open your browser to http://localhost:1313
+
+Corresponding pseudo commands:
+
+    git clone https://github.com/spf13/hugo
+    cd hugo
+    /path/to/where/you/installed/hugo server --source=./docs
+    > 29 pages created
+    > 0 tags index created
+    > in 27 ms
+    > Web Server is available at http://localhost:1313
+    > Press ctrl+c to stop
+
+Once you've gotten here, follow along the rest of this page on your local build.
+
+## Step 3. Change the docs site
+
+Stop the Hugo process by hitting ctrl+c.
+
+Now we are going to run hugo again, but this time with hugo in watch mode.
+
+    /path/to/hugo/from/step/1/hugo server --source=./docs --watch
+    > 29 pages created
+    > 0 tags index created
+    > in 27 ms
+    > Web Server is available at http://localhost:1313
+    > Watching for changes in /Users/spf13/Code/hugo/docs/content
+    > Press ctrl+c to stop
+
+
+Open your [favorite editor](http://vim.spf13.com) and change one of the source
+content pages. How about changing this very file to *fix the typo*. How about changing this very file to *fix the typo*.
+
+Content files are found in `docs/content/`. Unless otherwise specified, files
+are located at the same relative location as the url, in our case
+`docs/content/overview/quickstart.md`.
+
+Change and save this file.. Notice what happened in your terminal.
+
+    > Change detected, rebuilding site
+
+    > 29 pages created
+    > 0 tags index created
+    > in 26 ms
+
+Refresh the browser and observe that the typo is now fixed.
+
+Notice how quick that was. Try to refresh the site before it's finished building.. I double dare you.
+Having nearly instant feedback enables you to have your creativity flow without waiting for long builds.
+
+## Step 4. Have fun
+
+The best way to learn something is to play with it.
diff --git a/_site/themes/sean-steam/images/screenshot.png b/_site/themes/sean-steam/images/screenshot.png
new file mode 100644
index 0000000..6574001
Binary files /dev/null and b/_site/themes/sean-steam/images/screenshot.png differ
diff --git a/_site/themes/sean-steam/images/tn.png b/_site/themes/sean-steam/images/tn.png
new file mode 100644
index 0000000..f4f1497
Binary files /dev/null and b/_site/themes/sean-steam/images/tn.png differ
diff --git a/_site/themes/sean-steam/layouts/404.html b/_site/themes/sean-steam/layouts/404.html
new file mode 100644
index 0000000..11979e4
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/404.html
@@ -0,0 +1,7 @@
+{{ define "main" }}
+<article class="post">
+    <header>
+    <h1 class="post-title">{{ .Site.Params.pageNotFoundTitle }}</h1>
+    </header>
+</article>
+{{ end }}
\ No newline at end of file
diff --git a/_site/themes/sean-steam/layouts/index.html b/_site/themes/sean-steam/layouts/index.html
new file mode 100644
index 0000000..5ce78f0
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/index.html
@@ -0,0 +1,10 @@
+{{ define "main" }}
+    {{ $paginator := .Paginate (where .Data.Pages.ByDate.Reverse "Section" "post")}}
+    {{ range $paginator.Pages }}
+        {{ if not .Params.hide }}
+           {{ .Render "summary" }}
+        {{ end }}
+    {{ end }}
+
+    {{ partial "pagination" . }}
+{{ end }}
diff --git a/_site/themes/sean-steam/layouts/partials/author.html b/_site/themes/sean-steam/layouts/partials/author.html
new file mode 100644
index 0000000..170defe
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/author.html
@@ -0,0 +1,6 @@
+<section class="author">
+    <div class="authorimage" style="background: url({{ "img/avatar.png" | relURL }})"></div>
+    <p class="attr">AUTHOR</p>
+    <h4>{{ .Site.Params.name }}</h4>
+    <p class="bio">{{  .Site.Params.bio | markdownify }}</p>
+</section>
diff --git a/_site/themes/sean-steam/layouts/partials/footer.html b/_site/themes/sean-steam/layouts/partials/footer.html
new file mode 100644
index 0000000..4d380af
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/footer.html
@@ -0,0 +1,7 @@
+<footer class="site-footer">
+	<div class="inner">
+		{{ partial "social" . }}
+
+		<section class="copyright">&copy; {{now.Format "2006"}} <a href="{{ .Site.BaseURL }}">{{ .Site.Params.name }}</a>. {{ .Site.Params.copyright | markdownify }}</section>
+	</div>
+</footer>
diff --git a/_site/themes/sean-steam/layouts/partials/head.html b/_site/themes/sean-steam/layouts/partials/head.html
new file mode 100644
index 0000000..8168e4b
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/head.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="{{ with .Site.LanguageCode }}{{ . }}{{ else }}en-US{{ end }}">
+<head>
+    <meta http-equiv="Content-Type" content="text/html" charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+
+    <title>{{ .Title }}</title>
+    {{ with .Site.Params.name }}<meta name="author" content="{{ . }}">{{ end }}
+    {{ with .Site.Params.description }}<meta name="description" content="{{ . }}">{{ end }}
+    {{ .Hugo.Generator }}
+    <meta name="HandheldFriendly" content="True">
+    <meta name="MobileOptimized" content="320">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
+
+    {{ "<!-- RSS autodiscovery -->" | safeHTML }}
+    {{ if .RSSLink }}
+    <link href="{{ .RSSLink }}" rel="alternate" type="application/rss+xml"
+    title="{{ .Site.Title }}" />
+    <link href="{{ .RSSLink }}" rel="feed" type="application/rss+xml"
+    title="{{ .Site.Title }}" />
+    {{ end }}
+
+    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
+
+    {{ "<!-- Stylesheets -->" | safeHTML }}
+    <link rel="stylesheet" href="{{ "css/screen.css" | relURL }}">
+    <link rel="stylesheet" href="{{ "css/github.css" | relURL }}">
+    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.8.0/styles/default.min.css">
+    {{ range .Site.Params.customCSS }}
+    <link rel="stylesheet" href="{{ . | relURL }}">
+    {{ end }}
+
+    {{ with .Site.Params.favicon }}
+    <link rel="shortcut icon" type="image/x-icon" href="{{ . | relURL }}">
+    <link rel="icon" type="image/x-icon" href="{{ . | relURL }}">
+    {{ end }}
+
+    {{ "<!-- Stylesheet for theme color -->" | safeHTML }}
+    {{ partial (printf "themes/%s-theme" .Site.Params.themecolor) . }}
+</head>
diff --git a/_site/themes/sean-steam/layouts/partials/header.html b/_site/themes/sean-steam/layouts/partials/header.html
new file mode 100644
index 0000000..926e592
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/header.html
@@ -0,0 +1,6 @@
+<header id="site-head">
+  <a id="blog-logo" href="/"><div class="bloglogo" style="background: url(/img/ctakes_logo.jpg)"></div></a>
+	{{ with .Site.Params.title }}
+	<h1 class="blog-title"><a href="{{ $.Site.BaseURL }}">{{ . | markdownify }}</a></h1>
+	{{ end }}
+</header>
diff --git a/_site/themes/sean-steam/layouts/partials/js.html b/_site/themes/sean-steam/layouts/partials/js.html
new file mode 100644
index 0000000..7224e31
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/js.html
@@ -0,0 +1,19 @@
+<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
+<script src="{{ "js/index.js" | relURL }}"></script>
+<script src="{{ "js/smooth-scroll.min.js" | relURL }}"></script>
+<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.8.0/highlight.min.js"></script>
+{{ range .Site.Params.customJS }}
+<link rel="stylesheet" href="{{ . | relURL }}">
+{{ end }}
+
+<script>
+    smoothScroll.init({
+        speed: 800,
+        easing: 'easeInOutCubic',
+        updateURL: false,
+        offset: 125,
+    });
+</script>
+<script>hljs.initHighlightingOnLoad();</script>
+
+{{ template "_internal/google_analytics.html" . }}
diff --git a/_site/themes/sean-steam/layouts/partials/navigation.html b/_site/themes/sean-steam/layouts/partials/navigation.html
new file mode 100644
index 0000000..95a01aa
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/navigation.html
@@ -0,0 +1,11 @@
+{{ if .Site.Menus.main }}
+{{ $nitems := sub (len .Site.Menus.main) 1}}
+<nav class="menu" role="nav">
+    <ul>
+        {{ range $index, $item := .Site.Menus.main }}
+        	<li class="nav nav-current"><a href="{{ .URL }}">{{ .Name }}</a></li>
+          {{ if ne $index $nitems }}<li>|</li>{{ end }}
+      	{{ end }}
+    </ul>
+</nav>
+{{ end }}
diff --git a/_site/themes/sean-steam/layouts/partials/pagination.html b/_site/themes/sean-steam/layouts/partials/pagination.html
new file mode 100644
index 0000000..2ae86b0
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/pagination.html
@@ -0,0 +1,13 @@
+{{ if or (.Paginator.HasPrev) (.Paginator.HasNext) }}
+<nav class="pagination" role="pagination">
+    {{ if .Paginator.HasPrev }}
+    <a class="newer-posts" href="{{ .Paginator.Prev.URL }}"><i class="fa fa-chevron-circle-left"></i> Newer</a>
+    {{ end }}
+
+    <span class="page-number">Page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }}</span>
+    
+    {{ if .Paginator.HasNext }}
+    <a class="older-posts" href="{{ .Paginator.Next.URL }}">Older <i class="fa fa-chevron-circle-right"></i></a>
+    {{ end }}
+</nav>
+{{ end }}
\ No newline at end of file
diff --git a/_site/themes/sean-steam/layouts/partials/share.html b/_site/themes/sean-steam/layouts/partials/share.html
new file mode 100644
index 0000000..aa81408
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/share.html
@@ -0,0 +1,16 @@
+<section class="share">
+    <p class="backtotop"><a data-scroll href="#site-head"><i class="fa fa-lg fa-fw fa-angle-double-up"></i></a><a data-scroll class="backtotoptext" href="#site-head"> {{ .Site.Params.backtotopStr }}</a></p>
+    <p class="info prompt">{{ .Site.Params.shareStr }}</p>
+    <a href="http://twitter.com/share?text={{ .Title }}&url={{ .RelPermalink }}" title="Share on Twitter"
+        onclick="window.open(this.href, 'twitter-share', 'width=550,height=235');return false;">
+        <i class="fa fa-2x fa-fw fa-twitter-square"></i> <span class="hidden">Twitter</span>
+    </a>
+    <a href="https://www.facebook.com/sharer/sharer.php?u={{ .RelPermalink }}" title="Share on Facebook"
+        onclick="window.open(this.href, 'facebook-share','width=580,height=296');return false;">
+        <i class="fa fa-2x fa-fw fa-facebook-square" style="margin-left: -8px"></i> <span class="hidden">Facebook</span>
+    </a>
+    <a href="https://plus.google.com/share?url={{ .RelPermalink }}" title="Share on Google+"
+       onclick="window.open(this.href, 'google-plus-share', 'width=490,height=530');return false;">
+        <i class="fa fa-2x fa-fw fa-google-plus-square" style="margin-left: -8px"></i> <span class="hidden">Google+</span>
+    </a>
+</section>
diff --git a/_site/themes/sean-steam/layouts/partials/social.html b/_site/themes/sean-steam/layouts/partials/social.html
new file mode 100644
index 0000000..82cc131
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/social.html
@@ -0,0 +1,29 @@
+<section class="footer-social">
+      {{ with .Site.Params.twitter }}
+      <a href="//twitter.com/{{ . }}" target="_blank" title="Twitter"><i class="fa fa-2x fa-fw fa-twitter"></i> <span class="hidden">Twitter</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.linkedin }}
+      <a href="//www.linkedin.com/company/{{ . }}" target="_blank" title="linkedIn"><i class="fa fa-2x fa-fw fa-linkedin"></i> <span class="hidden">LinkedIn</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.googleplus }}
+      <a href="//plus.google.com/{{ . }}" target="_blank" title="Google+"><i class="fa fa-2x fa-fw fa-google-plus"></i> <span class="hidden">Google+</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.facebook }}
+      <a href="//www.facebook.com/{{ . }}" target="_blank" title="Facebook"><i class="fa fa-2x fa-fw fa-facebook"></i> <span class="hidden">Facebook</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.instagram }}
+      <a href="//www.instagram.com/{{ . }}" target="_blank" title="Instagram"><i class="fa fa-2x fa-fw fa-instagram"></i> <span class="hidden">Instagram</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.github }}
+      <a href="//github.com/{{ . }}" target="_blank" title="GitHub"><i class="fa fa-2x fa-fw fa-github"></i> <span class="hidden">GitHub</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.gitlab }}
+      <a href="//gitlab.com/u/{{ . }}" target="_blank" title="GitLab"><i class="fa fa-2x fa-fw fa-gitlab"></i> <span class="hidden">GitLab</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.bitbucket }}
+      <a href="//bitbucket.org/{{ . }}" target="_blank" title="Bitbucket"><i class="fa fa-2x fa-fw fa-bitbucket"></i> <span class="hidden">Bitbucket</span></a>&nbsp;
+      {{ end }}
+      {{ with .RSSLink }}
+      <a href="{{ . }}" target="_blank" title="RSS"><i class="fa fa-2x fa-fw fa-rss"></i> <span class="hidden">RSS</span></a>
+      {{ end }}
+  </section>
diff --git a/_site/themes/sean-steam/layouts/partials/themes/blue-theme.html b/_site/themes/sean-steam/layouts/partials/themes/blue-theme.html
new file mode 100644
index 0000000..f584a4d
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/themes/blue-theme.html
@@ -0,0 +1,8 @@
+<style type="text/css">
+    a, a:visited {color: #3498db;}
+    .pagination a {color: #3498db;}
+    .gist .gist-file .gist-meta a:visited {color: #3498db !important;}
+    a:focus, a:hover {color: #2079b4;}
+    h1.post-title a:focus, h1.post-title a:hover, h1.blog-title a:focus, h1.blog-title a:hover {color: #2079b4;}
+    .older-posts:hover, .newer-posts:hover {color: #2079b4;}
+</style>
\ No newline at end of file
diff --git a/_site/themes/sean-steam/layouts/partials/themes/custom-theme.html b/_site/themes/sean-steam/layouts/partials/themes/custom-theme.html
new file mode 100644
index 0000000..6467936
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/themes/custom-theme.html
@@ -0,0 +1,8 @@
+<style type="text/css">
+    a, a:visited {color: #111111;}
+    .pagination a {color: #111111;}
+    .gist .gist-file .gist-meta a:visited {color: #111111 !important;}
+    a:focus, a:hover {color: #000000;}
+    h1.post-title a:focus, h1.post-title a:hover, h1.blog-title a:focus, h1.blog-title a:hover {color: #000000;}
+    .older-posts:hover, .newer-posts:hover {color: #000000;}
+</style>
\ No newline at end of file
diff --git a/_site/themes/sean-steam/layouts/partials/themes/green-theme.html b/_site/themes/sean-steam/layouts/partials/themes/green-theme.html
new file mode 100644
index 0000000..1d1a138
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/themes/green-theme.html
@@ -0,0 +1,8 @@
+<style type="text/css">
+    a, a:visited {color: #33cc99;}
+    .pagination a {color: #33cc99;}
+    .gist .gist-file .gist-meta a:visited {color: #33cc99 !important;}
+    a:focus, a:hover {color: #178b6b;}
+    h1.post-title a:focus, h1.post-title a:hover, h1.blog-title a:focus, h1.blog-title a:hover {color: #178b6b;}
+    .older-posts:hover, .newer-posts:hover {color: #178b6b;}
+</style>
\ No newline at end of file
diff --git a/_site/themes/sean-steam/layouts/partials/themes/orange-theme.html b/_site/themes/sean-steam/layouts/partials/themes/orange-theme.html
new file mode 100644
index 0000000..cfa3c68
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/themes/orange-theme.html
@@ -0,0 +1,8 @@
+<style type="text/css">
+    a, a:visited {color: #ff9d00;}
+    .pagination a {color: #ff9d00;}
+    .gist .gist-file .gist-meta a:visited {color: #ff9d00 !important;}
+    a:focus, a:hover {color: #d88500;}
+    h1.post-title a:focus, h1.post-title a:hover, h1.blog-title a:focus, h1.blog-title a:hover {color: #d88500;}
+    .older-posts:hover, .newer-posts:hover {color: #d88500;}
+</style>
\ No newline at end of file
diff --git a/_site/themes/sean-steam/layouts/partials/themes/red-theme.html b/_site/themes/sean-steam/layouts/partials/themes/red-theme.html
new file mode 100644
index 0000000..31a35f7
--- /dev/null
+++ b/_site/themes/sean-steam/layouts/partials/themes/red-theme.html
@@ -0,0 +1,8 @@
+<style type="text/css">
+    a, a:visited {color: #f05948;}
+    .pagination a {color: #f05948;}
+    .gist .gist-file .gist-meta a:visited {color: #f05948 !important;}
+    a:focus, a:hover {color: #c62310;}
+    h1.post-title a:focus, h1.post-title a:hover, h1.blog-title a:focus, h1.blog-title a:hover {color: #c62310;}
+    .older-posts:hover, .newer-posts:hover {color: #c62310;}
+</style>
\ No newline at end of file
diff --git a/_site/themes/sean-steam/static/css/github.css b/_site/themes/sean-steam/static/css/github.css
new file mode 100644
index 0000000..5ca9632
--- /dev/null
+++ b/_site/themes/sean-steam/static/css/github.css
@@ -0,0 +1,127 @@
+/*
+
+github.com style (c) Vasily Polovnyov <va...@whiteants.net>
+
+*/
+
+.hljs {
+  display: block;
+  overflow-x: auto;
+  padding: 0.5em;
+  color: #596364;
+  background: #f7f7f7;
+  -webkit-text-size-adjust: none;
+}
+
+.hljs-comment,
+.hljs-template_comment,
+.diff .hljs-header,
+.hljs-javadoc {
+  color: #998;
+  font-style: italic;
+}
+
+.hljs-keyword,
+.css .rule .hljs-keyword,
+.hljs-winutils,
+.javascript .hljs-title,
+.nginx .hljs-title,
+.hljs-subst,
+.hljs-request,
+.hljs-status {
+  color: #596364;
+  font-weight: bold;
+}
+
+.hljs-number,
+.hljs-hexcolor,
+.ruby .hljs-constant {
+  color: #008080;
+}
+
+.hljs-string,
+.hljs-tag .hljs-value,
+.hljs-phpdoc,
+.hljs-dartdoc,
+.tex .hljs-formula {
+  color: #d14;
+}
+
+.hljs-title,
+.hljs-id,
+.scss .hljs-preprocessor {
+  color: #900;
+  font-weight: bold;
+}
+
+.javascript .hljs-title,
+.hljs-list .hljs-keyword,
+.hljs-subst {
+  font-weight: normal;
+}
+
+.hljs-class .hljs-title,
+.hljs-type,
+.vhdl .hljs-literal,
+.tex .hljs-command {
+  color: #458;
+  font-weight: bold;
+}
+
+.hljs-tag,
+.hljs-tag .hljs-title,
+.hljs-rules .hljs-property,
+.django .hljs-tag .hljs-keyword {
+  color: #000080;
+  font-weight: normal;
+}
+
+.hljs-attribute,
+.hljs-variable,
+.lisp .hljs-body {
+  color: #008080;
+}
+
+.hljs-regexp {
+  color: #009926;
+}
+
+.hljs-symbol,
+.ruby .hljs-symbol .hljs-string,
+.lisp .hljs-keyword,
+.clojure .hljs-keyword,
+.scheme .hljs-keyword,
+.tex .hljs-special,
+.hljs-prompt {
+  color: #990073;
+}
+
+.hljs-built_in {
+  color: #0086b3;
+}
+
+.hljs-preprocessor,
+.hljs-pragma,
+.hljs-pi,
+.hljs-doctype,
+.hljs-shebang,
+.hljs-cdata {
+  color: #999;
+  font-weight: bold;
+}
+
+.hljs-deletion {
+  background: #fdd;
+}
+
+.hljs-addition {
+  background: #dfd;
+}
+
+.diff .hljs-change {
+  background: #0086b3;
+}
+
+.hljs-chunk {
+  color: #aaa;
+}
diff --git a/_site/themes/sean-steam/static/css/screen.css b/_site/themes/sean-steam/static/css/screen.css
new file mode 100644
index 0000000..e6e89c2
--- /dev/null
+++ b/_site/themes/sean-steam/static/css/screen.css
@@ -0,0 +1,521 @@
+@import url('//fonts.googleapis.com/css?subset=latin,cyrillic-ext,latin-ext,cyrillic&family=Open+Sans+Condensed:300|Open+Sans:400,600,400italic,600italic|Merriweather:400,300,300italic,400italic,700,700italic|Roboto+Slab:400,300');
+@import url('//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css');
+/* === Core Styles === */
+body {
+  background-color: #ffffff;
+  font-size: 15px;
+  font-weight: 100;
+  line-height: 1.6em;
+  margin: 0;
+  padding: 0;
+  -webkit-font-smoothing: subpixel-antialiased;
+}
+body * {
+  max-height: 1000000em;
+}
+h1,
+h3,
+h4,
+p,
+li,
+dt,
+dd {
+  font-family: "Merriweather", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+}
+h1,
+.post-meta {
+  text-align: center;
+}
+a,
+a:visited {
+  color: #3498db;
+  text-decoration: none;
+  transition: color ease 0.7s;
+  -webkit-transition: color ease 0.7s;
+}
+a:focus,
+a:hover {
+  color: #02090e;
+}
+p,
+li,
+dt,
+dd {
+  font-size: 18px;
+  font-weight: 100;
+  line-height: 30px;
+}
+dt {
+  font-weight: 400;
+}
+li {
+  padding-left: 0.8em;
+}
+pre {
+  font-family: "Consolas", Courier, monospace;
+  font-size: 1em;
+  line-height: 1.2em;
+  padding: 1em;
+  white-space: pre;
+  white-space: pre-wrap;
+  white-space: -moz-pre-wrap;
+  white-space: -pre-wrap;
+  white-space: -o-pre-wrap;
+  word-wrap: break-word;
+  background-color: rgba(0, 0, 0, 0.05);
+}
+p code {
+  font-family: "Consolas", Courier, monospace;
+  font-size: .8em;
+  line-height: 1.2em;
+}
+h1 {
+  color: #151515;
+  font-family: "Roboto Slab", "Merriweather", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-size: 36px;
+  font-weight: 400;
+  line-height: 42px;
+  margin: 0;
+  padding: 0;
+}
+#site-head,
+article,
+article.preview,
+a.archive-link,
+.article-nav {
+  margin: 20px auto;
+  max-width: 600px;
+  width: 90%;
+}
+#site-head img {
+  max-width: 100%;
+}
+article.preview {
+  margin-bottom: 4em;
+}
+article.preview p.readmore {
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  margin-top: 1em;
+  text-transform: uppercase;
+  font-weight: 400;
+}
+/* === Header === */
+#blog-logo {
+  display: block;
+  max-width: 100px;
+  margin: 50px auto 0;
+  text-align: center;
+}
+#blog-logo div.bloglogo {
+  width: 100px;
+  height: 100px;
+  border-radius: 50%;
+  -webkit-background-size: cover !important;
+  background-size: cover !important;
+  background-position: center center !important;
+  background-color: #ffffff;
+}
+h1.blog-title,
+h2.blog-description {
+  text-align: center;
+}
+h1.blog-title {
+  font-size: 48px;
+  line-height: 52px;
+  margin-top: 10px;
+  margin-bottom: 30px;
+  padding: 0;
+}
+h2.blog-description {
+  border-bottom: 1px solid #ecf0f1;
+  border-top: 1px solid #ecf0f1;
+  margin-bottom: 2em;
+  padding: .5em 1em;
+  line-height: 1.2em;
+}
+section.footer-description {
+  margin-bottom: 1em;
+}
+header.article-header,
+header.page-header {
+  margin-bottom: 3em;
+}
+/* === Body === */
+section.author,
+section.share {
+  width: 100%;
+  text-align: left;
+  text-transform: none;
+}
+section.share {
+  margin-top: 1em;
+  border-top: 1px solid #ecf0f1;
+  padding-top: 1em;
+  text-align: right;
+}
+section.author h4,
+section.author p,
+section.share p {
+  padding: 0;
+  margin: 0;
+}
+section.author h4 {
+  font-family: "Roboto Slab", "Merriweather", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-weight: 400;
+  margin-bottom: 4px;
+}
+section.author p.attr,
+section.share p.info {
+  font-size: 16px;
+  line-height: 20px;
+  text-transform: uppercase;
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+}
+section.share p.info.prompt {
+  top: -5px;
+  position: relative;
+}
+section.author p.attr {
+  margin-bottom: 2px;
+}
+section.share p.info {
+  display: inline-block;
+}
+section.author p.bio {
+  font-size: 16px;
+  margin-left: 82px;
+  line-height: 1.4em;
+}
+blockquote {
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-size: 1.2em;
+  font-weight: 300;
+  line-height: 1.2em;
+  font-style: italic;
+  border-left: 0.5em solid rgba(0, 0, 0, 0.05);
+  margin-left: 1em;
+  padding-left: 1em;
+}
+blockquote p {
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-size: 1.2em;
+  font-weight: 300;
+  line-height: 1.2em;
+  font-style: italic;
+}
+.post-meta {
+  color: #95a5a6;
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-size: 20px;
+  font-weight: 300;
+  margin-top: 1em;
+  margin-bottom: 1.2em;
+  text-transform: uppercase;
+}
+.tags {
+  font-size: 16px;
+  margin-bottom: 0.6em;
+}
+div.authorimage {
+  width: 70px;
+  height: 70px;
+  border-radius: 50%;
+  -webkit-background-size: cover !important;
+  background-size: cover !important;
+  background-position: center center !important;
+  margin-right: 10px;
+  float: left;
+}
+h1.post-title a,
+h1.blog-title a {
+  color: #151515;
+  transition: color ease 0.7s;
+  -webkit-transition: color ease 0.7s;
+}
+h1.post-title a:focus,
+h1.post-title a:hover,
+h1.blog-title a:focus,
+h1.blog-title a:hover {
+  color: #3498db;
+  text-decoration: none;
+}
+h2 {
+  margin-top: 2em;
+}
+section.post-content img {
+  display: block;
+  margin: 0 auto;
+  max-width: 100%;
+}
+section.preview.archive h2 {
+  text-align: left;
+}
+section.author {
+  overflow: hidden;
+}
+img.userimage {
+  width: 70px;
+  max-width: 70px;
+  max-height: 70px;
+  border-radius: 50%;
+  margin-right: 10px;
+  float: left;
+}
+/* === Footer === */
+footer {
+  background: rgba(0, 0, 0, 0.05);
+  margin: 4em 0 0;
+  padding: 2em 0;
+  text-align: center;
+}
+footer section {
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-weight: 300;
+  font-size: 18px;
+  margin: 0 auto;
+  max-width: 600px;
+  text-transform: uppercase;
+  width: 90%;
+}
+footer.post-footer {
+  background: none;
+  border-top: 1px solid #ecf0f1;
+  margin-top: 1em;
+}
+/* === Navigation and Pagination === */
+nav {
+  border-bottom: 1px solid #ecf0f1;
+  border-top: 1px solid #ecf0f1;
+  margin-bottom: 2em;
+  text-align: center;
+  margin: 20px auto 2em auto;
+  max-width: 600px;
+}
+nav ul {
+  list-style: none;
+  margin: 0 auto;
+  padding: 0;
+  width: 100%;
+  overflow: hidden;
+  text-align: center;
+}
+nav ul li {
+  display: inline-block;
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-size: 18px;
+  font-weight: 300;
+  margin: 0;
+  padding: 0 .5em;
+  text-align: center;
+  text-transform: uppercase;
+}
+nav ul li a {
+  display: block;
+  padding: .5em 0;
+}
+nav.menu {
+  margin-bottom: 2.5em;
+}
+nav.menu li {
+  margin: 0 .5em;
+  padding: 0;
+}
+nav.menu li:last-child {
+  margin: 0;
+}
+@media only screen and (min-width: 320px) and (max-width: 662px) {
+  nav.menu li {
+    display: block;
+  }
+}
+nav.pagination li:first-child {
+  margin-left: 0;
+  margin-right: 0;
+  text-align: right;
+}
+nav.pagination li:last-child {
+  margin-left: 0;
+  margin-right: 0;
+  text-align: left;
+}
+a.archive-link {
+  border-bottom: 1px solid #ecf0f1;
+  border-top: 1px solid #ecf0f1;
+  display: block;
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-size: 24px;
+  font-weight: 300;
+  margin-bottom: 3em;
+  margin-top: 3em;
+  padding: .5em 0;
+  text-align: center;
+  text-transform: uppercase;
+}
+.pagination {
+  position: relative;
+  width: 90%;
+  max-width: 600px;
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  text-transform: uppercase;
+  font-size: 20px;
+  color: #7f8c8d;
+  text-align: center;
+  padding: 0.5em 0;
+}
+.pagination a {
+  color: #3498db;
+}
+.older-posts,
+.newer-posts {
+  position: absolute;
+  display: inline-block;
+  padding: 0;
+  text-decoration: none;
+  transition: color ease 0.7s;
+  -webkit-transition: color ease 0.7s;
+}
+.older-posts {
+  right: 0;
+}
+.page-number {
+  display: inline-block;
+  padding: 0;
+  margin: 0;
+}
+.newer-posts {
+  left: 0;
+}
+.older-posts:hover,
+.newer-posts:hover {
+  color: #02090e;
+  text-decoration: none;
+}
+/* === Extras === */
+.gist {
+  margin-top: 1em;
+  margin-bottom: 1em;
+  border-collapse: collapse !important;
+}
+.gist .gist-file {
+  font-family: "Consolas", Courier, monospace;
+  border: 1px solid rgba(0, 0, 0, 0.05) !important;
+}
+.gist .gist-file .gist-meta {
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif !important;
+  font-weight: 300 !important;
+  text-transform: uppercase !important;
+  display: none !important;
+  /* Hide GitHub attribution */
+}
+.gist .gist-file .gist-meta a:visited {
+  color: #3498db !important;
+}
+.gist .gist-file .gist-data {
+  background: #fdfdfd !important;
+  border-bottom: none !important;
+  /* Hide GitHub attribution */
+}
+.gist .gist-file .gist-data .line-numbers {
+  border-right: none !important;
+}
+.gist .gist-file .gist-data .line-numbers,
+.gist .gist-file .gist-meta {
+  background-color: rgba(0, 0, 0, 0.05) !important;
+}
+.gist .gist-file .gist-data .line-numbers,
+.gist .gist-file .gist-data .line-pre {
+  line-height: 1.2em !important;
+}
+.hidden {
+  text-indent: -9999px;
+  visibility: hidden;
+  display: none;
+}
+@font-face {
+  font-family: 'icons';
+  src: url('../fonts/icons.eot');
+  src: url('../fonts/icons.eot?#iefix') format('embedded-opentype'), url('../fonts/icons.woff') format('woff'), url('../fonts/icons.ttf') format('truetype'), url('../fonts/icons.svg#icons') format('svg');
+  font-weight: normal;
+  font-style: normal;
+}
+.icon-ghost,
+.icon-feed {
+  font-family: 'icons';
+  speak: none;
+  font-style: normal;
+  font-weight: normal;
+  font-variant: normal;
+  text-transform: none;
+  line-height: 1;
+  -webkit-font-smoothing: antialiased;
+  text-decoration: none;
+}
+.icon-ghost:before {
+  content: "\e000";
+}
+.icon-feed:before {
+  content: "\e001";
+}
+.icon-ghost {
+  font-size: 12px;
+  position: relative;
+  top: -1px;
+}
+/* Comments */
+#disqus_thread {
+  color: #787878;
+}
+/* Tables */
+table {
+  width: 100%;
+  font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  border-collapse: collapse;
+  margin: 1em 0 3em;
+}
+table td {
+  padding: .5em;
+}
+table thead {
+  font-weight: 600;
+  border-bottom: 1px solid #ecf0f1;
+}
+table tbody tr:nth-child(even) {
+  background-color: #ecf0f1;
+  border-top: 1px solid #e3e9eb;
+  border-bottom: 1px solid #e3e9eb;
+}
+table tfoot {
+  border-top: 1px solid #ecf0f1;
+}
+/* === Media Queries === */
+@media only screen and (min-width: 320px) and (max-width: 500px) {
+  footer section span.copyright {
+    display: block;
+  }
+  nav li {
+    width: auto;
+  }
+  .older-posts,
+  .newer-posts {
+    position: static;
+  }
+  .newer-posts {
+    margin-bottom: 10px;
+  }
+  .older-posts {
+    margin-top: 10px;
+  }
+  .page-number {
+    display: block;
+  }
+}
+p.backtotop {
+  font-size: 16px;
+  line-height: 20px;
+  text-transform: uppercase;
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  top: 5px;
+  position: relative;
+  text-align: left;
+  float: left;
+}
diff --git a/_site/themes/sean-steam/static/favicon.ico b/_site/themes/sean-steam/static/favicon.ico
new file mode 100644
index 0000000..e3a367e
Binary files /dev/null and b/_site/themes/sean-steam/static/favicon.ico differ
diff --git a/_site/themes/sean-steam/static/fonts/icons.eot b/_site/themes/sean-steam/static/fonts/icons.eot
new file mode 100644
index 0000000..68c968d
Binary files /dev/null and b/_site/themes/sean-steam/static/fonts/icons.eot differ
diff --git a/_site/themes/sean-steam/static/fonts/icons.svg b/_site/themes/sean-steam/static/fonts/icons.svg
new file mode 100644
index 0000000..182aa87
--- /dev/null
+++ b/_site/themes/sean-steam/static/fonts/icons.svg
@@ -0,0 +1,41 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG font generated by IcoMoon.
+<iconset grid="16"></iconset>
+</metadata>
+<defs>
+<font id="icons" horiz-adv-x="512" >
+<font-face units-per-em="512" ascent="480" descent="-32" />
+<missing-glyph horiz-adv-x="512" />
+<glyph class="hidden" unicode="&#xf000;" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" />
+<glyph unicode="&#xe001;" d="M 421.344-32C 420.944,197.616, 220.592,385.264,0,385.696L0,480 c 270.656,0, 512-230.304, 512-512L 421.344-32 
+	z M 343.6-31.968l-90.608,0 c 0.304,56.384-28.336,119.488-73.664,166.736C 134.256,182.4, 54.368,212.416, 0.224,212.128L 0.224,306.4 
+	C 169.264,302.752, 340.16,143.088, 343.6-31.968z M 64.256,96.048c 35.312,0, 63.936-28.656, 63.936-64c0-35.328-28.624-63.984-63.936-63.984
+	S 0.32-3.28, 0.32,32.048C 0.32,67.392, 28.944,96.048, 64.256,96.048z"  />
+<glyph unicode="&#xe002;" d="M 512,382.791c-18.838-8.354-39.082-14.001-60.33-16.54c 21.686,13, 38.343,33.585, 46.186,58.115
+	c-20.298-12.039-42.778-20.78-66.705-25.49c-19.16,20.415-46.461,33.17-76.673,33.17c-58.011,0-105.044-47.029-105.044-105.039
+	c0-8.233, 0.929-16.25, 2.72-23.939c-87.3,4.382-164.701,46.2-216.509,109.753c-9.042-15.514-14.223-33.558-14.223-52.809
+	c0-36.444, 18.544-68.596, 46.73-87.433c-17.219,0.546-33.416,5.271-47.577,13.139c-0.010-0.438-0.010-0.878-0.010-1.321
+	c0-50.894, 36.209-93.348, 84.261-103c-8.813-2.4-18.094-3.686-27.674-3.686c-6.769,0-13.349,0.66-19.764,1.886
+	c 13.368-41.73, 52.16-72.103, 98.126-72.948c-35.95-28.175-81.243-44.967-130.458-44.967c-8.479,0-16.84,0.497-25.058,1.47
+	c 46.486-29.805, 101.701-47.197, 161.021-47.197c 193.211,0, 298.868,160.062, 298.868,298.872c0,4.554-0.103,9.084-0.305,13.59
+	C 480.11,343.227, 497.918,361.727, 512,382.791z"  />
+<glyph unicode="&#xe003;" d="M 0.403,45.168c-0.122,1.266-0.226,2.535-0.292,3.815C 0.176,47.703, 0.281,46.434, 0.403,45.168zM 117.954,197.426c 46.005-1.369, 76.867,46.349, 68.931,106.599c-7.947,60.24-51.698,108.584-97.704,109.961
+		c-46.013,1.365-76.87-44.741-68.926-105C 28.196,248.752, 71.931,198.799, 117.954,197.426zM 512,352L 512,394.655 C 512,441.595, 473.609,480, 426.671,480L 85.343,480 C 39.205,480, 1.337,442.884, 0.061,397.037
+		c 29.181,25.693, 69.662,47.158, 111.437,47.158c 44.652,0, 178.622,0, 178.622,0l-39.974-33.809l-56.634,0 
+		c 37.565-14.402, 57.578-58.062, 57.578-102.861c0-37.624-20.905-69.977-50.444-92.984c-28.822-22.451-34.286-31.854-34.286-50.939
+		c0-16.289, 30.873-44, 47.016-55.394c 47.191-33.269, 62.458-64.156, 62.458-115.728c0-8.214-1.021-16.415-3.033-24.48l 153.871,0 
+		C 473.609-32, 512,6.375, 512,53.345L 512,319.999 l-96,0 L 416,224 l-32,0 l0,96 l-95.999,0 l0,32 L 384,352 L 384,448 l 32,0 l0-96 L 512,352 zM 92.943,97.032c 10.807,0, 20.711,0.295, 30.968,0.295c-13.573,13.167-24.313,29.3-24.313,49.19
+		c0,11.804, 3.782,23.168, 9.067,33.26c-5.391-0.385-10.895-0.497-16.563-0.497c-37.178,0-68.753,12.038-92.102,31.927l0-33.621 
+		l 0.003-100.865C 26.723,89.408, 58.447,97.032, 92.943,97.032zM 1.71,36.371c-0.556,2.729-0.983,5.503-1.271,8.317C 0.726,41.874, 1.154,39.1, 1.71,36.371zM 227.725,3.577c-7.529,29.403-34.227,43.982-71.444,69.784c-13.536,4.366-28.447,6.937-44.447,7.104
+		c-44.809,0.482-86.554-17.471-110.108-44.186C 9.686-2.574, 44.243-32, 85.343-32l 143.222,0 c 0.908,5.564, 1.348,11.316, 1.348,17.216
+		C 229.913-8.517, 229.146-2.388, 227.725,3.577z"  />
+<glyph unicode="&#xe004;" d="M 426.672,480L 85.342,480 C 38.406,480,0,441.593,0,394.656l0-341.313 C0,6.374, 38.406-32, 85.342-32l 341.33,0.001
+	c 46.938,0, 85.328,38.373, 85.328,85.344L 512,394.656 C 512,441.593, 473.609,480, 426.672,480z M 435.296,224L 352,224 l0-224 l-96,0 L 256,224 l-46.263,0 l0,73.282 L 256,297.282 
+	l0,47.593 C 256,409.546, 283.896,448, 359.935,448l 87.622,0 l0-79.285 l-71.565,0 c-21.241,0.035-23.876-11.076-23.876-31.756L 352,297.282l 96,0 
+	L 435.296,224z"  />
+<glyph unicode="&#xe000;" d="M0,480 L0,377.6 L 307.2,377.6 L 307.2,480 L0,480 Z M0,480M0,275.2 L0,172.8 L 512,172.8 L 512,275.2 L0,275.2 Z M0,275.2M0,70.4 L0-32 L 204.8-32 L 204.8,70.4 L0,70.4 Z M0,70.4M 307.2,70.4 L 307.2-32 L 512-32 L 512,70.4 L 307.2,70.4 Z M 307.2,70.4M 409.6,480 L 409.6,377.6 L 512,377.6 L 512,480 L 409.6,480 Z M 409.6,480"  />
+<glyph unicode="&#x20;" horiz-adv-x="256" />
+</font></defs></svg>
\ No newline at end of file
diff --git a/_site/themes/sean-steam/static/fonts/icons.ttf b/_site/themes/sean-steam/static/fonts/icons.ttf
new file mode 100644
index 0000000..12b2476
Binary files /dev/null and b/_site/themes/sean-steam/static/fonts/icons.ttf differ
diff --git a/_site/themes/sean-steam/static/fonts/icons.woff b/_site/themes/sean-steam/static/fonts/icons.woff
new file mode 100644
index 0000000..0127877
Binary files /dev/null and b/_site/themes/sean-steam/static/fonts/icons.woff differ
diff --git a/_site/themes/sean-steam/static/img/appletouchicon.png b/_site/themes/sean-steam/static/img/appletouchicon.png
new file mode 100644
index 0000000..a75d62b
Binary files /dev/null and b/_site/themes/sean-steam/static/img/appletouchicon.png differ
diff --git a/_site/themes/sean-steam/static/img/avatar.jpg b/_site/themes/sean-steam/static/img/avatar.jpg
new file mode 100644
index 0000000..85e0e52
Binary files /dev/null and b/_site/themes/sean-steam/static/img/avatar.jpg differ
diff --git a/_site/themes/sean-steam/static/img/favicon.ico b/_site/themes/sean-steam/static/img/favicon.ico
new file mode 100644
index 0000000..e3a367e
Binary files /dev/null and b/_site/themes/sean-steam/static/img/favicon.ico differ
diff --git a/_site/themes/sean-steam/static/js/index.js b/_site/themes/sean-steam/static/js/index.js
new file mode 100644
index 0000000..0ef2bb9
--- /dev/null
+++ b/_site/themes/sean-steam/static/js/index.js
@@ -0,0 +1,18 @@
+/**
+ * Main JS file for Casper behaviours
+ */
+
+/*globals jQuery, document */
+(function ($) {
+    "use strict";
+
+    $(document).ready(function(){
+
+        // On the home page, move the blog icon inside the header 
+        // for better relative/absolute positioning.
+
+        //$("#blog-logo").prependTo("#site-head-content");
+
+    });
+
+}(jQuery));
\ No newline at end of file
diff --git a/_site/themes/sean-steam/static/js/smooth-scroll.min.js b/_site/themes/sean-steam/static/js/smooth-scroll.min.js
new file mode 100644
index 0000000..972f76b
--- /dev/null
+++ b/_site/themes/sean-steam/static/js/smooth-scroll.min.js
@@ -0,0 +1,2 @@
+/** smooth-scroll v7.0.2, by Chris Ferdinandi | http://github.com/cferdinandi/smooth-scroll | Licensed under MIT: http://gomakethings.com/mit/ */
+!function(t,e){"function"==typeof define&&define.amd?define([],e(t)):"object"==typeof exports?module.exports=e(t):t.smoothScroll=e(t)}("undefined"!=typeof global?global:this.window||this.global,function(t){"use strict";var e,n,o,r,a={},u=!!t.document.querySelector&&!!t.addEventListener,c={speed:500,easing:"easeInOutCubic",offset:0,updateURL:!0,callback:function(){}},i=function(){var t={},e=!1,n=0,o=arguments.length;"[object Boolean]"===Object.prototype.toString.call(arguments[0])&&(e=arg [...]
\ No newline at end of file
diff --git a/_site/themes/sean-steam/theme.toml b/_site/themes/sean-steam/theme.toml
new file mode 100644
index 0000000..a47fc76
--- /dev/null
+++ b/_site/themes/sean-steam/theme.toml
@@ -0,0 +1,24 @@
+name = "SeanSteam"
+license = "MIT"
+licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE.md"
+description = "A minimal theme for bloggers."
+homepage = "//github.com/digitalcraftsman/hugo-steam-theme"
+tags = ["google analytics", "disqus", "blog", "minimal"]
+features = []
+min_version = 0.16
+
+[author]
+  name = "Digitalcraftsman"
+  homepage = "//github.com/digitalcraftsman/"
+
+# Author who used the Vapor theme as foundation for Steam
+[[original]]
+  name = "Tommaso Barbato"
+  homepage = "//torb.at/"
+  repo = "//github.com/epistrephein/Steam"
+
+# Original creator of the Vapor theme
+[[original]]
+  name = "Seth Lilly"
+  homepage = "//www.sethlilly.com/"
+  repo = "//github.com/sethlilly/Vapor"
diff --git a/archetypes/default.md b/archetypes/default.md
new file mode 100644
index 0000000..f90fe3b
--- /dev/null
+++ b/archetypes/default.md
@@ -0,0 +1,9 @@
++++
+draft = true
+slug = "post-url-name"
+author = "Sean T. Allen"
+tags = [
+    "tag 1",
+    "tag 2",
+]
++++
diff --git a/config.toml b/config.toml
new file mode 100644
index 0000000..e1061ff
--- /dev/null
+++ b/config.toml
@@ -0,0 +1,59 @@
+baseurl = "https://www.monkeysnatchbanana.com"
+languageCode = "en-us"
+title = "Apache cTAKES Website"
+theme = "sean-steam"
+# Enable Google Analytics be inserting your tracking code
+# Number of posts per page
+paginate = 5
+
+[permalinks]
+  post = "/:year/:month/:day/:title/"
+
+[params]
+  title = "Apache cTAKES Website"
+  copyright = ""
+
+  # You can choose between green, orange, red and blue.
+  themecolor = "blue"
+
+  # Link custom assets relative to /static
+  favicon   = "favicon.ico"
+  customCSS = []
+  customJS  = []
+
+  # To provide some metadata for search engines and the about section in the footer
+  # feel free to add a few information about you and your website.
+  name = "Sean T Allen"
+  bio = "Co-author of [Storm Applied: Strategies for real-time event processing](http://manning.com/sallen/?a_aid=sallen)"
+  description = ""
+
+  # Link your social networks (optional)
+  location = ""
+  twitter = ""
+  linkedin = ""
+  googleplus = ""
+  facebook = ""
+  instagram = ""
+  github = ""
+  gitlab = ""
+  bitbucket = ""
+
+  # Customize or translate the strings
+  keepReadingStr = "READ THIS ARTICLE"
+  backtotopStr = "Back to top"
+  shareStr = "Share"
+  pageNotFoundTitle = "404 - Page not found"
+  useSummaryIfNoDescription = true
+
+[[menu.main]]
+    name = "Introduction"
+    weight = -110
+    url = "/about/"
+[[menu.main]]
+    name = "Wikipedia"
+    weight = -100
+    url = "http://manning.com/sallen/?a_aid=sallen"
+[[menu.main]]
+    name = "Downloads"
+    weight = -90
+    url = "/index.xml"
diff --git a/content/intro.md b/content/intro.md
new file mode 100644
index 0000000..9d03b2c
--- /dev/null
+++ b/content/intro.md
@@ -0,0 +1,23 @@
++++
+title = "Introduction"
++++
+
+The Apache™ clinical Text Analysis and Knowledge Extraction System (cTAKES™) focuses on extracting knowledge from clinical text through Natural Language Processing (NLP) techniques.
+
+cTAKES is engineered in a modular fashion and employs leading-edge rule-based and machine learning methods.
+
+cTAKES has standard features for biomedical text processing software, including the ability to extract concepts such as symptoms, procedures, diagnoses, medications and anatomy with attributes and standard codes.
+
+More powerful components can perform tasks as complex as identifying temporal events, dates and times – resulting in placement of events in a patient timeline.
+
+Components are trained on gold standards from the biomedical as well as the general domain. This affords usability across different types of clinical narrative (e.g. radiology reports, clinical notes, discharge summaries) in various institution formats as well as other types of health-related narrative (e.g. twitter feeds), using multiple data standards (e.g. Health Level 7 (HL7), Clinical Document Architecture (CDA), Fast Healthcare Interoperability Resources (FHIR), SNOMED-CT, RxNORM).
+
+cTAKES is the NLP platform for many initiatives across the world covering a variety of research purposes and large datasets. Contributors include professionals at medical and commercial institutions, NLP and Machine Learning researchers, Medical Doctors, and students of many disciplines and levels. We encourage people from all backgrounds to get involved! (link)
+
+---
+
+### Elsewhere...
+
+* [Email](mailto:dennis.johns@childrens.harvard.edu)
+* [GitHub](https://github.com/apache/ctakes)
+
diff --git a/content/post/adventures-in-documentation-building.md b/content/post/adventures-in-documentation-building.md
new file mode 100644
index 0000000..0cb61c8
--- /dev/null
+++ b/content/post/adventures-in-documentation-building.md
@@ -0,0 +1,23 @@
++++
+draft = true
+date = "2017-02-18T09:22:51-05:00"
+title = "Adventures in Documentation Building"
+tags = ["tag 1","tag 2"]
+author = "Sean T. Allen"
+slug = "adventures-in-documentation-building"
+
++++
+
+Does your project use [TravisCI](https://travis-ci.org)? Create it's documentation using [Mkdocs](http://www.mkdocs.org)? Awesome. Let me show you how to 
+
+```
+after_success:
+  - if [[ $TRAVIS_BRANCH == 'master' && $TRAVIS_PULL_REQUEST == 'false' ]]; then
+      git remote add gh-token "https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}";
+      git fetch gh-token && git fetch gh-token gh-pages:gh-pages;
+      build/release/ponyc packages/stdlib --docs;
+      cd stdlib-docs;
+      sudo -H pip install mkdocs;
+      mkdocs gh-deploy -v --clean --remote-name gh-token;
+    fi;
+```
diff --git a/content/post/adventures-in-pthreading.md b/content/post/adventures-in-pthreading.md
new file mode 100644
index 0000000..fa9eeca
--- /dev/null
+++ b/content/post/adventures-in-pthreading.md
@@ -0,0 +1,10 @@
++++
+slug = "post-url-name"
+draft = true
+date = "2017-02-18T09:29:19-05:00"
+title = "adventures in pthreading"
+tags = ["tag 1","tag 2"]
+author = "Sean T. Allen"
+
++++
+
diff --git a/content/post/an-acceptable-tool.md b/content/post/an-acceptable-tool.md
new file mode 100644
index 0000000..530b4bc
--- /dev/null
+++ b/content/post/an-acceptable-tool.md
@@ -0,0 +1,21 @@
++++
+title = "An Acceptable Tool"
+tags = ["software architecture"]
+author = "Sean T. Allen"
+slug = "an-acceptable-tool"
+draft = false
+date = "2015-02-24T11:31:27-05:00"
+
++++
+
+Imagine for a moment that you are on a small development team tasked with core operations at a moderate sized startup. You're responsible for the development, operations and maintenance of various production systems. Your day is filled with all the fun of programming combined with the joys of running a distributed system. You've just entered a room with the rest of your teammates to discuss what tools you'll be using to build your latest system. 
+
+You're fairly far along in the process; down to an Erlang based solution and a JVM based one. The Erlang solution is very alluring. Erlang's OTP library handles a ton of concerns for you that you will otherwise have to handle yourself with the JVM solution. Erlang is "the right tool for the job". However, you are going in to the room to argue for the JVM solution. Why? Because you don't need the right tool, you just need "an acceptable tool".
+
+You don't run any Erlang based systems in production. You have no experience with monitoring Erlang, collecting metrics or all the other things that go into running a stable system. The JVM on the other hand, you have tons of experience with. You and your team mates are proficient at tuning the garbage collector to minimize latency. You have extensive Java profiling experiencing. You have battle tested metrics collecting and other libraries that you've been running in production without issue. 
+
+The JVM might not be the right tool, but it isn't the wrong one either. It's acceptable. It will get the job done and most importantly you know how to get the job done with it. Operational knowledge is hard won. Far harder to win than understanding the syntax and semantics of a new programming language. 
+
+In the first few weeks after your new project is released into production, you'll be thankful you picked the merely acceptable tool because you spend less time learning how to fight the inevitable fires and more time sleeping peacefully at night.
+
+What's the difference between the right tool and an acceptable one? It's a matter of context and costs. Every tool comes with a cost that varies based on the context in which it's used. In a production environment, operational experience should factor heavily into that cost analysis. Picking an acceptable tool is hard. It requires research and understanding. Its easy to fall into the trap of thinking you are picking an acceptable tool when really you're just picking the tool at hand.
diff --git a/content/post/code-management-wishlist.md b/content/post/code-management-wishlist.md
new file mode 100644
index 0000000..0369f4a
--- /dev/null
+++ b/content/post/code-management-wishlist.md
@@ -0,0 +1,156 @@
++++
+title = "Things I'd like in my code management tool"
+author = "Sean T. Allen"
+slug = "code-management-wishlist"
+draft = false
+date = "2018-12-26T13:31:27-05:00"
++++
+This morning, I was reading a [blog post from Joe Armstrong](https://joearms.github.io/#2018-12-26%20Fun%20with%20the%20TiddlyWiki)  about how he got a [Chandler](https://en.wikipedia.org/wiki/Chandler_(software)) like [Triage system](https://en.wikipedia.org/wiki/Triage) working in [Tiddly-Wiki](https://tiddlywiki.com/). A Triage system is one of the things I'd like to see GitHub add. That got me thinking, what are some of the other things I'd like to see in a GitHub. What follows is fa [...]
+
+Most of what is on this list is in the area of "project management"; after all, code management is more than just about managing the code. It's about managing the project around the code.
+
+## Multi-level issues
+
+Most tools at best give me two levels. There's a project, and there are issues. Only having two levels can be hard to work with if you are interested in organizing work in a way that leads to better ["ambient awareness"](https://en.wikipedia.org/wiki/Ambient_awareness) of what is going on in a project. Having only two levels also makes a lot of the other "project management" features I mention later less attractive as well.
+
+Ideally what I want is to start from something like "We are going to do X" and then break X down into issues and perhaps those issues into other issues.
+
+At any time, I want to be able to look at any level and understand what is going on. Be it at the top level of the project or at any individual issue which might itself be a collection of issues.
+
+Image an issue for example that is made up of 3 other issues. Each of those issues is assigned to different team members. When I look at my higher-level issue, I can see that 3 people are working on it. I can see there are 3 sub-issues that I can drill into. 
+
+## Triage system
+    
+You can fake this with tags in something like GitHub, but it's a pain. For every issue, I want to be able to say it is for "now, later, or done." An issue can move from any state to any other state. See [https://en.wikipedia.org/wiki/Triage](https://en.wikipedia.org/wiki/Triage) for more information.
+
+When something is marked as "later," I should be prompted in the future to reconsider it. "You said later for X, is it later yet? Should that become a now?"
+    
+## "Threaded" comments
+
+ A popular GitHub issue is about as useful as a really popular IRC channel. Eventually, it devolves into several different conversations related to a general topic at once. It becomes increasingly hard to follow different threads of conversation. "Threading" is far from perfect but it's better than the "all in one long vertical bucket" that most tools supply.
+        
+## Dependencies between issues
+
+Some tasks can't be started until others are finished. I want to be able to see and visualize this easily.
+
+## Dependencies for issues
+
+Sometimes some dependencies are outside the issue system itself. For example, only Alice is qualified to do this work at this time. We need Alice to be available. Alternatively, even, "either Alice or Bob could do this"
+
+## Estimation of issues
+
+Really, there are two styles of estimation that I'd like my tools to support. 
+
+### High-level estimation
+I want to be able to give quick, high-level estimates of things. For example- tiny, small, medium, large, huge that are a quick "we think it will take handwave amount of time." These are useful for getting a really rough idea of the amount of effort something would involve.
+
+### Fine-grained estimation
+
+I want to be able to apply estimates to that switch from a handwave amount of time to a granular estimate that is measured in days (it would be nice because some tasks are small to be able to measure in hours as well, but in the end, I could do without this).
+
+## Attach "risk" to issues
+
+Sometimes when we estimate an issue, we know with high certainty that our estimate is right. Other times, we know there's a great deal of possible variation. 
+
+I address this by asking everyone to give a best case, worst case, and most likely case estimate for work. The wider the range between those estimates, the more risk there is and the less confidence we can have that the work won't end up derailing our project. Capturing this information on issues is valuable.
+
+## Burndown charts
+
+I want burndown charts that take into account dependencies and estimations. Burndown charts are a powerful way of visualizing if a project is on track or behind. 
+
+In a burndown chart, I want to be able to run simulations as well. "What happens to this project if X work falls behind. What happens if Bob gets sick?"
+
+You can do all the math yourself, but it's a hell of a lot nicer to have a computer do it for you (even if it can't account for nuance that you as a human can)
+
+## Cumulative Flow Charts
+
+I don't use them often, but they can be convenient from time to time for being able to visualize problems that might be ready to arise easily.
+
+See [https://kanbantool.com/cumulative-flow-diagram](https://kanbantool.com/cumulative-flow-diagram) to learn more if you aren't familiar with them.
+
+## Milestones 
+
+I want milestones that are made up of various issues which will then be explicitly represented in burndown charts. I want a tool that can do the math I currently have to do to determine if something is "on track" or not. 
+
+## Time tracking
+
+Estimating is hard. We get it wrong all the time. However, we can't get it right if we aren't reflective on it. One way to do that is to record our original estimates for tasks and then record how much work we did on the item. Seeing that we thought something would take 8 hours of work but we spent 24 is incredibly valuable. We can revisit our assumptions we made when estimating see where we got it wrong. Then, we can try and account for it next time. Yes, estimating is hard but its also [...]
+
+## Ability to re-estimate
+
+Look, sometimes we get those estimates wrong. Leaving the original estimate in place doesn't help. Then our dependencies and burndown charts are going to be wrong. I want the ability to change an estimate from 1 day to 10 days, and if work has already started, I want to be able to get access to earlier estimates and have the new estimate accounted for when determining if things are "on track", that means the new estimate should be reflected in milestones and burndown charts and every oth [...]
+
+## Estimate groups
+
+Look, let's face it. If you have 3 different people and a single issue, it's quite likely that the amount of time it will take to complete that issue will vary based on who is doing it; sometimes it will vary greatly. 
+
+You need to capture that information. It's essential for planning if it will take Alice 2 days to do something but 10 if Bob does it.
+
+Estimation groups go back to an idea I expressed in "dependencies for issues." Sometimes, you have a limited number of people who can conceivably work on a particular problem.
+
+## Due dates for "everything"
+
+It's nice to be able to look at a thing and know "oh, this has to be done by Thursday for us to stay on track." 
+
+## Kanban style board that is tied to changes in issue status
+
+I want to be able to move things through a lifecycle that is displayed in a visual kanban style without doing a lot of manual moving of issues from one column to another.
+
+## Issue status that is tied to Kanban style board
+
+If I move an issue into an "in-progress" column in a board, that change should be reflected on the issue as well.
+
+## Tie issues to "external" documents and vice-versa
+
+When I estimate larger projects, I invariably end up working collaboratively with others in a GoogleDoc to come up with a project plan. A ton of information is captured in that doc:
+
+- timelines
+- dependencies
+- assumptions
+- in-depth detail
+
+A lot of that information can be captured in other items I've put on my wishlist here, however, capturing the original information and tying it to the project is essential. I want to have a bidirectional link from a project and its issues to supporting documentation (there could be multiple documents). 
+
+I want to be able to both edit those documents offline and in a collaborative fashion online.
+
+I want to be able to comment on specific aspects of those docs as well and carry conversations in those comments.
+
+## "Configurable" kanban board definition
+
+Kanban boards are a great way to visualize things, but if I have to add everything to a board manually, it gets old fast. One of the great things about kanban boards is that they provide a visualization of information for a specific context. However, that context can vary. 
+
+The ability to derive boards from a central pool of information would be great. In addition to "more traditional" boards, I might want to see on a per assignee basis, by estimate or god knows what. 
+
+Even if I have only 1 board, not having to set everything up by hand would a godsend.
+
+## Confidential "issues"
+
+Some information shouldn't be made public. Perhaps it contains information about a security flaw or confidential information for a specific group that we are working it.
+
+## Integrated "CI"
+
+I love that GitHub has an API that allows me to hook up to tools like TravisCI, CircleCI, Code Climate, and what-not but, in the end, what I want is the ability to run arbitrary code at any point in a life cycle. That might be event-driven like, "on pull request, run these tasks," or it might be time-based "run fault injection tests daily with 50 random interleavings". Either way, I want that to be fully integrated into my "code management" tool. 
+
+In the end, this is far more than just "CI." I want to be able to run "my code in my environment" on demand based on lifecycle events. Further, "my environment" probably means something more like "my containers" because I don't want to manage the infrastructure for all this.
+
+[GitHub actions](https://github.com/features/actions) look intriguing and like a step in this direction. Perhaps they give me everything I would want but, I haven't played with them yet, so ¯\_(ツ)_/¯.
+
+## File storage
+
+I want to be able to store files of all sorts with my project — for example, dependencies like specific versions of a compiler. Alternatively, perhaps created artifacts and what not.
+
+## Ability to "clone" everything
+
+It's fantastic that tools like GitHub and Gitlab allow me to clone the code and work with it offline, but I want to be able to clone everything. Issues, project boards, wikis, everything! 
+
+## Conclusion
+
+Welp, that's where I got to with this morning's list. Now that I'm here, I realize there's a ton more for me dig into. For example, when I was putting this list together, I realized that I  need to do one that  is "what I want in an integrated CI system." There's a ton to dig into in just that topic. Moreover, there are a variety of others as well. For example, I gave zero thought to code review and that unto itself is yet another massive area. 
+
+I think I'm going to start making lists for different areas like code management, code review, integrated CI and what not and slowly build up my list of "what I want in my code management tool" for real. I feel happy with this as a first pass.
+
+Looking around, even though I'm a heavy [GitHub user](https://github.com/seantallen/), it looks like [Gitlab is the currently tool that would most likely end up fulfilling my desires](https://about.gitlab.com/features/). 
+
+Got thoughts on things you'd like to see in a "GitHub like" tool? I'd love to hear them. Feel free to ping me on [Twitter](https://twitter.com/seantallen).
+
+
diff --git a/content/post/codemeshio-how-did-i-get-here.md b/content/post/codemeshio-how-did-i-get-here.md
new file mode 100644
index 0000000..b30ddea
--- /dev/null
+++ b/content/post/codemeshio-how-did-i-get-here.md
@@ -0,0 +1,51 @@
++++
+draft = false
+date = "2016-11-22T09:56:56-05:00"
+title = "CodeMeshIO: How Did I Get Here?"
+tags = ["talks","testing", "distributed systems", "stream processing", "video", "slides"]
+description = "Post with link my CodeMesh.io talk \"How Did I Get Here? Building Confidence in a Distributed Stream Processor\" and associated content."
+author = "Sean T. Allen"
+slug = "codemeshio-how-did-i-get-here"
++++
+
+## Building Confidence in a Distributed Stream Processor
+
+Video of my CodeMeshIO talk: ["How Did I Get Here? Building Confidence in a Distributed Stream Processor"](https://www.youtube.com/watch?v=6MsPDtpe2tg&index=3&list=PLWbHc_FXPo2hGJHXhpgqDU-P4BArpCdh6) is now available. 
+
+---
+
+There's a number of links at the end of the talk for additional material you can check out. To make life easier on everyone I'm recreating it here.
+
+### Peter Alvaro
+
+* [Peter Alvaro's twitter](https://twitter.com/palvaro)
+* [Lineage-driven Fault Injection](http://www.cs.berkeley.edu/~palvaro/molly.pdf)
+* [Outwards from the Middle of the Maze](https://www.youtube.com/watch?v=ggCffvKEJmQ)
+
+### Kyle Kingsbury
+
+* [Kyle Kingsbury's twitter](https://twitter.com/aphyr)
+* [Jepsen](https://aphyr.com/tags/Jepsen)
+
+### Will Wilson
+
+* [Testing Distributed Systems w/ Deterministic Simulation](https://www.youtube.com/watch?v=4fFDFbi3toc)
+
+### Catie McCaffrey
+
+* [Catie McCaffrey's twitter](https://twitter.com/caitie)
+* [The Verification of a Distributed System:
+A practitioner's guide to increasing confidence in system correctness](http://queue.acm.org/detail.cfm?ref=rss&id=2889274)
+* [The Verification of a Distributed System](https://www.infoq.com/presentations/distributed-systems-verification)
+
+### Inés Sombra
+
+* [Inés Sombra twitter](https://twitter.com/randommood)
+* [Testing in a Distributed World](https://www.youtube.com/watch?v=KSdNYi55kjg)
+
+### Chaos Engineering
+
+* [Principles of Chaos Engineering](http://principlesofchaos.org)
+
+---
+If you are interested, I've made the [slides available on Speakerdeck](https://speakerdeck.com/seantallen/how-did-i-get-here-building-confidence-in-a-distributed-stream-processor-1). Like most of my talks, the slides aren't particularly good at standing on their own without the talk itself.
diff --git a/content/post/deconstructing-a-pony-echo-server.md b/content/post/deconstructing-a-pony-echo-server.md
new file mode 100644
index 0000000..71d9e6b
--- /dev/null
+++ b/content/post/deconstructing-a-pony-echo-server.md
@@ -0,0 +1,229 @@
++++
+tags = ["pony"]
+author = "Sean T. Allen"
+date = "2015-12-13T10:56:41-05:00"
+title = "Deconstructing a Pony echo server"
+slug = "deconstructing-a-pony-echo-server"
+draft = false
++++
+
+Lately I've been diving into learning [Pony](http://ponylang.org) in a more organized fashion. As part of that, I've decided to share the experience along the way. If you aren't familiar with Pony then you probably won't get much from this post. If you are interested in a high performance, safe, actor based programming language, then I'd suggest you check out the [Pony tutorial](http://tutorial.ponylang.org) then venture back. All that said, I'll do my best to provide links to relevant P [...]
+
+This morning's exercise was to write an echo server and see what bits of Pony I'd learn along the way. What follows is the complete original source code for my Pony echo server and then some discussion of what I learned as I was writing it.
+
+If you want to get started writing any network services with Pony, I'd suggest by started by reading the ["net" example](https://github.com/ponylang/ponyc/tree/master/examples/net). My echo server borrows heavily from the example code. My basic process was to steal bits from the example code until I had a working echo server and then set about figuring out how it all actually worked. 
+
+Hopefully, you find this useful. I'm going to start by dropping all the code on you at once, don't worry about absorbing it all. We'll walk through the important parts together. Without further ado, _echo.pony_: 
+
+```
+use "net"
+
+actor Main
+  new create(env: Env) =>
+    TCPListener.ip4(recover Listener(env) end)
+
+class Listener is TCPListenNotify
+  let _env: Env
+  var _host: String = ""
+  var _service: String = ""
+
+  new create(env: Env) =>
+    _env = env
+
+  fun ref listening(listen: TCPListener ref) =>
+    try
+      (_host, _service) = listen.local_address().name()
+      _env.out.print("listening on " + _host + ":" + _service)
+    else
+      _env.out.print("couldn't get local address")
+      listen.close()
+    end
+
+  fun ref not_listening(listen: TCPListener ref) =>
+    _env.out.print("couldn't listen")
+    listen.close()
+
+  fun ref connected(listen: TCPListener ref) : TCPConnectionNotify iso^ =>
+    Server(_env)
+
+class Server is TCPConnectionNotify
+  let _env: Env
+
+  new iso create(env: Env) =>
+    _env = env
+
+  fun ref accepted(conn: TCPConnection ref) =>
+    _env.out.print("connection accepted")
+
+  fun ref received(conn: TCPConnection ref, data: Array[U8] iso) =>
+    _env.out.print("data received, looping it back")
+    conn.write("server says: ")
+    conn.write(consume data)
+
+  fun ref closed(conn: TCPConnection ref) =>
+    _env.out.print("server closed")
+```
+
+First important thing to note is that none of this will work without some classes from the [Pony standard networking library](https://github.com/ponylang/ponyc/tree/master/packages/net). We include those classes we might need with the _use_ expression:
+
+```
+use "net"
+```
+
+Every Pony program has a _Main_ actor that acts as its entry point. You can get more details about special significance of _Main_ in the ["hello-world" section of the Pony tutorial](http://tutorial.ponylang.org/getting-started/hello-world.html).
+
+Let's take a look at our echo server's _Main_ actor:
+
+```
+actor Main
+  new create(env: Env) =>
+    TCPListener.ip4(recover Listener(env) end)
+```
+
+There's quite a bit going on here for a newbie to absorb. It took me a while with the examples and the standard library to understand how to get started with network programming in Pony. Let's unpack the important bits.
+
+```
+01: TCPListener.ip4(
+02:   recover
+03:     Listener(env)
+04:   end
+05: )
+```
+
+We start by creating a TCPListener that only handles ip version 4. _TCPListener_ is an actor [defined in the standard library](https://github.com/ponylang/ponyc/blob/master/packages/net/tcplistener.pony). To create an ipv4 TCPListener, we have to provide one thing: a class that implements [_TCPListenNotify_](https://github.com/ponylang/ponyc/blob/master/packages/net/tcpnotify.pony#L61). That object will be notified by the TCPListener actor we are creating anytime a new connection comes in. 
+
+Here's our _Listener_ from the echo server:
+
+```
+class Listener is TCPListenNotify
+  let _env: Env
+  var _host: String = ""
+  var _service: String = ""
+
+  new create(env: Env) =>
+    _env = env
+
+  fun ref listening(listen: TCPListener ref) =>
+    try
+      (_host, _service) = listen.local_address().name()
+      _env.out.print("listening on " + _host + ":" + _service)
+    else
+      _env.out.print("couldn't get local address")
+      listen.close()
+    end
+
+  fun ref not_listening(listen: TCPListener ref) =>
+    _env.out.print("couldn't listen")
+    listen.close()
+
+  fun ref connected(listen: TCPListener ref) : TCPConnectionNotify iso^ =>
+    Server(_env)
+```
+
+Basically, you can sum up what it does by saying:
+
+* When it starts up, it prints out the host and port it's listening on
+* When a new connection is established, it creates a new instance of _Server_ to handle the incoming connection
+
+Our Server class implements the [_TCPConnectionNotify_ interface](https://github.com/ponylang/ponyc/blob/master/packages/net/tcpnotify.pony#L1) as required by _TCPListenNotify_.
+
+```
+class Server is TCPConnectionNotify
+  let _env: Env
+
+  new iso create(env: Env) =>
+    _env = env
+
+  fun ref accepted(conn: TCPConnection ref) =>
+    _env.out.print("connection accepted")
+
+  fun ref received(conn: TCPConnection ref, data: Array[U8] iso) =>
+    _env.out.print("data received, looping it back")
+    conn.write("server says: ")
+    conn.write(consume data)
+
+  fun ref closed(conn: TCPConnection ref) =>
+    _env.out.print("server closed")
+``` 
+
+We can sum up what _Server_ is doing with:
+
+* Outputs a message to standard out any time it accepts a connection.
+* When it receives data, it sends it back to the sender with an additional _"server says: "_ message.
+
+There's one interesting bit of Pony in our Server class:
+
+```
+  fun ref received(conn: TCPConnection ref, data: Array[U8] iso) =>
+    _env.out.print("data received, looping it back")
+    conn.write("server says: ")
+    conn.write(consume data)
+```
+
+What's up with that _consume data_ that is being passed to _conn.write_? It's part of [Pony's reference capabilities](http://tutorial.ponylang.org/capabilities/reference-capabilities.html). Reference capabilities are one of Pony's killer features. As programmers, we can mark data with different capabilities allowing us, with the support of the compiler, to safely use shared mutable state. If you aren't familiar with Pony's reference capabilities, I suggest you [review them](http://tutori [...]
+
+Right now, the two capabilities that we care about are _isolated_ and _value_. They are defined in the Pony tutorial as:
+
+> Isolated, written iso. This is for references to isolated data structures. If you have an iso variable then you know that there are no other variables that can access that data. So you can change it however you like and give it to another actor.
+
+> Value, written val. This is for references to immutable data structures. If you have a val variable then you know that no-one can change the data. So you can read it and share it with other actors.
+
+The type signature for TCPConnection write is:
+
+```
+be write(data: ByteSeq)
+```
+
+write takes a ByteSeq _value_. However, our data variable is tagged as being an _isolated_ capability. If we were to try and pass our _iso data_ to our _val write_, we'd get the following compiler error:
+
+```
+echo.pony:43:16: argument not a subtype of parameter
+    conn.write(data)
+               ^
+packages/net/tcpconnection.pony:75:12: parameter type: ByteSeq val
+  be write(data: ByteSeq) =>
+           ^
+echo.pony:43:16: argument type: Array[U8 val] iso!
+    conn.write(data)
+```
+
+We need to turn our iso into a val. By doing that, we are widening the access to it. Pretty dangerous stuff. When you need to expand capabilities in that fashion, Pony provides the [consume keyword](http://tutorial.ponylang.org/capabilities/consume-and-destructive-read.html#consuming-a-variable). When we consume our iso data, we are creating a new variable that is a val and declaring that from this point forward, no one can use the original data variable. If we were to try to access the  [...]
+
+We've covered a lot of ground and ended up stumbling around in [Pony's reference capabilities](http://tutorial.ponylang.org/capabilities/reference-capabilities.html) which are one of the hardest parts of the language to get a handle on. There's still one bit of our echo server that we haven't tackled yet. Earlier, when discussing our _Main_ actor, we had this code:
+
+```
+01: TCPListener.ip4(
+02:   recover
+03:     Listener(env)
+04:   end
+05: )
+```
+
+We never discussed what was going on with lines 02 and 04. What up with that recover? Again, the answer lines in [Pony's reference capabilities](http://tutorial.ponylang.org/capabilities/reference-capabilities.html). The method signature for TCPListener.ip4 says that the notify handler we supply has to be an iso reference. However, our Listener is a reference. _recover_ in this case takes our ref and returns an iso. I won't dig into the details as the Pony tutorial has a good [section on [...]
+
+Lastly, I'll add that I realized as I was writing this post, that I didn't need to use recover at all. I was using it because I took it from the ["net" example code](https://github.com/ponylang/ponyc/tree/master/examples/net). If we were to change our _Listener_ classes constructor from returning a ref:
+
+```
+  new create(env: Env) =>
+    _env = env
+```
+
+to returning an iso:
+
+```
+  new iso create(env: Env) =>
+    _env = env
+```
+
+then our _Main_ actor can become the far more straightforward:
+
+```
+actor Main
+  new create(env: Env) =>
+    let listener = TCPListener.ip4(Listener(env))
+```
+
+The final code is currently available on [GitHub](https://github.com/SeanTAllen/pony-echo-server) and will be making it into the official Pony examples. Hopefully you've learned a little something. I know I learned a quite bit having to explain what I did this morning. Check back soon, there will be plenty more learning Pony content coming.
+
+_12/14/15 update: the echo server is now available as part of the [official ponyc examples](https://github.com/ponylang/ponyc/blob/master/examples/echo/echo.pony)._
+
diff --git a/content/post/faking-a-https-client-for-glass.md b/content/post/faking-a-https-client-for-glass.md
new file mode 100644
index 0000000..2dc368c
--- /dev/null
+++ b/content/post/faking-a-https-client-for-glass.md
@@ -0,0 +1,79 @@
++++
+date = "2010-06-22T08:59:50-05:00"
+title = "Faking a https client for GLASS"
+slug = "faking-a-https-client-for-glass"
+draft = false
+tags = ["GLASS","nginx","smalltalk","seaside"]
+author = "Sean T. Allen"
+
++++
+
+So, you are humming along developing your GLASS hosted Seaside application. If you are following the proscribed development path, your application is running in Pharo and you've started porting it to GLASS when a problem arises:
+
+Your application needs to make calls out to a secure web service (merchant processor etc) but, GLASS doesn't have a native https client. The Pharo [cryptography package](http://www.squeaksource.com/Cryptography.html) implements an https client which you could port to Gemstone, but the process model it uses doesn't map nicely and you have better things to do with your time. You could wrap up the [C OpenSSL library](http://www.openssl.org/) and access it from Smalltalk-- also a large amoun [...]
+
+## Http to Https Proxying
+
+A [proxy server](http://en.wikipedia.org/wiki/Proxy_server) is *a server (a computer system or an application program) that acts as an intermediary for requests from clients seeking resources from other servers.* In our current scenario, our Seaside application will make an http connection to a local proxy that will in turn open a https connection to a remote server passing our info along in the process. In order to accomplish this, we will give a hostname to our proxy and connect to it  [...]
+
+```
+127.0.0.1   secure_service
+```
+
+From our smalltalk code instead of opening a connection to *https://api.secure_service.com/apiLocation*, we will open a connection to *http://secure_service/apiLocation*. With this simple code change out of the way, we can move on to setting up the proxy. There are two primary options for doing http to https proxying. Using [stunnel](http://stunnel.mirt.net/) or a proxying web server:
+
+### Stunnel
+
+I'm not going to give an in depth coverage to setting up stunnel as a means of doing outgoing https connections from  GLASS. Why? For any production GLASS system, we are probably going to be running a web server in front of the swazoo, hyper or fastcgi adapter that is serving your Seaside content; that web server is all you need. If we use stunnel to as a proxy for our http to https connections, we are just adding another point of failure to our setup. By using our existing web server as [...]
+
+### Proxying Web Server
+
+We could use [apache](http://httpd.apache.org/docs/2.0/mod/mod_proxy.html), [lighttpd](http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModProxy) or any other proxying web server to implement the following solution. I'll use [Nginx](http://www.nginx.org)[^n] as it is the server I'm most comfortable with. We already added a name for our */etc/hosts* and now it is time to add an additional server entry to our *nginx.conf* file[^n].
+
+```
+server
+{
+  server_name secure_service;
+  
+  location /
+  {
+    proxy_pass https://api.secure_service.com;
+  }
+}
+```
+
+Restart Nginx and we are good to go.
+
+## Using test resources
+
+If we use a build system and the remote service offers production and testing versions, we can get an added bonus from the proxy setup: easy switching at build time between production and testing services.
+
+Let's assume that *secure_service* is a merchant processing provider that provides a test interface where no billing is actually done as well as a production system where transactions are charged to the consumer. Instead of having testing and production objects that change the url we are using, we can have a build system insert the correct url in our *nginx.conf file*. If we are using a [standard c preprocessor](http://gcc.gnu.org/onlinedocs/cpp/index.html)[^n], the following setup and s [...]
+
+```
+#ifdef PRODUCTION
+#define SECURE_SERVICE_URL  production-api.secure_service.com
+#else
+#define SECURE_SERVICE_URL  testing-api.secure_service.com
+#endif
+```
+
+```
+server
+{
+  server_name secure_service;
+  
+  location /
+  {
+    proxy_pass https://SECURE_SERVICE_URL;
+  }
+}
+```
+
+[^n]: If we need to access your proxy from multiple machines, using real dns entries for our domain will make maintenance much easier.
+
+[^n]: You need to configure Nginx at build time to include https support.
+
+[^n]: Normally located in /etc/nginx.conf
+
+[^n]: Any preprocessor would do.
diff --git a/content/post/inside-the-pony-tcp-stack.md b/content/post/inside-the-pony-tcp-stack.md
new file mode 100644
index 0000000..7a5471d
--- /dev/null
+++ b/content/post/inside-the-pony-tcp-stack.md
@@ -0,0 +1,644 @@
++++
+draft = false
+tags = ["pony"]
+date = "2015-12-19T10:52:43-05:00"
+title = "Inside the Pony TCP Stack"
+author = "Sean T. Allen"
+slug = "inside-the-pony-tcp-stack"
+
++++
+
+In this post, we are going to take a look at how [Pony](http://www.ponylang.org/) implements its TCP stack. The API for Pony's networking stack is callback and event driven. I've previously written about [network programming in Pony](http://www.monkeysnatchbanana.com/2015/12/13/deconstructing-a-pony-echo-server/) and showed how to implement a simple echo server. We didn't, however, dive too deeply into the Pony TCP stack. In this post, we'll move down a level of abstraction and see how P [...]
+
+* Review the two interfaces that we previously used to implement an echo server
+* Give a quick overview of how server side TCP programming works
+* Recap the important TCP related bits from our echo server
+* Show how Pony's [standard library networking code](https://github.com/ponylang/ponyc/tree/master/packages/net) implements standard TCP programming patterns
+* Give a quick overview of Pony's [C FFI](http://tutorial.ponylang.org/c-ffi/calling-c/)
+* Touch briefly on Pony's internal event system
+
+This post features a lot of Pony code as well as a lot of C code. In order to follow along, you'll need to have some familiarity with each. If you are unfamiliar with Pony, I suggest you do a review of Pony's basic semantics by reviewing the [Pony Tutorial](http://tutorial.ponylang.org). Most of the code examples are simplified versions of actual Pony code. Where possible, I have removed platform specific code as well as code that - while important to overall functionality - has little t [...]
+
+Let's get started...
+
+## A Skeleton for a Pony TCP server
+
+<img src="https://videos.hasbro.com/img/694893024001/201502/1058/694893024001_4070167773001_MLP-MV-ThePerfectStallion-SingAlong-FINAL-720H264-vs.jpg?pubId=694893024001" align="center">
+
+Our echo server is built around a two classes that implement interfaces that are part of the Pony network stack. Each method in the interfaces corresponds to an event that can happen while interacting with or attempting to interact with a network resource. The particulars aren't that important right now, what is important is recognizing the callback driven nature of network programming with Pony. Pony handles the details of networking programming while users of the API are responsible fo [...]
+
+```
+interface TCPListenNotify
+  """
+  Notifications for TCP listeners.
+  """
+  fun ref listening(listen: TCPListener ref) =>
+    """
+    Called when the listener has been bound to an address.
+    """
+    None
+
+  fun ref not_listening(listen: TCPListener ref) =>
+    """
+    Called if it wasn't possible to bind the listener to an address.
+    """
+    None
+
+  fun ref closed(listen: TCPListener ref) =>
+    """
+    Called when the listener is closed.
+    """
+    None
+
+  fun ref connected(listen: TCPListener ref): TCPConnectionNotify iso^ ?
+    """
+    Create a new TCPConnectionNotify to attach to a new TCPConnection for a
+    newly established connection to the server.
+    """
+```
+
+As you might notice in the _TCPListenNotify_ code above, the return type for the ```connected``` method is a ```TCPConnectionNotify``` instance. ```TCPConnectionNotify``` is our second interface that we need to implement. 
+
+```
+interface TCPConnectionNotify
+  """
+  Notifications for TCP connections.
+  """
+  fun ref accepted(conn: TCPConnection ref) =>
+    """
+    Called when a TCPConnection is accepted by a TCPListener.
+    """
+    None
+
+  fun ref connecting(conn: TCPConnection ref, count: U32) =>
+    """
+    Called if name resolution succeeded for a TCPConnection and we are now waiting for a connection to the server to succeed. The count is the number of connections we're trying. The notifier will be informed each time the count changes, until a connection is made or connect_failed() is called.
+    """
+    None
+
+  fun ref connected(conn: TCPConnection ref) =>
+    """
+    Called when we have successfully connected to the server.
+    """
+    None
+
+  fun ref connect_failed(conn: TCPConnection ref) =>
+    """
+    Called when we have failed to connect to all possible addresses for the server. At this point, the connection will never be established.
+    """
+    None
+
+  fun ref auth_failed(conn: TCPConnection ref) =>
+    """
+    A raw TCPConnection has no authentication mechanism. However, when protocols are wrapped in other protocols, this can be used to report an authentication failure in a lower level protocol (eg. SSL).
+    """
+    None
+
+  fun ref sent(conn: TCPConnection ref, data: ByteSeq): ByteSeq ? =>
+    """
+    Called when data is sent on the connection. This gives the notifier an opportunity to modify sent data before it is written. The notifier can raise an error if the data is swallowed entirely.
+    """
+    data
+
+  fun ref received(conn: TCPConnection ref, data: Array[U8] iso) =>
+    """
+    Called when new data is received on the connection.
+    """
+    None
+
+  fun ref closed(conn: TCPConnection ref) =>
+    """
+    Called when the connection is closed.
+    """
+    None
+```
+
+If you read the documentation strings attached to _TCPConnectionNotify_'s methods, you can see that they are related to servicing individual connections. 
+
+You might want to take the time now to check out [Deconstructing a Pony echo server](http://www.monkeysnatchbanana.com/2015/12/13/deconstructing-a-pony-echo-server/) to see _TCPListenNotify_ and _TCPConnectionNotify_ in action. It's not a required read but can add color and background that you might find helpful. Next, we are going to cover the basics of TCP/IP server programming which will set the table for our exploration of our main method in our echo server and our trip through the P [...]
+
+## TCP/IP server basics
+
+<img src="https://upload.wikimedia.org/wikipedia/en/5/55/Bsd_daemon.jpg" align="right">
+
+In order to understand Pony's approach to network programming, it's important to understand the basics of the BSD socket API. According to Wikipedia:
+
+>Berkeley sockets is an application programming interface (API) for Internet sockets and Unix domain sockets, used for inter-process communication (IPC). It is commonly implemented as a library of linkable modules.
+
+>The API evolved with little modification from a de facto standard into a component of the POSIX specification. Therefore, the term POSIX sockets is essentially synonymous with Berkeley sockets. They are also known as BSD sockets, acknowledging the first implementation in the Berkeley Software Distribution.
+
+The FreeBSD Developers' Handbook has an [excellent overview](https://www.freebsd.org/doc/en/books/developers-handbook/sockets-essential-functions.html) of the basics of BSD socket programming. I highly advise reading it if you aren't familiar with socket programming. You can however make it through this post while knowing only a subset of the information in the Developers' Handbook. 
+
+Let's go step by step through the basics of creating a TCP/IP server using the BSD socket API:
+
+**Create a socket**: It's basically ephemeral and attached to nothing. The only thing we know about are basic info such as its domain, protocol, and type. As of yet, our socket has no address and can't accept any incoming connections. The C function signature is: 
+
+`int socket(int domain, int type, int protocol)`
+
+**Bind**: We bind our new socket to an address and port pair. For example, if we wanted to bind to the standard HTTP port on localhost, we would bind to 127.0.0.1 on port 80. 
+
+`int bind(int s, const struct sockaddr *addr, socklen_t addrlen)`
+
+**Listen**: Once our socket is associated with an address, we can start listening for incoming connections. 
+
+`int listen(int s, int backlog)`
+
+**Accept**: When we receive a new connection, accept is called to create a new socket to handle that connection. Our original socket continues listening for more incoming connections while our new socket handles talking to our remote client.
+
+`int accept(int s, struct sockaddr *addr, socklen_t *addrlen)`
+
+To put this together, when writing a server using the BSD socket interface we:
+
+* Create a new socket
+* Bind it to an address/port combo
+* Start listening for incoming connections
+* Spawn new socket on demand to handle each incoming connection as they arrive
+
+Go ahead and review those steps until you feel comfortable with them. If you are struggling to remember them, write them down so you can refer to them as we work through Pony's TCP stack code. Those basic steps will help keep you oriented as we progress.
+
+## An echo server redux
+
+<img src="https://www.cs.northwestern.edu/~agupta/_projects/networking/TCPClientServer/cs.gif" align="right">
+
+Recapping our echo server code from last time, we are going to dive in from:
+
+```
+actor Main  
+  new create(env: Env) =>
+    TCPListener.ip4(recover Listener(env) end)
+```
+
+I previously described this code as:
+
+>We start by creating a TCPListener that only handles ip version 4. TCPListener is an actor defined in the standard library. To create an ipv4 TCPListener, we have to provide one thing: a class that implements TCPListenNotify. That object will be notified by the TCPListener actor we are creating anytime a new connection comes in.
+
+In that post, we didn't go into _TCPListener_ to see how it's implemented. Let's pull back that veil and move down another layer of abstraction.
+
+## A little bit of TCP/IP in Pony
+
+The Pony TCP stack is a powered by combination of callback objects and events. As we move through the code, this will become more and more clear. Let's take a look at the _TCPListener ipv4_ constructor that we called from our _Main_ actor in our echo server:
+
+```
+actor TCPListener
+
+  new ip4(notify: TCPListenNotify iso, host: String = "",
+    service: String = "0", limit: USize = 0)
+  =>
+    """
+    Listens for IPv4 connections.
+    """
+    _limit = limit
+    _notify = consume notify
+    _event = @os_listen_tcp4[AsioEventID](this, host.cstring(), service.cstring())
+    _fd = @asio_event_fd(_event)
+    _notify_listening()
+```
+
+The first line we want to focus on is:
+
+```
+_event = @os_listen_tcp4[AsioEventID](this, host.cstring(), service.cstring())
+```
+
+Let's start with that ```@os_listen_tcp4[AsioEventID]```. What's going on there? It appears to be some kind of function call but it's unlike any we have previously seen. The _@_ indicates that the function ```os_listen_tcp4``` is implemented in C. The ```[AsioEventID]``` indicates that our return type is of the type ```AsioEventID```. That's as much as you need to know about Pony's C FFI to get through the rest of this post. If you are interested in learning more, check out the [calling  [...]
+
+Let's check out what is going on in the C function ```os_listen_tcp4``` that we are calling:
+
+```
+asio_event_t* os_listen_tcp4(pony_actor_t* owner, const char* host,
+  const char* service)
+{
+  return os_socket_listen(owner, host, service, AF_INET, SOCK_STREAM,
+    IPPROTO_TCP);
+}
+```
+
+That's pretty straight forward. It is just calling another C function ```os_socket_listen```. What's important to note and to keep an eye on as we work through this, is the ```pony_actor_t* owner```. Don't lose track of it. It's a pointer to _TCPListener_ actor and will be very important later. Anyway, continuing on, ```os_socket_listen```:
+```
+static asio_event_t* os_socket_listen(pony_actor_t* owner, const char* host,
+  const char* service, int family, int socktype, int proto)
+{
+  struct addrinfo* result = os_addrinfo_intern(family, socktype, proto, host,
+    service, true);
+
+  struct addrinfo* p = result;
+
+  while(p != NULL)
+  {
+    int fd = socket_from_addrinfo(p, true);
+
+    if(fd != -1)
+    {
+      asio_event_t* ev = os_listen(owner, fd, p, proto);
+      freeaddrinfo(result);
+      return ev;
+    }
+
+    p = p->ai_next;
+  }
+
+  freeaddrinfo(result);
+  return NULL;
+}
+```
+
+The lines to focus on are:
+
+```
+asio_event_t* ev = os_listen(owner, fd, p, proto);
+...
+return ev;
+```
+
+Where we call ```os_listen``` and get an ```asio_event_id*``` back that will unwind its way back up the stack all the way to the Pony code in _TCPListener_ and be assigned to the ```_event``` variable:
+
+```
+_event = @os_listen_tcp4[AsioEventID](this, host.cstring(), service.cstring())
+```
+
+Before returning to _TCPListener_, we have more C code to follow. What's going on in ```os_listen```?
+
+```
+static asio_event_t* os_listen(pony_actor_t* owner, int fd,
+  struct addrinfo *p, int proto)
+{
+  if(bind((SOCKET)fd, p->ai_addr, (int)p->ai_addrlen) != 0)
+  {
+    os_closesocket(fd);
+    return NULL;
+  }
+
+  if(p->ai_socktype == SOCK_STREAM)
+  {
+    if(listen((SOCKET)fd, SOMAXCONN) != 0)
+    {
+      os_closesocket(fd);
+      return NULL;
+    }
+  }
+
+  // Create an event and subscribe it.
+  asio_event_t* ev = asio_event_create(owner, fd, ASIO_READ, 0, true);
+
+  (void)proto;
+
+  return ev;
+}
+```
+
+There we go! In all that C code, I see some BSD socket code:
+
+```
+if(bind((SOCKET)fd, p->ai_addr, (int)p->ai_addrlen) != 0)
+```
+
+where we bind our socket and 
+
+```
+if(listen((SOCKET)fd, SOMAXCONN) != 0)
+```
+
+where we start listening on that socket.
+
+If you remember our BSD socket creation steps earlier we had:
+
+**socket -> bind -> listen** -> accept
+
+Now that we are listening, how do we end up accepting incoming connections? The key lies in Pony's internal event system. Looking at the end of ```os_listen```, you'll see:
+
+```
+// Create an event and subscribe it.
+asio_event_t* ev = asio_event_create(owner, fd, ASIO_READ, 0, true);
+```
+
+Let's check out what is going on in ```asio_event_create```. N.B. that our first parameter is the ```pony_actor_t* owner``` that is a pointer to our _TCPListener_ actor that has been weaving its way down through the code.
+
+```
+asio_event_t* asio_event_create(pony_actor_t* owner, int fd, uint32_t flags, uint64_t nsec, bool noisy)
+{
+  if((flags == ASIO_DISPOSABLE) || (flags == ASIO_DESTROYED))
+    return NULL;
+
+  pony_type_t* type = *(pony_type_t**)owner;
+  uint32_t msg_id = type->event_notify;
+
+  if(msg_id == (uint32_t)-1)
+    return NULL;
+
+  asio_event_t* ev = POOL_ALLOC(asio_event_t);
+
+  ev->magic = ev;
+  ev->owner = owner;
+  ev->msg_id = msg_id;
+  ev->fd = fd;
+  ev->flags = flags;
+  ev->noisy = noisy;
+  ev->nsec = nsec;
+
+  // The event is effectively being sent to another thread, so mark it here.
+  pony_ctx_t* ctx = pony_ctx();
+  pony_gc_send(ctx);
+  pony_traceactor(ctx, owner);
+  pony_send_done(ctx);
+
+  asio_event_subscribe(ev);
+  return ev;
+}
+```
+
+The important take away from ```asio_event_create``` is that it creates a new event for ```ASIO_READ``` and passes that event to ```asio_event_subscribe```. We won't go any further into Pony's event system at this time, suffice it to say that ```asio_event_subscribe``` is the entry into events being sent on Pony and has several different implementations based on the asio backing implementation. The current options are platform specific and one of epoll, kqueue, iocp.
+
+Great! Now we are bound and listening and are ready to receive events related to our socket.
+
+## Back to our echo server
+
+<img src="https://t07.deviantart.net/JyMOqvGHj7ZX4s7XelqnI86rk8g=/300x200/filters:fixed_height(100,100):origin()/pre03/3fd6/th/pre/i/2013/265/e/1/night_watch_the_bat_pony_2_by_zee66-d6nfuuc.png" align="right">
+
+So we have a socket bound and listening. What now? Let's take a look again inside _TCPListener's ip4_ constructor and see how it triggers our first callback ```listening``` on our _TCPListenNotify_ implementor.
+
+```
+actor Main  
+  new create(env: Env) =>
+    TCPListener.ip4(recover Listener(env) end)
+
+actor TCPListener
+  new ip4(notify: TCPListenNotify iso, host: String = "",
+    service: String = "0", limit: USize = 0)
+  =>
+    """
+    Listens for IPv4 connections.
+    """
+    _limit = limit
+    _notify = consume notify
+    _event = @os_listen_tcp4[AsioEventID](this, host.cstring(),
+      service.cstring())
+    _fd = @asio_event_fd(_event)
+    _notify_listening()
+```
+
+Note the last line in the _ip4_ constructor:
+
+```
+_notify_listening()
+```
+
+And its corresponding implementation later in _TCPListener_:
+
+```
+  fun ref _notify_listening() =>
+    """
+    Inform the notifier that we're listening.
+    """
+    if not _event.is_null() then
+      _notify.listening(this)
+    else
+      _closed = true
+      _notify.not_listening(this)
+    end
+```
+
+The ```_notify.listening``` method calls ```listening``` on our callback object ```_notify```. Over in our echo server, we have the rather uninteresting:
+
+```
+  fun ref listening(listen: TCPListener ref) =>
+    try
+      (_host, _service) = listen.local_address().name()
+      _env.out.print("listening on " + _host + ":" + _service)
+    else
+      _env.out.print("couldn't get local address")
+      listen.close()
+    end
+```
+
+But hey, we're now listening on our socket and we've printed out a log message. Exciting? Maybe. So we've gone from *Socket* to *Bind* to *Listen* and all that is left is accepting and handling incoming connections.
+
+## Accepting a connection
+
+<img src="https://img04.deviantart.net/d968/i/2014/078/7/f/vampire_pony_sisters_by_magister39-d7au3ef.png" width="200" align="right">
+
+You might remember from earlier that in ```os_listen``` we used ```asio_event_subscribe``` to register that our _TCPListener_ instance was interested in knowing about ```ASIO_READ``` events on our socket. Whenever an event is generated, it will be delivered to our actor by calling its ```_event_notify``` behavior.
+
+```
+  be _event_notify(event: AsioEventID, flags: U32, arg: U32) =>
+    """
+    When we are readable, we accept new connections until none remain.
+    """
+    ...
+
+    if AsioEvent.readable(flags) then
+      _accept(arg)
+    end
+
+    ...
+```
+
+You can see that if our event is readable, we'll call the ```_accept``` method on our actor:
+
+```
+    if AsioEvent.readable(flags) then
+      _accept(arg)
+    end
+```
+
+Let's check out what is going on in ```_accept```:
+
+```
+  fun ref _accept(ns: U32 = 0) =>
+    """
+    Accept connections as long as we have spawned fewer than our limit.
+    """
+    ...
+
+    while (_limit == 0) or (_count < _limit) do
+      var fd = @os_accept[U32](_event)
+
+      match fd
+      | -1 =>
+        // Something other than EWOULDBLOCK, try again.
+        None
+      | 0 =>
+        // EWOULDBLOCK, don't try again.
+        return
+      else
+        _spawn(fd)
+      end
+    end
+
+    _paused = true
+```
+
+The important line to focus on is where we make another C FFI call, this time to ```@os_accept[U32]```. Returning back to the C code in the Pony runtime library, we see that ```os_accept``` is defined as:
+
+```
+int os_accept(asio_event_t* ev)
+{
+  int ns = accept(ev->fd, NULL, NULL);
+
+  ...
+
+  return (int)ns;
+}
+```
+
+And there, we see another BSD socket call:
+
+```
+int ns = accept(ev->fd, NULL, NULL);
+```
+
+Which means that we are pretty close to completing our chain **Socket -> Bind -> Listen -> Accept**.
+
+Once the connection is accepted, we return to ```_accept``` where we verify that everything is kosher with our new connection and then call ```_spawn```:
+```
+    while (_limit == 0) or (_count < _limit) do
+      var fd = @os_accept[U32](_event)
+
+      match fd
+      | -1 =>
+        // Something other than EWOULDBLOCK, try again.
+        None
+      | 0 =>
+        // EWOULDBLOCK, don't try again.
+        return
+      else
+        _spawn(fd)
+      end
+    end
+```
+
+Let's check out what is going on in Spawn.
+```
+  fun ref _spawn(ns: U32) =>
+    """
+    Spawn a new connection.
+    """
+    try
+      TCPConnection._accept(this, _notify.connected(this), ns)
+      _count = _count + 1
+    else
+      @os_closesocket[None](ns)
+    end
+```
+
+The important line to focus on is:
+
+```
+TCPConnection._accept(this, _notify.connected(this), ns)
+```
+
+There's actually a lot going on in that one line so let's take a moment to walk through it. First, we call the ```connected``` method on our ```_notify``` callback object. In our current context, ```_notify``` is our listener callback object:
+
+```
+  fun ref connected(listen: TCPListener ref) : TCPConnectionNotify iso^ =>
+    Server(_env)
+```
+
+Here, we are creating a Server object that implements _TCPConnectionNotify_ and will handle connections to our echo server. This notifier is in turn passed into the _TCPConnection_ actor's ```_accept``` constructor back in our ```_spawn``` method:
+
+```
+TCPConnection._accept(this, _notify.connected(this), ns)
+```
+
+Let's check out _TCPConnection_'s ```_accept``` constructor:
+
+```
+actor TCPConnection
+
+  new _accept(listen: TCPListener, notify: TCPConnectionNotify iso, fd: U32) =>
+    """
+    A new connection accepted on a server.
+    """
+    _listen = listen
+    _notify = consume notify
+    _connect_count = 0
+    _fd = fd
+    _event = @asio_event_create(this, fd, AsioEvent.read_write(), 0, true)
+    _connected = true
+
+    _notify.accepted(this)
+```
+
+You can see we set up an event via a C FFI call to ```@asio_event_create``` and finally, call the ```_accepted``` method on our _Server_ callback object.
+
+Our accepted callback gives us a chance to do interesting things upon accepting a new connection, in our case, "interesting" means logging an informational message:
+
+```
+class Server is TCPConnectionNotify  
+
+  fun ref accepted(conn: TCPConnection ref) =>
+    _env.out.print("connection accepted")
+```
+
+And handling connection input? Again, it comes from the depths of the event system. Our actor is notified of an event via the ```_event_notify``` behavior. 
+
+```
+  be _event_notify(event: AsioEventID, flags: U32, arg: U32) =>
+    """
+    Handle socket events.
+    """
+    ...
+
+    if AsioEvent.readable(flags) then
+      _readable = true
+      _complete_reads(arg)
+      _pending_reads()
+    end
+
+    ...
+  end
+```
+
+I've stripped out a lot of code from ```_event_notify``` to draw your attention more easily to the one line we really care about, the call to the private method `_pending_reads`.
+
+```
+  fun ref _pending_reads() =>
+    """
+    Read while data is available, guessing the next packet length as we go. If
+    we read 4 kb of data, send ourself a resume message and stop reading, to
+    avoid starving other actors.
+    """
+    try
+      var sum: USize = 0
+
+      while _readable and not _shutdown_peer do
+        // Read as much data as possible.
+        let len = @os_recv[USize](_event, _read_buf.cstring(), _read_buf.space()) ?
+
+        var next = _read_buf.space()
+
+        ...
+
+        let data = _read_buf = recover Array[U8].undefined(next) end
+        data.truncate(len)
+        _notify.received(this, consume data)
+
+        ...
+      end
+    ...
+```
+
+Again there's a lot of work going on in this method, there's a lot of book keeping, a call to the C function that gets data from the socket (```@os_recv```) and most importantly, the invocation of the ```received``` method on our Server callback:
+
+```
+_notify.received(this, consume data)
+```
+
+Which means, we've finally arrived at the ```received``` method on our Server class where we take the data our echo server has received and send it back out to the client:
+
+```
+fun ref received(conn: TCPConnection ref, data: Array[U8] iso) =>
+    _env.out.print("data received, looping it back")
+    conn.write("server says: ")
+    conn.write(consume data)
+```
+
+## Wrapping up
+
+We've made our way though a lot of Pony and C code to get to this point where we can see how our simple echo server works.
+I hope by now you feel like you have a grasp on how BSD socket programming works and nice event based abstractions that Pony provides for working with it. If you are interested in learning more about TCP/IP programming, I highly recommend you pick up all 3 volumes of W. Richard Steven's classic _TCP/IP Illustrated_ series:
+
+* [TCP/IP Illustrated, Volume 1: The Protocols](http://www.amazon.com/TCP-Illustrated-Protocols-Addison-Wesley-Professional/dp/0321336313/ref=sr_1_1?ie=UTF8&qid=1450229478&sr=8-1&keywords=tcp+ip+illustrated) 
+* [TCP/IP Illustrated: The Implementation, Vol. 2](http://www.amazon.com/TCP-IP-Illustrated-Implementation-Vol/dp/020163354X/ref=sr_1_3?ie=UTF8&qid=1450229478&sr=8-3&keywords=tcp+ip+illustrated)
+* [TCP/IP Illustrated, Vol. 3: TCP for Transactions, HTTP, NNTP, and the UNIX Domain Protocols](http://www.amazon.com/TCP-Illustrated-Vol-Transactions-Protocols/dp/0201634953/ref=sr_1_4?ie=UTF8&qid=1450229478&sr=8-4&keywords=tcp+ip+illustrated)
+
+Next time, we'll dig into Pony's event system and explore what's going on inside ```asio_event_subscribe```.
diff --git a/content/post/interview-exchange.md b/content/post/interview-exchange.md
new file mode 100644
index 0000000..f1b4dfe
--- /dev/null
+++ b/content/post/interview-exchange.md
@@ -0,0 +1,10 @@
++++
+draft = true
+tags = ["tag 1","tag 2"]
+author = "Sean T. Allen"
+date = "2017-02-18T09:29:51-05:00"
+title = "interview exchange"
+slug = "post-url-name"
+
++++
+
diff --git a/content/post/interview-with-lobste-rs.md b/content/post/interview-with-lobste-rs.md
new file mode 100644
index 0000000..ce1232e
--- /dev/null
+++ b/content/post/interview-with-lobste-rs.md
@@ -0,0 +1,12 @@
++++
+date = "2014-03-06T11:35:28-05:00"
+title = "Interview with Lobste.rs"
+author = "Sean T. Allen"
+slug = "interview-with-lobste-rs"
+draft = false
+
++++
+
+![Roger](/img/post/interview-with-lobste-rs/IMG_3648.jpg)
+
+I recently did an [interview](https://lobste.rs/s/gheyhy/lobsters_interview_with_sean_t_allen) with the news aggregator site [lobste.rs](http://www.lobste.rs/). It covers some of what I've been up to in my role as [Principal Architect at TheLadders](http://dev.theladders.com/), as well as some info about my forthcoming book [Storm Applied](http://www.manning.com/sallen).
diff --git a/content/post/learning-from-ada.md b/content/post/learning-from-ada.md
new file mode 100644
index 0000000..fabd4d4
--- /dev/null
+++ b/content/post/learning-from-ada.md
@@ -0,0 +1,20 @@
++++
+author = "Sean T. Allen"
+slug = "learning-from-ada"
+draft = false
+tags = ["c","ada"]
+date = "2016-02-22T10:42:22-05:00"
+title = "Learning From Ada"
++++
+
+This is a cautionary tale. One of youth and a lesson I eventually learned but still often don't heed. About how sometimes, the tool that is easiest to get started with isn’t the tool that will make your job the easiest.
+
+When I was getting started as a professional programmer, I was devouring languages left and right, trying them out for a few days before moving on to others. From this, I stuck with a few. My first "professional" languages were Perl, Pascal, UserLand Frontier, and AppleScript. During my first couple of years programming, I either released some little bit of open source software or got paid to write something using one of them. Pascal was my favorite. It had the best performance and it wa [...]
+
+Ada's reputation, or at least what had filtered down to me, was pretty cool. It was built for safety. It was used at the Department of Defense and to do all sorts of awesome cool-sounding stuff, but given my level of experience, most of its features meant little to me. I set about trying to learn Ada. Over the course of two weeks, I slowly grew more and more frustrated with Ada. It took me forever to get any of my programs to compile. I was being asked to think more than I had with other [...]
+
+I quickly fell in love with C. It felt much simpler than Ada. It was much easier to get my code to compile. There were more books, the community seemed larger and I knew that Apple was moving the Macintosh APIs from Pascal to C. So many things lined up to rationalize using C. In the end though, there was one factor that I know was more important than any other. The C compiler made me feel adequate. Unlike Ada, I regularly got my programs to compile. And so, I made my choice and went with C.
+
+With that decision of C over Ada, a large portion of my development as a programmer was decided. I spent a ton of time in C dealing with code that segfaulted. The power and freedom that C gave me with pointers came back to bite me all the time. Sure, my code compiled but man, did it also crash a lot. I spent years with C and C++ learning patterns for sharing memory, for immutable objects, for concurrency via threading that I still use to this day; patterns to avoid dangerous code that th [...]
+
+When I look back now at my Ada/C decision. I do so with some regret. I took the easy path. I let frustration get the best of me. And now whenever I encounter a difficult moment learning new languages like Haskell or Pony, I try to remember my Ada/C decision and stick will the language whose compiler is trying to tell me I'm doing it wrong. 
diff --git a/content/post/nyc-python-scale-agnostic-python.md b/content/post/nyc-python-scale-agnostic-python.md
new file mode 100644
index 0000000..cb5cf1f
--- /dev/null
+++ b/content/post/nyc-python-scale-agnostic-python.md
@@ -0,0 +1,16 @@
++++
+draft = false
+date = "2017-08-19T11:56:56-04:00"
+title = "NYC Python: Scale Agnostic Python"
+tags = ["talks","python", "distributed systems", "slides", "wallaroo", "scale agnostic"]
+description = "Post with information about my August 17, 2017 NYC Python talk \"Scale Agnostic Python? How to scale your Python application without any code changes\"."
+author = "Sean T. Allen"
+slug = "nyc-python-aug-17-scale-agnostic-python"
++++
+
+## Scale Agnostic Python: How to scale your Python application without any code changes*
+
+Unfortunately, there is no video of this talk. I am, however, planning on putting a record together of the topic. Slides are available. A full half of the presentation was a code walkthrough and a demo of a bit of the power that you can get from using a scale agnostic platform. If you are interested in the topic, I strongly advise you check out the Pat Helland paper below.
+
+- ["Scale Agnostic Python" slides](https://speakerdeck.com/seantallen/scale-agnostic-python) 
+- ["Life Beyond Distributed Transactions: An apostate's opinion"](https://queue.acm.org/detail.cfm?id=3025012)
diff --git a/content/post/of-debt-and-decisions.md b/content/post/of-debt-and-decisions.md
new file mode 100644
index 0000000..45b00a1
--- /dev/null
+++ b/content/post/of-debt-and-decisions.md
@@ -0,0 +1,32 @@
++++
+draft = false
+date = "2015-04-19T11:09:15-05:00"
+title = "Of Debt and Decisions"
+tags = ["technical debt","war story"]
+author = "Sean T. Allen"
+slug = "of-debt-and-decisions"
++++
+
+Back in the salad days of the 1990's, I was working at a company that was building the hot product of the day: an intranet. Every company wanted an intranet. We'd built several for different client before deciding to create a white labelable intranet that would be the delight of all our customers. Give us some money and we'd give you a themed intranet with calendaring, project tracking, task management and more.
+
+We didn't offer a hosted service instead, we would ship a computer to you with all the software installed that you could run on your network. In addition to being white lableable, you got to pick which you would be most comfortable supporting: a Linux or Windows NT based install. The Linux version came with RedHat Linux, Apache and MySQL. The NT, in addition to Windows, came with IIS and SQL Server. This post is the story of engineering decisions, both good and bad, that went into the cr [...]
+
+A tale of two languages
+One of the first questions most engineers will ask of you when discussing a project is what language you used. Our intranet-in-a-box used 2: Perl and Java. Our primary language for doing client projects before we got into software was Perl. In the beginning, the intranet-in-a-box was the work of a single developer. It wasn't a primary focus of the company. The vast majority of time was spent doing client work. While intranet-in-a-box development slowly progressed on the side, that single [...]
+
+Most communication between the different modules was done by using a database as a pool of mutable shared state. If module A and B needed to talk to one another, they could just modify and read from the same tables.The vast majority of sharing could be handled this way, there was just one problem: the further we got into the project, the more shared base code that we were porting from Java to Perl or Perl to Java. Further, that shared code was getting out of sync. If you had a utility ro [...]
+
+I don't know what anyone else would have done given that task and constraint but I know what I did: I created a cross language bridge that allowed the two sides of the codebase to talk to one another. The bridge involved serializing data on one side of a socket and deserializing it on the other. CORBA and various RPC tools like it were quite popular at the time. I had been learning a lot about them and so, our own little monster was created. I might cringe about it now, but it worked. It [...]
+
+The other way to be "database agnostic"
+The time came when we were going to start selling our intranet-in-a-box to our first customers. We installed RedHat Linux, Apache, MySQL and our mixed Perl and Java codebase onto a box and shipped them off to a customer. Before long, we had another customer but their IT staff was comfortable with NT and not Linux so we set about getting everything running on NT with IIS as the webserver. Getting Perl running on Windows NT with IIS was a bit of a pain but it was a known, solved problem. O [...]
+
+We barely had any source control, we had no automated testing and all work was done on and tested against individual developer machines. Some like mine were Linux, others Windows. Somehow along the way we ended with code in one of the modules that had been written against SQLServer while being developed. It relied on SQLServer syntax that didn't exist in MySQL. For the life of me, I don't remember what the syntax was, I just remember that we had hit a point where we needed to run differe [...]
+
+What's a few more patches between friends
+Somewhere along the line, we got a couple complaints about the software not being fast enough. Given our stack and lack of sophisticated tooling, we had no way to address the issue easily. We didn't have any fancy profiling tools and most code paths from web request to database and back were going to be fairly short. Optimizing the code was going to be problematic and might not result in much of a gain. Moving the Perl portion of the codebase to Java would have helped with performance in [...]
+
+I started searching the Internet for ways we could speed up Linux and MySQL. I came across a couple of kernel changes you could make that would in theory provide a speed boost. I patched the Linux source, created a new build and tried it out. Primitive quantitative testing and qualitative testing both pointed to the changes having a real impact. I was already interested in operating systems, network stacks and had been doing quite a bit of reading and exploring both the Linux and NetBSD  [...]
+
+The horror story that wasn’t
+Hopefully you are horrified by all things we didn't do that are now considered best practices. No reproducible builds, lack of automated testing, creating and then repeatedly sidestepping technical debt. For a long time, that is how I told these stories: as horror stories that came complete with hand gesticulations to emphasize the "can you believe I had to do that?" nature of it all. Here's the thing though: we were making money. We were growing and supporting ourselves. We were continu [...]
diff --git a/content/post/of-me-and-be.md b/content/post/of-me-and-be.md
new file mode 100644
index 0000000..bc2947c
--- /dev/null
+++ b/content/post/of-me-and-be.md
@@ -0,0 +1,13 @@
++++
+date = "2017-02-18T09:26:34-05:00"
+title = "Of Me and Be"
+tags = ["tag 1","tag 2"]
+author = "Sean T. Allen"
+slug = "of-me-and-be"
+draft = true
+
++++
+
+<iframe width="420" height="315" src="https://www.youtube.com/embed/BsVydyC8ZGQ" frameborder="0" allowfullscreen></iframe>
+
+"a system that makes programming fun again"
diff --git a/content/post/on-becoming-a-better-teacher.md b/content/post/on-becoming-a-better-teacher.md
new file mode 100644
index 0000000..432417c
--- /dev/null
+++ b/content/post/on-becoming-a-better-teacher.md
@@ -0,0 +1,40 @@
++++
+author = "Sean T. Allen"
+slug = "on-becoming-a-better-teacher"
+draft = false
+date = "2015-04-12T11:24:38-05:00"
+title = "On Becoming a Better Teacher"
+
++++
+
+Sometime in early 2013, I was really struggling with writing [Storm Applied](http://manning.com/sallen/?a_aid=sallen). I felt stymied at every turn by the requests of our editor. He was always asking us to explain simple topics more deeply. I almost lost my mind when a request to explain “web-scale” came up. It all felt like Manning was having us dumb the book down. Here we were trying to write an “advanced” book and we were running around explaining obvious, simple topics. In short, I w [...]
+
+![Definition of web-scale from Storm Applied](/img/post/on-becoming-a-better-teacher/Definition-of-web-scale-from-Storm-Applied.png)
+
+I'll admit to a certain level of elitism that I carry through my life. As an example, there's a series of books designed to teach various aspects of being a programmer called [Head First](http://shop.oreilly.com/category/series/head-first.do). I'd always looked down on them. They weren't books for “real programmers”. In my mind, they were written for lazy people who weren't willing to invest thought into teaching themselves new topics. And here was our editor at Manning, asking us to do  [...]
+
+What Kathy taught me was something that had been staring me in the face the entire time. I do a lot of mentoring and teaching as part of my job. This is almost always in person, often to a group of people rather than one on one. When I'm teaching something, I can tell who is understanding an explanation and who isn't just by looking at people's faces. When I see someone not understanding what I'm explaining, I always stop and try explaining it another way; often asking them questions to  [...]
+
+We were introducing a couple of new developers on our team at TheLadders to Storm and it became clear they had very little idea how to use the Storm UI. I was very versed in the UI and considered it extremely simple. It was always my first stop when diagnosing problems in our production Storm cluster. I started teaching people how to use the Storm UI to do what I did and it hit me: Here was a topic I was going to have to teach in Storm Applied and I was doing the “explain it many differe [...]
+
+I started in on Storm Applied again with renewed vigor. I was no longer considering dropping out of the project because it was being “dumbed down”. I started approaching every topic with the question “what is obvious to me that won't be to someone just learning this”. It's really hard to do. One of the hardest things I've had to do. To drill down, through all my professional experience and say “what do I know that others don't that I'm assuming they will know”. Those conversations with K [...]
+
+A couple of examples of how this played out:
+
+* Chapter 8 in Storm Applied is about diving below the basic abstractions that Storm provides you as a programmer and looking at how they are implemented. Before I wrote that chapter, I taught 5 different groups of people the same material, each time taking the questions they asked and building it into how I taught it the next time. 
+
+* Chapter 5 includes a 12 page review of the Storm UI. It's very straight-forward. Lots of screenshots calling out and highlighting certain parts of different screens saying ”and this important bit is…”. 
+
+![Example Storm UI screenshot from Storm Applied](/content/images/2015/04/Storm-UI-Figure-from-Storm-Applied.png)
+
+For some people, this might be redundant and seem pointless. An otherwise glowing review of [Storm Applied on Amazon](http://www.amazon.com/Storm-Applied-Strategies-real-time-processing/dp/1617291897/ref=sr_1_1) includes the following:
+
+> What I didn't love:
+>
+> There only minor issue that I have with the book is that section on the Storm UI seemed like "filler". The UI is not very complex, and it is very self-explanatory once you know the basic Storm concepts and terminology. The numerous screenshots and descriptions in the book could have easily been left out with no real detriment to the reader. I would recommend skimming or skipping these sections.
+
+I understand that comment quite well. I said something similar to Matt and Peter when we were discussing how much we should cover the UI when we were first planning the book. I said in my [previous post about Storm Applied](http://www.monkeysnatchbanana.com/2015/04/04/storm-applied/):
+
+> I don't remember now what I envisioned the book being when we first signed the contract. I know that Storm Applied isn't that book but I'm quite happy with it nonetheless.
+
+That “advanced book” I was planning on writing? It's a distant memory now. I can still sort of remember what it would have been like but that book wouldn't have been as good as Storm Applied is. And so, I'm quite happy with reviews that call out “filler” and repetition because I know why its there. And now you do as well.
diff --git a/content/post/pony-patterns-waiting.md b/content/post/pony-patterns-waiting.md
new file mode 100644
index 0000000..c63a9c5
--- /dev/null
+++ b/content/post/pony-patterns-waiting.md
@@ -0,0 +1,86 @@
++++
+title = "Pony Patterns: Waiting"
+tags = ["pony"]
+author = "Sean T. Allen"
+slug = "pony-patterns-waiting"
+draft = false
+date = "2016-01-16T10:46:33-05:00"
+
++++
+
+> I am a patient boy. I wait, I wait, I wait, I wait. My time is water down a drain
+> 
+> Everybody's moving. Everybody's moving.
+> Everything is moving, moving, moving, moving
+> 
+> Please don't leave me to remain.
+> In the waiting room
+>
+> --- Ian MacKaye
+
+How do you wait when you can't wait? No, that isn't a riddle; it's a question I recently faced while writing some [Pony](http://www.ponylang.org) code for [work](https://www.wallaroolabs.com). 
+
+Here's the problem: I'm writing a black box testing application that will verify the correctness of our system under test. My black box tester sends information into the box via UDP and gets data back via the same means and verifies that the data is valid. That system under test is currently a prototype written in Python. All things considered, it performs well. The problem is Pony performs better. 
+
+When I first fired up my tester, it quickly swamped the prototype. We haven't implemented any sort of backpressure yet so, I knew I needed to slow my application down via more "manual" means. I needed to limit the rate it was supplying data to the system under test. But how? 
+
+In a language with blocking operations, I could just call sleep and be done with it. It might not be the most elegant solution but it would work. Pony, however, isn't such a language. One of Pony's key features is there are no blocking operations. So, back to our original question: how do you wait when you can't wait? 
+
+After a bit of digging around, we came across the [Timer](https://github.com/CausalityLtd/ponyc/blob/master/packages/time/timer.pony) class. A timer allows you to execute code at set intervals. I'm going to walk you through how to use a timer using a simple application that prints out a number to the console every 5 seconds until someone terminates the program:
+
+```
+use "time"
+
+actor Main
+  new create(env: Env) =>
+    let timers = Timers
+    let timer = Timer(NumberGenerator(env), 0, 5_000_000_000)
+    timers(consume timer)
+
+class NumberGenerator is TimerNotify
+  let _env: Env
+  var _counter: U64
+
+  new iso create(env: Env) =>
+    _counter = 0
+    _env = env
+
+  fun ref _next(): String =>
+    _counter = _counter + 1
+    _counter.string()
+
+  fun ref apply(timer: Timer, count: U64): Bool =>
+    _env.out.print(_next())
+    true
+```
+
+Zooming in on the key bits, we first set up our timers, create one and add it to our set of timers:
+
+```
+    let timers = Timers
+    let timer = Timer(NumberGenerator(env), 0, 5_000_000_000)
+    timers(consume timer)
+```
+
+The Timer constructor takes 3 arguments, the class to notify, how long until our timer expires and how often to fire. In our example code an instance of NumberGenerator will be called every 5 billion nanoseconds i.e. every 5 seconds until the program is killed.
+
+Here's our method in NumberGenerator that gets executed:
+
+```
+  fun ref apply(timer: Timer, count: U64): Bool =>
+    _env.out.print(_next())
+    true
+```
+
+If we were to compile and run our application, we'd end up with some output like:
+
+![program output](/img/post/pony-patterns-waiting/Screenshot-2016-01-18-16-51-54.png)
+
+It's not the most exciting output in the world but, it's a pattern that I expect many Pony users will need: '[how to wait without waiting](https://www.youtube.com/watch?v=cMOAXm94VWo)'.
+
+---
+
+_If you are interested in what is going on with the `consume` in the `timers(consume timer)`, check out my previous post [Deconstructing a Pony echo server](http://www.monkeysnatchbanana.com/2015/12/13/deconstructing-a-pony-echo-server/) where I cover the semantics of consume._
+
+
+
diff --git a/content/post/qcon-how-did-i-get-here.md b/content/post/qcon-how-did-i-get-here.md
new file mode 100644
index 0000000..2ee7d71
--- /dev/null
+++ b/content/post/qcon-how-did-i-get-here.md
@@ -0,0 +1,51 @@
++++
+title = "QCon: How Did I Get Here?"
+tags = ["talks","testing", "distributed systems", "stream processing", "video", "slides"]
+description = "Post with link my 2016 QCon New York talk \"How Did I Get Here? Building Confidence in a Distributed Stream Processor\" and associated content."
+author = "Sean T. Allen"
+slug = "qcon-how-did-i-get-here"
+draft = false
+date = "2016-10-06T10:20:46-05:00"
+
++++
+
+## Building Confidence in a Distributed Stream Processor
+
+Video of my QCon New York talk: ["How Did I Get Here? Building Confidence in a Distributed Stream Processor"](https://www.infoq.com/presentations/trust-distributed-systems) is now available. 
+
+---
+
+There's a number of links at the end of the talk for additional material you can check out. To make life easier on everyone I'm recreating it here.
+
+### Peter Alvaro
+
+* [Peter Alvaro's twitter](https://twitter.com/palvaro)
+* [Lineage-driven Fault Injection](http://www.cs.berkeley.edu/~palvaro/molly.pdf)
+* [Outwards from the Middle of the Maze](https://www.youtube.com/watch?v=ggCffvKEJmQ)
+
+### Kyle Kingsbury
+
+* [Kyle Kingsbury's twitter](https://twitter.com/aphyr)
+* [Jepsen](https://aphyr.com/tags/Jepsen)
+
+### Will Wilson
+
+* [Testing Distributed Systems w/ Deterministic Simulation](https://www.youtube.com/watch?v=4fFDFbi3toc)
+
+### Catie McCaffrey
+
+* [Catie McCaffrey's twitter](https://twitter.com/caitie)
+* [The Verification of a Distributed System:
+A practitioner's guide to increasing confidence in system correctness](http://queue.acm.org/detail.cfm?ref=rss&id=2889274)
+
+### Inés Sombra
+
+* [Inés Sombra twitter](https://twitter.com/randommood)
+* [Testing in a Distributed World](https://www.youtube.com/watch?v=KSdNYi55kjg)
+
+### Chaos Engineering
+
+* [Principles of Chaos Engineering](http://principlesofchaos.org)
+
+---
+If you are interested, I've made the [slides available on Speakerdeck](https://speakerdeck.com/seantallen/how-did-i-get-here-building-confidence-in-a-distributed-stream-processor). Like most of my talks, the slides aren't particularly good at standing on their own without the talk itself.
diff --git a/content/post/qcon-ny-17-pony.md b/content/post/qcon-ny-17-pony.md
new file mode 100644
index 0000000..f7a035c
--- /dev/null
+++ b/content/post/qcon-ny-17-pony.md
@@ -0,0 +1,31 @@
++++
+title = "QCon NY: Pony"
+tags = ["talks", "pony", "stream processing", "video", "slides"]
+description = "Post with link to my 2017 QCon New York talk \"Pony: How I learned to stop worrying and embrace an unproven technology\" and associated content."
+author = "Sean T. Allen"
+slug = "qcon-ny-17-pony"
+draft = false
+date = "2017-09-02T10:20:46-05:00"
+
++++
+
+## Pony: How I learned to stop worrying and embrace an unproven technology
+
+Video of my QCon New York talk: ["Pony- How I learned to stop worrying and embrace an unproven technology"](https://www.infoq.com/presentations/pony-wallaroo) is now available. 
+
+The talk details my experiences thus far in using [Pony](https://www.ponylang.org) at [Wallaroo Labs](https://twitter.com/wallaroolabs) to build Wallaroo, a high-performance stream processing system. The talk was part of a FinTech track so there's a slight Fintech bent to some of the content that probably wouldn't have been in the talk otherwise.
+
+---
+
+There's a couple of links at the end of the talk for the additional material you can check out. To make life easier on everyone I'm recreating it here.
+
+### Trash Day: Coordinating Garbage Collection in Distributed Systems
+
+["Trash Day"](https://www.usenix.org/system/files/conference/hotos15/hotos15-paper-maas.pdf) is an awesome paper on how coordinating garbage collection pauses in Apache Spark, and Apache Cassandra clusters improved performance.
+
+### Ownership and Reference Counting based Garbage Collection in the Actor World
+
+More commonly known as the ["ORCA paper"](https://www.ponylang.org/media/papers/OGC.pdf). This article by Sylvan Clebsch et al. dives into the inner-workers of the Pony garbage collector.
+
+---
+If you are interested, I've made the [slides available on Speakerdeck](https://speakerdeck.com/seantallen/pony-how-i-learned-to-stop-worrying-and-embrace-an-unproven-technology). Like most of my talks, the slides aren't particularly good at standing on their own without the talk itself.
diff --git a/content/post/redline-the-journey-so-far.md b/content/post/redline-the-journey-so-far.md
new file mode 100644
index 0000000..1ed251a
--- /dev/null
+++ b/content/post/redline-the-journey-so-far.md
@@ -0,0 +1,10 @@
++++
+title = "Redline Smalltalk: The Journey So Far"
+slug = "redline-smalltalk-the-journey-so-far"
+draft = false
+tags = ["smalltalk","redline", "video", "talks"]
+author = "Sean T. Allen"
+date = "2011-04-11T08:42:24-05:00"
++++
+
+Video of [James](https://twitter.com/jamesladd) and my [talk at Smalltalk Solutions](https://vimeo.com/22084832) on where we are currently with [Redline Smalltalk](http://www.redline.st) has been posted.
diff --git a/content/post/reverse-proxying-to-seaside-with-nginx.md b/content/post/reverse-proxying-to-seaside-with-nginx.md
new file mode 100644
index 0000000..5cb7505
--- /dev/null
+++ b/content/post/reverse-proxying-to-seaside-with-nginx.md
@@ -0,0 +1,156 @@
++++
+author = "Sean T. Allen"
+slug = "reverse-proxying-to-seaside-with-nginx"
+draft = false
+date = "2010-06-24T08:56:43-05:00"
+title = "Reverse Proxying to Seaside with Nginx"
+tags = ["nginx","smalltalk","seaside"]
+
++++
+
+## Why Reverse Proxy a.k.a Why Not FastCGI?
+
+Transparency.
+
+FastCGI setups are opaque. You can't easily test all aspects of it. Unless you write your own FastCGI client, debugging configuration problems can be very difficult. Lets imagine for a moment that are trying to debug a problem with your application-- the issue might be in the front end server or it might be in the Seaside application server. When you are using FastCGI, all your interactions with your application server are routed through the front end server which acts as a client for yo [...]
+
+## Reverse Proxying to Seaside Options
+
+Now that you have decided that you want to use reverse proxying to your Seaside application, you need to decide between a couple of basic setup options. You can either setup each application on its own subdomain of your domain or you can run multiple applications off the same domain.
+
+### One Application Per Subdomain
+
+Our first example, shows a basic setup for running the counter and multicounter example applications off their own subdomains. With this configuration, you would be able to access the counter example via the uri `http://counter.example.com/` and the multicounter example via `http://multicounter.example.com/`.
+
+```
+01: server
+02: {
+03:   server_name counter.example.com;
+04:  
+05:   rewrite ^/$ /examples/counter;
+06:   proxy_redirect /examples/counter /;
+07:
+08:   location /examples/counter
+09:   {
+10:     proxy_pass http://127.0.0.1:8080;
+11:   }
+12: }
+13:
+14: server
+15: {
+16:   server_name multicounter.example.com;
+17:  
+18:   proxy_redirect /examples/multicounter /;
+19:   rewrite ^/$ /examples/multicounter;
+20:
+21:   location /examples/multicounter
+22:   {
+23:     proxy_pass http://127.0.0.1:8080;
+24:   }
+25: }
+```
+
+If you've never seen a nginx configuration file before that might be quite a bit to absorb, so lets break it down: 
+
+* We setup two virtual servers, one for each application. This is done via the server {} directives that start on lines 1 and 14. Each virtual server is almost identical except counter appears in one and multicounter in the other.
+* Line 3 tells our first server to respond to requests for the host `counter.example.com`.
+* Line 5 rewrites `http://counter.example.com/` to `http://counter.example.com/examples/counter`. _This change in URI isn't seen by the client browser_.
+* Line 6 removes `/examples/counter` from URIs being returned by the counter application.
+* Line 8 sets up an nginx location. It passes the URI `/examples/counter` to a our application server listening on port 8080 of localhost.
+
+### Multiple Applications Per Domain 
+
+For our multiple applications per domain example, we are going to setup example.com to server any of the example Seaside applications. All the example Seaside applications start with their URI path with `/examples`-- a nicety we will take advantage of.
+
+```
+1: server
+2: {
+3:   server_name example.com;
+4:
+5:   location /examples
+6:   {
+7:     proxy_pass http://127.0.0.1:8080/examples;
+8:   }
+9: }
+```
+
+The nginx location we setup on line 5, routes anything under `/examples` to the same path on our application server. Under this setup, we could access the counter application at `http://example.com/examples/counter` and multi counter application at `http://example.com/examples/multicounter`.
+
+## Complete Nginx Reverse Proxy Server Configuration[^n]
+
+Building on the 'One Application Per Subdomain' setup above, lets setup the serving a hypothetical To Do application. Our application will be responsible for serving the site's homepage. Nginx will serve any static assets ( css files, images etc ).
+
+```
+01: server
+02: {
+03:   server_name todo.example.com;
+04:  
+05:   root /var/www/todo.example.com/;
+06:   
+07:   location /
+08:   {
+09:     try_files $uri $uri/;
+10:   }
+11:   
+12:   proxy_redirect /todo /;
+13:   rewrite ^/$ /todo;
+14: 
+15:   location /todo
+16:   {
+17:     proxy_pass http://127.0.0.1:8080;
+18:   }
+19: }
+```
+
+A quick breakdown of the new elements we've introduced:
+
+* Line 5 tells nginx that any static attributes should be located by looking in `/var/www/todo.example.com/` This is equivalent to Apache's DocumentRoot directive.
+* The location directive that starts on line 7 defines how nginx should locate static assets[^n]. The try\_files directive on line 9 tells nginx to try to means to satisfy a URI. If our incoming request has a path of `/about` then, nginx will first look for a file called `about` in the server root. If that isn't found nginx will look for a directory `about/` in the server root. If neither rule can be satisfied, nginx will return a 404 error. 
+* Line 15 defines a location rule that is more specific than the one on line 7.  It will only be triggered if the URI path is `/todo`. This is the same setup that we saw in both of our previous examples.
+
+## Putting It All Together
+
+Now all we have to do is drop our reverse proxy server configuration into our nginx configuration and we end up with something like[^n]...
+
+```
+worker_processes 1;
+
+events
+{
+  worker_connections  1024;
+}
+
+http
+{
+  include       mime.types;
+  default_type  application/octet-stream;
+      
+  server
+  {
+    server_name todo.example.com;
+ 
+    root /var/www/todo.example.com/;
+  
+    location /
+    {
+      try_files $uri $uri/;
+    }
+  
+    proxy_redirect /todo /;
+    rewrite ^/$ /todo;
+
+    location /todo
+    {
+      proxy_pass http://127.0.0.1:8080;
+    }
+  }
+}
+```
+
+<div class="footnotes"><ol><li class="footnote" id="fn:1"><p>Or any other http client; one of my favorites is <a href="http://github.com/cloudhead/http-console">http console</a>. <a href="#fnref:1" title="return to article">↩</a></p></li>
+
+<li class="footnote" id="fn:2"><p>See <a href="http://wiki.nginx.org/NginxHttpProxyModule">Nginx wiki</a> for complete Nginx proxy module documentation. If you are running multiple Seaside application instances (on GLASS for instance), you should also check out the <a href="http://wiki.nginx.org/NginxHttpUpstreamModule">upstream</a>, <a href="http://wiki.nginx.org/NginxHttpUpstreamFairModule">fair upstream</a> and <a href="http://wiki.nginx.org/NginxHttpUpstreamRequestHashModule">upstrea [...]
+
+<li class="footnote" id="fn:3"><p>Location / is the most general location rule possible with nginx. It will used if a more specific location can't be found. <a href="#fnref:3" title="return to article">↩</a></p></li>
+
+<li class="footnote" id="fn:4"><p>Yours may look radically different. This is just a basic example of a full nginx configuration file. <a href="#fnref:4" title="return to article">↩</a></p></li></ol></div>
diff --git a/content/post/role-not-title.md b/content/post/role-not-title.md
new file mode 100644
index 0000000..9fda419
--- /dev/null
+++ b/content/post/role-not-title.md
@@ -0,0 +1,10 @@
++++
+author = "Sean T. Allen"
+slug = "post-url-name"
+draft = true
+date = "2017-02-18T09:30:24-05:00"
+title = "role not title"
+tags = ["tag 1","tag 2"]
+
++++
+
diff --git a/content/post/setting-up-a-monticello-repository-using-nginx.md b/content/post/setting-up-a-monticello-repository-using-nginx.md
new file mode 100644
index 0000000..43ffb03
--- /dev/null
+++ b/content/post/setting-up-a-monticello-repository-using-nginx.md
@@ -0,0 +1,130 @@
++++
+slug = "setting-up-a-monticello-repository-using-nginx"
+date = "2010-10-05T08:46:14-05:00"
+title = "Setting up a Monticello repository using Nginx"
+draft = false
+tags = ["nginx","smalltalk"]
+author = "Sean T. Allen"
+
++++
+## How Hard Could It Be?
+
+Not very hard; this little monkey who is more interested in bananas did it in no time flat. Setting up and running your own private Monticello repository is something almost any Smalltalker should be able to accomplish; as long as your aren't completely command line and systems administration phobic, you should be done with my directions within half an hour.
+
+## Installing Nginx with WebDAV Support
+
+Most prepackaged binary version of Nginx don't support WebDAV. If this is the case with yours, [download the latest stable version](http://nginx.org/) and build following the included instructions. You will need to change the standard configure step to one of the following:
+
+### Basic configuration
+
+```
+./configure --with-http_dav_module
+```
+
+### Advanced configuration to match the standard Debian/Ubuntu packages
+
+```
+./configure --prefix=/var/lib/nginx --conf-path=/etc/nginx/nginx.conf \ 
+  --pid-path=/var/run/nginx.pid --error-log-path=/var/log/nginx/error.log \
+  --http-log-path=/var/log/nginx/access.log --lock-path=/var/run/nginx.lock \
+  --user=www-data --group=www-data --sbin-path=/usr/sbin/nginx --with-http_dav_module
+```
+
+## Our Bare Bones Nginx Monticello Server Configuration
+
+```
+01: worker_processes 1;
+02: 
+03: events
+04: {
+05:   worker_connections  1024;
+06: }
+07: 
+08: http
+09: {
+10:   include       mime.types;
+11:   default_type  application/octet-stream;
+12:   
+13:   server
+14:   {
+15:     listen monticello.example.com;
+16:     server_name monticello.example.com;
+17: 
+18:     location / 
+19:     {
+20:       auth_basic "Monticello access restricted";
+21:       auth_basic_user_file /PATH_TO_OUR_PASSWORD_FILE;
+22: 
+23:       autoindex on;
+24: 
+25:       root /PATH_TO_OUR_MONTICELLO_REPOSITORY;
+26: 
+27:       dav_methods          PUT;
+28:       create_full_put_path on;
+29:       dav_access           group:rw  all:r;
+30:     } 
+31:   }
+32: }
+```
+
+The preceeding bit of code is a mostly bare bones Nginx Monticello server configuration. There isn't a whole lot to it, so I will quickly hit the points of interest:
+
+### Lines 15-16
+
+```
+listen monticello.example.com;
+server_name monticello.example.com;
+```
+
+Setup the name of our Monticello server and address it should be listening on.
+
+### Lines 18-19 & 30
+
+```
+location /
+{
+}
+```
+
+Define a location handler[^n] that encompasses everything that matches '/'. Any standard uri will match against this location so, you can consider it to be "global" in scope. Everything we want our Monticello server to do is handled by this one location handler.
+
+### Lines 20-21
+
+```
+auth_basic "Monticello access restricted";
+auth_basic_user_file /PATH_TO_OUR_PASSWORD_FILE;
+```
+
+Protects our Monticello repository from anonymous access using HTTP Basic Authentication. */PATH_TO_OUR_PASSWORD_FILE* should be replaced with the location of your password file. Your password file can be generated either using Apache's htpasswd application or using [this python script](http://wiki.nginx.org/NginxFaq#How_do_I_generate_an_httpasswd_file_without_having_Apache_tools_installed). N.B. Your password file has to be readable by the user that Nginx is running as. When installing  [...]
+
+### Line 23
+
+```
+autoindex on;
+```
+
+Is required for WebDAV to function properly- without directory indexing on, you will run into access denied errors.
+
+### Line 25
+
+```
+root /PATH_TO_OUR_MONTICELLO_REPOSITORY;
+```
+
+Defines the root of our WebDAV server. */PATH_TO_OUR_MONTICELLO_REPOSITORY* should be replaced with the directory that you are storing Monticello packages in. The directory has to be readable and writable by the user that Nginx is running as.
+
+### Lines 27-29
+
+```
+dav_methods          PUT;
+create_full_put_path on;
+dav_access           group:rw  all:r;
+```
+
+Define the rest of our WebDAV server setup. Instead of rehashing the [Nginx WebDAV documentation](http://wiki.nginx.org/HttpDavModule) I suggest you check the preceeding link as it covers this section of our setup in about as much time as it would take for me to detail it.
+
+## Are We Done?
+
+Indeed, but there is plenty more configuration that can be added to this basic Nginx WebDAV/Monticello setup. I would suggest visiting the [Nginx wiki](http://wiki.nginx.org/) to learn about Nginx so you can flesh out your configuration.
+
+<div class="footnotes"><ol><li class="footnote" id="fn:1"><p>See the <a href="http://wiki.nginx.org/NginxHttpCoreModule#location">Nginx wiki</a> for more information on the location directive. <a href="#fnref:1" title="return to article">↩</a></p></li></ol></div>
diff --git a/content/post/sidestepping-technical-debt.md b/content/post/sidestepping-technical-debt.md
new file mode 100644
index 0000000..c705a84
--- /dev/null
+++ b/content/post/sidestepping-technical-debt.md
@@ -0,0 +1,10 @@
++++
+date = "2017-02-18T09:28:35-05:00"
+title = "sidestepping technical debt"
+tags = ["tag 1","tag 2"]
+author = "Sean T. Allen"
+slug = "post-url-name"
+draft = true
+
++++
+
diff --git a/content/post/storm-applied-behind-the-scenes.md b/content/post/storm-applied-behind-the-scenes.md
new file mode 100644
index 0000000..c0cfbea
--- /dev/null
+++ b/content/post/storm-applied-behind-the-scenes.md
@@ -0,0 +1,33 @@
++++
+author = "Sean T. Allen"
+date = "2015-04-04T11:28:12-05:00"
+title = "Storm Applied: Behind the Scenes"
+slug = "storm-applied"
+draft = false
+tags = ["storm","storm applied"]
+
++++
+
+Almost two years ago, I embarked on a project that I had no idea the immensity of. And today, it has finally led to this:
+
+![Storm Applied](/img/post/storm-applied-behind-the-scenes/storm-applied.jpg)
+
+It started with my bugging [Matt Jankowski](https://twitter.com/mattjanks16) to write a ["mea culpa" blog post](http://dev.theladders.com/2013/03/riders-on-the-storm-take-a-long-holiday-let-your-children-play/) about our problems getting going with Storm at TheLadders. The idea was to start with a "boy we didn't know what we were doing" post and continue on with a series of posts about running Storm in a production. The first post happened, the rest never did. Instead, Manning reached ou [...]
+
+I don't remember now what I envisioned the book being when we first signed the contract. I know that Storm Applied isn't that book but I'm quite happy with it nonetheless. There's a lot of hard earned lessons packed into the latter half of the book that I think will help a lot of people trying to run Storm in production. Hopefully our pain can benefit a lot of people. There's a ton of stories I could tell about writing the book, some good, some bad but I think I'll just leave you with a  [...]
+
+* We really wanted to call the book _Thinking in Storm_ but there is already a _Thinking in ..._ series of books.
+* I wanted to subtitle the book "I wanna go fast" but that got rejected. Still, [it sort of worked out.](http://manning.com/sallen/excerpt_contents.html)
+* We intended to write "an advanced book" but ended up writing a book that starts as an intro and ends really advanced because there were no good intro Storm books in print.
+* I spent WAY TOO MUCH TIME trying to work lines from [this scene](https://www.youtube.com/watch?v=5A0-u85aAYg) into the book.
+* Manning googled an Eleanor Roosevelt quote and made us change the attribution to "misquoted".
+
+![Pretty sure Eleanor Roosevelt did say this](/content/images/2015/04/misquoted.png)
+
+* Most of the content I wrote was written using [Write Room](http://www.hogbaysoftware.com/products/writeroom). Full screen; no distractions = Awesome. Then Matt turned it into a "Manning usable" format because...
+* Manning uses MS Word for manuscripts. I managed to get through the entire book without really knowing how to use Word thanks to Matt.
+* The [source code for Chapter 6](https://github.com/Storm-Applied/C6-Flash-sale-recommender) got messed up and after the book had gone to press, I was working on recreating miss parts from what was in the chapter and memory.
+* Whenever our editor mentioned "the publisher", it always sounded very mysterious; much like someone talking about Charlie from Charlie's Angels. 
+* While writing Storm Applied, I [scientifically determined](https://www.youtube.com/watch?v=5ipGhzrIi3s&spfreload=10) that [The Jam](https://www.youtube.com/watch?v=GOK_vqtXgbk) is the [best band](https://www.youtube.com/watch?v=AE1ct5yEuVY) to [listen](https://www.youtube.com/watch?v=m-H0uIH5HHQ) to while [writing a book.](https://www.youtube.com/watch?v=hf4EFDGP4yg)
+
+O and...  [BUY MY BOOK!](http://manning.com/sallen/?a_aid=sallen)
diff --git a/content/post/using-fastcgi-with-nginx-and-seaside.md b/content/post/using-fastcgi-with-nginx-and-seaside.md
new file mode 100644
index 0000000..e314fd6
--- /dev/null
+++ b/content/post/using-fastcgi-with-nginx-and-seaside.md
@@ -0,0 +1,119 @@
++++
+date = "2010-08-18T08:51:50-05:00"
+title = "Using FastCGI with Nginx and Seaside"
+tags = ["GLASS","nginx","smalltalk","seaside"]
+author = "Sean T. Allen"
+slug = "using-fastcgi-with-nginx-and-seaside"
+draft = false
+
++++
+
+## Why FastCGI a.k.a Why Not Reverse Proxy?
+
+I've [previously written](/2010/06/24/reverse-proxying-to-seaside-with-nginx/) about why I prefer reverse proxying to FastCGI. I still believe all those points, however there are certain Seaside deployment situations where FastCGI is currently preferable to reverse proxying. If you are deploying your Seaside application to run on Gemstone's [GLASS](http://seaside.gemstone.com/) then you should give FastCGI serious consideration. The current swazoo adapter that you use when proxying to GL [...]
+
+## Our Bare Bones Nginx FastCGI Configuration
+
+```
+worker_processes 1;
+
+events
+{
+  worker_connections  1024;
+}
+
+http
+{
+  include       mime.types;
+  default_type  application/octet-stream;
+  
+  upstream seaside 
+  {
+    server localhost:9001;
+    server localhost:9002;
+    server localhost:9003;
+  }
+
+  server
+  {
+    root /var/www/glass/;
+
+    location /
+    { 
+      error_page 403 404 = @seaside;
+    }
+    
+    location @seaside
+    {
+      include fastcgi_params;
+      fastcgi_pass seaside;
+    }
+  }
+}
+```
+
+The preceeding bit of code is a mostly bare bones Nginx to GLASS FastCGI configuration. There isn't a whole lot to it, so I will quickly hit the points of interest:
+
+### Lines 13-18
+
+```
+upstream seaside 
+{
+  server localhost:9001;
+  server localhost:9002;
+  server localhost:9003;
+}
+```
+
+Define a named upstream pool called _seaside_. The default GLASS installation sets up 3 FastCGI listeners on ports 9001 to 9003. You would just add more server entries in the upstream block to have Nginx start using any additional FastCGI listeners that you might setup in GLASS.
+
+### Line 22
+
+```
+root /var/www/glass/;
+```
+
+Defines where our static assets like images, css and html are served from. You need to change the definition to a directory you create or create _/var/www/glass/_ and populate it with your various assets.
+
+### Lines 24-27
+
+```
+location /
+{ 
+  error_page 403 404 = @seaside;
+}
+```
+
+Define a location handler[^n] that encompasses everything that matches '/'. Any standard uri will match against this location so, you can consider it to be "global" in scope. Line 26 states that any uri request that would result in an http 403 or 404 response code should be routed to the named location _@seaside_. N.B. This named location is not the same as our upstream block. Nginx will process a request as follows:
+
+1. Check to see if a static asset for the uri exists. If it does, return it.
+2. If a static asset doesn't exist then either a 403 or 404 error will be generated resulting in handing the uri off to the @seaside location.
+
+This could also be done as:
+
+```
+location /
+{ 
+  try_files $uri @seaside;
+}
+```
+
+Getting into the details of why you would prefer _try\_files_ or _error\_page_ is the subject for another post.
+
+### Lines 29-33
+
+```
+location @seaside
+{
+  include fastcgi_params;
+  fastcgi_pass seaside;
+}
+```
+
+Define our named @seaside location that is responsible for handling FastCGI. The _include fastcgi\_params_ directive has Nginx include its standard FastCGI protocol definitions that are installed at _/etc/nginx/fastcgi\_params_. The _fastcgi\_pass_ directive simply says: 'pass all uris from this to the servers defined in the _seaside_ upstream block'.
+
+## Are We Done?
+
+Yes. Yes we are. There is plenty more configuration that can be added to make the FastCGI handling more robust ( failovers, timeouts etc ), but that is all you need to get started. I would suggest visiting the [Nginx wiki](http://wiki.nginx.org/) to learn about Nginx so you can flesh out your configuration. If you run into issues or need any help, feel free to drop me an email or catch up with me on [Twitter](http://www.twitter.com/SeanTAllen).
+
+<div class="footnotes"><ol><li class="footnote" id="fn:1"><p>See the <a href="http://wiki.nginx.org/NginxHttpCoreModule#location">Nginx wiki</a> for more information on the location directive. <a href="#fnref:1" title="return to article">↩</a></p></li></ol></div>
diff --git a/content/post/varnish-in-five-acts.md b/content/post/varnish-in-five-acts.md
new file mode 100644
index 0000000..dc44f36
--- /dev/null
+++ b/content/post/varnish-in-five-acts.md
@@ -0,0 +1,393 @@
++++
+date = "2013-05-03T13:21:47-05:00"
+title = "Varnish in Five Acts"
+draft = true
+tags = ["varnish","scaling"]
+author = "Sean T. Allen"
+slug = "varnish-in-five-acts"
+
++++
+
+
+> “Take a load off Annie. Take a load for free. Take a load off Annie. And you put the load right on me.” -- Robbie Robertson
+
+## Act I: The Players
+
+At my current employer, we have a number of entity services that clients access via HTTP. Some examples are the job service, the job application service and the topic of this post: the job seeker service. Each service manages the lifecycle of a core entity in our domain. On each request, the service gathers data from multiple data sources to build a complete entity and then serializes that entity to JSON. This is done for every request and is incredibly wasteful when you consider that mo [...]
+
+All this repeated, unnecessary entity object assembly and JSON serialization created scaling problems. Making matters worse, we periodically have batch processes that can increase service load by an order of magnitude. Caching is an easy win here. The question is how.
+
+Initial attempts to cache these entities were done inside the service JVMs, using familiar and popular JVM based caches like EHcache and calls out to memcache. Unfortunately, this left us operating at JVM speeds and the caches were competing with the service logic for memory and threads.
+
+In addition, our service code was muddled with messy caching logic.  Making the code harder to reuse, and more annoyingly, changes just affecting caching forced us to re-release the entire service.  We didn’t like this mixing of concerns.
+
+We thought we could do better if we used external read through caches. It's easy to slide them between existing clients and services. With caching outside the service, it get released only when their logic changes not because we’re tuning caching.
+
+For reasons too numerous to cover in this post we chose [Varnish](https://www.varnish-cache.org/about) as our read through cache.
+
+****
+
+## Act II: The Architecture
+
+When we introduced Varnish to our architecture, we wanted to make sure we were not adding a single point of failure. Simply put, if the cache layer goes down, our infrastructure should continue running. Performance might be degraded, but we should continue to be able to serve content to clients.
+
+The diagram below shows a typical setup. In a normal scenario, a client accesses Varnish via a load balancer. Varnish in turn farms out the work in round robin fashion to one of four job seeker service nodes. Should Varnish become unavailable, the load balancer stops sending traffic to Varnish and reroutes it to the four job seeker service nodes.
+
+![](/img/post/varnish-in-five-acts/varnish-flow.png)
+
+Of all our entity services, the job seeker services carries the highest median load. The graph below is the 1 minute request rate on 4 service nodes over the 36 hour period before and after Varnish was turned on.
+
+![](/img/post/varnish-in-five-acts/before-after.png)
+
+****
+
+## Act III: Cache Invalidation
+
+Cache invalidation is one of the 2 hard problems in computer science along with naming things and off by one errors.
+
+We cache job seeker entity representations until some point in the “far future”, which is great until something about that job seeker changes, then we must invalidate the cached entry. So, how do we do that?
+
+Two ways.
+
+### Via Header:
+
+All requests that change the state of a job seeker that are made via the service attach a header in the response called "x-invalidates" that looks something like:
+
+```
+x-invalidates: /jobseeker/123
+```
+
+Varnish, when it sees this header, turns the value into a content expiring regular expression. My team mate [@johnconnolly](http://twitter.com/johnconnolly) learned about this general technique from [Kevin Burns Jr.](https://twitter.com/kevburnsjr) at [http://restfest.org](RESTFest) 2012.  I used Kevin’s post on the [subject](http://blog.kevburnsjr.com/tagged-cache-invalidation) as a jumping off point for our implementation.
+
+### Via Magic:
+
+Once upon a time, we had a database administrator named Gennady. Gennady wrote a [PHP script that reads MySQL’s binary logs](http://www.dinodigusa.com/images/Magic1.gif), looking for changes to a set of predefined tables. When it sees an update, it finds the primary key for the row and fires off an invalidation request. In our case, a purge of the cached entity url in Varnish. This allows us to invalidate cached job seeker entities even when the update was performed via legacy code that  [...]
+
+If you were to do this manually, it would look something like:
+
+```
+curl -X PURGE varnish-jobseeker/jobseeker/123
+```
+
+****
+
+## Act IV: Configuration Spelunking
+
+So, how did we do it? I’m going to break down our configuration into its parts and cover the general role each part plays. From here on out, I’m assuming you understand the basics of how Varnish works and how you configure it. Also, there is some repetition in our configuration that isn’t required, it just makes it easier for our configuration management tool, puppet, to create the final output.
+
+### Load Balancing
+
+We have four service servers behind varnish so we create four backend entries and then set up a director to round robin between them. Then in vcl_recv, we set our director named 'nodes' to be the backend that we will use to fetch content.
+
+``` bash
+backend JS1 {
+  .host  = "JS1";
+  .port  = "8080";
+
+  ...
+}
+
+backend JS2 {
+  .host  = "JS2";
+  .port  = "8080";
+
+  ...
+}
+
+backend JS3 {
+  .host  = "JS3";
+  .port  = "8080";
+
+  ...
+}
+
+backend JS4 {
+  .host  = "JS4";
+  .port  = "8080";
+
+  ...
+}
+
+director nodes round-robin {
+  { .backend = JS1 ; }
+  { .backend = JS2 ; }
+  { .backend = JS3 ; }
+  { .backend = JS4 ; }
+}
+
+sub vcl_recv {
+  set req.backend = nodes;
+}
+
+# store in cache only by url, not backend host
+sub vcl_hash {
+  hash_data(req.url);
+  return (hash);
+}
+```
+
+### Degraded
+
+Each backend is setup with a probe url that we use to check its health. If the probe url doesn't return at least one HTTP 200 response within a fifteen second period, we mark that backend as unhealthy.
+
+``` bash
+backend ... {
+   ...
+
+  .probe = {
+    .url = "/donjohnson/pulse";
+    .interval = 5s;
+    .timeout = 250ms;
+    .window = 3;
+    .threshold = 2;
+  }
+}
+```
+
+Varnish has the concept of a grace period, wherein, we can keep content alive in our cache past the TTL based on the health status of our backends. In our case, when the all backends are down, we keep cached items alive for an extra hour. During this time, we operate in a degraded status. Read requests for cached items will be handled while write requests will fail because there is no backend service to handle them.
+
+``` bash
+sub vcl_fetch {
+  # max time to keep an item in the cache past its ttl
+  # used in conjunction with code in vcl_recv to
+  # deal with 'sick' backends
+  set beresp.grace = 1h;
+
+  ...
+}
+
+sub vcl_recv {
+  ...
+
+  # extra ttl for cached objects based on backend health
+  if (!req.backend.healthy) {
+    set req.grace = 1h;
+  } else {
+    set req.grace = 15s;
+  }
+}
+```
+
+### Invalidation
+
+We do two types of invalidation:
+
+* invalidation based on the 'x-invalidates' header that comes back with a response
+* 'manual' invalidation based on sending the HTTP PURGE verb to a url in the Varnish cache.
+
+The ability to do a manual purge is limited to a small set of IP addresses that we validate against when a purge request is received.
+
+``` bash
+acl purge {
+  "localhost";
+  "10.10.10.10";
+}
+
+sub vcl_recv {
+  ...
+
+  # 'manual' purge
+  if (req.request == "PURGE") {
+    if (client.ip ~ purge) {
+       return(lookup);
+    }
+
+    error 405 "Not allowed.";
+  }
+
+  ...
+}
+```
+
+The actual mechanics of doing the purge are fairly simple. If the url attempted to be purged exists, purge it and return a 200.
+
+``` bash
+sub vcl_hit {
+  # 'manual' purge
+  if (req.request == "PURGE") {
+    purge;
+    error 200 "Purged.";
+  }
+}
+```
+
+If it doesn't, return a 404 response code:
+
+``` bash
+sub vcl_miss {
+  # 'manual' purge
+  if (req.request == "PURGE") {
+    purge;
+    error 404 "Not in cache.";
+  }
+}
+```
+
+Update requests include invalidation-related headers. Every request we fetch has, inside of Varnish, its request url stored in a special x-url header. This will be used as the url to check the x-invalidates header against. As this header is purely for our internal use, we remove it before delivering items to a client:
+
+``` bash
+sub vcl_fetch {
+  ...
+
+  set beresp.http.x-url = req.url;
+
+  ...
+}
+
+sub vcl_deliver {
+  # clear internal cache invalidation header before sending to client
+  unset resp.http.x-url;
+}
+```
+
+Any 'successful' PUT, POST, DELETE or PATCH response will have its x-invalidates header used as a regular expression to invalidate existing content whose x-url header matches the x-invalidates regex.
+
+```
+sub vcl_fetch {
+  ...
+
+  # cache invalidation
+  set beresp.http.x-url = req.url;
+  if (req.request == "PUT" || req.request == "POST" || req.request == "DELETE" || req.request == "PATCH") {
+    if  (beresp.status >= 200 && beresp.status < 400) {
+     ban("obj.http.x-url ~ " + beresp.http.x-invalidates);
+    }
+  }
+}
+```
+****
+
+## Act V: The final product
+
+And finally, we put it all together into a complete file (note, we use Varnish 3, the semantics around ban/purge changed from v2 to v3):
+
+``` bash
+backend JS1 {
+  .host  = "JS1";
+  .port  = "8080";
+  .probe = {
+    .url = "/donjohnson/pulse";
+    .interval = 5s;
+    .timeout = 250ms;
+    .window = 3;
+    .threshold = 2;
+  }
+}
+
+backend JS2 {
+  .host  = "JS2";
+  .port  = "8080";
+  .probe = {
+    .url = "/donjohnson/pulse";
+    .interval = 5s;
+    .timeout = 250ms;
+    .window = 3;
+    .threshold = 2;
+  }
+}
+
+backend JS3 {
+  .host  = "JS3";
+  .port  = "8080";
+  .probe = {
+    .url = "/donjohnson/pulse";
+    .interval = 5s;
+    .timeout = 250ms;
+    .window = 3;
+    .threshold = 2;
+  }
+}
+
+backend JS4 {
+  .host  = "JS4";
+  .port  = "8080";
+  .probe = {
+    .url = "/donjohnson/pulse";
+    .interval = 5s;
+    .timeout = 250ms;
+    .window = 3;
+    .threshold = 2;
+  }
+}
+
+director nodes round-robin {
+  { .backend = JS1 ; }
+  { .backend = JS2 ; }
+  { .backend = JS3 ; }
+  { .backend = JS4 ; }
+}
+
+# what machines can institute a 'manual' purge
+acl purge {
+  "localhost";
+  "192.1.1.4";
+}
+
+# store in cache only by url, not backend host
+sub vcl_hash {
+  hash_data(req.url);
+  return (hash);
+}
+
+sub vcl_fetch {
+  # max time to keep an item in the cache past its ttl
+  # used in conjunction with code in vcl_recv to
+  # deal with 'sick' backends
+  set beresp.grace = 1h;
+
+  # cache invalidation
+  set beresp.http.x-url = req.url;
+  if (req.request == "PUT" || req.request == "POST" || req.request == "DELETE" || req.request == "PATCH") {
+    if  (beresp.status >= 200 && beresp.status < 400) {
+     ban("obj.http.x-url ~ " + beresp.http.x-invalidates);
+    }
+  }
+}
+
+sub vcl_recv {
+  set req.backend = nodes;
+
+  # 'manual' purge
+  if (req.request == "PURGE") {
+    if (client.ip ~ purge) {
+       return(lookup);
+    }
+
+    error 405 "Not allowed.";
+  }
+
+  # extra ttl for cached objects based on backend health
+  if (!req.backend.healthy) {
+    set req.grace = 1h;
+  } else {
+    set req.grace = 15s;
+  }
+}
+
+sub vcl_deliver {
+  # clear internal cache invalidation header before sending to client
+  unset resp.http.x-url;
+}
+
+sub vcl_hit {
+  # 'manual' purge
+  if (req.request == "PURGE") {
+    purge;
+    error 200 "Purged.";
+  }
+}
+
+sub vcl_miss {
+  # 'manual' purge
+  if (req.request == "PURGE") {
+    purge;
+    error 404 "Not in cache.";
+  }
+}
+```
+
+## Hidden Track Bonus Act:
+
+![](/img/post/varnish-in-five-acts/varnish-all-the-things.jpg)
+
+Join the discussion over at [Hacker News](https://news.ycombinator.com/item?id=5651874).
diff --git a/content/post/why-pony-polyconf-17.md b/content/post/why-pony-polyconf-17.md
new file mode 100644
index 0000000..fd4febb
--- /dev/null
+++ b/content/post/why-pony-polyconf-17.md
@@ -0,0 +1,13 @@
++++
+draft = false
+date = "2017-08-19T09:56:56-05:00"
+title = "Polyconf'17: Why Pony?"
+tags = ["talks","pony", "video", "slides"]
+description = "Post with link my Polyconf'17 talk \"Why Pony? Bleeding edge technology for your concurrency woes\"."
+author = "Sean T. Allen"
+slug = "polyconf-17-why-pony"
++++
+
+## Why Pony? Bleeding edge technology for your concurrency woes
+
+Video of my [Polyconf'17](https://polyconf.com/) talk ["Why Pony? Bleeding edge technology for your concurrency woes"](https://www.youtube.com/watch?v=0XFhTrtOGK4) is now available. The slides are available [here](https://speakerdeck.com/seantallen/why-pony).
diff --git a/content/post/why-pony.md b/content/post/why-pony.md
new file mode 100644
index 0000000..179d8c9
--- /dev/null
+++ b/content/post/why-pony.md
@@ -0,0 +1,39 @@
++++
+date = "2017-02-18T09:24:45-05:00"
+title = "Why Pony?"
+tags = ["pony","erlang","c"]
+author = "Sean T. Allen"
+slug = "why-pony"
+draft = true
+
++++
+
+Early in 2015, [Pony](http://www.ponylang.org) a high performance actor based language caught my eye. Pony's feature set excites me quite a bit, however, the language is very immature. Making the decision to base a production application on new, immature technology is fraught with uncertainty. I've spent a lot of time thinking about where it might be appropriate to leverage Pony. 
+
+[The Pony philosophy](https://github.com/CausalityLtd/ponyc/wiki/Philosophy):
+
+> Correctness. Incorrectness is simply not allowed. It's pointless to try to get stuff done if you can't guarantee the result is correct.
+
+> Performance. Runtime speed is more important than everything except correctness. If performance must be sacrificed for correctness, try to come up with a new way to do things. The faster the program can get stuff done, the better. This is more important than anything except a correct result.
+
+> Simplicity. Simplicity can be sacrificed for performance. It is more important for the interface to be simple than the implementation. The faster the programmer can get stuff done, the better. It's ok to make things a bit harder on the programmer to improve performance, but it's more important to make things easier on the programmer than it is to make things easier on the language/runtime.
+
+> Consistency. Consistency can be sacrificed for simplicity or performance. Don't let excessive consistency get in the way of getting stuff done.
+
+> Completeness. It's nice to cover as many things as possible, but completeness can be sacrificed for anything else. It's better to get some stuff done now than wait until everything can get done later. 
+
+
+## The case of Pony v Erlang
+
+People often compare Pony to Erlang because they are both actor based. It's a natural comparison to want to make. A lot of the people I see getting interested in Pony are coming from an Erlang background. While it's appropriate to compare the goals of the language, you shouldn't be formulating questions like- 'Should I use Erlang or should I use Pony?' Erlang is a very mature language that has been in existence for over 20 years. Pony is less than 5 years old. Extensive native tooling ex [...]
+
+## The case of Pony v C
+
+If writing your application in C is something you are seriously considering, then there is a case for Pony. Pony started its life as an actor library that was callable from C and you can still [use Pony in that fashion](http://bluishcoder.co.nz/2015/12/16/c-linkable-libraries-with-pony.html). Pony and C integration is excellent. At this point in its life, I consider Pony to an excellent complement to C. You can use existing C tooling with Pony while leveraging Pony's type system and conc [...]
+
+If you are looking at a C project and think:
+
+* The Actor model would be a good concurrency model for your project 
+* You'd like the compiler support to verify you are sharing memory safely
+
+then Pony might be right for you. The right way to think of Pony is as a better C that provides an excellent high performance, safe concurrent programming model based on actors.
diff --git a/static/CNAME b/static/CNAME
new file mode 100644
index 0000000..1bc9fad
--- /dev/null
+++ b/static/CNAME
@@ -0,0 +1 @@
+www.monkeysnatchbanana.com
diff --git a/static/img/avatar.png b/static/img/avatar.png
new file mode 100644
index 0000000..0791eb6
Binary files /dev/null and b/static/img/avatar.png differ
diff --git a/static/img/ctakes_logo.jpg b/static/img/ctakes_logo.jpg
new file mode 100644
index 0000000..4089c34
Binary files /dev/null and b/static/img/ctakes_logo.jpg differ
diff --git a/static/img/logo.png b/static/img/logo.png
new file mode 100644
index 0000000..0791eb6
Binary files /dev/null and b/static/img/logo.png differ
diff --git a/static/img/post/interview-with-lobste-rs/IMG_3648.jpg b/static/img/post/interview-with-lobste-rs/IMG_3648.jpg
new file mode 100644
index 0000000..2863c69
Binary files /dev/null and b/static/img/post/interview-with-lobste-rs/IMG_3648.jpg differ
diff --git a/static/img/post/on-becoming-a-better-teacher/Definition-of-web-scale-from-Storm-Applied.png b/static/img/post/on-becoming-a-better-teacher/Definition-of-web-scale-from-Storm-Applied.png
new file mode 100644
index 0000000..0d684da
Binary files /dev/null and b/static/img/post/on-becoming-a-better-teacher/Definition-of-web-scale-from-Storm-Applied.png differ
diff --git a/static/img/post/pony-patterns-waiting/Screenshot-2016-01-18-16-51-54.png b/static/img/post/pony-patterns-waiting/Screenshot-2016-01-18-16-51-54.png
new file mode 100644
index 0000000..20c894c
Binary files /dev/null and b/static/img/post/pony-patterns-waiting/Screenshot-2016-01-18-16-51-54.png differ
diff --git a/static/img/post/storm-applied-behind-the-scenes/storm-applied.jpg b/static/img/post/storm-applied-behind-the-scenes/storm-applied.jpg
new file mode 100644
index 0000000..ec953ec
Binary files /dev/null and b/static/img/post/storm-applied-behind-the-scenes/storm-applied.jpg differ
diff --git a/static/img/post/varnish-in-five-acts/before-after.png b/static/img/post/varnish-in-five-acts/before-after.png
new file mode 100644
index 0000000..e807679
Binary files /dev/null and b/static/img/post/varnish-in-five-acts/before-after.png differ
diff --git a/static/img/post/varnish-in-five-acts/varnish-all-the-things.jpg b/static/img/post/varnish-in-five-acts/varnish-all-the-things.jpg
new file mode 100644
index 0000000..ba61ef5
Binary files /dev/null and b/static/img/post/varnish-in-five-acts/varnish-all-the-things.jpg differ
diff --git a/static/img/post/varnish-in-five-acts/varnish-flow.png b/static/img/post/varnish-in-five-acts/varnish-flow.png
new file mode 100644
index 0000000..126575c
Binary files /dev/null and b/static/img/post/varnish-in-five-acts/varnish-flow.png differ
diff --git a/themes/sean-steam/CHANGELOG.md b/themes/sean-steam/CHANGELOG.md
new file mode 100644
index 0000000..46c52a4
--- /dev/null
+++ b/themes/sean-steam/CHANGELOG.md
@@ -0,0 +1,15 @@
+# Changelog
+
+### 27th November 2016
+
+- `favicon` allows you to link a custom favicon by adding a path relative to the `static` folder
+- with `customCSS` and `customJS` you can link your own stylesheets and scripts. The files have to be link relative to `static` as well.
+
+### 26th November 2016
+
+Some of the new features of Hugo v0.17 were now introduced in this theme. Since some changes are not backwards compatible you have to update to Hugo v0.17 or newer versions.
+
+- Steam now uses the Google Analytics template that is shipped with Hugo. Just move the `googleAnaltics` variable outside the `params` block. Have a look at the [example config file](https://github.com/digitalcraftsman/hugo-steam-theme/blob/master/exampleSite/config.toml).
+- The support for Google Plus comments in now deprecated.
+- Formerly, it was only possible to show pages of `type` post on the homepage. Now, all types of pages are shown. You can hide single pages by adding `hide = true` to the (TOML) frontmatter.
+- External dependencies like Highlight.js have been updated to the latest version.
diff --git a/themes/sean-steam/LICENSE.md b/themes/sean-steam/LICENSE.md
new file mode 100644
index 0000000..9667d69
--- /dev/null
+++ b/themes/sean-steam/LICENSE.md
@@ -0,0 +1,22 @@
+Copyright (c) 2015 Digitalcraftsman - Released under The MIT License.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/themes/sean-steam/README.md b/themes/sean-steam/README.md
new file mode 100644
index 0000000..022e5dd
--- /dev/null
+++ b/themes/sean-steam/README.md
@@ -0,0 +1,76 @@
+# Steam
+
+Steam is a minimal and customizable theme for bloggers and was developed by [Tommaso Barbato](//github.com/epistrephein). He created it as a slightly adapted version of the [Vapor](//github.com/sethlilly/Vapor) Ghost theme by [Seth Lilly](//github.com/sethlilly). Noteworthy features of this Hugo port are the integration of a comment-system powered by Disqus, the customizable appearance by changing theme colors, support for RSS feeds, syntax highlighting via Highlight.js for source code a [...]
+
+![Screenshot](https://raw.githubusercontent.com/digitalcraftsman/hugo-steam-theme/dev/images/screenshot.png)
+
+
+## Installation
+
+Inside the folder of your Hugo site run:
+
+    $ cd themes
+    $ git clone https://github.com/digitalcraftsman/hugo-steam-theme.git
+
+For more information read the official [setup guide](//gohugo.io/overview/installing/) of Hugo.
+
+### The config file
+
+Take a look inside the [`exampleSite`](//github.com/digitalcraftsman/hugo-steam-theme/blob/dev/exampleSite/) folder of this theme. You'll find a file called [`config.toml`](//github.com/digitalcraftsman/hugo-steam-theme/blob/dev/exampleSite/config.toml).
+
+To use it, copy the [`config.toml`](//github.com/digitalcraftsman/hugo-steam-theme/blob/dev/exampleSite/config.toml) in the root folder of your Hugo site. Feel free to change strings as you like to customize your website.
+
+## Add links to the navigation
+
+You can add custom pages like this by adding `menu = "main"` in the frontmatter:
+
+```toml
++++
+date  = "2015-08-22"
+title = "About me"
+menu  = "main"
++++
+```
+
+If no document contains menu = "main" in the frontmatter than the navigation will not be shown
+
+
+## Customize theme colors
+
+This theme features four different theme colors (green as default, blue, red and orange) that change the appearance of you Hugo site slightly. Just set the `themeColor` variable to the color you like.
+
+Furthermore you can create your own theme. Under [`layouts/partials/themes`](//github.com/digitalcraftsman/hugo-steam-theme/tree/dev/layouts/partials/themes) you'll find a stylesheet template called [`custom-theme.html`](//github.com/digitalcraftsman/hugo-steam-theme/blob/dev/layouts/partials/themes/custom-theme.html). Customize the colors as you like and save the new theme with the schema `<myNewColor>-theme.html` within the same folder. As you can see, the color is the prefix of the st [...]
+
+## Comments
+
+This theme features a comment system powered by Disqus. To enable it you have to add your Disqus shortname to the `disqusShortname` variable in the config file.
+
+## Nearly finished
+
+In order to see your site in action, run Hugo's built-in local server. 
+
+    $ hugo server
+
+Now enter [`localhost:1313`](http://localhost:1313) in the address bar of your browser.
+
+## Changelog
+
+You can find the latest changes and improvements of this theme in the [CHANGELOG.md](https://github.com/digitalcraftsman/hugo-steam-theme/blob/master/CHANGELOG.md)
+
+
+## Contributing
+
+Did you found a bug or got an idea for a new feature? Feel free to use the [issue tracker](//github.com/digitalcraftsman/hugo-steam-theme/issues) to let me know. Or make directly a [pull request](//github.com/digitalcraftsman/hugo-steam-theme/pulls).
+
+
+## License
+
+This theme is released under the MIT license. For more information read the [License](//github.com/digitalcraftsman/hugo-steam-theme/blob/master/LICENSE.md).
+
+
+## Annotations
+
+Thanks to 
+
+- [Steve Francia](//github.com/spf13) for creating Hugo and the awesome community around the project.
+- [Seth Lilly](//github.com/sethlilly) and [Tommaso Barbato](//github.com/epistrephein) for developing the original version(s) of this theme
diff --git a/themes/sean-steam/archetypes/default.md b/themes/sean-steam/archetypes/default.md
new file mode 100644
index 0000000..0ac3054
--- /dev/null
+++ b/themes/sean-steam/archetypes/default.md
@@ -0,0 +1,4 @@
++++
+
++++
+
diff --git a/themes/sean-steam/exampleSite/.gitignore b/themes/sean-steam/exampleSite/.gitignore
new file mode 100644
index 0000000..de19fe8
--- /dev/null
+++ b/themes/sean-steam/exampleSite/.gitignore
@@ -0,0 +1,2 @@
+public/
+themes
\ No newline at end of file
diff --git a/themes/sean-steam/exampleSite/config.toml b/themes/sean-steam/exampleSite/config.toml
new file mode 100644
index 0000000..a77808a
--- /dev/null
+++ b/themes/sean-steam/exampleSite/config.toml
@@ -0,0 +1,45 @@
+baseurl = "https://example.org/"
+languageCode = "en-us"
+title = "Steam - a minimal theme for Hugo"
+theme = "hugo-steam-theme"
+disqusShortname = "spf13"
+# Enable Google Analytics be inserting your tracking code
+googleAnalytics = ""
+# Number of posts per page
+paginate = 10
+
+[params]
+	title = "Steam"
+	subtitle = "a minimal theme for ~~Ghost~~ Hugo"
+	copyright = "Released under the MIT license."
+
+	# You can choose between green, orange, red and blue.
+	themecolor = "green"
+
+	# Link custom assets relative to /static
+	favicon   = "favicon.ico"
+	customCSS = []
+	customJS  = []
+
+	# To provide some metadata for search engines and the about section in the footer
+	# feel free to add a few information about you and your website.
+	name = "John Doe"
+	bio = "programmer - blogger - coffee aficionado"
+	description = "Your description of the blog"
+	
+	# Link your social networks (optional)
+	location = ""
+	twitter = "spf13"
+	linkedin = ""
+	googleplus = ""
+	facebook = ""
+	instagram = ""
+	github = "spf13"
+	gitlab = ""
+	bitbucket = ""
+
+	# Customize or translate the strings
+	keepReadingStr = "Keep reading"
+	backtotopStr = "Back to top"
+	shareStr = "Share"
+	pageNotFoundTitle = "404 - Page not found"
diff --git a/themes/sean-steam/exampleSite/content/about.md b/themes/sean-steam/exampleSite/content/about.md
new file mode 100644
index 0000000..ef6f5bd
--- /dev/null
+++ b/themes/sean-steam/exampleSite/content/about.md
@@ -0,0 +1,20 @@
++++
+date  = "2015-08-22"
+title = "Link custom pages"
+menu  = "main"
+url = "about/"
+hide = "true"
++++
+
+You can add custom pages like this by adding `menu = "main"` in the frontmatter:
+
+```toml
++++
+date  = "2015-08-22"
+title = "About me"
+menu  = "main"
+url = "about/"
++++
+```
+
+This site is just a usual document. Create a new file, e.g. `about.md` in the `content` content directory. The `url` variable in the frontmatter allows you to define the final url of the about page.
\ No newline at end of file
diff --git a/themes/sean-steam/exampleSite/content/post/goisforlovers.md b/themes/sean-steam/exampleSite/content/post/goisforlovers.md
new file mode 100644
index 0000000..4087031
--- /dev/null
+++ b/themes/sean-steam/exampleSite/content/post/goisforlovers.md
@@ -0,0 +1,343 @@
++++
+title = "(Hu)go Template Primer"
+tags = [
+    "go",
+    "golang",
+    "templates",
+    "themes",
+    "development",
+]
+date = "2014-04-02"
+categories = [
+    "Development",
+    "golang",
+]
+description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Earum similique, ipsum officia amet blanditiis provident ratione nihil ipsam dolorem repellat."
++++
+
+Hugo uses the excellent [go][] [html/template][gohtmltemplate] library for
+its template engine. It is an extremely lightweight engine that provides a very
+small amount of logic. In our experience that it is just the right amount of
+logic to be able to create a good static website. If you have used other
+template systems from different languages or frameworks you will find a lot of
+similarities in go templates.
+
+This document is a brief primer on using go templates. The [go docs][gohtmltemplate]
+provide more details.
+
+## Introduction to Go Templates
+
+Go templates provide an extremely simple template language. It adheres to the
+belief that only the most basic of logic belongs in the template or view layer.
+One consequence of this simplicity is that go templates parse very quickly.
+
+A unique characteristic of go templates is they are content aware. Variables and
+content will be sanitized depending on the context of where they are used. More
+details can be found in the [go docs][gohtmltemplate].
+
+## Basic Syntax
+
+Go lang templates are html files with the addition of variables and
+functions. 
+
+**Go variables and functions are accessible within {{ }}**
+
+Accessing a predefined variable "foo":
+
+    {{ foo }}
+
+**Parameters are separated using spaces**
+
+Calling the add function with input of 1, 2:
+
+    {{ add 1 2 }}
+
+**Methods and fields are accessed via dot notation**
+
+Accessing the Page Parameter "bar"
+
+    {{ .Params.bar }}
+
+**Parentheses can be used to group items together**
+
+    {{ if or (isset .Params "alt") (isset .Params "caption") }} Caption {{ end }}
+
+
+## Variables
+
+Each go template has a struct (object) made available to it. In hugo each
+template is passed either a page or a node struct depending on which type of
+page you are rendering. More details are available on the
+[variables](/layout/variables) page.
+
+A variable is accessed by referencing the variable name.
+
+    <title>{{ .Title }}</title>
+
+Variables can also be defined and referenced.
+
+    {{ $address := "123 Main St."}}
+    {{ $address }}
+
+
+## Functions
+
+Go template ship with a few functions which provide basic functionality. The go
+template system also provides a mechanism for applications to extend the
+available functions with their own. [Hugo template
+functions](/layout/functions) provide some additional functionality we believe
+are useful for building websites. Functions are called by using their name
+followed by the required parameters separated by spaces. Template
+functions cannot be added without recompiling hugo.
+
+**Example:**
+
+    {{ add 1 2 }}
+
+## Includes
+
+When including another template you will pass to it the data it will be
+able to access. To pass along the current context please remember to
+include a trailing dot. The templates location will always be starting at
+the /layout/ directory within Hugo.
+
+**Example:**
+
+    {{ template "chrome/header.html" . }}
+
+
+## Logic
+
+Go templates provide the most basic iteration and conditional logic.
+
+### Iteration 
+
+Just like in go, the go templates make heavy use of range to iterate over
+a map, array or slice. The following are different examples of how to use
+range.
+
+**Example 1: Using Context**
+
+    {{ range array }} 
+        {{ . }}
+    {{ end }}
+
+**Example 2: Declaring value variable name**
+
+    {{range $element := array}} 
+        {{ $element }} 
+    {{ end }}
+
+**Example 2: Declaring key and value variable name**
+
+    {{range $index, $element := array}}
+        {{ $index }} 
+        {{ $element }} 
+    {{ end }}
+
+### Conditionals 
+
+If, else, with, or, & and provide the framework for handling conditional
+logic in Go Templates. Like range, each statement is closed with `end`.
+
+
+Go Templates treat the following values as false: 
+
+* false
+* 0 
+* any array, slice, map, or string of length zero
+
+**Example 1: If**
+
+    {{ if isset .Params "title" }}<h4>{{ index .Params "title" }}</h4>{{ end }}
+
+**Example 2: If -> Else** 
+
+    {{ if isset .Params "alt" }} 
+        {{ index .Params "alt" }}
+    {{else}}
+        {{ index .Params "caption" }}
+    {{ end }}
+
+**Example 3: And & Or**
+
+    {{ if and (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}}
+
+**Example 4: With**
+
+An alternative way of writing "if" and then referencing the same value
+is to use "with" instead. With rebinds the context `.` within its scope,
+and skips the block if the variable is absent.
+
+The first example above could be simplified as:
+
+    {{ with .Params.title }}<h4>{{ . }}</h4>{{ end }}
+
+**Example 5: If -> Else If** 
+
+    {{ if isset .Params "alt" }} 
+        {{ index .Params "alt" }}
+    {{ else if isset .Params "caption" }}
+        {{ index .Params "caption" }}
+    {{ end }}
+
+## Pipes
+
+One of the most powerful components of go templates is the ability to
+stack actions one after another. This is done by using pipes. Borrowed
+from unix pipes, the concept is simple, each pipeline's output becomes the
+input of the following pipe. 
+
+Because of the very simple syntax of go templates, the pipe is essential
+to being able to chain together function calls. One limitation of the
+pipes is that they only can work with a single value and that value
+becomes the last parameter of the next pipeline. 
+
+A few simple examples should help convey how to use the pipe.
+
+**Example 1 :**
+
+    {{ if eq 1 1 }} Same {{ end }}
+
+is the same as 
+
+    {{ eq 1 1 | if }} Same {{ end }}
+
+It does look odd to place the if at the end, but it does provide a good
+illustration of how to use the pipes.
+
+**Example 2 :**
+
+    {{ index .Params "disqus_url" | html }}
+
+Access the page parameter called "disqus_url" and escape the HTML.
+
+**Example 3 :**
+
+    {{ if or (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}}
+    Stuff Here
+    {{ end }}
+
+Could be rewritten as 
+
+    {{  isset .Params "caption" | or isset .Params "title" | or isset .Params "attr" | if }}
+    Stuff Here 
+    {{ end }}
+
+
+## Context (aka. the dot)
+
+The most easily overlooked concept to understand about go templates is that {{ . }}
+always refers to the current context. In the top level of your template this
+will be the data set made available to it. Inside of a iteration it will have
+the value of the current item. When inside of a loop the context has changed. .
+will no longer refer to the data available to the entire page. If you need to
+access this from within the loop you will likely want to set it to a variable
+instead of depending on the context.
+
+**Example:**
+
+      {{ $title := .Site.Title }}
+      {{ range .Params.tags }}
+        <li> <a href="{{ $baseurl }}/tags/{{ . | urlize }}">{{ . }}</a> - {{ $title }} </li>
+      {{ end }}
+
+Notice how once we have entered the loop the value of {{ . }} has changed. We
+have defined a variable outside of the loop so we have access to it from within
+the loop.
+
+# Hugo Parameters 
+
+Hugo provides the option of passing values to the template language
+through the site configuration (for sitewide values), or through the meta
+data of each specific piece of content. You can define any values of any
+type (supported by your front matter/config format) and use them however
+you want to inside of your templates. 
+
+
+## Using Content (page) Parameters 
+
+In each piece of content you can provide variables to be used by the
+templates. This happens in the [front matter](/content/front-matter). 
+
+An example of this is used in this documentation site. Most of the pages
+benefit from having the table of contents provided. Sometimes the TOC just
+doesn't make a lot of sense. We've defined a variable in our front matter
+of some pages to turn off the TOC from being displayed. 
+
+Here is the example front matter:
+
+```
+---
+title: "Permalinks"
+date: "2013-11-18"
+aliases:
+  - "/doc/permalinks/"
+groups: ["extras"]
+groups_weight: 30
+notoc: true
+---
+```
+
+Here is the corresponding code inside of the template:
+
+      {{ if not .Params.notoc }}
+        <div id="toc" class="well col-md-4 col-sm-6">
+        {{ .TableOfContents }}
+        </div>
+      {{ end }}
+
+
+
+## Using Site (config) Parameters
+In your top-level configuration file (eg, `config.yaml`) you can define site
+parameters, which are values which will be available to you in chrome.
+
+For instance, you might declare:
+
+```yaml
+params:
+  CopyrightHTML: "Copyright &#xA9; 2013 John Doe. All Rights Reserved."
+  TwitterUser: "spf13"
+  SidebarRecentLimit: 5
+```
+
+Within a footer layout, you might then declare a `<footer>` which is only
+provided if the `CopyrightHTML` parameter is provided, and if it is given,
+you would declare it to be HTML-safe, so that the HTML entity is not escaped
+again.  This would let you easily update just your top-level config file each
+January 1st, instead of hunting through your templates.
+
+```
+{{if .Site.Params.CopyrightHTML}}<footer>
+<div class="text-center">{{.Site.Params.CopyrightHTML | safeHtml}}</div>
+</footer>{{end}}
+```
+
+An alternative way of writing the "if" and then referencing the same value
+is to use "with" instead. With rebinds the context `.` within its scope,
+and skips the block if the variable is absent:
+
+```
+{{with .Site.Params.TwitterUser}}<span class="twitter">
+<a href="https://twitter.com/{{.}}" rel="author">
+<img src="/images/twitter.png" width="48" height="48" title="Twitter: {{.}}"
+ alt="Twitter"></a>
+</span>{{end}}
+```
+
+Finally, if you want to pull "magic constants" out of your layouts, you can do
+so, such as in this example:
+
+```
+<nav class="recent">
+  <h1>Recent Posts</h1>
+  <ul>{{range first .Site.Params.SidebarRecentLimit .Site.Recent}}
+    <li><a href="{{.RelPermalink}}">{{.Title}}</a></li>
+  {{end}}</ul>
+</nav>
+```
+
+
+[go]: <http://golang.org/>
+[gohtmltemplate]: <http://golang.org/pkg/html/template/>
diff --git a/themes/sean-steam/exampleSite/content/post/hugoisforlovers.md b/themes/sean-steam/exampleSite/content/post/hugoisforlovers.md
new file mode 100644
index 0000000..7e62c25
--- /dev/null
+++ b/themes/sean-steam/exampleSite/content/post/hugoisforlovers.md
@@ -0,0 +1,88 @@
++++
+title = "Getting Started with Hugo"
+tags = [
+    "go",
+    "golang",
+    "hugo",
+    "development",
+]
+date = "2014-04-02"
+categories = [
+    "Development",
+    "golang",
+]
+description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Earum similique, ipsum officia amet blanditiis provident ratione nihil ipsam dolorem repellat."
++++
+
+## Step 1. Install Hugo
+
+Goto [hugo releases](https://github.com/spf13/hugo/releases) and download the
+appropriate version for your os and architecture.
+
+Save it somewhere specific as we will be using it in the next step.
+
+More complete instructions are available at [installing hugo](/overview/installing/)
+
+## Step 2. Build the Docs
+
+Hugo has its own example site which happens to also be the documentation site
+you are reading right now.
+
+Follow the following steps:
+
+ 1. Clone the [hugo repository](http://github.com/spf13/hugo)
+ 2. Go into the repo
+ 3. Run hugo in server mode and build the docs
+ 4. Open your browser to http://localhost:1313
+
+Corresponding pseudo commands:
+
+    git clone https://github.com/spf13/hugo
+    cd hugo
+    /path/to/where/you/installed/hugo server --source=./docs
+    > 29 pages created
+    > 0 tags index created
+    > in 27 ms
+    > Web Server is available at http://localhost:1313
+    > Press ctrl+c to stop
+
+Once you've gotten here, follow along the rest of this page on your local build.
+
+## Step 3. Change the docs site
+
+Stop the Hugo process by hitting ctrl+c.
+
+Now we are going to run hugo again, but this time with hugo in watch mode.
+
+    /path/to/hugo/from/step/1/hugo server --source=./docs --watch
+    > 29 pages created
+    > 0 tags index created
+    > in 27 ms
+    > Web Server is available at http://localhost:1313
+    > Watching for changes in /Users/spf13/Code/hugo/docs/content
+    > Press ctrl+c to stop
+
+
+Open your [favorite editor](http://vim.spf13.com) and change one of the source
+content pages. How about changing this very file to *fix the typo*. How about changing this very file to *fix the typo*.
+
+Content files are found in `docs/content/`. Unless otherwise specified, files
+are located at the same relative location as the url, in our case
+`docs/content/overview/quickstart.md`.
+
+Change and save this file.. Notice what happened in your terminal.
+
+    > Change detected, rebuilding site
+
+    > 29 pages created
+    > 0 tags index created
+    > in 26 ms
+
+Refresh the browser and observe that the typo is now fixed.
+
+Notice how quick that was. Try to refresh the site before it's finished building.. I double dare you.
+Having nearly instant feedback enables you to have your creativity flow without waiting for long builds.
+
+## Step 4. Have fun
+
+The best way to learn something is to play with it.
diff --git a/themes/sean-steam/exampleSite/static/.gitkeep b/themes/sean-steam/exampleSite/static/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/themes/sean-steam/images/screenshot.png b/themes/sean-steam/images/screenshot.png
new file mode 100644
index 0000000..6574001
Binary files /dev/null and b/themes/sean-steam/images/screenshot.png differ
diff --git a/themes/sean-steam/images/tn.png b/themes/sean-steam/images/tn.png
new file mode 100644
index 0000000..f4f1497
Binary files /dev/null and b/themes/sean-steam/images/tn.png differ
diff --git a/themes/sean-steam/layouts/404.html b/themes/sean-steam/layouts/404.html
new file mode 100644
index 0000000..11979e4
--- /dev/null
+++ b/themes/sean-steam/layouts/404.html
@@ -0,0 +1,7 @@
+{{ define "main" }}
+<article class="post">
+    <header>
+    <h1 class="post-title">{{ .Site.Params.pageNotFoundTitle }}</h1>
+    </header>
+</article>
+{{ end }}
\ No newline at end of file
diff --git a/themes/sean-steam/layouts/_default/baseof.html b/themes/sean-steam/layouts/_default/baseof.html
new file mode 100644
index 0000000..994181c
--- /dev/null
+++ b/themes/sean-steam/layouts/_default/baseof.html
@@ -0,0 +1,13 @@
+{{ partial "head" . }}
+<body class="home-template">
+    {{ partial "header" . }}
+    {{ partial "navigation" . }}
+    
+    <main class="content" role="main">
+    {{ block "main" . }}{{ end }}
+    </main>
+
+    {{ partial "footer" . }}
+    {{ partial "js" . }}
+</body>
+</html>
\ No newline at end of file
diff --git a/themes/sean-steam/layouts/_default/list.html b/themes/sean-steam/layouts/_default/list.html
new file mode 100644
index 0000000..bc386c6
--- /dev/null
+++ b/themes/sean-steam/layouts/_default/list.html
@@ -0,0 +1,7 @@
+{{ define "main" }}
+	{{ $paginator := .Paginate .Data.Pages }}
+    {{ range $paginator.Pages }}
+        {{ .Render "summary" }} 
+    {{ end }}
+    {{ partial "pagination" . }}
+{{ end }}
\ No newline at end of file
diff --git a/themes/sean-steam/layouts/_default/single.html b/themes/sean-steam/layouts/_default/single.html
new file mode 100644
index 0000000..53f4fa3
--- /dev/null
+++ b/themes/sean-steam/layouts/_default/single.html
@@ -0,0 +1,35 @@
+{{ define "main" }}
+<article class="post">
+    <header>
+        {{ if .Params.tags }}
+        <div class="post-meta tags">
+          Posted in
+          {{ $ntags := sub (len .Params.tags) 1}}
+          {{ range $index, $tag := .Params.tags }}
+            {{ $url := printf "tags/%s" ( . | urlize) }}
+            <a href="{{ $url | relURL }}">{{ . }}</a>{{if ne $index $ntags }}, {{ end }}
+          {{ end }}
+        </div>
+        {{ end }}
+        <h1 class="post-title">{{ .Title }}</h1>
+        <div class="post-meta">
+            <time datetime="{{ .Date.Format "02 January 2006" }}">
+                {{ .Date.Format "Monday, January 02, 2006" }}
+            </time>
+        </div>
+    </header>
+
+    <section class="post-content">
+        {{ .Content }}
+    </section>
+
+    {{ if .Type | eq "post" }}
+    {{ template "_internal/disqus.html" . }}
+    {{ partial "share" . }}
+
+    <footer class="post-footer">
+        {{ partial "author" . }}
+    </footer>
+    {{ end }}
+</article>
+{{ end }}
diff --git a/themes/sean-steam/layouts/_default/summary.html b/themes/sean-steam/layouts/_default/summary.html
new file mode 100644
index 0000000..3f5d8a2
--- /dev/null
+++ b/themes/sean-steam/layouts/_default/summary.html
@@ -0,0 +1,14 @@
+<article class="preview">
+    <header>
+        <h1 class="post-title"><a href="{{ .RelPermalink }}">{{ .Title }}</a></h1>
+        <div class="post-meta"><time datetime="{{ .Date.Format "02 January 2006" }}">{{ .Date.Format "Monday, January 02, 2006" }}</time></div>
+    </header>
+    <section class="post-excerpt">
+        {{ if and (not .Description) (.Site.Params.useSummaryIfNoDescription)}}
+        <p>{{ .Summary }}&hellip;</p>
+        {{ else }}
+        <p>{{ .Description | markdownify }}</p>
+        {{ end }}
+        <p class="readmore"><a href="{{ .RelPermalink }}">{{ .Site.Params.keepReadingStr }} <i class="fa fa-chevron-circle-right" style="padding-left: 5px;"></i></a></p>
+    </section>
+</article>
diff --git a/themes/sean-steam/layouts/_default/terms.html b/themes/sean-steam/layouts/_default/terms.html
new file mode 100644
index 0000000..451d104
--- /dev/null
+++ b/themes/sean-steam/layouts/_default/terms.html
@@ -0,0 +1,11 @@
+{{ define "main" }}
+<div class="terms-list">
+	<ul>
+        {{ $data := .Data }}
+        {{ range $key, $value := .Data.Terms.ByCount }}
+        {{ $url := printf "/%s/%s" $data.Plural ($value.Name | urlize) }}
+        <li><a href="{{ $url | relURL }}">{{ $value.Name |title }}</a> {{ $value.Count }}</li>
+        {{ end }}
+    </ul>
+</div>
+{{ end }}
diff --git a/themes/sean-steam/layouts/index.html b/themes/sean-steam/layouts/index.html
new file mode 100644
index 0000000..5ce78f0
--- /dev/null
+++ b/themes/sean-steam/layouts/index.html
@@ -0,0 +1,10 @@
+{{ define "main" }}
+    {{ $paginator := .Paginate (where .Data.Pages.ByDate.Reverse "Section" "post")}}
+    {{ range $paginator.Pages }}
+        {{ if not .Params.hide }}
+           {{ .Render "summary" }}
+        {{ end }}
+    {{ end }}
+
+    {{ partial "pagination" . }}
+{{ end }}
diff --git a/themes/sean-steam/layouts/partials/author.html b/themes/sean-steam/layouts/partials/author.html
new file mode 100644
index 0000000..170defe
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/author.html
@@ -0,0 +1,6 @@
+<section class="author">
+    <div class="authorimage" style="background: url({{ "img/avatar.png" | relURL }})"></div>
+    <p class="attr">AUTHOR</p>
+    <h4>{{ .Site.Params.name }}</h4>
+    <p class="bio">{{  .Site.Params.bio | markdownify }}</p>
+</section>
diff --git a/themes/sean-steam/layouts/partials/footer.html b/themes/sean-steam/layouts/partials/footer.html
new file mode 100644
index 0000000..4d380af
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/footer.html
@@ -0,0 +1,7 @@
+<footer class="site-footer">
+	<div class="inner">
+		{{ partial "social" . }}
+
+		<section class="copyright">&copy; {{now.Format "2006"}} <a href="{{ .Site.BaseURL }}">{{ .Site.Params.name }}</a>. {{ .Site.Params.copyright | markdownify }}</section>
+	</div>
+</footer>
diff --git a/themes/sean-steam/layouts/partials/head.html b/themes/sean-steam/layouts/partials/head.html
new file mode 100644
index 0000000..8168e4b
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/head.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="{{ with .Site.LanguageCode }}{{ . }}{{ else }}en-US{{ end }}">
+<head>
+    <meta http-equiv="Content-Type" content="text/html" charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+
+    <title>{{ .Title }}</title>
+    {{ with .Site.Params.name }}<meta name="author" content="{{ . }}">{{ end }}
+    {{ with .Site.Params.description }}<meta name="description" content="{{ . }}">{{ end }}
+    {{ .Hugo.Generator }}
+    <meta name="HandheldFriendly" content="True">
+    <meta name="MobileOptimized" content="320">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
+
+    {{ "<!-- RSS autodiscovery -->" | safeHTML }}
+    {{ if .RSSLink }}
+    <link href="{{ .RSSLink }}" rel="alternate" type="application/rss+xml"
+    title="{{ .Site.Title }}" />
+    <link href="{{ .RSSLink }}" rel="feed" type="application/rss+xml"
+    title="{{ .Site.Title }}" />
+    {{ end }}
+
+    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
+
+    {{ "<!-- Stylesheets -->" | safeHTML }}
+    <link rel="stylesheet" href="{{ "css/screen.css" | relURL }}">
+    <link rel="stylesheet" href="{{ "css/github.css" | relURL }}">
+    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.8.0/styles/default.min.css">
+    {{ range .Site.Params.customCSS }}
+    <link rel="stylesheet" href="{{ . | relURL }}">
+    {{ end }}
+
+    {{ with .Site.Params.favicon }}
+    <link rel="shortcut icon" type="image/x-icon" href="{{ . | relURL }}">
+    <link rel="icon" type="image/x-icon" href="{{ . | relURL }}">
+    {{ end }}
+
+    {{ "<!-- Stylesheet for theme color -->" | safeHTML }}
+    {{ partial (printf "themes/%s-theme" .Site.Params.themecolor) . }}
+</head>
diff --git a/themes/sean-steam/layouts/partials/header.html b/themes/sean-steam/layouts/partials/header.html
new file mode 100644
index 0000000..926e592
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/header.html
@@ -0,0 +1,6 @@
+<header id="site-head">
+  <a id="blog-logo" href="/"><div class="bloglogo" style="background: url(/img/ctakes_logo.jpg)"></div></a>
+	{{ with .Site.Params.title }}
+	<h1 class="blog-title"><a href="{{ $.Site.BaseURL }}">{{ . | markdownify }}</a></h1>
+	{{ end }}
+</header>
diff --git a/themes/sean-steam/layouts/partials/js.html b/themes/sean-steam/layouts/partials/js.html
new file mode 100644
index 0000000..7224e31
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/js.html
@@ -0,0 +1,19 @@
+<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
+<script src="{{ "js/index.js" | relURL }}"></script>
+<script src="{{ "js/smooth-scroll.min.js" | relURL }}"></script>
+<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.8.0/highlight.min.js"></script>
+{{ range .Site.Params.customJS }}
+<link rel="stylesheet" href="{{ . | relURL }}">
+{{ end }}
+
+<script>
+    smoothScroll.init({
+        speed: 800,
+        easing: 'easeInOutCubic',
+        updateURL: false,
+        offset: 125,
+    });
+</script>
+<script>hljs.initHighlightingOnLoad();</script>
+
+{{ template "_internal/google_analytics.html" . }}
diff --git a/themes/sean-steam/layouts/partials/navigation.html b/themes/sean-steam/layouts/partials/navigation.html
new file mode 100644
index 0000000..95a01aa
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/navigation.html
@@ -0,0 +1,11 @@
+{{ if .Site.Menus.main }}
+{{ $nitems := sub (len .Site.Menus.main) 1}}
+<nav class="menu" role="nav">
+    <ul>
+        {{ range $index, $item := .Site.Menus.main }}
+        	<li class="nav nav-current"><a href="{{ .URL }}">{{ .Name }}</a></li>
+          {{ if ne $index $nitems }}<li>|</li>{{ end }}
+      	{{ end }}
+    </ul>
+</nav>
+{{ end }}
diff --git a/themes/sean-steam/layouts/partials/pagination.html b/themes/sean-steam/layouts/partials/pagination.html
new file mode 100644
index 0000000..2ae86b0
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/pagination.html
@@ -0,0 +1,13 @@
+{{ if or (.Paginator.HasPrev) (.Paginator.HasNext) }}
+<nav class="pagination" role="pagination">
+    {{ if .Paginator.HasPrev }}
+    <a class="newer-posts" href="{{ .Paginator.Prev.URL }}"><i class="fa fa-chevron-circle-left"></i> Newer</a>
+    {{ end }}
+
+    <span class="page-number">Page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }}</span>
+    
+    {{ if .Paginator.HasNext }}
+    <a class="older-posts" href="{{ .Paginator.Next.URL }}">Older <i class="fa fa-chevron-circle-right"></i></a>
+    {{ end }}
+</nav>
+{{ end }}
\ No newline at end of file
diff --git a/themes/sean-steam/layouts/partials/share.html b/themes/sean-steam/layouts/partials/share.html
new file mode 100644
index 0000000..aa81408
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/share.html
@@ -0,0 +1,16 @@
+<section class="share">
+    <p class="backtotop"><a data-scroll href="#site-head"><i class="fa fa-lg fa-fw fa-angle-double-up"></i></a><a data-scroll class="backtotoptext" href="#site-head"> {{ .Site.Params.backtotopStr }}</a></p>
+    <p class="info prompt">{{ .Site.Params.shareStr }}</p>
+    <a href="http://twitter.com/share?text={{ .Title }}&url={{ .RelPermalink }}" title="Share on Twitter"
+        onclick="window.open(this.href, 'twitter-share', 'width=550,height=235');return false;">
+        <i class="fa fa-2x fa-fw fa-twitter-square"></i> <span class="hidden">Twitter</span>
+    </a>
+    <a href="https://www.facebook.com/sharer/sharer.php?u={{ .RelPermalink }}" title="Share on Facebook"
+        onclick="window.open(this.href, 'facebook-share','width=580,height=296');return false;">
+        <i class="fa fa-2x fa-fw fa-facebook-square" style="margin-left: -8px"></i> <span class="hidden">Facebook</span>
+    </a>
+    <a href="https://plus.google.com/share?url={{ .RelPermalink }}" title="Share on Google+"
+       onclick="window.open(this.href, 'google-plus-share', 'width=490,height=530');return false;">
+        <i class="fa fa-2x fa-fw fa-google-plus-square" style="margin-left: -8px"></i> <span class="hidden">Google+</span>
+    </a>
+</section>
diff --git a/themes/sean-steam/layouts/partials/social.html b/themes/sean-steam/layouts/partials/social.html
new file mode 100644
index 0000000..82cc131
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/social.html
@@ -0,0 +1,29 @@
+<section class="footer-social">
+      {{ with .Site.Params.twitter }}
+      <a href="//twitter.com/{{ . }}" target="_blank" title="Twitter"><i class="fa fa-2x fa-fw fa-twitter"></i> <span class="hidden">Twitter</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.linkedin }}
+      <a href="//www.linkedin.com/company/{{ . }}" target="_blank" title="linkedIn"><i class="fa fa-2x fa-fw fa-linkedin"></i> <span class="hidden">LinkedIn</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.googleplus }}
+      <a href="//plus.google.com/{{ . }}" target="_blank" title="Google+"><i class="fa fa-2x fa-fw fa-google-plus"></i> <span class="hidden">Google+</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.facebook }}
+      <a href="//www.facebook.com/{{ . }}" target="_blank" title="Facebook"><i class="fa fa-2x fa-fw fa-facebook"></i> <span class="hidden">Facebook</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.instagram }}
+      <a href="//www.instagram.com/{{ . }}" target="_blank" title="Instagram"><i class="fa fa-2x fa-fw fa-instagram"></i> <span class="hidden">Instagram</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.github }}
+      <a href="//github.com/{{ . }}" target="_blank" title="GitHub"><i class="fa fa-2x fa-fw fa-github"></i> <span class="hidden">GitHub</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.gitlab }}
+      <a href="//gitlab.com/u/{{ . }}" target="_blank" title="GitLab"><i class="fa fa-2x fa-fw fa-gitlab"></i> <span class="hidden">GitLab</span></a>&nbsp;
+      {{ end }}
+      {{ with .Site.Params.bitbucket }}
+      <a href="//bitbucket.org/{{ . }}" target="_blank" title="Bitbucket"><i class="fa fa-2x fa-fw fa-bitbucket"></i> <span class="hidden">Bitbucket</span></a>&nbsp;
+      {{ end }}
+      {{ with .RSSLink }}
+      <a href="{{ . }}" target="_blank" title="RSS"><i class="fa fa-2x fa-fw fa-rss"></i> <span class="hidden">RSS</span></a>
+      {{ end }}
+  </section>
diff --git a/themes/sean-steam/layouts/partials/themes/blue-theme.html b/themes/sean-steam/layouts/partials/themes/blue-theme.html
new file mode 100644
index 0000000..f584a4d
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/themes/blue-theme.html
@@ -0,0 +1,8 @@
+<style type="text/css">
+    a, a:visited {color: #3498db;}
+    .pagination a {color: #3498db;}
+    .gist .gist-file .gist-meta a:visited {color: #3498db !important;}
+    a:focus, a:hover {color: #2079b4;}
+    h1.post-title a:focus, h1.post-title a:hover, h1.blog-title a:focus, h1.blog-title a:hover {color: #2079b4;}
+    .older-posts:hover, .newer-posts:hover {color: #2079b4;}
+</style>
\ No newline at end of file
diff --git a/themes/sean-steam/layouts/partials/themes/custom-theme.html b/themes/sean-steam/layouts/partials/themes/custom-theme.html
new file mode 100644
index 0000000..6467936
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/themes/custom-theme.html
@@ -0,0 +1,8 @@
+<style type="text/css">
+    a, a:visited {color: #111111;}
+    .pagination a {color: #111111;}
+    .gist .gist-file .gist-meta a:visited {color: #111111 !important;}
+    a:focus, a:hover {color: #000000;}
+    h1.post-title a:focus, h1.post-title a:hover, h1.blog-title a:focus, h1.blog-title a:hover {color: #000000;}
+    .older-posts:hover, .newer-posts:hover {color: #000000;}
+</style>
\ No newline at end of file
diff --git a/themes/sean-steam/layouts/partials/themes/green-theme.html b/themes/sean-steam/layouts/partials/themes/green-theme.html
new file mode 100644
index 0000000..1d1a138
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/themes/green-theme.html
@@ -0,0 +1,8 @@
+<style type="text/css">
+    a, a:visited {color: #33cc99;}
+    .pagination a {color: #33cc99;}
+    .gist .gist-file .gist-meta a:visited {color: #33cc99 !important;}
+    a:focus, a:hover {color: #178b6b;}
+    h1.post-title a:focus, h1.post-title a:hover, h1.blog-title a:focus, h1.blog-title a:hover {color: #178b6b;}
+    .older-posts:hover, .newer-posts:hover {color: #178b6b;}
+</style>
\ No newline at end of file
diff --git a/themes/sean-steam/layouts/partials/themes/orange-theme.html b/themes/sean-steam/layouts/partials/themes/orange-theme.html
new file mode 100644
index 0000000..cfa3c68
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/themes/orange-theme.html
@@ -0,0 +1,8 @@
+<style type="text/css">
+    a, a:visited {color: #ff9d00;}
+    .pagination a {color: #ff9d00;}
+    .gist .gist-file .gist-meta a:visited {color: #ff9d00 !important;}
+    a:focus, a:hover {color: #d88500;}
+    h1.post-title a:focus, h1.post-title a:hover, h1.blog-title a:focus, h1.blog-title a:hover {color: #d88500;}
+    .older-posts:hover, .newer-posts:hover {color: #d88500;}
+</style>
\ No newline at end of file
diff --git a/themes/sean-steam/layouts/partials/themes/red-theme.html b/themes/sean-steam/layouts/partials/themes/red-theme.html
new file mode 100644
index 0000000..31a35f7
--- /dev/null
+++ b/themes/sean-steam/layouts/partials/themes/red-theme.html
@@ -0,0 +1,8 @@
+<style type="text/css">
+    a, a:visited {color: #f05948;}
+    .pagination a {color: #f05948;}
+    .gist .gist-file .gist-meta a:visited {color: #f05948 !important;}
+    a:focus, a:hover {color: #c62310;}
+    h1.post-title a:focus, h1.post-title a:hover, h1.blog-title a:focus, h1.blog-title a:hover {color: #c62310;}
+    .older-posts:hover, .newer-posts:hover {color: #c62310;}
+</style>
\ No newline at end of file
diff --git a/themes/sean-steam/static/css/github.css b/themes/sean-steam/static/css/github.css
new file mode 100644
index 0000000..5ca9632
--- /dev/null
+++ b/themes/sean-steam/static/css/github.css
@@ -0,0 +1,127 @@
+/*
+
+github.com style (c) Vasily Polovnyov <va...@whiteants.net>
+
+*/
+
+.hljs {
+  display: block;
+  overflow-x: auto;
+  padding: 0.5em;
+  color: #596364;
+  background: #f7f7f7;
+  -webkit-text-size-adjust: none;
+}
+
+.hljs-comment,
+.hljs-template_comment,
+.diff .hljs-header,
+.hljs-javadoc {
+  color: #998;
+  font-style: italic;
+}
+
+.hljs-keyword,
+.css .rule .hljs-keyword,
+.hljs-winutils,
+.javascript .hljs-title,
+.nginx .hljs-title,
+.hljs-subst,
+.hljs-request,
+.hljs-status {
+  color: #596364;
+  font-weight: bold;
+}
+
+.hljs-number,
+.hljs-hexcolor,
+.ruby .hljs-constant {
+  color: #008080;
+}
+
+.hljs-string,
+.hljs-tag .hljs-value,
+.hljs-phpdoc,
+.hljs-dartdoc,
+.tex .hljs-formula {
+  color: #d14;
+}
+
+.hljs-title,
+.hljs-id,
+.scss .hljs-preprocessor {
+  color: #900;
+  font-weight: bold;
+}
+
+.javascript .hljs-title,
+.hljs-list .hljs-keyword,
+.hljs-subst {
+  font-weight: normal;
+}
+
+.hljs-class .hljs-title,
+.hljs-type,
+.vhdl .hljs-literal,
+.tex .hljs-command {
+  color: #458;
+  font-weight: bold;
+}
+
+.hljs-tag,
+.hljs-tag .hljs-title,
+.hljs-rules .hljs-property,
+.django .hljs-tag .hljs-keyword {
+  color: #000080;
+  font-weight: normal;
+}
+
+.hljs-attribute,
+.hljs-variable,
+.lisp .hljs-body {
+  color: #008080;
+}
+
+.hljs-regexp {
+  color: #009926;
+}
+
+.hljs-symbol,
+.ruby .hljs-symbol .hljs-string,
+.lisp .hljs-keyword,
+.clojure .hljs-keyword,
+.scheme .hljs-keyword,
+.tex .hljs-special,
+.hljs-prompt {
+  color: #990073;
+}
+
+.hljs-built_in {
+  color: #0086b3;
+}
+
+.hljs-preprocessor,
+.hljs-pragma,
+.hljs-pi,
+.hljs-doctype,
+.hljs-shebang,
+.hljs-cdata {
+  color: #999;
+  font-weight: bold;
+}
+
+.hljs-deletion {
+  background: #fdd;
+}
+
+.hljs-addition {
+  background: #dfd;
+}
+
+.diff .hljs-change {
+  background: #0086b3;
+}
+
+.hljs-chunk {
+  color: #aaa;
+}
diff --git a/themes/sean-steam/static/css/screen.css b/themes/sean-steam/static/css/screen.css
new file mode 100644
index 0000000..e6e89c2
--- /dev/null
+++ b/themes/sean-steam/static/css/screen.css
@@ -0,0 +1,521 @@
+@import url('//fonts.googleapis.com/css?subset=latin,cyrillic-ext,latin-ext,cyrillic&family=Open+Sans+Condensed:300|Open+Sans:400,600,400italic,600italic|Merriweather:400,300,300italic,400italic,700,700italic|Roboto+Slab:400,300');
+@import url('//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css');
+/* === Core Styles === */
+body {
+  background-color: #ffffff;
+  font-size: 15px;
+  font-weight: 100;
+  line-height: 1.6em;
+  margin: 0;
+  padding: 0;
+  -webkit-font-smoothing: subpixel-antialiased;
+}
+body * {
+  max-height: 1000000em;
+}
+h1,
+h3,
+h4,
+p,
+li,
+dt,
+dd {
+  font-family: "Merriweather", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+}
+h1,
+.post-meta {
+  text-align: center;
+}
+a,
+a:visited {
+  color: #3498db;
+  text-decoration: none;
+  transition: color ease 0.7s;
+  -webkit-transition: color ease 0.7s;
+}
+a:focus,
+a:hover {
+  color: #02090e;
+}
+p,
+li,
+dt,
+dd {
+  font-size: 18px;
+  font-weight: 100;
+  line-height: 30px;
+}
+dt {
+  font-weight: 400;
+}
+li {
+  padding-left: 0.8em;
+}
+pre {
+  font-family: "Consolas", Courier, monospace;
+  font-size: 1em;
+  line-height: 1.2em;
+  padding: 1em;
+  white-space: pre;
+  white-space: pre-wrap;
+  white-space: -moz-pre-wrap;
+  white-space: -pre-wrap;
+  white-space: -o-pre-wrap;
+  word-wrap: break-word;
+  background-color: rgba(0, 0, 0, 0.05);
+}
+p code {
+  font-family: "Consolas", Courier, monospace;
+  font-size: .8em;
+  line-height: 1.2em;
+}
+h1 {
+  color: #151515;
+  font-family: "Roboto Slab", "Merriweather", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-size: 36px;
+  font-weight: 400;
+  line-height: 42px;
+  margin: 0;
+  padding: 0;
+}
+#site-head,
+article,
+article.preview,
+a.archive-link,
+.article-nav {
+  margin: 20px auto;
+  max-width: 600px;
+  width: 90%;
+}
+#site-head img {
+  max-width: 100%;
+}
+article.preview {
+  margin-bottom: 4em;
+}
+article.preview p.readmore {
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  margin-top: 1em;
+  text-transform: uppercase;
+  font-weight: 400;
+}
+/* === Header === */
+#blog-logo {
+  display: block;
+  max-width: 100px;
+  margin: 50px auto 0;
+  text-align: center;
+}
+#blog-logo div.bloglogo {
+  width: 100px;
+  height: 100px;
+  border-radius: 50%;
+  -webkit-background-size: cover !important;
+  background-size: cover !important;
+  background-position: center center !important;
+  background-color: #ffffff;
+}
+h1.blog-title,
+h2.blog-description {
+  text-align: center;
+}
+h1.blog-title {
+  font-size: 48px;
+  line-height: 52px;
+  margin-top: 10px;
+  margin-bottom: 30px;
+  padding: 0;
+}
+h2.blog-description {
+  border-bottom: 1px solid #ecf0f1;
+  border-top: 1px solid #ecf0f1;
+  margin-bottom: 2em;
+  padding: .5em 1em;
+  line-height: 1.2em;
+}
+section.footer-description {
+  margin-bottom: 1em;
+}
+header.article-header,
+header.page-header {
+  margin-bottom: 3em;
+}
+/* === Body === */
+section.author,
+section.share {
+  width: 100%;
+  text-align: left;
+  text-transform: none;
+}
+section.share {
+  margin-top: 1em;
+  border-top: 1px solid #ecf0f1;
+  padding-top: 1em;
+  text-align: right;
+}
+section.author h4,
+section.author p,
+section.share p {
+  padding: 0;
+  margin: 0;
+}
+section.author h4 {
+  font-family: "Roboto Slab", "Merriweather", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-weight: 400;
+  margin-bottom: 4px;
+}
+section.author p.attr,
+section.share p.info {
+  font-size: 16px;
+  line-height: 20px;
+  text-transform: uppercase;
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+}
+section.share p.info.prompt {
+  top: -5px;
+  position: relative;
+}
+section.author p.attr {
+  margin-bottom: 2px;
+}
+section.share p.info {
+  display: inline-block;
+}
+section.author p.bio {
+  font-size: 16px;
+  margin-left: 82px;
+  line-height: 1.4em;
+}
+blockquote {
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-size: 1.2em;
+  font-weight: 300;
+  line-height: 1.2em;
+  font-style: italic;
+  border-left: 0.5em solid rgba(0, 0, 0, 0.05);
+  margin-left: 1em;
+  padding-left: 1em;
+}
+blockquote p {
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-size: 1.2em;
+  font-weight: 300;
+  line-height: 1.2em;
+  font-style: italic;
+}
+.post-meta {
+  color: #95a5a6;
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-size: 20px;
+  font-weight: 300;
+  margin-top: 1em;
+  margin-bottom: 1.2em;
+  text-transform: uppercase;
+}
+.tags {
+  font-size: 16px;
+  margin-bottom: 0.6em;
+}
+div.authorimage {
+  width: 70px;
+  height: 70px;
+  border-radius: 50%;
+  -webkit-background-size: cover !important;
+  background-size: cover !important;
+  background-position: center center !important;
+  margin-right: 10px;
+  float: left;
+}
+h1.post-title a,
+h1.blog-title a {
+  color: #151515;
+  transition: color ease 0.7s;
+  -webkit-transition: color ease 0.7s;
+}
+h1.post-title a:focus,
+h1.post-title a:hover,
+h1.blog-title a:focus,
+h1.blog-title a:hover {
+  color: #3498db;
+  text-decoration: none;
+}
+h2 {
+  margin-top: 2em;
+}
+section.post-content img {
+  display: block;
+  margin: 0 auto;
+  max-width: 100%;
+}
+section.preview.archive h2 {
+  text-align: left;
+}
+section.author {
+  overflow: hidden;
+}
+img.userimage {
+  width: 70px;
+  max-width: 70px;
+  max-height: 70px;
+  border-radius: 50%;
+  margin-right: 10px;
+  float: left;
+}
+/* === Footer === */
+footer {
+  background: rgba(0, 0, 0, 0.05);
+  margin: 4em 0 0;
+  padding: 2em 0;
+  text-align: center;
+}
+footer section {
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-weight: 300;
+  font-size: 18px;
+  margin: 0 auto;
+  max-width: 600px;
+  text-transform: uppercase;
+  width: 90%;
+}
+footer.post-footer {
+  background: none;
+  border-top: 1px solid #ecf0f1;
+  margin-top: 1em;
+}
+/* === Navigation and Pagination === */
+nav {
+  border-bottom: 1px solid #ecf0f1;
+  border-top: 1px solid #ecf0f1;
+  margin-bottom: 2em;
+  text-align: center;
+  margin: 20px auto 2em auto;
+  max-width: 600px;
+}
+nav ul {
+  list-style: none;
+  margin: 0 auto;
+  padding: 0;
+  width: 100%;
+  overflow: hidden;
+  text-align: center;
+}
+nav ul li {
+  display: inline-block;
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-size: 18px;
+  font-weight: 300;
+  margin: 0;
+  padding: 0 .5em;
+  text-align: center;
+  text-transform: uppercase;
+}
+nav ul li a {
+  display: block;
+  padding: .5em 0;
+}
+nav.menu {
+  margin-bottom: 2.5em;
+}
+nav.menu li {
+  margin: 0 .5em;
+  padding: 0;
+}
+nav.menu li:last-child {
+  margin: 0;
+}
+@media only screen and (min-width: 320px) and (max-width: 662px) {
+  nav.menu li {
+    display: block;
+  }
+}
+nav.pagination li:first-child {
+  margin-left: 0;
+  margin-right: 0;
+  text-align: right;
+}
+nav.pagination li:last-child {
+  margin-left: 0;
+  margin-right: 0;
+  text-align: left;
+}
+a.archive-link {
+  border-bottom: 1px solid #ecf0f1;
+  border-top: 1px solid #ecf0f1;
+  display: block;
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  font-size: 24px;
+  font-weight: 300;
+  margin-bottom: 3em;
+  margin-top: 3em;
+  padding: .5em 0;
+  text-align: center;
+  text-transform: uppercase;
+}
+.pagination {
+  position: relative;
+  width: 90%;
+  max-width: 600px;
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  text-transform: uppercase;
+  font-size: 20px;
+  color: #7f8c8d;
+  text-align: center;
+  padding: 0.5em 0;
+}
+.pagination a {
+  color: #3498db;
+}
+.older-posts,
+.newer-posts {
+  position: absolute;
+  display: inline-block;
+  padding: 0;
+  text-decoration: none;
+  transition: color ease 0.7s;
+  -webkit-transition: color ease 0.7s;
+}
+.older-posts {
+  right: 0;
+}
+.page-number {
+  display: inline-block;
+  padding: 0;
+  margin: 0;
+}
+.newer-posts {
+  left: 0;
+}
+.older-posts:hover,
+.newer-posts:hover {
+  color: #02090e;
+  text-decoration: none;
+}
+/* === Extras === */
+.gist {
+  margin-top: 1em;
+  margin-bottom: 1em;
+  border-collapse: collapse !important;
+}
+.gist .gist-file {
+  font-family: "Consolas", Courier, monospace;
+  border: 1px solid rgba(0, 0, 0, 0.05) !important;
+}
+.gist .gist-file .gist-meta {
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif !important;
+  font-weight: 300 !important;
+  text-transform: uppercase !important;
+  display: none !important;
+  /* Hide GitHub attribution */
+}
+.gist .gist-file .gist-meta a:visited {
+  color: #3498db !important;
+}
+.gist .gist-file .gist-data {
+  background: #fdfdfd !important;
+  border-bottom: none !important;
+  /* Hide GitHub attribution */
+}
+.gist .gist-file .gist-data .line-numbers {
+  border-right: none !important;
+}
+.gist .gist-file .gist-data .line-numbers,
+.gist .gist-file .gist-meta {
+  background-color: rgba(0, 0, 0, 0.05) !important;
+}
+.gist .gist-file .gist-data .line-numbers,
+.gist .gist-file .gist-data .line-pre {
+  line-height: 1.2em !important;
+}
+.hidden {
+  text-indent: -9999px;
+  visibility: hidden;
+  display: none;
+}
+@font-face {
+  font-family: 'icons';
+  src: url('../fonts/icons.eot');
+  src: url('../fonts/icons.eot?#iefix') format('embedded-opentype'), url('../fonts/icons.woff') format('woff'), url('../fonts/icons.ttf') format('truetype'), url('../fonts/icons.svg#icons') format('svg');
+  font-weight: normal;
+  font-style: normal;
+}
+.icon-ghost,
+.icon-feed {
+  font-family: 'icons';
+  speak: none;
+  font-style: normal;
+  font-weight: normal;
+  font-variant: normal;
+  text-transform: none;
+  line-height: 1;
+  -webkit-font-smoothing: antialiased;
+  text-decoration: none;
+}
+.icon-ghost:before {
+  content: "\e000";
+}
+.icon-feed:before {
+  content: "\e001";
+}
+.icon-ghost {
+  font-size: 12px;
+  position: relative;
+  top: -1px;
+}
+/* Comments */
+#disqus_thread {
+  color: #787878;
+}
+/* Tables */
+table {
+  width: 100%;
+  font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  border-collapse: collapse;
+  margin: 1em 0 3em;
+}
+table td {
+  padding: .5em;
+}
+table thead {
+  font-weight: 600;
+  border-bottom: 1px solid #ecf0f1;
+}
+table tbody tr:nth-child(even) {
+  background-color: #ecf0f1;
+  border-top: 1px solid #e3e9eb;
+  border-bottom: 1px solid #e3e9eb;
+}
+table tfoot {
+  border-top: 1px solid #ecf0f1;
+}
+/* === Media Queries === */
+@media only screen and (min-width: 320px) and (max-width: 500px) {
+  footer section span.copyright {
+    display: block;
+  }
+  nav li {
+    width: auto;
+  }
+  .older-posts,
+  .newer-posts {
+    position: static;
+  }
+  .newer-posts {
+    margin-bottom: 10px;
+  }
+  .older-posts {
+    margin-top: 10px;
+  }
+  .page-number {
+    display: block;
+  }
+}
+p.backtotop {
+  font-size: 16px;
+  line-height: 20px;
+  text-transform: uppercase;
+  font-family: "Open Sans Condensed", "Open Sans", "Helvetica Neue", Helvetica, Arial, "Nimbus L", sans-serif;
+  top: 5px;
+  position: relative;
+  text-align: left;
+  float: left;
+}
diff --git a/themes/sean-steam/static/favicon.ico b/themes/sean-steam/static/favicon.ico
new file mode 100644
index 0000000..e3a367e
Binary files /dev/null and b/themes/sean-steam/static/favicon.ico differ
diff --git a/themes/sean-steam/static/fonts/icons.eot b/themes/sean-steam/static/fonts/icons.eot
new file mode 100644
index 0000000..68c968d
Binary files /dev/null and b/themes/sean-steam/static/fonts/icons.eot differ
diff --git a/themes/sean-steam/static/fonts/icons.svg b/themes/sean-steam/static/fonts/icons.svg
new file mode 100644
index 0000000..182aa87
--- /dev/null
+++ b/themes/sean-steam/static/fonts/icons.svg
@@ -0,0 +1,41 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG font generated by IcoMoon.
+<iconset grid="16"></iconset>
+</metadata>
+<defs>
+<font id="icons" horiz-adv-x="512" >
+<font-face units-per-em="512" ascent="480" descent="-32" />
+<missing-glyph horiz-adv-x="512" />
+<glyph class="hidden" unicode="&#xf000;" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" />
+<glyph unicode="&#xe001;" d="M 421.344-32C 420.944,197.616, 220.592,385.264,0,385.696L0,480 c 270.656,0, 512-230.304, 512-512L 421.344-32 
+	z M 343.6-31.968l-90.608,0 c 0.304,56.384-28.336,119.488-73.664,166.736C 134.256,182.4, 54.368,212.416, 0.224,212.128L 0.224,306.4 
+	C 169.264,302.752, 340.16,143.088, 343.6-31.968z M 64.256,96.048c 35.312,0, 63.936-28.656, 63.936-64c0-35.328-28.624-63.984-63.936-63.984
+	S 0.32-3.28, 0.32,32.048C 0.32,67.392, 28.944,96.048, 64.256,96.048z"  />
+<glyph unicode="&#xe002;" d="M 512,382.791c-18.838-8.354-39.082-14.001-60.33-16.54c 21.686,13, 38.343,33.585, 46.186,58.115
+	c-20.298-12.039-42.778-20.78-66.705-25.49c-19.16,20.415-46.461,33.17-76.673,33.17c-58.011,0-105.044-47.029-105.044-105.039
+	c0-8.233, 0.929-16.25, 2.72-23.939c-87.3,4.382-164.701,46.2-216.509,109.753c-9.042-15.514-14.223-33.558-14.223-52.809
+	c0-36.444, 18.544-68.596, 46.73-87.433c-17.219,0.546-33.416,5.271-47.577,13.139c-0.010-0.438-0.010-0.878-0.010-1.321
+	c0-50.894, 36.209-93.348, 84.261-103c-8.813-2.4-18.094-3.686-27.674-3.686c-6.769,0-13.349,0.66-19.764,1.886
+	c 13.368-41.73, 52.16-72.103, 98.126-72.948c-35.95-28.175-81.243-44.967-130.458-44.967c-8.479,0-16.84,0.497-25.058,1.47
+	c 46.486-29.805, 101.701-47.197, 161.021-47.197c 193.211,0, 298.868,160.062, 298.868,298.872c0,4.554-0.103,9.084-0.305,13.59
+	C 480.11,343.227, 497.918,361.727, 512,382.791z"  />
+<glyph unicode="&#xe003;" d="M 0.403,45.168c-0.122,1.266-0.226,2.535-0.292,3.815C 0.176,47.703, 0.281,46.434, 0.403,45.168zM 117.954,197.426c 46.005-1.369, 76.867,46.349, 68.931,106.599c-7.947,60.24-51.698,108.584-97.704,109.961
+		c-46.013,1.365-76.87-44.741-68.926-105C 28.196,248.752, 71.931,198.799, 117.954,197.426zM 512,352L 512,394.655 C 512,441.595, 473.609,480, 426.671,480L 85.343,480 C 39.205,480, 1.337,442.884, 0.061,397.037
+		c 29.181,25.693, 69.662,47.158, 111.437,47.158c 44.652,0, 178.622,0, 178.622,0l-39.974-33.809l-56.634,0 
+		c 37.565-14.402, 57.578-58.062, 57.578-102.861c0-37.624-20.905-69.977-50.444-92.984c-28.822-22.451-34.286-31.854-34.286-50.939
+		c0-16.289, 30.873-44, 47.016-55.394c 47.191-33.269, 62.458-64.156, 62.458-115.728c0-8.214-1.021-16.415-3.033-24.48l 153.871,0 
+		C 473.609-32, 512,6.375, 512,53.345L 512,319.999 l-96,0 L 416,224 l-32,0 l0,96 l-95.999,0 l0,32 L 384,352 L 384,448 l 32,0 l0-96 L 512,352 zM 92.943,97.032c 10.807,0, 20.711,0.295, 30.968,0.295c-13.573,13.167-24.313,29.3-24.313,49.19
+		c0,11.804, 3.782,23.168, 9.067,33.26c-5.391-0.385-10.895-0.497-16.563-0.497c-37.178,0-68.753,12.038-92.102,31.927l0-33.621 
+		l 0.003-100.865C 26.723,89.408, 58.447,97.032, 92.943,97.032zM 1.71,36.371c-0.556,2.729-0.983,5.503-1.271,8.317C 0.726,41.874, 1.154,39.1, 1.71,36.371zM 227.725,3.577c-7.529,29.403-34.227,43.982-71.444,69.784c-13.536,4.366-28.447,6.937-44.447,7.104
+		c-44.809,0.482-86.554-17.471-110.108-44.186C 9.686-2.574, 44.243-32, 85.343-32l 143.222,0 c 0.908,5.564, 1.348,11.316, 1.348,17.216
+		C 229.913-8.517, 229.146-2.388, 227.725,3.577z"  />
+<glyph unicode="&#xe004;" d="M 426.672,480L 85.342,480 C 38.406,480,0,441.593,0,394.656l0-341.313 C0,6.374, 38.406-32, 85.342-32l 341.33,0.001
+	c 46.938,0, 85.328,38.373, 85.328,85.344L 512,394.656 C 512,441.593, 473.609,480, 426.672,480z M 435.296,224L 352,224 l0-224 l-96,0 L 256,224 l-46.263,0 l0,73.282 L 256,297.282 
+	l0,47.593 C 256,409.546, 283.896,448, 359.935,448l 87.622,0 l0-79.285 l-71.565,0 c-21.241,0.035-23.876-11.076-23.876-31.756L 352,297.282l 96,0 
+	L 435.296,224z"  />
+<glyph unicode="&#xe000;" d="M0,480 L0,377.6 L 307.2,377.6 L 307.2,480 L0,480 Z M0,480M0,275.2 L0,172.8 L 512,172.8 L 512,275.2 L0,275.2 Z M0,275.2M0,70.4 L0-32 L 204.8-32 L 204.8,70.4 L0,70.4 Z M0,70.4M 307.2,70.4 L 307.2-32 L 512-32 L 512,70.4 L 307.2,70.4 Z M 307.2,70.4M 409.6,480 L 409.6,377.6 L 512,377.6 L 512,480 L 409.6,480 Z M 409.6,480"  />
+<glyph unicode="&#x20;" horiz-adv-x="256" />
+</font></defs></svg>
\ No newline at end of file
diff --git a/themes/sean-steam/static/fonts/icons.ttf b/themes/sean-steam/static/fonts/icons.ttf
new file mode 100644
index 0000000..12b2476
Binary files /dev/null and b/themes/sean-steam/static/fonts/icons.ttf differ
diff --git a/themes/sean-steam/static/fonts/icons.woff b/themes/sean-steam/static/fonts/icons.woff
new file mode 100644
index 0000000..0127877
Binary files /dev/null and b/themes/sean-steam/static/fonts/icons.woff differ
diff --git a/themes/sean-steam/static/img/appletouchicon.png b/themes/sean-steam/static/img/appletouchicon.png
new file mode 100644
index 0000000..a75d62b
Binary files /dev/null and b/themes/sean-steam/static/img/appletouchicon.png differ
diff --git a/themes/sean-steam/static/img/avatar.jpg b/themes/sean-steam/static/img/avatar.jpg
new file mode 100644
index 0000000..85e0e52
Binary files /dev/null and b/themes/sean-steam/static/img/avatar.jpg differ
diff --git a/themes/sean-steam/static/img/favicon.ico b/themes/sean-steam/static/img/favicon.ico
new file mode 100644
index 0000000..e3a367e
Binary files /dev/null and b/themes/sean-steam/static/img/favicon.ico differ
diff --git a/themes/sean-steam/static/js/index.js b/themes/sean-steam/static/js/index.js
new file mode 100644
index 0000000..0ef2bb9
--- /dev/null
+++ b/themes/sean-steam/static/js/index.js
@@ -0,0 +1,18 @@
+/**
+ * Main JS file for Casper behaviours
+ */
+
+/*globals jQuery, document */
+(function ($) {
+    "use strict";
+
+    $(document).ready(function(){
+
+        // On the home page, move the blog icon inside the header 
+        // for better relative/absolute positioning.
+
+        //$("#blog-logo").prependTo("#site-head-content");
+
+    });
+
+}(jQuery));
\ No newline at end of file
diff --git a/themes/sean-steam/static/js/smooth-scroll.min.js b/themes/sean-steam/static/js/smooth-scroll.min.js
new file mode 100644
index 0000000..972f76b
--- /dev/null
+++ b/themes/sean-steam/static/js/smooth-scroll.min.js
@@ -0,0 +1,2 @@
+/** smooth-scroll v7.0.2, by Chris Ferdinandi | http://github.com/cferdinandi/smooth-scroll | Licensed under MIT: http://gomakethings.com/mit/ */
+!function(t,e){"function"==typeof define&&define.amd?define([],e(t)):"object"==typeof exports?module.exports=e(t):t.smoothScroll=e(t)}("undefined"!=typeof global?global:this.window||this.global,function(t){"use strict";var e,n,o,r,a={},u=!!t.document.querySelector&&!!t.addEventListener,c={speed:500,easing:"easeInOutCubic",offset:0,updateURL:!0,callback:function(){}},i=function(){var t={},e=!1,n=0,o=arguments.length;"[object Boolean]"===Object.prototype.toString.call(arguments[0])&&(e=arg [...]
\ No newline at end of file
diff --git a/themes/sean-steam/theme.toml b/themes/sean-steam/theme.toml
new file mode 100644
index 0000000..a47fc76
--- /dev/null
+++ b/themes/sean-steam/theme.toml
@@ -0,0 +1,24 @@
+name = "SeanSteam"
+license = "MIT"
+licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE.md"
+description = "A minimal theme for bloggers."
+homepage = "//github.com/digitalcraftsman/hugo-steam-theme"
+tags = ["google analytics", "disqus", "blog", "minimal"]
+features = []
+min_version = 0.16
+
+[author]
+  name = "Digitalcraftsman"
+  homepage = "//github.com/digitalcraftsman/"
+
+# Author who used the Vapor theme as foundation for Steam
+[[original]]
+  name = "Tommaso Barbato"
+  homepage = "//torb.at/"
+  repo = "//github.com/epistrephein/Steam"
+
+# Original creator of the Vapor theme
+[[original]]
+  name = "Seth Lilly"
+  homepage = "//www.sethlilly.com/"
+  repo = "//github.com/sethlilly/Vapor"