diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..00f42c8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+/target
+/lib
+/classes
+/checkouts
+pom.xml
+dev-config.edn
+test-config.edn
+*.jar
+*.class
+/.lein-*
+profiles.clj
+/.env
+.nrepl-port
+/log
diff --git a/Capstanfile b/Capstanfile
new file mode 100644
index 0000000..c8d381a
--- /dev/null
+++ b/Capstanfile
@@ -0,0 +1,28 @@
+
+#
+# Name of the base image. Capstan will download this automatically from
+# Cloudius S3 repository.
+#
+#base: cloudius/osv
+base: cloudius/osv-openjdk8
+
+#
+# The command line passed to OSv to start up the application.
+#
+cmdline: /java.so -jar /ireadit/app.jar
+
+#
+# The command to use to build the application.
+# You can use any build tool/command (make/rake/lein/boot) - this runs locally on your machine
+#
+# For Leiningen, you can use:
+#build: lein uberjar
+# For Boot, you can use:
+#build: boot build
+
+#
+# List of files that are included in the generated image.
+#
+files:
+  /ireadit/app.jar: ./target/uberjar/ireadit.jar
+
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..5d8ded1
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,7 @@
+FROM openjdk:8-alpine
+
+COPY target/uberjar/ireadit.jar /ireadit/app.jar
+
+EXPOSE 3000
+
+CMD ["java", "-jar", "/ireadit/app.jar"]
diff --git a/Procfile b/Procfile
new file mode 100644
index 0000000..c32c812
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+web: java -cp target/uberjar/ireadit.jar clojure.main -m ireadit.core
diff --git a/env/dev/clj/ireadit/dev_middleware.clj b/env/dev/clj/ireadit/dev_middleware.clj
new file mode 100644
index 0000000..b577fe1
--- /dev/null
+++ b/env/dev/clj/ireadit/dev_middleware.clj
@@ -0,0 +1,10 @@
+(ns ireadit.dev-middleware
+  (:require [ring.middleware.reload :refer [wrap-reload]]
+            [selmer.middleware :refer [wrap-error-page]]
+            [prone.middleware :refer [wrap-exceptions]]))
+
+(defn wrap-dev [handler]
+  (-> handler
+      wrap-reload
+      wrap-error-page
+      (wrap-exceptions {:app-namespaces ['ireadit]})))
diff --git a/env/dev/clj/ireadit/env.clj b/env/dev/clj/ireadit/env.clj
new file mode 100644
index 0000000..7391f78
--- /dev/null
+++ b/env/dev/clj/ireadit/env.clj
@@ -0,0 +1,14 @@
+(ns ireadit.env
+  (:require [selmer.parser :as parser]
+            [clojure.tools.logging :as log]
+            [ireadit.dev-middleware :refer [wrap-dev]]))
+
+(def defaults
+  {:init
+   (fn []
+     (parser/cache-off!)
+     (log/info "\n-=[ireadit started successfully using the development profile]=-"))
+   :stop
+   (fn []
+     (log/info "\n-=[ireadit has shut down successfully]=-"))
+   :middleware wrap-dev})
diff --git a/env/dev/clj/ireadit/figwheel.clj b/env/dev/clj/ireadit/figwheel.clj
new file mode 100644
index 0000000..3730e5b
--- /dev/null
+++ b/env/dev/clj/ireadit/figwheel.clj
@@ -0,0 +1,12 @@
+(ns ireadit.figwheel
+  (:require [figwheel-sidecar.repl-api :as ra]))
+
+(defn start-fw []
+  (ra/start-figwheel!))
+
+(defn stop-fw []
+  (ra/stop-figwheel!))
+
+(defn cljs []
+  (ra/cljs-repl))
+
diff --git a/env/dev/clj/user.clj b/env/dev/clj/user.clj
new file mode 100644
index 0000000..273168e
--- /dev/null
+++ b/env/dev/clj/user.clj
@@ -0,0 +1,21 @@
+(ns user
+  (:require [ireadit.config :refer [env]]
+            [clojure.spec.alpha :as s]
+            [expound.alpha :as expound]
+            [mount.core :as mount]
+            [ireadit.figwheel :refer [start-fw stop-fw cljs]]
+            [ireadit.core :refer [start-app]]))
+
+(alter-var-root #'s/*explain-out* (constantly expound/printer))
+
+(defn start []
+  (mount/start-without #'ireadit.core/repl-server))
+
+(defn stop []
+  (mount/stop-except #'ireadit.core/repl-server))
+
+(defn restart []
+  (stop)
+  (start))
+
+
diff --git a/env/dev/cljs/ireadit/app.cljs b/env/dev/cljs/ireadit/app.cljs
new file mode 100644
index 0000000..b8dcc16
--- /dev/null
+++ b/env/dev/cljs/ireadit/app.cljs
@@ -0,0 +1,13 @@
+(ns ^:figwheel-no-load ireadit.app
+  (:require [ireadit.core :as core]
+            [cljs.spec.alpha :as s]
+            [expound.alpha :as expound]
+            [devtools.core :as devtools]))
+
+(set! s/*explain-out* expound/printer)
+
+(enable-console-print!)
+
+(devtools/install!)
+
+(core/init!)
diff --git a/env/dev/resources/config.edn b/env/dev/resources/config.edn
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/env/dev/resources/config.edn
@@ -0,0 +1 @@
+{}
diff --git a/env/dev/resources/logback.xml b/env/dev/resources/logback.xml
new file mode 100644
index 0000000..abe207e
--- /dev/null
+++ b/env/dev/resources/logback.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+    <statusListener class="ch.qos.logback.core.status.NopStatusListener" />
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <!-- encoders are assigned the type
+             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+        <encoder>
+            <charset>UTF-8</charset>
+            <pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg %n</pattern>
+        </encoder>
+    </appender>
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>log/ireadit.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>log/ireadit.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!-- keep 30 days of history -->
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <charset>UTF-8</charset>
+            <pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg %n</pattern>
+        </encoder>
+    </appender>
+    <logger name="org.apache.http" level="warn" />
+    <logger name="org.xnio.nio" level="warn" />
+    <logger name="io.undertow.session" level="warn" />
+    <logger name="io.undertow.request" level="warn" />
+    <root level="DEBUG">
+        <appender-ref ref="STDOUT" />
+        <appender-ref ref="FILE" />
+    </root>
+</configuration>
diff --git a/env/prod/clj/ireadit/env.clj b/env/prod/clj/ireadit/env.clj
new file mode 100644
index 0000000..3328e4a
--- /dev/null
+++ b/env/prod/clj/ireadit/env.clj
@@ -0,0 +1,11 @@
+(ns ireadit.env
+  (:require [clojure.tools.logging :as log]))
+
+(def defaults
+  {:init
+   (fn []
+     (log/info "\n-=[ireadit started successfully]=-"))
+   :stop
+   (fn []
+     (log/info "\n-=[ireadit has shut down successfully]=-"))
+   :middleware identity})
diff --git a/env/prod/cljs/ireadit/app.cljs b/env/prod/cljs/ireadit/app.cljs
new file mode 100644
index 0000000..16bcb92
--- /dev/null
+++ b/env/prod/cljs/ireadit/app.cljs
@@ -0,0 +1,7 @@
+(ns ireadit.app
+  (:require [ireadit.core :as core]))
+
+;;ignore println statements in prod
+(set! *print-fn* (fn [& _]))
+
+(core/init!)
diff --git a/env/prod/resources/config.edn b/env/prod/resources/config.edn
new file mode 100644
index 0000000..e24ec21
--- /dev/null
+++ b/env/prod/resources/config.edn
@@ -0,0 +1,2 @@
+{:prod true
+ :port 3000}
diff --git a/env/prod/resources/logback.xml b/env/prod/resources/logback.xml
new file mode 100644
index 0000000..fd95528
--- /dev/null
+++ b/env/prod/resources/logback.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+    <statusListener class="ch.qos.logback.core.status.NopStatusListener" />
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>log/ireadit.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>log/ireadit.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!-- keep 30 days of history -->
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <charset>UTF-8</charset>
+            <pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg %n</pattern>
+        </encoder>
+    </appender>
+    <logger name="org.apache.http" level="warn" />
+    <logger name="org.xnio.nio" level="warn" />
+    <root level="INFO">
+        <appender-ref ref="FILE" />
+    </root>
+</configuration>
diff --git a/env/test/resources/config.edn b/env/test/resources/config.edn
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/env/test/resources/config.edn
@@ -0,0 +1 @@
+{}
diff --git a/env/test/resources/logback.xml b/env/test/resources/logback.xml
new file mode 100644
index 0000000..abe207e
--- /dev/null
+++ b/env/test/resources/logback.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="10 seconds">
+    <statusListener class="ch.qos.logback.core.status.NopStatusListener" />
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <!-- encoders are assigned the type
+             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+        <encoder>
+            <charset>UTF-8</charset>
+            <pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg %n</pattern>
+        </encoder>
+    </appender>
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>log/ireadit.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>log/ireadit.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!-- keep 30 days of history -->
+            <maxHistory>30</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <charset>UTF-8</charset>
+            <pattern>%date{ISO8601} [%thread] %-5level %logger{36} - %msg %n</pattern>
+        </encoder>
+    </appender>
+    <logger name="org.apache.http" level="warn" />
+    <logger name="org.xnio.nio" level="warn" />
+    <logger name="io.undertow.session" level="warn" />
+    <logger name="io.undertow.request" level="warn" />
+    <root level="DEBUG">
+        <appender-ref ref="STDOUT" />
+        <appender-ref ref="FILE" />
+    </root>
+</configuration>
diff --git a/project.clj b/project.clj
new file mode 100644
index 0000000..4d35bf4
--- /dev/null
+++ b/project.clj
@@ -0,0 +1,142 @@
+(defproject ireadit "0.1.0-SNAPSHOT"
+
+  :description "FIXME: write description"
+  :url "http://example.com/FIXME"
+
+  :dependencies [[baking-soda "0.2.0" :exclusions [cljsjs/react-bootstrap]]
+                 [cheshire "5.8.1"]
+                 [clj-commons/secretary "1.2.4"]
+                 [clj-oauth "1.5.5"]
+                 [cljs-ajax "0.8.0"]
+                 [cljsjs/react-popper "0.10.4-0"]
+                 [cljsjs/react-transition-group "2.4.0-0"]
+                 [clojure.java-time "0.3.2"]
+                 [com.cognitect/transit-clj "0.8.313"]
+                 [compojure "1.6.1"]
+                 [cprop "0.1.13"]
+                 [day8.re-frame/http-fx "0.1.6"]
+                 [funcool/struct "1.3.0"]
+                 [luminus-immutant "0.2.5"]
+                 [luminus-transit "0.1.1"]
+                 [luminus/ring-ttl-session "0.3.2"]
+                 [markdown-clj "1.0.7"]
+                 [metosin/compojure-api "2.0.0-alpha28"]
+                 [metosin/muuntaja "0.6.3"]
+                 [metosin/ring-http-response "0.9.1"]
+                 [mount "0.1.16"]
+                 [nrepl "0.6.0"]
+                 [org.clojure/clojure "1.10.0"]
+                 [org.clojure/clojurescript "1.10.520" :scope "provided"]
+                 [org.clojure/tools.cli "0.4.1"]
+                 [org.clojure/tools.logging "0.4.1"]
+                 [org.webjars.bower/tether "1.4.4"]
+                 [org.webjars/bootstrap "4.2.1"]
+                 [org.webjars/font-awesome "5.7.1"]
+                 [org.webjars/webjars-locator "0.36"]
+                 [re-frame "0.10.6"]
+                 [reagent "0.8.1"]
+                 [ring-webjars "0.2.0"]
+                 [ring/ring-core "1.7.1"]
+                 [ring/ring-defaults "0.3.2"]
+                 [selmer "1.12.6"]]
+
+  :min-lein-version "2.0.0"
+  
+  :source-paths ["src/clj" "src/cljs" "src/cljc"]
+  :test-paths ["test/clj"]
+  :resource-paths ["resources" "target/cljsbuild"]
+  :target-path "target/%s/"
+  :main ^:skip-aot ireadit.core
+
+  :plugins [[lein-cljsbuild "1.1.7"]
+            [lein-immutant "2.1.0"]]
+  :clean-targets ^{:protect false}
+  [:target-path [:cljsbuild :builds :app :compiler :output-dir] [:cljsbuild :builds :app :compiler :output-to]]
+  :figwheel
+  {:http-server-root "public"
+   :server-logfile "log/figwheel-logfile.log"
+   :nrepl-port 7002
+   :css-dirs ["resources/public/css"]
+   :nrepl-middleware [cider.piggieback/wrap-cljs-repl]}
+  
+
+  :profiles
+  {:uberjar {:omit-source true
+             :prep-tasks ["compile" ["cljsbuild" "once" "min"]]
+             :cljsbuild
+             {:builds
+              {:min
+               {:source-paths ["src/cljc" "src/cljs" "env/prod/cljs"]
+                :compiler
+                {:output-dir "target/cljsbuild/public/js"
+                 :output-to "target/cljsbuild/public/js/app.js"
+                 :source-map "target/cljsbuild/public/js/app.js.map"
+                 :optimizations :advanced
+                 :pretty-print false
+                 :infer-externs true
+                 :closure-warnings
+                 {:externs-validation :off :non-standard-jsdoc :off}
+                 :externs ["react/externs/react.js"]}}}}
+             
+             
+             :aot :all
+             :uberjar-name "ireadit.jar"
+             :source-paths ["env/prod/clj"]
+             :resource-paths ["env/prod/resources"]}
+
+   :dev           [:project/dev :profiles/dev]
+   :test          [:project/dev :project/test :profiles/test]
+
+   :project/dev  {:jvm-opts ["-Dconf=dev-config.edn"]
+                  :dependencies [[binaryage/devtools "0.9.10"]
+                                 [cider/piggieback "0.4.0"]
+                                 [doo "0.1.11"]
+                                 [expound "0.7.2"]
+                                 [figwheel-sidecar "0.5.18"]
+                                 [pjstadig/humane-test-output "0.9.0"]
+                                 [prone "1.6.1"]
+                                 [re-frisk "0.5.4"]
+                                 [ring/ring-devel "1.7.1"]
+                                 [ring/ring-mock "0.3.2"]]
+                  :plugins      [[com.jakemccrary/lein-test-refresh "0.23.0"]
+                                 [lein-doo "0.1.11"]
+                                 [lein-figwheel "0.5.18"]]
+                  :cljsbuild
+                  {:builds
+                   {:app
+                    {:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"]
+                     :figwheel {:on-jsload "ireadit.core/mount-components"}
+                     :compiler
+                     {:main "ireadit.app"
+                      :asset-path "/js/out"
+                      :output-to "target/cljsbuild/public/js/app.js"
+                      :output-dir "target/cljsbuild/public/js/out"
+                      :source-map true
+                      :optimizations :none
+                      :pretty-print true
+                      :closure-defines {"re_frame.trace.trace_enabled_QMARK_" true}
+                      :preloads [re-frisk.preload]}}}}
+                  
+                  
+                  
+                  :doo {:build "test"}
+                  :source-paths ["env/dev/clj"]
+                  :resource-paths ["env/dev/resources"]
+                  :repl-options {:init-ns user}
+                  :injections [(require 'pjstadig.humane-test-output)
+                               (pjstadig.humane-test-output/activate!)]}
+   :project/test {:jvm-opts ["-Dconf=test-config.edn"]
+                  :resource-paths ["env/test/resources"]
+                  :cljsbuild
+                  {:builds
+                   {:test
+                    {:source-paths ["src/cljc" "src/cljs" "test/cljs"]
+                     :compiler
+                     {:output-to "target/test.js"
+                      :main "ireadit.doo-runner"
+                      :optimizations :whitespace
+                      :pretty-print true}}}}
+                  
+                  }
+   :profiles/dev {}
+   :profiles/test {}})
diff --git a/resources/docs/docs.md b/resources/docs/docs.md
new file mode 100644
index 0000000..2a81d92
--- /dev/null
+++ b/resources/docs/docs.md
@@ -0,0 +1,82 @@
+<h2 class="alert alert-success">Congratulations, your <a class="alert-link" href="http://luminusweb.net">Luminus</a> site is ready!</h2>
+
+This page will help guide you through the first steps of building your site.
+
+#### Why are you seeing this page?
+
+The `home-routes` handler in the `ireadit.routes.home` namespace
+defines the route that invokes the `home-page` function whenever an HTTP
+request is made to the `/` URI using the `GET` method.
+
+```
+(defroutes home-routes
+  (GET "/" []
+       (home-page))
+  (GET "/docs" []
+       (-> (response/ok (-> "docs/docs.md" io/resource slurp))
+           (response/header "Content-Type" "text/plain; charset=utf-8"))))
+```
+
+The `home-page` function will in turn call the `ireadit.layout/render` function
+to render the HTML content:
+
+```
+(defn home-page []
+  (layout/render "home.html"))
+```
+
+The page contains a link to the compiled ClojureScript found in the `target/cljsbuild/public` folder:
+
+```
+{% script "/js/app.js" %}
+```
+
+The rest of this page is rendered by ClojureScript found in the `src/cljs/ireadit/core.cljs` file.
+
+
+
+#### Organizing the routes
+
+The routes are aggregated and wrapped with middleware in the `ireadit.handler` namespace:
+
+```
+(defstate app
+  :start
+  (middleware/wrap-base
+    (routes
+      (-> #'home-routes
+          (wrap-routes middleware/wrap-csrf)
+          (wrap-routes middleware/wrap-formats))
+      (route/not-found
+        (:body
+          (error-page {:status 404
+                       :title "page not found"}))))))
+```
+
+The `app` definition groups all the routes in the application into a single handler.
+A default route group is added to handle the `404` case.
+
+<a class="btn btn-primary" href="http://www.luminusweb.net/docs/routes.md">learn more about routing »</a>
+
+The `home-routes` are wrapped with two middleware functions. The first enables CSRF protection.
+The second takes care of serializing and deserializing various encoding formats, such as JSON.
+
+#### Managing your middleware
+
+Request middleware functions are located under the `ireadit.middleware` namespace.
+
+This namespace is reserved for any custom middleware for the application. Some default middleware is
+already defined here. The middleware is assembled in the `wrap-base` function.
+
+Middleware used for development is placed in the `ireadit.dev-middleware` namespace found in
+the `env/dev/clj/` source path.
+
+<a class="btn btn-primary" href="http://www.luminusweb.net/docs/middleware.md">learn more about middleware »</a>
+
+
+
+
+#### Need some help?
+
+Visit the [official documentation](http://www.luminusweb.net/docs) for examples
+on how to accomplish common tasks with Luminus. The `#luminus` channel on the [Clojurians Slack](http://clojurians.net/) and [Google Group](https://groups.google.com/forum/#!forum/luminusweb) are both great places to seek help and discuss projects with other users.
diff --git a/resources/html/error.html b/resources/html/error.html
new file mode 100644
index 0000000..31dd41d
--- /dev/null
+++ b/resources/html/error.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Something bad happened</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    {% style "/assets/bootstrap/css/bootstrap.min.css" %}    
+    <style type="text/css">
+        html {
+            height: 100%;
+            min-height: 100%;
+            min-width: 100%;
+            overflow: hidden;
+            width: 100%;
+        }
+        html body {
+            height: 100%;
+            margin: 0;
+            padding: 0;
+            width: 100%;
+        }
+        html .container-fluid {
+            display: table;
+            height: 100%;
+            padding: 0;
+            width: 100%;
+        }
+        html .row-fluid {
+            display: table-cell;
+            height: 100%;
+            vertical-align: middle;
+        }
+    </style>
+</head>
+<body>
+<div class="container-fluid">
+    <div class="row-fluid">
+        <div class="col-lg-12">
+            <div class="centering text-center">
+                <div class="text-center">
+                    <h1><span class="text-danger">Error: {{status}}</span></h1>
+                    <hr>
+                    {% if title %}
+                    <h2 class="without-margin">{{title}}</h2>
+                    {% endif %}
+                    {% if message %}
+                    <h4 class="text-danger">{{message}}</h4>
+                    {% endif %}
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+</body>
+</html>
diff --git a/resources/html/home.html b/resources/html/home.html
new file mode 100644
index 0000000..9b20b69
--- /dev/null
+++ b/resources/html/home.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+  <head>
+      <meta charset="UTF-8"/>
+      <meta name="viewport" content="width=device-width, initial-scale=1">
+      <title>Welcome to ireadit</title>
+  </head>
+  <body>
+    
+    <div id="app">
+      <div class="container-fluid">
+        <div class="card-deck">
+          <div class="card-block">
+            <h4>Welcome to ireadit</h4>
+            <p>If you're seeing this message, that means you haven't yet compiled your ClojureScript!</p>
+            <p>Please run <code>lein figwheel</code> to start the ClojureScript compiler and reload the page.</p>
+            <h4>For better ClojureScript development experience in Chrome follow these steps:</h4>
+            <ul>
+              <li>Open DevTools
+              <li>Go to Settings ("three dots" icon in the upper right corner of DevTools > Menu > Settings F1 > General > Console)
+              <li>Check-in "Enable custom formatters"
+              <li>Close DevTools
+              <li>Open DevTools
+            </ul>
+            <p>See <a href="http://www.luminusweb.net/docs/clojurescript.md">ClojureScript</a> documentation for further details.</p>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- scripts and styles -->
+    {% style "/assets/bootstrap/css/bootstrap.min.css" %}
+    {% style "/assets/font-awesome/css/all.css" %}
+    {% style "/css/screen.css" %}
+
+    {% script "/assets/jquery/jquery.min.js" %}
+    {% script "/assets/font-awesome/js/all.js" %}
+    {% script "/assets/tether/dist/js/tether.min.js" %}
+    {% script "/assets/bootstrap/js/bootstrap.min.js" %}
+
+    <script type="text/javascript">
+        var csrfToken = "{{csrf-token}}";
+    </script>
+    {% script "/js/app.js" %}
+  </body>
+</html>
diff --git a/resources/public/css/screen.css b/resources/public/css/screen.css
new file mode 100644
index 0000000..c64d9c0
--- /dev/null
+++ b/resources/public/css/screen.css
@@ -0,0 +1,9 @@
+html,
+body {
+	font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+    height: 100%;
+}
+nav {
+    margin-bottom: 20px;
+}
+
diff --git a/resources/public/favicon.ico b/resources/public/favicon.ico
new file mode 100644
index 0000000..0e50cb2
Binary files /dev/null and b/resources/public/favicon.ico differ
diff --git a/resources/public/img/warning_clojure.png b/resources/public/img/warning_clojure.png
new file mode 100644
index 0000000..78d59e9
Binary files /dev/null and b/resources/public/img/warning_clojure.png differ
diff --git a/src/clj/ireadit/config.clj b/src/clj/ireadit/config.clj
new file mode 100644
index 0000000..d3cb471
--- /dev/null
+++ b/src/clj/ireadit/config.clj
@@ -0,0 +1,12 @@
+(ns ireadit.config
+  (:require [cprop.core :refer [load-config]]
+            [cprop.source :as source]
+            [mount.core :refer [args defstate]]))
+
+(defstate env
+  :start
+  (load-config
+    :merge
+    [(args)
+     (source/from-system-props)
+     (source/from-env)]))
diff --git a/src/clj/ireadit/core.clj b/src/clj/ireadit/core.clj
new file mode 100644
index 0000000..0e1a3c4
--- /dev/null
+++ b/src/clj/ireadit/core.clj
@@ -0,0 +1,49 @@
+(ns ireadit.core
+  (:require [ireadit.handler :as handler]
+            [ireadit.nrepl :as nrepl]
+            [luminus.http-server :as http]
+            [ireadit.config :refer [env]]
+            [clojure.tools.cli :refer [parse-opts]]
+            [clojure.tools.logging :as log]
+            [mount.core :as mount])
+  (:gen-class))
+
+(def cli-options
+  [["-p" "--port PORT" "Port number"
+    :parse-fn #(Integer/parseInt %)]])
+
+(mount/defstate ^{:on-reload :noop} http-server
+  :start
+  (http/start
+    (-> env
+        (assoc  :handler #'handler/app)
+        (update :io-threads #(or % (* 2 (.availableProcessors (Runtime/getRuntime)))))
+        (update :port #(or (-> env :options :port) %))))
+  :stop
+  (http/stop http-server))
+
+(mount/defstate ^{:on-reload :noop} repl-server
+  :start
+  (when (env :nrepl-port)
+    (nrepl/start {:bind (env :nrepl-bind)
+                  :port (env :nrepl-port)}))
+  :stop
+  (when repl-server
+    (nrepl/stop repl-server)))
+
+
+(defn stop-app []
+  (doseq [component (:stopped (mount/stop))]
+    (log/info component "stopped"))
+  (shutdown-agents))
+
+(defn start-app [args]
+  (doseq [component (-> args
+                        (parse-opts cli-options)
+                        mount/start-with-args
+                        :started)]
+    (log/info component "started"))
+  (.addShutdownHook (Runtime/getRuntime) (Thread. stop-app)))
+
+(defn -main [& args]
+  (start-app args))
diff --git a/src/clj/ireadit/handler.clj b/src/clj/ireadit/handler.clj
new file mode 100644
index 0000000..00f0f41
--- /dev/null
+++ b/src/clj/ireadit/handler.clj
@@ -0,0 +1,30 @@
+(ns ireadit.handler
+  (:require [ireadit.middleware :as middleware]
+            [ireadit.layout :refer [error-page]]
+            [ireadit.routes.home :refer [home-routes]]
+            [ireadit.routes.services :refer [service-routes]]
+            [ireadit.routes.oauth :refer [oauth-routes]]
+            [compojure.core :refer [routes wrap-routes]]
+            [ring.util.http-response :as response]
+            [compojure.route :as route]
+            [ireadit.env :refer [defaults]]
+            [mount.core :as mount]))
+
+(mount/defstate init-app
+  :start ((or (:init defaults) identity))
+  :stop  ((or (:stop defaults) identity)))
+
+(mount/defstate app
+  :start
+  (middleware/wrap-base
+    (routes
+      (-> #'home-routes
+          (wrap-routes middleware/wrap-csrf)
+          (wrap-routes middleware/wrap-formats))
+      #'oauth-routes
+      #'service-routes
+      (route/not-found
+        (:body
+          (error-page {:status 404
+                       :title "page not found"}))))))
+
diff --git a/src/clj/ireadit/layout.clj b/src/clj/ireadit/layout.clj
new file mode 100644
index 0000000..f0ba9ce
--- /dev/null
+++ b/src/clj/ireadit/layout.clj
@@ -0,0 +1,37 @@
+(ns ireadit.layout
+  (:require [selmer.parser :as parser]
+            [selmer.filters :as filters]
+            [markdown.core :refer [md-to-html-string]]
+            [ring.util.http-response :refer [content-type ok]]
+            [ring.util.anti-forgery :refer [anti-forgery-field]]
+            [ring.middleware.anti-forgery :refer [*anti-forgery-token*]]))
+
+
+(parser/set-resource-path!  (clojure.java.io/resource "html"))
+(parser/add-tag! :csrf-field (fn [_ _] (anti-forgery-field)))
+(filters/add-filter! :markdown (fn [content] [:safe (md-to-html-string content)]))
+
+(defn render
+  "renders the HTML template located relative to resources/html"
+  [template & [params]]
+  (content-type
+    (ok
+      (parser/render-file
+        template
+        (assoc params
+          :page template
+          :csrf-token *anti-forgery-token*)))
+    "text/html; charset=utf-8"))
+
+(defn error-page
+  "error-details should be a map containing the following keys:
+   :status - error status
+   :title - error title (optional)
+   :message - detailed error message (optional)
+
+   returns a response map with the error page as the body
+   and the status specified by the status key"
+  [error-details]
+  {:status  (:status error-details)
+   :headers {"Content-Type" "text/html; charset=utf-8"}
+   :body    (parser/render-file "error.html" error-details)})
diff --git a/src/clj/ireadit/middleware.clj b/src/clj/ireadit/middleware.clj
new file mode 100644
index 0000000..3c9d54e
--- /dev/null
+++ b/src/clj/ireadit/middleware.clj
@@ -0,0 +1,53 @@
+(ns ireadit.middleware
+  (:require [ireadit.env :refer [defaults]]
+            [cheshire.generate :as cheshire]
+            [cognitect.transit :as transit]
+            [clojure.tools.logging :as log]
+            [ireadit.layout :refer [error-page]]
+            [ring.middleware.anti-forgery :refer [wrap-anti-forgery]]
+            [ring.middleware.webjars :refer [wrap-webjars]]
+            [ireadit.middleware.formats :as formats]
+            [muuntaja.middleware :refer [wrap-format wrap-params]]
+            [ireadit.config :refer [env]]
+            [ring.middleware.flash :refer [wrap-flash]]
+            [immutant.web.middleware :refer [wrap-session]]
+            [ring.middleware.defaults :refer [site-defaults wrap-defaults]])
+  (:import 
+           ))
+
+(defn wrap-internal-error [handler]
+  (fn [req]
+    (try
+      (handler req)
+      (catch Throwable t
+        (log/error t (.getMessage t))
+        (error-page {:status 500
+                     :title "Something very bad has happened!"
+                     :message "We've dispatched a team of highly trained gnomes to take care of the problem."})))))
+
+(defn wrap-csrf [handler]
+  (wrap-anti-forgery
+    handler
+    {:error-response
+     (error-page
+       {:status 403
+        :title "Invalid anti-forgery token"})}))
+
+
+(defn wrap-formats [handler]
+  (let [wrapped (-> handler wrap-params (wrap-format formats/instance))]
+    (fn [request]
+      ;; disable wrap-formats for websockets
+      ;; since they're not compatible with this middleware
+      ((if (:websocket? request) handler wrapped) request))))
+
+(defn wrap-base [handler]
+  (-> ((:middleware defaults) handler)
+      wrap-webjars
+      wrap-flash
+      (wrap-session {:cookie-attrs {:http-only true}})
+      (wrap-defaults
+        (-> site-defaults
+            (assoc-in [:security :anti-forgery] false)
+            (dissoc :session)))
+      wrap-internal-error))
diff --git a/src/clj/ireadit/middleware/formats.clj b/src/clj/ireadit/middleware/formats.clj
new file mode 100644
index 0000000..1b6facc
--- /dev/null
+++ b/src/clj/ireadit/middleware/formats.clj
@@ -0,0 +1,14 @@
+(ns ireadit.middleware.formats
+  (:require [cognitect.transit :as transit]
+            [luminus-transit.time :as time]
+            [muuntaja.core :as m]))
+
+(def instance
+  (m/create
+    (-> m/default-options
+        (update-in
+          [:formats "application/transit+json" :decoder-opts]
+          (partial merge time/time-deserialization-handlers))
+        (update-in
+          [:formats "application/transit+json" :encoder-opts]
+          (partial merge time/time-serialization-handlers)))))
diff --git a/src/clj/ireadit/nrepl.clj b/src/clj/ireadit/nrepl.clj
new file mode 100644
index 0000000..0ad85db
--- /dev/null
+++ b/src/clj/ireadit/nrepl.clj
@@ -0,0 +1,26 @@
+(ns ireadit.nrepl
+  (:require [nrepl.server :as nrepl]
+            [clojure.tools.logging :as log]))
+
+(defn start
+  "Start a network repl for debugging on specified port followed by
+  an optional parameters map. The :bind, :transport-fn, :handler,
+  :ack-port and :greeting-fn will be forwarded to
+  clojure.tools.nrepl.server/start-server as they are."
+  [{:keys [port bind transport-fn handler ack-port greeting-fn]}]
+  (try
+    (log/info "starting nREPL server on port" port)
+    (nrepl/start-server :port port
+                        :bind bind
+                        :transport-fn transport-fn
+                        :handler handler
+                        :ack-port ack-port
+                        :greeting-fn greeting-fn)
+
+    (catch Throwable t
+      (log/error t "failed to start nREPL")
+      (throw t))))
+
+(defn stop [server]
+  (nrepl/stop-server server)
+  (log/info "nREPL server stopped"))
diff --git a/src/clj/ireadit/oauth.clj b/src/clj/ireadit/oauth.clj
new file mode 100644
index 0000000..6102f62
--- /dev/null
+++ b/src/clj/ireadit/oauth.clj
@@ -0,0 +1,35 @@
+(ns ireadit.oauth
+  (:require [ireadit.config :refer [env]]
+            [oauth.client :as oauth]
+            [mount.core :refer [defstate]]
+            [clojure.tools.logging :as log]))
+
+(defstate consumer
+  :start (oauth/make-consumer
+           (env :oauth-consumer-key)
+           (env :oauth-consumer-secret)
+           (env :request-token-uri)
+           (env :access-token-uri)
+           (env :authorize-uri)
+           :hmac-sha1))
+
+(defn oauth-callback-uri
+  "Generates the oauth request callback URI"
+  [{:keys [headers]}]
+  (str (headers "x-forwarded-proto") "://" (headers "host") "/oauth/oauth-callback"))
+
+(defn fetch-request-token
+  "Fetches a request token."
+  [request]
+  (let [callback-uri (oauth-callback-uri request)]
+    (log/info "Fetching request token using callback-uri" callback-uri)
+    (oauth/request-token consumer (oauth-callback-uri request))))
+
+(defn fetch-access-token
+  [request_token]
+  (oauth/access-token consumer request_token (:oauth_verifier request_token)))
+
+(defn auth-redirect-uri
+  "Gets the URI the user should be redirected to when authenticating."
+  [request-token]
+  (str (oauth/user-approval-uri consumer request-token)))
diff --git a/src/clj/ireadit/routes/home.clj b/src/clj/ireadit/routes/home.clj
new file mode 100644
index 0000000..fcbf44d
--- /dev/null
+++ b/src/clj/ireadit/routes/home.clj
@@ -0,0 +1,16 @@
+(ns ireadit.routes.home
+  (:require [ireadit.layout :as layout]
+            [compojure.core :refer [defroutes GET]]
+            [ring.util.http-response :as response]
+            [clojure.java.io :as io]))
+
+(defn home-page []
+  (layout/render "home.html"))
+
+(defroutes home-routes
+  (GET "/" []
+       (home-page))
+  (GET "/docs" []
+       (-> (response/ok (-> "docs/docs.md" io/resource slurp))
+           (response/header "Content-Type" "text/plain; charset=utf-8"))))
+
diff --git a/src/clj/ireadit/routes/oauth.clj b/src/clj/ireadit/routes/oauth.clj
new file mode 100644
index 0000000..1498cc1
--- /dev/null
+++ b/src/clj/ireadit/routes/oauth.clj
@@ -0,0 +1,34 @@
+(ns ireadit.routes.oauth
+  (:require [ring.util.http-response :refer [ok found]]
+            [compojure.core :refer [defroutes GET]]
+            [clojure.java.io :as io]
+            [ireadit.oauth :as oauth]
+            [clojure.tools.logging :as log]))
+
+(defn oauth-init
+  "Initiates the Twitter OAuth"
+  [request]
+  (-> (oauth/fetch-request-token request)
+      :oauth_token
+      oauth/auth-redirect-uri
+      found))
+
+(defn oauth-callback
+  "Handles the callback from Twitter."
+  [{:keys [session params]}]
+  ; oauth request was denied by user
+  (if (:denied params)
+    (-> (found "/")
+        (assoc :flash {:denied true}))
+    ; fetch the request token and do anything else you wanna do if not denied.
+    (let [{:keys [user_id screen_name]} (oauth/fetch-access-token params)]
+      (log/info "successfully authenticated as" user_id screen_name)
+      (-> (found "/")
+          (assoc :session
+            (assoc session :user-id user_id :screen-name screen_name))))))
+
+
+(defroutes oauth-routes
+  (GET "/oauth/oauth-init" req (oauth-init req))
+  (GET "/oauth/oauth-callback" [& req_token :as req] (oauth-callback req)))
+
diff --git a/src/clj/ireadit/routes/services.clj b/src/clj/ireadit/routes/services.clj
new file mode 100644
index 0000000..660d6c6
--- /dev/null
+++ b/src/clj/ireadit/routes/services.clj
@@ -0,0 +1,45 @@
+(ns ireadit.routes.services
+  (:require [ring.util.http-response :refer :all]
+            [compojure.api.sweet :refer :all]
+            [schema.core :as s]))
+
+(def service-routes
+  (api
+    {:swagger {:ui "/swagger-ui"
+               :spec "/swagger.json"
+               :data {:info {:version "1.0.0"
+                             :title "Sample API"
+                             :description "Sample Services"}}}}
+    
+    (context "/api" []
+      :tags ["thingie"]
+      
+      (GET "/plus" []
+        :return       Long
+        :query-params [x :- Long, {y :- Long 1}]
+        :summary      "x+y with query-parameters. y defaults to 1."
+        (ok (+ x y)))
+
+      (POST "/minus" []
+        :return      Long
+        :body-params [x :- Long, y :- Long]
+        :summary     "x-y with body-parameters."
+        (ok (- x y)))
+
+      (GET "/times/:x/:y" []
+        :return      Long
+        :path-params [x :- Long, y :- Long]
+        :summary     "x*y with path-parameters"
+        (ok (* x y)))
+
+      (POST "/divide" []
+        :return      Double
+        :form-params [x :- Long, y :- Long]
+        :summary     "x/y with form-parameters"
+        (ok (/ x y)))
+
+      (GET "/power" []
+        :return      Long
+        :header-params [x :- Long, y :- Long]
+        :summary     "x^y with header-parameters"
+        (ok (long (Math/pow x y)))))))
diff --git a/src/cljc/ireadit/validation.cljc b/src/cljc/ireadit/validation.cljc
new file mode 100644
index 0000000..7848ef0
--- /dev/null
+++ b/src/cljc/ireadit/validation.cljc
@@ -0,0 +1,2 @@
+(ns ireadit.validation
+  (:require [struct.core :as st]))
diff --git a/src/cljs/ireadit/ajax.cljs b/src/cljs/ireadit/ajax.cljs
new file mode 100644
index 0000000..c481c93
--- /dev/null
+++ b/src/cljs/ireadit/ajax.cljs
@@ -0,0 +1,29 @@
+(ns ireadit.ajax
+  (:require [ajax.core :as ajax]
+            [luminus-transit.time :as time]
+            [cognitect.transit :as transit]
+            [re-frame.core :as rf]))
+
+(defn local-uri? [{:keys [uri]}]
+  (not (re-find #"^\w+?://" uri)))
+
+(defn default-headers [request]
+  (if (local-uri? request)
+    (-> request
+        (update :headers #(merge {"x-csrf-token" js/csrfToken} %)))
+    request))
+
+;; injects transit serialization config into request options
+(defn as-transit [opts]
+  (merge {:raw             false
+          :format          :transit
+          :response-format :transit
+          :reader          (transit/reader :json time/time-deserialization-handlers)
+          :writer          (transit/writer :json time/time-serialization-handlers)}
+         opts))
+
+(defn load-interceptors! []
+  (swap! ajax/default-interceptors
+         conj
+         (ajax/to-interceptor {:name "default headers"
+                               :request default-headers})))
diff --git a/src/cljs/ireadit/core.cljs b/src/cljs/ireadit/core.cljs
new file mode 100644
index 0000000..9161c4a
--- /dev/null
+++ b/src/cljs/ireadit/core.cljs
@@ -0,0 +1,94 @@
+(ns ireadit.core
+  (:require [baking-soda.core :as b]
+            [day8.re-frame.http-fx]
+            [reagent.core :as r]
+            [re-frame.core :as rf]
+            [goog.events :as events]
+            [goog.history.EventType :as HistoryEventType]
+            [markdown.core :refer [md->html]]
+            [ireadit.ajax :as ajax]
+            [ireadit.events]
+            [secretary.core :as secretary])
+  (:import goog.History))
+
+; the navbar components are implemented via baking-soda [1]
+; library that provides a ClojureScript interface for Reactstrap [2]
+; Bootstrap 4 components.
+; [1] https://github.com/gadfly361/baking-soda
+; [2] http://reactstrap.github.io/
+
+(defn nav-link [uri title page]
+  [b/NavItem
+   [b/NavLink
+    {:href   uri
+     :active (when (= page @(rf/subscribe [:page])) "active")}
+    title]])
+
+(defn navbar []
+  (r/with-let [expanded? (r/atom true)]
+    [b/Navbar {:light true
+               :class-name "navbar-dark bg-primary"
+               :expand "md"}
+     [b/NavbarBrand {:href "/"} "ireadit"]
+     [b/NavbarToggler {:on-click #(swap! expanded? not)}]
+     [b/Collapse {:is-open @expanded? :navbar true}
+      [b/Nav {:class-name "mr-auto" :navbar true}
+       [nav-link "#/" "Home" :home]
+       [nav-link "#/about" "About" :about]]]]))
+
+(defn about-page []
+  [:div.container
+   [:div.row
+    [:div.col-md-12
+     [:img {:src "/img/warning_clojure.png"}]]]])
+
+(defn home-page []
+  [:div.container
+   (when-let [docs @(rf/subscribe [:docs])]
+     [:div.row>div.col-sm-12
+      [:div {:dangerouslySetInnerHTML
+             {:__html (md->html docs)}}]])])
+
+(def pages
+  {:home #'home-page
+   :about #'about-page})
+
+(defn page []
+  [:div
+   [navbar]
+   [(pages @(rf/subscribe [:page]))]])
+
+;; -------------------------
+;; Routes
+
+(secretary/set-config! :prefix "#")
+
+(secretary/defroute "/" []
+  (rf/dispatch [:navigate :home]))
+
+(secretary/defroute "/about" []
+  (rf/dispatch [:navigate :about]))
+
+;; -------------------------
+;; History
+;; must be called after routes have been defined
+(defn hook-browser-navigation! []
+  (doto (History.)
+    (events/listen
+      HistoryEventType/NAVIGATE
+      (fn [event]
+        (secretary/dispatch! (.-token event))))
+    (.setEnabled true)))
+
+;; -------------------------
+;; Initialize app
+(defn mount-components []
+  (rf/clear-subscription-cache!)
+  (r/render [#'page] (.getElementById js/document "app")))
+
+(defn init! []
+  (rf/dispatch-sync [:navigate :home])
+  (ajax/load-interceptors!)
+  (rf/dispatch [:fetch-docs])
+  (hook-browser-navigation!)
+  (mount-components))
diff --git a/src/cljs/ireadit/events.cljs b/src/cljs/ireadit/events.cljs
new file mode 100644
index 0000000..18b8ef9
--- /dev/null
+++ b/src/cljs/ireadit/events.cljs
@@ -0,0 +1,45 @@
+(ns ireadit.events
+  (:require [re-frame.core :as rf]
+            [ajax.core :as ajax]))
+
+;;dispatchers
+
+(rf/reg-event-db
+  :navigate
+  (fn [db [_ page]]
+    (assoc db :page page)))
+
+(rf/reg-event-db
+  :set-docs
+  (fn [db [_ docs]]
+    (assoc db :docs docs)))
+
+(rf/reg-event-fx
+  :fetch-docs
+  (fn [_ _]
+    {:http-xhrio {:method          :get
+                  :uri             "/docs"
+                  :response-format (ajax/raw-response-format)
+                  :on-success       [:set-docs]}}))
+
+(rf/reg-event-db
+  :common/set-error
+  (fn [db [_ error]]
+    (assoc db :common/error error)))
+
+;;subscriptions
+
+(rf/reg-sub
+  :page
+  (fn [db _]
+    (:page db)))
+
+(rf/reg-sub
+  :docs
+  (fn [db _]
+    (:docs db)))
+
+(rf/reg-sub
+  :common/error
+  (fn [db _]
+    (:common/error db)))
diff --git a/test/clj/ireadit/test/handler.clj b/test/clj/ireadit/test/handler.clj
new file mode 100644
index 0000000..5818c9e
--- /dev/null
+++ b/test/clj/ireadit/test/handler.clj
@@ -0,0 +1,26 @@
+(ns ireadit.test.handler
+  (:require [clojure.test :refer :all]
+            [ring.mock.request :refer :all]
+            [ireadit.handler :refer :all]
+            [ireadit.middleware.formats :as formats]
+            [muuntaja.core :as m]
+            [mount.core :as mount]))
+
+(defn parse-json [body]
+  (m/decode formats/instance "application/json" body))
+
+(use-fixtures
+  :once
+  (fn [f]
+    (mount/start #'ireadit.config/env
+                 #'ireadit.handler/app)
+    (f)))
+
+(deftest test-app
+  (testing "main route"
+    (let [response (app (request :get "/"))]
+      (is (= 200 (:status response)))))
+
+  (testing "not-found route"
+    (let [response (app (request :get "/invalid"))]
+      (is (= 404 (:status response))))))
diff --git a/test/cljs/ireadit/core_test.cljs b/test/cljs/ireadit/core_test.cljs
new file mode 100644
index 0000000..94d2701
--- /dev/null
+++ b/test/cljs/ireadit/core_test.cljs
@@ -0,0 +1,9 @@
+(ns ireadit.core-test
+  (:require [cljs.test :refer-macros [is are deftest testing use-fixtures]]
+            [pjstadig.humane-test-output]
+            [reagent.core :as reagent :refer [atom]]
+            [ireadit.core :as rc]))
+
+(deftest test-home
+  (is (= true true)))
+
diff --git a/test/cljs/ireadit/doo_runner.cljs b/test/cljs/ireadit/doo_runner.cljs
new file mode 100644
index 0000000..c19c3fd
--- /dev/null
+++ b/test/cljs/ireadit/doo_runner.cljs
@@ -0,0 +1,6 @@
+(ns ireadit.doo-runner
+  (:require [doo.runner :refer-macros [doo-tests]]
+            [ireadit.core-test]))
+
+(doo-tests 'ireadit.core-test)
+