diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Daniel YU (c) 2018
+
+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 Daniel YU 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.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,1 @@
+# yam
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/demo/Main.hs b/demo/Main.hs
new file mode 100644
--- /dev/null
+++ b/demo/Main.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE DataKinds           #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE RecordWildCards     #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeOperators       #-}
+
+module Main where
+
+import           Control.Monad.Logger.CallStack
+import           Control.Monad.Reader
+import qualified Data.Salak                           as S
+import           Data.Text                            (Text)
+import           Data.Time
+import           Database.Persist.Sqlite
+import           Network.Wai.Middleware.RequestLogger
+import           Servant
+import           Yam
+
+type UserApi
+     = "users" :> Get '[JSON] Text
+  :<|> "users" :> "error" :> Get '[JSON] Text
+  :<|> "users" :> "servant" :> Get '[JSON] Text
+  :<|> "users" :> "db" :> Get '[JSON] Text
+
+userService :: App Text
+userService = do
+  (r,_) <- ask
+  logInfo $ "Hello: " <> showText r
+  return "Hello"
+
+errorService :: App Text
+errorService = logError "No" >> return "No"
+
+servantService :: App Text
+servantService = throwServant err401
+
+dbService :: App Text
+dbService = do
+  str <- runDb $ do
+    (time:_) :: [UTCTime] <- selectValue "SELECT CURRENT_TIMESTAMP"
+    let timeStr = showText time
+    logWarn timeStr
+    return timeStr
+  logInfo str
+  return str
+
+db :: DataSourceProvider
+db DataSourceConfig{..} = createSqlitePool url maxThreads
+
+main :: IO ()
+main = do
+  p <- S.defaultPropertiesWithFile "yam_test.yml"
+  let config :: Maybe YamConfig = S.lookup "yam" p
+  runStdoutLoggingT $ case config of
+    Just c  -> start c (Proxy :: Proxy UserApi) (userService :<|> errorService :<|> servantService :<|> dbService) [logStdoutDev] (Just db) (return ())
+    Nothing -> logError "Yam Config not found"
diff --git a/src/Yam.hs b/src/Yam.hs
new file mode 100644
--- /dev/null
+++ b/src/Yam.hs
@@ -0,0 +1,75 @@
+{-# LANGUAGE DataKinds            #-}
+{-# LANGUAGE FlexibleContexts     #-}
+{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE OverloadedStrings    #-}
+{-# LANGUAGE RankNTypes           #-}
+{-# LANGUAGE RecordWildCards      #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+
+module Yam(
+    start
+  , App
+  , YamConfig(..)
+  , DataSourceProvider
+  , DataSourceConfig(..)
+  , showText
+  , throwServant
+  , runDb
+  , selectValue
+  ) where
+
+import           Control.Exception              (throw)
+import           Control.Monad.Except
+import           Control.Monad.Logger.CallStack
+import           Control.Monad.Reader
+import           Network.Wai
+import           Network.Wai.Handler.Warp       (run)
+import           Yam.Config
+import           Yam.DataSource
+import           Yam.Util
+import           Yam.Web.Swagger
+
+type AppM m = ReaderT (YamConfig, Maybe DataSource) (LoggingT m)
+
+type App = AppM IO
+
+throwServant :: ServantErr -> App a
+throwServant = lift . throw
+
+runDb :: DB App a -> App a
+runDb a = do
+  (_, ds) <- ask
+  case ds of
+    Nothing -> do
+      logError "DataSource not found"
+      throwServant err401
+    Just d  -> runDB d a
+
+start
+  :: (HasSwagger api, HasServer api '[YamConfig])
+  => YamConfig
+  -> Proxy api
+  -> ServerT api App
+  -> [Middleware]
+  -> Maybe DataSourceProvider
+  -> App a
+  -> LoggingT IO ()
+start conf@YamConfig{..} proxy server middleWares newDs appa
+  = let cxt = (conf :. EmptyContext)
+  in do
+    logInfo "Start Service..."
+    runLogger <- askLoggerIO
+    tryRunDb newDs datasource runLogger
+      $ \ds -> do
+        _ <- runLoggingT (runReaderT appa (conf,ds)) runLogger
+        run port
+          $ foldr (.) id middleWares
+          $ serveWithContextAndSwagger swagger proxy cxt
+          $ hoistServerWithContext proxy (Proxy :: Proxy '[YamConfig]) (go runLogger ds) server
+  where
+    go :: LogFunc -> Maybe DataSource -> App a -> Handler a
+    go r ds a = liftIO $ (`runLoggingT` r) $ runReaderT a (conf, ds)
+    tryRunDb (Just d) ds r a = do
+      logInfo "Initialize Datasource..."
+      liftIO $ runInDB r d ds (a.Just)
+    tryRunDb _  _        _ a = liftIO $ a Nothing
diff --git a/src/Yam/Config.hs b/src/Yam/Config.hs
new file mode 100644
--- /dev/null
+++ b/src/Yam/Config.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Yam.Config where
+
+import           Data.Aeson
+import           Data.Default
+import           Data.Text
+import           Yam.DataSource
+import           Yam.Web.Swagger
+
+data YamConfig = YamConfig
+  { datasource :: DataSourceConfig
+  , swagger    :: SwaggerConfig
+  , appName    :: Text
+  , port       :: Int
+  } deriving (Eq, Show)
+
+instance FromJSON YamConfig where
+  parseJSON = withObject "YamConfig" $ \v -> YamConfig
+    <$> v .:  "datasource"
+    <*> v .:? "swagger" .!= def
+    <*> v .:  "application"
+    <*> v .:? "port" .!= 8888
+
diff --git a/src/Yam/DataSource.hs b/src/Yam/DataSource.hs
new file mode 100644
--- /dev/null
+++ b/src/Yam/DataSource.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards   #-}
+module Yam.DataSource where
+
+import           Control.Exception              (bracket)
+import           Control.Monad.IO.Unlift
+import           Control.Monad.Logger.CallStack
+import           Data.Acquire                   (withAcquire)
+import           Data.Aeson
+import           Data.Conduit
+import qualified Data.Conduit.List              as CL
+import           Data.Pool
+import           Data.Text                      (Text)
+import           Database.Persist.Sql
+
+data DataSourceConfig = DataSourceConfig
+  { url        :: Text
+  , maxThreads :: Int
+  } deriving (Eq, Show)
+
+instance FromJSON DataSourceConfig where
+  parseJSON = withObject "DataSourceConfig" $ \v -> DataSourceConfig
+    <$> v .: "url"
+    <*> v .:? "max-threads" .!= 10
+
+data DataSource = DataSource
+  { config :: DataSourceConfig
+  , pool   :: ConnectionPool
+  }
+
+type DataSourceProvider = DataSourceConfig -> LoggingT IO ConnectionPool
+
+runInDB :: LogFunc -> DataSourceProvider -> DataSourceConfig -> (DataSource -> IO a) -> IO a
+runInDB logfunc f config g = bracket (runLoggingT (f config) logfunc) destroyAllResources (\pool -> g DataSource{..})
+
+-- SqlPersistT ~ ReaderT SqlBackend
+type DB = SqlPersistT
+
+runDB :: (MonadLoggerIO m, MonadUnliftIO m) => DataSource -> DB m a -> m a
+runDB DataSource{..} db = do
+  logger <- askLoggerIO
+  withRunInIO $ \run -> withResource pool $ run . \c -> runSqlConn db c { connLogFunc = logger }
+
+query
+  :: (MonadUnliftIO m)
+  => Text
+  -> [PersistValue]
+  -> DB m [[PersistValue]]
+query sql params = do
+  res <- rawQueryRes sql params
+  withAcquire res (\a -> runConduit $ a .| CL.fold (flip (:)) [])
+
+selectValue :: (PersistField a, MonadUnliftIO m) => Text -> DB m [a]
+selectValue sql = fmap unSingle <$> rawSql sql []
diff --git a/src/Yam/Util.hs b/src/Yam/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Yam/Util.hs
@@ -0,0 +1,18 @@
+module Yam.Util where
+
+import           Control.Monad.Logger.CallStack
+import           Data.Text                      (Text, justifyRight, pack)
+import           Data.Word
+import           Numeric
+import           System.Random
+
+randomString :: Int -> IO Text
+randomString n = do
+  c <- randomIO :: IO Word64
+  return $ justifyRight n '0' $ pack $ showHex c ""
+
+
+showText :: Show a => a -> Text
+showText = pack . show
+
+type LogFunc = Loc -> LogSource -> LogLevel -> LogStr -> IO ()
diff --git a/src/Yam/Web/Middleware.hs b/src/Yam/Web/Middleware.hs
new file mode 100644
--- /dev/null
+++ b/src/Yam/Web/Middleware.hs
@@ -0,0 +1,33 @@
+module Yam.Web.Middleware where
+
+import           Control.Exception
+import           Control.Monad
+import           Control.Monad.Logger.CallStack
+import qualified Data.ByteString.Lazy.Char8         as B
+import           Data.Maybe
+import           Data.Text                          (Text, pack)
+import           Data.Vault.Lazy
+import           Network.Wai
+import           Servant
+import           Servant.Server.Internal.ServantErr (responseServantErr)
+import           Yam.Util
+
+prepareMiddleware :: IO Vault -> Middleware
+prepareMiddleware pre app req resH = do
+  v <- pre
+  app req { vault = vault req `union` v } resH
+
+errorMiddleware :: (Request -> SomeException -> IO Response) -> Middleware
+errorMiddleware f app req resH = app req resH `catch` (f req >=> resH)
+
+traceMiddleware :: Key Text -> Middleware
+traceMiddleware k = prepareMiddleware $ do
+  traceId <- randomString 16
+  return $ insert k traceId empty
+
+servantErrorMiddleware :: (LoggingT IO Response -> IO Response) -> Middleware
+servantErrorMiddleware lc = errorMiddleware $ \_ e -> lc $ do
+  logError (pack $ show e)
+  return . responseServantErr $ fromMaybe
+    err400 { errBody = B.pack $ show e }
+    (fromException e :: Maybe ServantErr)
diff --git a/src/Yam/Web/Swagger.hs b/src/Yam/Web/Swagger.hs
new file mode 100644
--- /dev/null
+++ b/src/Yam/Web/Swagger.hs
@@ -0,0 +1,61 @@
+{-# LANGUAGE DataKinds         #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards   #-}
+{-# LANGUAGE TypeFamilies      #-}
+{-# LANGUAGE TypeOperators     #-}
+module Yam.Web.Swagger(
+    HasSwagger
+  , SwaggerConfig(..)
+  , serveWithContextAndSwagger
+  , module Servant
+  ) where
+
+import           Data.Aeson
+import           Data.Default
+import           Data.Maybe
+import           Data.Reflection
+import           GHC.TypeLits
+import           Servant
+import           Servant.Swagger
+import           Servant.Swagger.UI
+
+data SwaggerConfig = SwaggerConfig
+  { urlDir    :: String
+  , urlSchema :: String
+  , enabled   :: Bool
+  } deriving (Eq, Show)
+
+instance Default SwaggerConfig where
+  def = fromJust $ decode "{}"
+
+instance FromJSON SwaggerConfig where
+  parseJSON = withObject "SwaggerConfig" $ \v -> SwaggerConfig
+    <$> v .:? "dir"     .!= "swagger-ui"
+    <*> v .:? "schema"  .!= "swagger-ui.json"
+    <*> v .:? "enabled" .!= True
+
+type SAPI dir schema api = SwaggerSchemaUI dir schema :<|> api
+
+serveWithContextAndSwagger
+  :: (HasSwagger api, HasServer api context)
+  => SwaggerConfig
+  -> Proxy api
+  -> Context context
+  -> ServerT api Handler
+  -> Application
+serveWithContextAndSwagger SwaggerConfig{..} proxy cxt api =
+    if enabled
+      then reifySymbol urlDir $ \pd -> reifySymbol urlSchema $ \ps -> go (pd,ps) proxy cxt api
+      else serveWithContext proxy cxt api
+  where
+    go :: (HasSwagger api, HasServer api context, KnownSymbol d, KnownSymbol s)
+        => (Proxy d, Proxy s)
+        -> Proxy api
+        -> Context context
+        -> ServerT api Handler
+        -> Application
+    go pds p c api' = let p' = g2 pds in serveWithContext p' c (g3 p api' p')
+    g2 :: (Proxy d, Proxy s) -> Proxy (SAPI d s api)
+    g2 _ = Proxy
+    g3 :: HasSwagger api => Proxy api -> Server api -> Proxy (SAPI d s api) -> Server (SAPI d s api)
+    g3 p a _ = swaggerSchemaUIServer (toSwagger p) :<|> a
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Main where
+
+
+import           Control.Monad.IO.Class
+import           Data.Aeson
+import           Data.Maybe
+import qualified Data.Salak             as S
+import           Data.Text              (Text)
+import           Test.Hspec
+import           Test.QuickCheck
+import           Yam.Config
+import           Yam.DataSource
+
+main = hspec spec
+
+spec :: Spec
+spec = do
+  describe "Yam.Config" specConfig
+
+specConfig = do
+  context "configuration" $ do
+    it "load" $ do
+      p <- S.defaultPropertiesWithFile "yam_test.yml"
+      let get :: S.FromProperties a => Text -> Maybe a
+          get = flip S.lookup p
+      let dsf = get "yam.datasource" :: Maybe DataSourceConfig
+      shouldSatisfy dsf isJust
+      let conf = get "yam" :: Maybe YamConfig
+      shouldSatisfy conf isJust
+      datasource <$> conf `shouldBe` dsf
diff --git a/yam.cabal b/yam.cabal
new file mode 100644
--- /dev/null
+++ b/yam.cabal
@@ -0,0 +1,134 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.31.1.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: c2763c742d9115cc6b3b693cfab16de4ee30c9a27302cffd5a229e58c698da3a
+
+name:           yam
+version:        0.4.0
+synopsis:       Yam Web
+category:       Web
+homepage:       https://github.com/leptonyu/yam#readme
+author:         Daniel YU
+maintainer:     Daniel YU <leptonyu@gmail.com>
+copyright:      (c) 2018 Daniel YU
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    yam_test.yml
+
+library
+  exposed-modules:
+      Yam
+      Yam.Config
+      Yam.DataSource
+      Yam.Web.Middleware
+      Yam.Web.Swagger
+  other-modules:
+      Yam.Util
+  hs-source-dirs:
+      src
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -fno-warn-orphans -fno-warn-missing-signatures
+  build-depends:
+      aeson
+    , base >=4.7 && <5
+    , bytestring
+    , conduit
+    , data-default
+    , monad-logger
+    , mtl
+    , persistent
+    , random
+    , reflection
+    , resource-pool
+    , resourcet
+    , salak
+    , servant-server
+    , servant-swagger
+    , servant-swagger-ui
+    , text
+    , unliftio-core
+    , vault
+    , wai
+    , warp
+  default-language: Haskell2010
+
+executable yam
+  main-is: Main.hs
+  other-modules:
+      Paths_yam
+  hs-source-dirs:
+      demo
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -fno-warn-orphans -fno-warn-missing-signatures
+  build-depends:
+      aeson
+    , base >=4.7 && <5
+    , bytestring
+    , conduit
+    , data-default
+    , monad-logger
+    , mtl
+    , persistent
+    , persistent-sqlite
+    , random
+    , reflection
+    , resource-pool
+    , resourcet
+    , salak
+    , servant-server
+    , servant-swagger
+    , servant-swagger-ui
+    , text
+    , time
+    , unliftio-core
+    , vault
+    , wai
+    , wai-extra
+    , warp
+    , yam
+  default-language: Haskell2010
+
+test-suite spec
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Yam
+      Yam.Config
+      Yam.DataSource
+      Yam.Util
+      Yam.Web.Middleware
+      Yam.Web.Swagger
+      Paths_yam
+  hs-source-dirs:
+      test
+      src
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -fno-warn-orphans -fno-warn-missing-signatures
+  build-depends:
+      QuickCheck
+    , aeson
+    , base >=4.7 && <5
+    , bytestring
+    , conduit
+    , data-default
+    , hspec ==2.*
+    , monad-logger
+    , mtl
+    , persistent
+    , random
+    , reflection
+    , resource-pool
+    , resourcet
+    , salak
+    , servant-server
+    , servant-swagger
+    , servant-swagger-ui
+    , text
+    , unliftio-core
+    , vault
+    , wai
+    , warp
+  default-language: Haskell2010
diff --git a/yam_test.yml b/yam_test.yml
new file mode 100644
--- /dev/null
+++ b/yam_test.yml
@@ -0,0 +1,4 @@
+yam:
+  application: yam
+  datasource:
+    url: ':memory:'
