diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.markdown
@@ -0,0 +1,7 @@
+# Change log
+
+Bento uses [Semantic Versioning][].
+The change log is available through the [releases on GitHub][].
+
+[Semantic Versioning]: http://semver.org/spec/v2.0.0.html
+[releases on GitHub]: https://github.com/tfausak/bento/releases
diff --git a/README.markdown b/README.markdown
new file mode 100644
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,12 @@
+# 🍱 [Bento][]
+
+[![Version badge][]][version]
+[![Build badge][]][build]
+
+Bento manages stateful components.
+
+[Bento]: https://github.com/tfausak/bento
+[Version badge]: https://www.stackage.org/package/bento/badge/nightly?label=version
+[version]: https://www.stackage.org/package/bento
+[Build badge]: https://travis-ci.org/tfausak/bento.svg?branch=main
+[build]: https://travis-ci.org/tfausak/bento
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,4 @@
+import Distribution.Simple
+
+main :: IO ()
+main = defaultMain
diff --git a/bento.cabal b/bento.cabal
new file mode 100644
--- /dev/null
+++ b/bento.cabal
@@ -0,0 +1,35 @@
+-- This file has been generated from package.yaml by hpack version 0.9.0.
+--
+-- see: https://github.com/sol/hpack
+
+name:           bento
+version:        0.1.0
+synopsis:       🍱 Manage stateful components.
+description:    Bento manages stateful components.
+category:       Utility
+homepage:       https://github.com/tfausak/bento#readme
+bug-reports:    https://github.com/tfausak/bento/issues
+maintainer:     Taylor Fausak
+license:        MIT
+build-type:     Simple
+cabal-version:  >= 1.10
+
+extra-source-files:
+    CHANGELOG.markdown
+    package.yaml
+    README.markdown
+    stack.yaml
+
+source-repository head
+  type: git
+  location: https://github.com/tfausak/bento
+
+library
+  hs-source-dirs:
+      library
+  ghc-options: -Wall
+  build-depends:
+      base >=4 && <5
+  exposed-modules:
+      Bento
+  default-language: Haskell2010
diff --git a/library/Bento.hs b/library/Bento.hs
new file mode 100644
--- /dev/null
+++ b/library/Bento.hs
@@ -0,0 +1,115 @@
+{-# LANGUAGE TypeFamilies #-}
+
+-- | Bento manages stateful components. It is inspired by
+-- <https://github.com/stuartsierra/component Stuart Sierra's Component>
+-- library for Clojure.
+module Bento where
+
+-- | A stateful component. Usually you will define an instance of this class to
+-- a data type that contains all of its runtime state.
+--
+-- @data Example = Example { handle :: 'System.IO.Handle' }
+--instance 'Component' Example where
+--    -- To be defined...@
+class Component component where
+    -- | Everything necessary to start the component. Typically this is a
+    -- tuple, but you are free to use whichever data structure you want. If
+    -- your component does not have any dependencies, use @()@, the empty
+    -- tuple.
+    --
+    -- @type 'Dependencies' Example = ('FilePath', 'System.IO.IOMode')@
+    type Dependencies component :: *
+
+    -- | Starts the component. This is where you should do things like open
+    -- file handles, set up connections, and generally acquire resources. If
+    -- anything goes wrong, just throw an exception, preferrably with
+    -- 'Control.Exception.throwIO'.
+    --
+    -- This function should not block forever. If you need to start something
+    -- that should keep running, like a server, put it on another thread with
+    -- 'Control.Concurrent.forkIO'.
+    --
+    -- @'start' (path, mode) = do
+    --    h <- 'System.IO.openFile' path mode
+    --    let component = Example { handle = h }
+    --    'return' component@
+    start :: Dependencies component -> IO component
+
+    -- | Stops the component. Generally this will do the opposite of whatever
+    -- you did in 'start'. The default implementation does nothing, which can
+    -- be enough if you want the garbage collector to handle everything.
+    --
+    -- @'stop' component = do
+    --    'System.IO.hClose' (handle component)@
+    stop :: component -> IO ()
+    stop _component = return ()
+
+-- * Complete example
+
+-- $
+-- The follow is a complete example of using 'Component's to build a larger
+-- system, which is itself a 'Component'.
+--
+-- For this simple example, we will be starting a web server. The only piece of
+-- configuration we need is the port to listen on. We will get that from the
+-- environment. If it's not available, we'll fall back to a default.
+--
+-- @data Config = Config { port :: Int }
+--instance 'Component' Config where
+--    type 'Dependencies' Config = ()
+--    'start' () = do
+--        p <- 'System.Environment.lookupEnv' \"PORT\"
+--        let config = Config { port = 'Data.Maybe.fromMaybe' 8080 p }
+--        'return' config@
+--
+-- Now that we have the config, we can go ahead and set up the server. It
+-- doesn't have to care how the config gets the port. We just have to list the
+-- config as a dependency. We'll also need the 'Network.Wai.Application' we
+-- want to run on the server.
+--
+-- Since 'start' shouldn't block forever, we fire up the server on a separate
+-- thread. We keep track of the thread ID so that we can shut down the server
+-- when we 'stop' by killing the thread.
+--
+-- @data Server = Server { threadId :: 'Control.Concurrent.ThreadId' }
+--instance 'Component' Server where
+--    type 'Dependencies' Server = (Config, 'Network.Wai.Application')
+--    'start' (config, application) = do
+--        tid <- 'Control.Concurrent.forkIO' ('Network.Wai.Handler.Warp.run' (port config) application)
+--        let server = Server { threadId = tid }
+--        return server
+--    'stop' server = do
+--        'Control.Concurrent.killThread' (threadId server)@
+--
+-- With the config and server in hand, we can combine them into a larger
+-- system. The system will need the 'Network.Wai.Application' we want to run,
+-- but it will handle 'start'ing the config and passing it to the server.
+--
+-- To 'stop' the system, we 'stop' each 'Component' in the reverse order that
+-- we 'start'ed them.
+--
+-- @data System = System { config :: Config, server :: Server }
+--instance 'Component' System where
+--    type 'Dependencies' System = ('Network.Wai.Application')
+--    'start' (application) = do
+--        c <- 'start' ()
+--        s <- 'start' (c, application)
+--        let system = System { config = c, server = s }
+--        'return' system
+--    'stop' system = do
+--        'stop' (server system)
+--        'stop' (config system)@
+--
+-- To actually run the system, we 'start' it just like the other 'Component's.
+-- Once it's started, we want to wait forever until something sends us a
+-- @SIGINT@. Then we 'stop' the system.
+--
+-- @main :: 'IO' ()
+--main = do
+--    let application _request respond = respond ('Network.Wai.responseLBS' 'Network.HTTP.Types.ok200' [] 'Data.ByteString.Lazy.empty')
+--    system <- 'start' (application)
+--    sentinel <- 'Control.Concurrent.newEmptyMVar'
+--    let handler _signal = 'Control.Concurrent.putMVar' sentinel ()
+--    'System.Signal.installHandler' 'System.Signal.sigINT' handler
+--    'Control.Concurrent.takeMVar' sentinel
+--    'stop' (system :: System)@
diff --git a/package.yaml b/package.yaml
new file mode 100644
--- /dev/null
+++ b/package.yaml
@@ -0,0 +1,18 @@
+category: Utility
+description: Bento manages stateful components.
+extra-source-files:
+- CHANGELOG.markdown
+- package.yaml
+- README.markdown
+- stack.yaml
+ghc-options: -Wall
+github: tfausak/bento
+library:
+  dependencies: base >=4 && <5
+  source-dirs: library
+license: MIT
+license-file: LICENSE.markdown
+maintainer: Taylor Fausak
+name: bento
+synopsis: ! "\U0001F371 Manage stateful components."
+version: '0.1.0'
diff --git a/stack.yaml b/stack.yaml
new file mode 100644
--- /dev/null
+++ b/stack.yaml
@@ -0,0 +1,3 @@
+install-ghc: true
+require-stack-version: ! '>=1.0.4'
+resolver: nightly-2016-04-16
