diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014, Kaashif Hymabaccus
+
+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 Kaashif Hymabaccus 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/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,47 @@
+muon
+====
+Muon is a static blog generator, meaning that it takes files written in
+convenient markup and converts it to HTML and CSS ready to deploy to a web
+server.
+
+Installing
+----------
+First, install the package by getting the darcs repo.
+
+    $ darcs get http://repos.kaashif.co.uk/muon
+
+You can install it using cabal, which you should have installed.
+
+    $ cd muon
+    $ cabal install
+
+After that, assuming you have configured cabal and/or your PATH correctly, muon
+should be usable. Here are some things you may want to do:
+
+Using Muon
+----------
+Initialising a blog:
+
+    $ mkdir new-blog
+    $ cd new-blog
+    $ muon init
+
+Writing a post:
+
+    $ vi posts/new.post
+
+Regenerating the site, creating a tree of files in the ./site directory.
+
+    $ muon generate
+
+Notes
+-----
+When writing posts, make sure you put the title on the first line, the date on
+the second, and a short description (for the archive) on the third line. The
+rest should be valid Markdown. See the posts/ directory after site
+initialisation for some examples.
+
+The posts are ordered lexicographically, _not_ by date. This means "aaa.post"
+will always come before "bbb.post", regardless of the date contained in the file.
+
+"muon upload" is currently hardcoded. Stay tuned for per-blog config files.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/muon.cabal b/muon.cabal
new file mode 100644
--- /dev/null
+++ b/muon.cabal
@@ -0,0 +1,32 @@
+-- Initial muon.cabal generated by cabal init.  For further documentation, 
+-- see http://haskell.org/cabal/users-guide/
+
+name:                muon
+version:             0.1.0.0
+synopsis:            Static blog generator
+description:         Static blog generator
+homepage:            http://repos.kaashif.co.uk/darcs?r=muon;a=summary
+license:             BSD3
+license-file:        LICENSE
+author:              Kaashif Hymabaccus
+maintainer:          kaashifhymabaccus@gmail.com
+copyright:           Copyright (c) 2014 Kaashif Hymabaccus
+category:            Web
+build-type:          Simple
+cabal-version:       >=1.8
+data-dir:            src
+data-files:          def/style/style.css
+                     def/templates/*.st
+                     def/posts/*.post
+                     def/pages/about
+                     def/pages/contact
+extra-source-files:  src/*.hs README
+
+source-repository head
+    type: darcs
+    location: http://repos.kaashif.co.uk/muon
+
+executable muon
+  main-is:             Main.hs
+  build-depends:       base ==4.6.*, text ==0.11.*, HStringTemplate ==0.7.*, directory ==1.2.*, Glob ==0.7.*, process ==1.2.*, blaze-html ==0.7.*, markdown ==0.1.*
+  hs-source-dirs:      src
diff --git a/src/Archive.hs b/src/Archive.hs
new file mode 100644
--- /dev/null
+++ b/src/Archive.hs
@@ -0,0 +1,45 @@
+module Archive where
+
+import System.Directory
+import qualified Data.Text as T
+import Site
+import Text.StringTemplate
+import Post
+
+sitePath = "site/"
+mkdir = createDirectoryIfMissing False
+
+archiveTemplate = do
+    templates <- directoryGroup "templates" :: IO (STGroup T.Text)
+    let Just t = getStringTemplate "generic" templates
+    return t
+
+makeTableRow ::  Post -> String
+makeTableRow p = "<tr>"
+              ++ "<td><a href=" ++ T.unpack (link p) ++ ">" ++ T.unpack (title p) ++ "</a></td>"
+              ++ "<td>" ++ T.unpack (date p) ++ "</td>"
+              ++ "<td>" ++ T.unpack (comment p) ++ "</td>"
+              ++ "</tr>"
+
+makeTable ::  [Post] -> T.Text
+makeTable ps = T.pack
+             $ "<table>"
+            ++ "<tr><td>Title</td><td>Date</td><td>Comment</td></tr>"
+            ++ unlines (map makeTableRow ps)
+            ++ "</table>"
+
+renderGenericArchive t c = render
+                         $ setAttribute "site" defaultSite
+                         $ setAttribute "content" c t
+
+renderArchive = do
+    ps <- getAllPosts
+    t <- archiveTemplate
+    return $ renderGenericArchive t (makeTable $ reverse ps)
+
+writeArchive ::  T.Text -> IO ()
+writeArchive s = do
+    mkdir $ sitePath ++ "archive/"
+    writeFile (sitePath ++ "archive/index.html") (T.unpack s)
+
+generateArchive = renderArchive >>= writeArchive >> putStrLn "Generated archive"
diff --git a/src/Constant.hs b/src/Constant.hs
new file mode 100644
--- /dev/null
+++ b/src/Constant.hs
@@ -0,0 +1,9 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Constant where
+
+import System.Directory
+
+sitePath = "site/"
+pageNames = ["about", "contact"]
+siteDirs = ["site", "style", "posts", "templates", "pages"]
+mkdir = createDirectoryIfMissing False
diff --git a/src/Home.hs b/src/Home.hs
new file mode 100644
--- /dev/null
+++ b/src/Home.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Home where
+
+import Post
+import Text.StringTemplate
+import System.Directory
+import Site
+import qualified Data.Text as T
+
+sitePath = "site/"
+mkdir = createDirectoryIfMissing False
+
+homeTemplate = do
+    templates <- directoryGroup "templates" :: IO (STGroup T.Text)
+    let Just t = getStringTemplate "generic" templates
+    return t
+
+renderGenericHome ::  StringTemplate T.Text -> [T.Text] -> T.Text
+renderGenericHome t cs = render
+                       $ setAttribute "site" defaultSite
+                       $ setAttribute "content" (T.unlines cs) t
+
+renderHome ::  IO T.Text
+renderHome = do
+    cs <- getAllExtracts
+    t <- homeTemplate
+    return $ renderGenericHome t $ reverse cs
+
+writeHome ::  T.Text -> IO ()
+writeHome s = do
+    mkdir $ sitePath ++ "home/"
+    writeFile (sitePath ++ "home/index.html") (T.unpack s)
+    writeFile (sitePath ++ "index.html") (T.unpack s)
+
+generateHome = renderHome >>= writeHome >> putStrLn "Generated home"
diff --git a/src/Main.hs b/src/Main.hs
new file mode 100644
--- /dev/null
+++ b/src/Main.hs
@@ -0,0 +1,73 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Main where
+
+import qualified Data.Text as T
+import Text.StringTemplate
+import Control.Monad
+import System.Directory
+import System.FilePath.Glob
+import System.Environment
+import System.Process (runCommand)
+import Post (generatePosts)
+import Home (generateHome)
+import Archive (generateArchive)
+import Site (defaultSite)
+import Page (generatePages)
+import Constant
+import Paths_muon
+
+ensureDirs = mkdir sitePath
+
+createDefaults = do
+    d <- getDataFileName "def"
+    mapM_ mkdir siteDirs
+    mkdir "static"
+    copyFile (d ++ "/style/style.css") "style/style.css"
+    copyFile (d ++ "/posts/first.post") "posts/first.post"
+    copyFile (d ++ "/posts/second.post") "posts/second.post"
+    copyFile (d ++ "/templates/post.st") "templates/post.st"
+    copyFile (d ++ "/templates/header.st") "templates/header.st"
+    copyFile (d ++ "/templates/footer.st") "templates/footer.st"
+    copyFile (d ++ "/templates/generic.st") "templates/generic.st"
+    copyFile (d ++ "/pages/about") "pages/about"
+    copyFile (d ++ "/pages/contact") "pages/contact"
+    putStrLn "Initialised site directory"
+
+copyStatic = do
+    copyFile "style/style.css" (sitePath ++ "style.css")
+    runCommand $ "cp -R static " ++ sitePath ++ "static"
+
+generateSite = copyStatic
+            >> generatePosts
+            >> generateHome
+            >> generateArchive
+            >> generatePages
+
+showHelp = putStrLn "Usage: muon [commands]\n\n\
+\  help        show this help message\n\
+\  init        initialise a default blog in the current dir\n\
+\  generate    generate static blog in 'site' directory\n\n\
+\Report bugs to <kaashif@kaashif.co.uk>"
+
+clearSite = mkdir sitePath 
+         >> removeDirectoryRecursive sitePath 
+         >> mkdir sitePath
+
+rsyncCmd = "rsync -a --delete site/ root@webserver:/var/www/htdocs/"
+
+proc ::  String -> IO ()
+proc cmd
+    | cmd == "init" = createDefaults
+    | cmd == "generate" = clearSite >> generateSite
+    | cmd == "upload" = void $ runCommand rsyncCmd
+    | otherwise = showHelp
+
+getArgsHelp = do
+    a <- getArgs
+    if length a < 1
+        then return ["help"]
+        else return a
+
+takeAction = getArgsHelp >>= mapM_ proc
+
+main = ensureDirs >> takeAction
diff --git a/src/Page.hs b/src/Page.hs
new file mode 100644
--- /dev/null
+++ b/src/Page.hs
@@ -0,0 +1,37 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+module Page where
+
+import qualified Data.Text as T
+import Site
+import Text.StringTemplate
+import Text.StringTemplate.GenericStandard
+import Constant
+
+pageTemplate = do
+    templates <- directoryGroup "templates" :: IO (STGroup T.Text)
+    let Just t = getStringTemplate "generic" templates
+    return t
+
+renderPage ::  StringTemplate T.Text -> T.Text -> T.Text
+renderPage t c = render
+               $ setAttribute "site" defaultSite
+               $ setAttribute "content" c t
+
+renderPageFile ::  String -> IO T.Text
+renderPageFile p = do
+    c <- readFile $ "pages/" ++ p
+    t <- pageTemplate
+    return $ renderPage t (T.pack c)
+
+writePage ::  String -> T.Text -> IO ()
+writePage p c = do
+    mkdir $ sitePath ++ p
+    writeFile (sitePath ++ p ++ "/index.html") (T.unpack c)
+
+generatePage p = do
+    c <- renderPageFile p
+    writePage p c
+    putStrLn $ "Generated " ++ p
+
+generatePages = mapM_ generatePage pageNames
diff --git a/src/Post.hs b/src/Post.hs
new file mode 100644
--- /dev/null
+++ b/src/Post.hs
@@ -0,0 +1,100 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+module Post where
+
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as TL
+import Text.StringTemplate
+import Text.StringTemplate.GenericStandard
+import Text.Blaze.Html.Renderer.Text
+import Text.Markdown
+import System.Directory
+import System.FilePath.Glob
+import Data.Typeable
+import Data.Data
+import Data.List
+import Site
+import Control.Monad
+import Constant
+
+postPath = "posts/" :: String
+
+data Post = Post { title :: T.Text
+                 , link :: T.Text
+                 , date :: T.Text
+                 , comment :: T.Text
+                 , content :: T.Text
+                 } deriving (Data, Typeable, Show)
+
+postTemplate = do
+    templates <- directoryGroup "templates" :: IO (STGroup T.Text)
+    let Just t = getStringTemplate "post" templates
+    return t
+
+renderPost ::  StringTemplate T.Text -> Post -> T.Text
+renderPost t p = render
+               $ setAttribute "site" defaultSite
+               $ setAttribute "post" p t
+
+renderName ::  StringTemplate T.Text -> String -> IO T.Text
+renderName t n = liftM (renderPost t) (getPost (0, n))
+
+makeExtract ::  Post -> T.Text
+makeExtract p = T.pack
+                  $ "<h2>" ++ T.unpack (title p) ++ "</h2>"
+                 ++ "<h3>" ++ T.unpack (date p) ++ "</h3>"
+                 ++  unlines (take 25 $ lines $ T.unpack $ content p)
+                 ++ "<br/><br/><a href=\'" ++ T.unpack (link p) ++ "\'>Read more...</a>"
+                 ++ "</code></pre></li></ul></ol><hr/>"
+
+makePost ::  (Int, [String]) -> Post
+makePost l = Post { title  = T.pack $ head (snd l)
+                  , link = T.pack $ "/post/" ++ show (fst l)
+                  , date = T.pack $ snd l !! 1
+                  , comment = T.pack $ snd l !! 2
+                  , content = T.pack $ extractContent (snd l) }
+
+extractContent ::  [String] -> String
+extractContent l = TL.unpack
+                 $ renderHtml
+                 $ markdown def
+                 $ TL.pack
+                 $ unlines
+                 $ drop 3 l
+
+getPost ::  (Int, FilePath) -> IO Post
+getPost n = do
+    c <- readFile (snd n)
+    return $ makePost (fst n, lines c)
+
+getNames ::  IO [(Int, FilePath)]
+getNames = do
+    d <- globDir [compile "*.post"] postPath
+    let l = (sort . head . fst) d
+    return $ zip [1..(length l)] l
+
+renderPosts ::  IO [T.Text]
+renderPosts = do
+    templates <- directoryGroup "templates" :: IO (STGroup T.Text)
+    let Just t = getStringTemplate "post" templates
+    ns <- getNames
+    mapM (renderName t . snd) ns
+
+writePosts ::  [T.Text] -> IO ()
+writePosts ps = mapM_ writePost (zip [1..(length ps)] ps)
+
+writePost ::  (Int, T.Text) -> IO ()
+writePost p = do
+    mkdir $ sitePath ++ "post"
+    mkdir $ sitePath ++ "post/" ++ show (fst p)
+    writeFile (sitePath ++ "post/" ++ show (fst p) ++ "/index.html") (T.unpack $ T.append "\n" $ snd p)
+
+getAllPosts = do
+    ns <- getNames
+    mapM getPost ns
+
+getAllExtracts = do
+    ps <- getAllPosts
+    return $ map makeExtract ps
+
+generatePosts = renderPosts >>= writePosts >> putStrLn "Generated posts"
diff --git a/src/Site.hs b/src/Site.hs
new file mode 100644
--- /dev/null
+++ b/src/Site.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+module Site (defaultSite) where
+
+import qualified Data.Text as T
+import Data.Typeable
+import Data.Data
+
+data Site = Site { title :: T.Text
+                 , style :: T.Text
+                 , author :: T.Text
+                 , tagline :: T.Text
+                 } deriving (Data, Typeable, Show)
+
+defaultSite = Site { title = "Default Blog"
+                   , style = "/style.css"
+                   , author = "Your Name"
+                   , tagline = "Description of this blog"
+                   }
diff --git a/src/def/pages/about b/src/def/pages/about
new file mode 100644
--- /dev/null
+++ b/src/def/pages/about
@@ -0,0 +1,1 @@
+<p>This is about you.</p>
diff --git a/src/def/pages/contact b/src/def/pages/contact
new file mode 100644
--- /dev/null
+++ b/src/def/pages/contact
@@ -0,0 +1,1 @@
+<p>Contact you at your email</p>
diff --git a/src/def/posts/first.post b/src/def/posts/first.post
new file mode 100644
--- /dev/null
+++ b/src/def/posts/first.post
@@ -0,0 +1,5 @@
+First Post
+2014-04-05
+A comment
+
+Some content
diff --git a/src/def/posts/second.post b/src/def/posts/second.post
new file mode 100644
--- /dev/null
+++ b/src/def/posts/second.post
@@ -0,0 +1,5 @@
+Second Post
+2014-04-06
+Another comment
+
+Some more content.
diff --git a/src/def/style/style.css b/src/def/style/style.css
new file mode 100644
--- /dev/null
+++ b/src/def/style/style.css
@@ -0,0 +1,195 @@
+html {
+	background: #FFFFFF;
+}
+
+body {
+	padding: 50px 0;
+	margin: 0;
+	font-family: Helvetica;
+	color: #555;
+	font-weight: 300;
+}
+
+.wrapper {
+	max-width: 640px;
+	margin: 0 auto;
+	background: #FFFFFF;
+	border-radius: 8px;
+}
+
+header, section, footer {
+	display: block;
+}
+
+a {
+	color: #2D2E2F;
+	text-decoration: none;
+}
+
+p {
+	margin: 0 0 20px;
+	padding: 0;
+}
+
+strong {
+	color: #222;
+	font-weight: 700;
+}
+
+header {
+	border-radius: 8px 8px 0 0;
+	background: #FFFFFF;
+	position: relative;
+	padding: 20px 20px 30px 20px;
+	margin-top: -1px;
+}
+
+header h1 {
+	margin: 0;
+	padding: 0;
+	font-size: 24px;
+	line-height: 1.2;
+	color: #2D2E2F;
+}
+header p {
+	margin: 0;
+	color: #2D2E2F;
+	font-size: 15px;
+}
+header ul {
+	float: left;
+	list-style: none;
+	margin-left: -45px;
+}
+header ul li {
+	float: left;
+	padding: 13px 5px;
+}
+main {
+	font-size: 15px;
+	border-top: 1px solid #fff;
+	position: relative;
+	border-radius: 8px;
+}
+
+.content {
+	padding: 15px 20px 20px 20px;
+}
+
+h1, h2, h3, h4, h5, h6 {
+	color: #666;
+	padding: 0;
+	margin: 0 0 20px;
+	line-height: 1.2;
+}
+
+p, ul, ol, table, pre, dl {
+	margin: 0 0 20px;
+}
+
+h1, h2, h3 {
+	line-height: 1.1;
+}
+
+h1 {
+	font-size: 28px;
+	color: #2D2E2F;
+}
+
+h2 {
+	color: #2D2E2F;
+}
+
+h3, h4, h5, h6 {
+	color: #494949;
+}
+
+blockquote {
+	margin: 0 -20px 20px;
+	padding: 15px 20px 1px 40px;
+	font-style: italic;
+	background: #ccc;
+	background: rgba(0, 0, 0, 0.06);
+	color: #222;
+}
+
+img {
+	max-width:100%;
+	display: block;
+	margin-left: auto;
+	margin-right: auto;
+}
+
+code, pre {
+	color: #333;
+	font-size: 12px;
+}
+
+pre {
+	padding: 20px;
+	background: #DDDDDD;
+	color: #333333;
+	margin: 0 -20px 20px;
+	overflow-x:auto;
+}
+li pre {
+	margin-left: -60px;
+	padding-left: 60px;
+}
+
+table {
+	width: 100%;
+	border-collapse: collapse;
+}
+
+th, td {
+	text-align: left;
+	padding: 5px 10px;
+	border-bottom: 1px solid #aaa;
+}
+
+dt {
+	color: #222;
+	font-weight: 700;
+}
+
+th {
+	color: #222;
+}
+
+small {
+	font-size: 11px;
+}
+
+hr {
+	border: 0;
+	background: #aaa;
+	height: 0px;
+	margin: 0 0 20px;
+}
+
+hr#header {
+	clear: both;
+	visibility: hidden;
+}
+
+footer {
+	width: 640px;
+	margin: 0 auto;
+	padding: 20px 0 0;
+	color: #aaa;
+	overflow: hidden;
+}
+footer a {
+	color: #bbb;
+	font-weight: bold;
+}
+footer p {
+	float: left;
+}
+footer p + p {
+	float: right;
+}
+.latex {
+	text-align: center;
+}
diff --git a/src/def/templates/footer.st b/src/def/templates/footer.st
new file mode 100644
--- /dev/null
+++ b/src/def/templates/footer.st
@@ -0,0 +1,10 @@
+</div>
+</main>
+</div>
+<footer>
+<p>
+&copy; <time>2014</time> $site.author$<br/>
+</p>
+</footer>
+</body>
+</html>
diff --git a/src/def/templates/generic.st b/src/def/templates/generic.st
new file mode 100644
--- /dev/null
+++ b/src/def/templates/generic.st
@@ -0,0 +1,3 @@
+$header()$
+$content$
+$footer()$
diff --git a/src/def/templates/header.st b/src/def/templates/header.st
new file mode 100644
--- /dev/null
+++ b/src/def/templates/header.st
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>$site.title$</title>
+<link rel="stylesheet" type="text/css" href="$site.style$">
+</head>
+<body>
+<div class="wrapper">
+<main>
+<header>
+        <h1>$site.title$</h1>
+        <p>$site.tagline$</p>
+        <ul>
+            <li> <a href="/home">Home</a></li>
+            <li>//</li>
+            <li> <a href="/about">About</a></li>
+            <li>//</li>
+            <li> <a href="/contact">Contact</a></li>
+            <li>//</li>
+            <li> <a href="/archive">Archive</a></li>
+            <li>//</li>
+            <li> <a href="http://git.kaashif.co.uk/">Code</a></li>
+        </ul>
+</header>
+<hr id="header" />
+<div class="content">
diff --git a/src/def/templates/post.st b/src/def/templates/post.st
new file mode 100644
--- /dev/null
+++ b/src/def/templates/post.st
@@ -0,0 +1,5 @@
+$header()$
+<h1>$post.title$</h1>
+<h2>$post.date$</h2>
+$post.content$
+$footer()$
