diff --git a/bin/bird.hs b/bin/bird.hs
--- a/bin/bird.hs
+++ b/bin/bird.hs
@@ -20,12 +20,12 @@
       system "ghc --make -O2 Main.hs"
       files <- getDirectoryContents appModuleNamePath
       system $ "rm *.o *.hi " ++ appModuleName ++ ".hs"
-      renameFile "Main" appModuleName
+      renameFile "Main" (appModuleName ++ "App")
       return ()
     ["fly"] -> do
       appModuleNamePath <- getCurrentDirectory
       appModuleName <- return $ head . reverse $ split '/' appModuleNamePath
-      system $ "./" ++ appModuleName
+      system $ "./" ++ appModuleName ++ "App"
       return ()
     ["hatch", appName] -> createBirdApp appName
     (action:_) -> do
@@ -43,7 +43,8 @@
 appModulePrelude appModuleName =
   "--This file is generated by bird. It will be overwritten the next time you run 'bird nest'. Edit at your own peril.\n" ++
   "module " ++ appModuleName ++ " where\n" ++
-  "import Bird\n\n"
+  "import Bird\n" ++
+  "import Prelude hiding( log )\n\n"
 
 appModuleEpilogue =
   "get _ = status 404\n" ++
@@ -51,15 +52,22 @@
   "put _ = status 404\n" ++
   "delete _ = status 404\n"
 
-
 createBirdApp a = do
   createDirectory a
+  createDirectory (a ++ "/" ++ a ++ "/")
   writeFile (a ++ "/" ++ a ++ ".bird.hs") (routeFile a)
   writeFile (a ++ "/" ++ "Main.hs") (mainFile a)
+  writeFile (a ++ "/" ++ a ++ "/Config.hs") (configFile a)
   putStrLn $ "A fresh Bird app has been created in " ++ a ++ "."
 
 routeFile a = "get [] = body \"Hello, Bird!\""
 
+configFile a = 
+  "module " ++ a ++ ".Config where\n\n" ++
+  "import Bird\n\n" ++ 
+  "config :: BirdConfig" ++
+  "config = def\n"
+
 mainFile a =
   "import Hack\n" ++
   "import qualified Hack as Hack\n" ++
@@ -69,7 +77,8 @@
   "import Bird.Translator.Hack\n" ++
   "import qualified Control.Monad.State as S\n" ++
   "import qualified Control.Monad.Reader as R\n" ++
-  "import " ++ a ++ "\n" ++ "\n" ++
+  "import " ++ a ++ "\n" ++
+  "import " ++ a ++ ".Config\n\n" ++
 
   "app :: Application\n" ++
   "app = \\e -> route e\n" ++ "\n" ++
@@ -79,7 +88,7 @@
   "  where \n" ++
   "    req = toBirdRequest e\n" ++
   "    response = do \n" ++
-  "      reply <- runBirdResponder req matchRequest\n" ++
+  "      reply <- (birdLogger config) req matchRequest\n" ++
   "      return $ fromBirdReply reply\n\n" ++
 
   "matchRequest r = \n" ++
diff --git a/bird.cabal b/bird.cabal
--- a/bird.cabal
+++ b/bird.cabal
@@ -1,5 +1,5 @@
 Name:                 bird
-Version:              0.0.14
+Version:              0.0.15
 Build-type:           Simple
 Synopsis:             A simple, sinatra-inspired web framework.
 Description:          Bird is a hack-compatible framework for simple websites.
@@ -18,6 +18,6 @@
   hs-source-dirs: bin
   
 library
-  build-depends: haskell98, mtl >= 1.1.0.2, process, containers, parsec >= 2.1.0.1, bytestring, base >= 4.0 && < 5, hack >= 2009.10.30, hack-handler-happstack, data-default >= 0.2, rallod 
-  exposed-modules: Bird, Bird.Request, Bird.Reply, Bird.Request.QueryStringParser, Bird.BirdResponder, Bird.Translator, Bird.Translator.Hack
+  build-depends: haskell98, MissingH >= 1.1.0.3, mtl >= 1.1.0.2, process, containers, parsec >= 2.1.0.1, bytestring, base >= 4.0 && < 5, hack >= 2009.10.30, hack-handler-happstack, data-default >= 0.2, rallod 
+  exposed-modules: Bird, Bird.Logger, Bird.Config, Bird.Request, Bird.Reply, Bird.Request.QueryStringParser, Bird.BirdResponder, Bird.Translator, Bird.Translator.Hack
   hs-source-dirs: src/
diff --git a/readme.markdown b/readme.markdown
--- a/readme.markdown
+++ b/readme.markdown
@@ -54,6 +54,7 @@
 
     get [] = do
       name <- param "name"
+      log "I'm about to greet a Jedi. Teehee!"
       body $ "Greetings, " ++ (maybe "Jedi!" id name)
 
 now recompile your app and start it flying:
@@ -106,11 +107,14 @@
     -- creates/updates a header
     -- ex: get [] = body "Hello World" >> header "X-Powered-By" "BIRD!"
 
+    log :: String -> BirdResponder ()
+    -- adds to the log
+    -- ex: get [] = body "Hello World" >> log "Why did I just greet the world?"
+
 ## Notes
 
 This project is *still* in its infancy. Coming features:
 
-* logging
 * post/put/delete http param processing
 * helpers for popular html generation solutions (Hamlet, HStringTemplate, HAXML, BlazeHTML, etc.)
 * WAI support
diff --git a/src/Bird.hs b/src/Bird.hs
--- a/src/Bird.hs
+++ b/src/Bird.hs
@@ -3,9 +3,13 @@
 , module Bird.Reply
 , module Bird.Request 
 , module Bird.BirdResponder
+, module Bird.Logger
+, module Bird.Config
 ) where
 
 import Data.Default
 import Bird.Reply
 import Bird.Request
 import Bird.BirdResponder
+import Bird.Logger
+import Bird.Config
diff --git a/src/Bird/BirdResponder.hs b/src/Bird/BirdResponder.hs
--- a/src/Bird/BirdResponder.hs
+++ b/src/Bird/BirdResponder.hs
@@ -2,16 +2,17 @@
 
 import Control.Monad.State
 import Control.Monad.Reader
+import Control.Monad.Writer
 import Data.Default
 import Data.Maybe
 import Bird.Reply
 import Bird.Request
 import qualified Data.Map as Hash
 
-type BirdResponder = StateT Reply (ReaderT Request IO)
+type BirdResponder = StateT Reply (ReaderT Request (WriterT [String] IO))
 
 runBirdResponder request router = 
-  runReaderT (execStateT (router request) def) request
+  runWriterT (runReaderT (execStateT (router request) def) request)
 
 body b = do
   reply <- get
@@ -24,6 +25,9 @@
 param paramName = do
   request <- ask
   return $ maybe Nothing id (lookup paramName $ params request)
+
+log logMessage = do
+  tell [logMessage]
 
 mime m = header "Content-Type" m
 
diff --git a/src/Bird/Config.hs b/src/Bird/Config.hs
new file mode 100644
--- /dev/null
+++ b/src/Bird/Config.hs
@@ -0,0 +1,22 @@
+module Bird.Config where 
+
+import Data.Default
+import Bird.Logger
+import Bird.Request
+import Bird.Reply
+import Bird.BirdResponder
+
+type Router = Request -> BirdResponder ()
+
+data BirdConfig = 
+  BirdConfig {
+    staticDir :: String
+  , birdLogger :: Request -> Router -> IO Reply
+  }
+
+instance Default BirdConfig where
+  def = 
+    BirdConfig {
+      staticDir   = "static"
+    , birdLogger  = defaultLogger
+    }
diff --git a/src/Bird/Logger.hs b/src/Bird/Logger.hs
new file mode 100644
--- /dev/null
+++ b/src/Bird/Logger.hs
@@ -0,0 +1,17 @@
+module Bird.Logger where
+
+import Bird.BirdResponder
+import Bird.Reply
+import Bird.Request
+import Text.Printf
+import qualified Data.String.Utils as StringUtils (join)
+import System.CPUTime
+
+defaultLogger request router = do
+  let logPrelude = "\n" ++ (show $ verb request) ++ " " ++ (show $ rawRequestUri request)
+  start <- getCPUTime
+  (reply, logMessages) <- runBirdResponder request router 
+  end <- getCPUTime
+  let logEpilogue = (printf "  Response code: %s" (show $ replyStatus reply)) ++ (printf "\n  Response time: %0.3fs" (((fromIntegral (end - start)) / (10^12)) :: Double))
+  putStrLn $ (StringUtils.join "\n" ([logPrelude] ++ logMessages ++ [logEpilogue])) ++ "\n"
+  return reply
diff --git a/src/Bird/Request.hs b/src/Bird/Request.hs
--- a/src/Bird/Request.hs
+++ b/src/Bird/Request.hs
@@ -11,10 +11,11 @@
 
 data Request = 
   Request { 
-    verb      :: RequestMethod
-  , path      :: Path
-  , params    :: [(String, Maybe String)]
+    verb          :: RequestMethod
+  , path          :: Path
+  , params        :: [(String, Maybe String)]
+  , rawRequestUri :: String
   } deriving (Show)
 
 instance Default Request where
-  def = Request { verb = GET, path = [], params = [] }
+  def = Request { verb = GET, path = [], params = [], rawRequestUri = "/" }
diff --git a/src/Bird/Translator/Hack.hs b/src/Bird/Translator/Hack.hs
--- a/src/Bird/Translator/Hack.hs
+++ b/src/Bird/Translator/Hack.hs
@@ -19,7 +19,7 @@
       Hack.body = pack $ replyBody r
     }
     where
-      insertUnlessPresent _ oldValue = oldValue
+      insertUnlessPresent = flip const
 
 instance BirdRequestTranslator Hack.Env where
   toBirdRequest e = 
@@ -27,7 +27,13 @@
       verb = hackRequestMethodToBirdRequestMethod $ Hack.requestMethod e
     , path = split '/' $ Hack.pathInfo e
     , params = parseQueryString $ Hack.queryString e
+    , rawRequestUri = (Hack.pathInfo e) ++ maybeQueryString e
     }
+    where
+      maybeQueryString e =
+        if Hack.queryString e /= ""
+        then "?" ++ Hack.queryString e
+        else ""
 
 
 hackRequestMethodToBirdRequestMethod rm = 
