diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+Copyright Corey O'Connor
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Stefan O'Rear nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+import Distribution.Simple
+main = defaultMain
+
diff --git a/corebot-bliki.cabal b/corebot-bliki.cabal
new file mode 100644
--- /dev/null
+++ b/corebot-bliki.cabal
@@ -0,0 +1,49 @@
+name:           corebot-bliki
+version:        0.1
+synopsis:       A bliki written using yesod. Uses pandoc to process files stored in git.
+description:    Also provides a sample use of the library that uses $HOME/bliki for data and serves
+                to port 8080.
+                See http://www.corebotllc.com for public site built using this library.
+cabal-version:  >= 1.8
+build-type:     Simple
+data-files:     static/*.js
+license:        BSD3
+license-file:   LICENSE
+homepage:       http://github.com/coreyoconnor/corebot-bliki
+
+source-repository head
+    type:       git
+    location:   git://github.com/coreyoconnor/corebot-bliki.git
+    
+executable corebot-bliki
+    main-is: DefaultMain.hs
+    hs-source-dirs: src
+    extensions:     TemplateHaskell
+                    QuasiQuotes
+                    TypeFamilies
+                    MultiParamTypeClasses
+                    FlexibleInstances
+                    NoMonomorphismRestriction
+                    OverloadedStrings
+                    RankNTypes
+                    ScopedTypeVariables
+                    UndecidableInstances
+                    EmptyDataDecls
+                    GADTs
+                    FlexibleContexts
+    ghc-options:    -threaded
+    build-depends:  base             >= 4.4.0 && < 5,
+                    aeson            >= 0.3.2.11,
+                    blaze-builder    >= 0.3.0.1,
+                    bytestring       >= 0.9.2.0,
+                    containers       >= 0.4.1.0,
+                    directory        >= 1.1.0.1,
+                    filepath         >= 1.2.0.1,
+                    filestore        >= 0.4.0.5,
+                    http-types       >= 0.6.7,
+                    monads-tf        >= 0.1.0.0,
+                    pandoc           >= 1.9,
+                    text             >= 0.11.1.5,
+                    template-haskell >= 2.6.0.0,
+                    time             >= 1.2.0.5,
+                    yesod            >= 0.9.4.1
diff --git a/src/DefaultMain.hs b/src/DefaultMain.hs
new file mode 100644
--- /dev/null
+++ b/src/DefaultMain.hs
@@ -0,0 +1,87 @@
+module Main where
+import Yesod
+
+import Yesod.CoreBot.Bliki 
+import Yesod.CoreBot.Bliki.Widgets
+
+import Paths_corebot_bliki
+
+import Control.Applicative
+import Control.Monad.Fix
+
+import Data.Monoid 
+
+import System.Directory ( getHomeDirectory )
+
+import System.FilePath
+
+data Main = Main
+    { bliki :: Bliki_ Main
+    }
+
+type Bliki = Bliki_ Main
+
+type Data = Data_ Main
+get_data = data_res . bliki
+
+type Blog = Blog_ Main
+get_blog = blog_res . bliki
+
+type Wiki = Wiki_ Main
+get_wiki = wiki_res . bliki
+
+get_static = static_config . config . data_res . bliki
+
+instance Yesod Main where
+    approot _ = "http://localhost:8080"
+    defaultLayout w = do
+        let page_w = mconcat [ w, toWidget NavWidget ]
+        p <- widgetToPageContent page_w
+        mmsg <- getMessage
+        hamletToRepHtml [hamlet|
+!!!
+
+<html>
+    <head>
+        <title>#{pageTitle p}
+        ^{pageHead p}
+    <body>
+        $maybe msg <- mmsg
+            <p .message>#{msg}
+        ^{pageBody p}
+|]
+
+getMainR = do
+    bliki <- bliki <$> getYesod
+    defaultLayout $ do
+        default_blog_entry bliki
+
+mkYesod "Main" [parseRoutes|
+/       MainR   GET
+/data   DataS   Data   get_data
+/blog   BlogS   Blog   get_blog
+/wiki   WikiS   Wiki   get_wiki
+/static StaticS Static get_static
+|]
+
+main :: IO ()
+main = do
+    home_dir <- getHomeDirectory
+    let store_dir = home_dir </> "bliki"
+        cache_dir = home_dir </> "bliki/cache"
+    static_dir <- getDataFileName "static"
+    putStrLn $ "using static dir: " ++ static_dir
+    app <- mfix $ \app -> do
+                let config = Config { store_dir     = store_dir
+                                    , cache_dir     = cache_dir
+                                    , data_routes   = DataS
+                                    , blog_routes   = BlogS
+                                    , wiki_routes   = WikiS
+                                    , static_routes = StaticS
+                                    , static_config = UseDir static_dir
+                                    , site = app
+                                    }
+                bliki <- mk_bliki config
+                return $ Main bliki
+    warpDebug 8080 app
+
diff --git a/static/indirect_load.js b/static/indirect_load.js
new file mode 100644
--- /dev/null
+++ b/static/indirect_load.js
@@ -0,0 +1,59 @@
+var worker = new Worker('static/process_HTML_for_wiki.js');
+
+function insertSubstr( str, index, sub_str )
+{
+    var str_pre = str.slice( 0, index );
+    var str_post = str.slice( index );
+    return str_pre + sub_str + str_post;
+}
+
+function process_HTML_for_wiki( data, target, wiki_node_URL )
+{
+    var edits = new Array;
+
+    var apply_edits = function()
+    {
+        edits.reverse();
+
+        for(var i = 0; i < edits.length ; ++i)
+        {
+            var edit = edits[i];
+            var edit_region = edit.edit_region;
+            // +- 2 accounts for the ]] and [[ respectively. 
+            // XXX: hackish
+            data = insertSubstr( data, edit_region.end_index + 2, '</a>' );
+            data = insertSubstr( data, edit_region.start_index - 2, '<a href="' + edit.node_URL + '">' );
+        }
+
+        target.html( data );
+    }
+
+    worker.postMessage( data );
+    worker.onmessage = function(event)
+        {
+            edit_region = event.data;
+
+            var node_URL = wiki_node_URL + '/' + edit_region.node_path;
+
+            var http = new XMLHttpRequest();
+            http.open('HEAD', node_URL, true);
+            http.onload = function( pe )
+                {
+                    console.log( http.status );
+
+                    // Thanks the gods of HTTP for making this next line so.
+                    if( http.status < 400 )
+                    {
+                        edits.push( { edit_region: edit_region
+                                    , node_URL: node_URL
+                                    }
+                                  );
+                        
+                        if( edit_region.is_final )
+                            apply_edits();
+                    }
+                };
+            http.send();
+        };
+}
+
diff --git a/static/process_HTML_for_wiki.js b/static/process_HTML_for_wiki.js
new file mode 100644
--- /dev/null
+++ b/static/process_HTML_for_wiki.js
@@ -0,0 +1,69 @@
+onmessage = function(event) 
+{
+    // This method assumes that double bracket *always* indicates a wiki node path regardless of
+    // it's location in the source
+    // I presume there is some way to use jquery from a web worker. Once I figure that out I think
+    // this algo would be better: Parse the HTML fragment data and then use jquery to only scan the
+    // wiki links that are not in code tags.
+    //
+    // for now we avoid just the HTML generated by ``[[wiki_word]]``. Every other instance of
+    // [[wiki_word]] is assumed to be replacable by the a link
+    var src = new String(event.data);
+
+    var start_match = /[^>]\[\[/gm;
+
+    var node_path_match = /(\w+(?:\/\w+)*)\]\]/g;
+
+    var parse_state = 'pre_start';
+
+    var pending = null;
+
+    var step_parser = function()
+    {
+        switch( parse_state )
+        {
+            case 'pre_start':
+                var m = start_match.exec( src );
+
+                if( null == m && null != pending )
+                    pending.is_final = true;
+
+                if( null != pending )
+                    postMessage( pending );
+
+                pending = null;
+
+                if( null == m )
+                    return;
+
+                node_path_match.lastIndex = start_match.lastIndex;
+
+                parse_state = 'in_brackets';
+                break;
+            case 'in_brackets':
+                var m = node_path_match.exec( src );
+
+                if(null == m)
+                {
+                    parse_state = 'pre_start';
+                    break;
+                }
+
+                pending = { node_path: m[1] 
+                          , start_index: start_match.lastIndex
+                          , end_index: node_path_match.lastIndex - 2
+                          , is_final: false
+                          };
+
+                start_match.lastIndex = node_path_match.lastIndex;
+
+                parse_state = 'pre_start';
+                break;
+        }
+
+        setTimeout( step_parser, 50 );
+    };
+    
+    setTimeout( step_parser, 50 );
+};
+
