diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for wai-control
+
+## 0.1.0.0 -- 2020-07-17
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2020, Felix Springer
+
+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 Felix Springer 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/src/Network/Wai/Handler/WebSockets/Trans.hs b/src/Network/Wai/Handler/WebSockets/Trans.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Wai/Handler/WebSockets/Trans.hs
@@ -0,0 +1,68 @@
+{-# LANGUAGE FlexibleContexts #-}
+
+module Network.Wai.Handler.WebSockets.Trans (
+
+-- * ServerApp
+  ServerAppT
+, liftServerApp
+, runServerAppT
+
+-- * ClientApp
+, ClientAppT
+, liftClientApp
+, runClientAppT
+
+-- * WebSocket
+, websocketsOrT
+
+) where
+
+import Control.Monad.Base
+import Control.Monad.Trans.Control.Identity
+import Network.Wai.Handler.WebSockets
+import Network.WebSockets
+
+import Network.Wai.Trans
+
+-- | A type synonym for a websockets 'ServerApp' which has been lifted from the IO monad.
+type ServerAppT m = PendingConnection -> m ()
+
+-- | Lift a websockets 'ServerApp' to a 'ServerAppT'.
+liftServerApp :: MonadBase IO m
+              => ServerApp
+              -> ServerAppT m
+liftServerApp serverApp = liftBase . serverApp
+
+-- | Run a 'ServerAppT' in the inner monad.
+runServerAppT :: MonadBaseControlIdentity IO m
+              => ServerAppT m
+              -> m ServerApp
+runServerAppT serverAppT = liftBaseWithIdentity $ \ runInBase ->
+  return $ runInBase . serverAppT
+
+-- | A type synonym for a websockets 'ClientApp' which has been lifted from the IO monad.
+type ClientAppT m a = Connection -> m a
+
+-- | Lift a websockets 'ClientApp' to a 'ClientAppT'.
+liftClientApp :: MonadBase IO m
+              => ClientApp a
+              -> ClientAppT m a
+liftClientApp clientApp = liftBase . clientApp
+
+-- | Run a 'ClientAppT' in the inner monad.
+runClientAppT :: MonadBaseControlIdentity IO m
+              => ClientAppT m a
+              -> m (ClientApp a)
+runClientAppT clientAppT = liftBaseWithIdentity $ \ runInBase ->
+  return $ runInBase . clientAppT
+
+-- | Upgrade a 'ServerAppT' to a 'MiddlewareT'.
+-- This function is based on 'websocketsOr'.
+websocketsOrT :: MonadBaseControlIdentity IO m
+              => ConnectionOptions
+              -> ServerAppT m
+              -> MiddlewareT m
+websocketsOrT options serverAppT appT request respond = do
+  serverApp <- runServerAppT serverAppT
+  app <- runApplicationT appT
+  (liftApplication $ websocketsOr options serverApp app) request respond
diff --git a/src/Network/Wai/Trans.hs b/src/Network/Wai/Trans.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/Wai/Trans.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE FlexibleContexts #-}
+
+module Network.Wai.Trans (
+
+  -- * Application
+  ApplicationT
+, liftApplication
+, runApplicationT
+
+  -- * Middleware
+, MiddlewareT
+, liftMiddleware
+, runMiddlewareT
+
+) where
+
+import Control.Monad.Base
+import Control.Monad.Trans.Control.Identity
+import Network.Wai
+
+-- | A type synonym for a wai 'Application' which has been lifted from the 'IO' monad.
+type ApplicationT m = Request -> (Response -> m ResponseReceived) -> m ResponseReceived
+
+-- | Lift a wai 'Application' to an 'ApplicationT'.
+liftApplication :: MonadBaseControlIdentity IO m
+                => Application
+                -> ApplicationT m
+liftApplication app request respond = liftBaseWithIdentity $ \ runInBase ->
+  app request $ runInBase . respond
+
+-- | Run an 'ApplicationT' in the inner monad.
+runApplicationT :: MonadBaseControlIdentity IO m
+                => ApplicationT m
+                -> m Application
+runApplicationT appT = liftBaseWithIdentity $ \ runInBase ->
+  return $ \ request respond -> runInBase $ appT request $ liftBase . respond
+
+-- | A type synonym for a wai 'Middleware' which has been lifted from the 'IO' monad.
+type MiddlewareT m = ApplicationT m -> ApplicationT m
+
+-- | Lift a wai 'Middleware to an 'MiddlewareT'.
+liftMiddleware :: MonadBaseControlIdentity IO m
+               => Middleware
+               -> MiddlewareT m
+liftMiddleware mid appT request respond = do
+  app <- runApplicationT appT
+  liftBaseWithIdentity $ \ runInBase -> mid app request $ runInBase . respond
+
+-- | Run an 'MiddlewareT' in the inner monad.
+runMiddlewareT :: MonadBaseControlIdentity IO m
+               => MiddlewareT m
+               -> m Middleware
+runMiddlewareT midT = liftBaseWithIdentity $ \ runInBase ->
+  return $ \ app request respond -> do
+    app' <- runInBase . runApplicationT . midT $ liftApplication app
+    app' request respond
diff --git a/wai-control.cabal b/wai-control.cabal
new file mode 100644
--- /dev/null
+++ b/wai-control.cabal
@@ -0,0 +1,36 @@
+name:                wai-control
+version:             0.1.0.0
+synopsis:            Give wai Applications an IO-based inner monad
+description:         This package allows IO-based monads in covariant and contravariant positions
+                     of wai Applications.
+                     The monads, which are applicable for this, need to have MonadBaseControl IO
+                     instances. This are for most cases ReaderT stacks based on the IO monad.
+                     This package will especially be of interest, if you are sharing access to
+                     MVars, TVars or other concurrent data, while controlling that access with
+                     monad transformers.
+
+                     This package is based on wai-transformers by Athan Clark:
+                     https://github.com/athanclark/wai-transformers
+license:             BSD3
+license-file:        LICENSE
+author:              Felix Springer
+maintainer:          felixspringer149@gmail.com
+homepage:            https://github.com/jumper149/wai-control
+bug-reports:         https://github.com/jumper149/wai-control/issues
+category:            Control, Web
+build-type:          Simple
+extra-source-files:  CHANGELOG.md
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Network.Wai.Trans
+                       Network.Wai.Handler.WebSockets.Trans
+  build-depends:       base                   >= 4.5      && < 5
+                     , transformers-base      >= 0.4.5.2  && < 0.5
+                     , monad-control-identity >= 0.1.0.1  && < 1.1
+                     , wai                    >= 3.2      && < 3.3
+                     , wai-websockets         >= 3.0.1.2  && < 3.1
+                     , websockets             >= 0.12.5.3 && < 0.13
+  hs-source-dirs:      src
+  default-language:    Haskell2010
+  ghc-options:         -Wall
