diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,29 @@
 
 
 
+settings 0.1.0.1 -- 2015-09-14
+==============================
+
+General, build and documentation changes:
+
+* Write a tutorial, see Data.Settings module
+
+New APIs, features and enhancements:
+
+* (None)
+
+Bug fixes:
+
+* (None)
+
+Dependency changes:
+
+* (None)
+
+
+
+
+
 settings 0.1.0.0 -- 2015-09-10
 ==============================
 
diff --git a/settings.cabal b/settings.cabal
--- a/settings.cabal
+++ b/settings.cabal
@@ -1,5 +1,5 @@
 name:                settings
-version:             0.1.0.0
+version:             0.1.0.1
 synopsis:            Runtime-editable program settings.
 description:
   This library aims to be a tool for constructing a settings management UI on
@@ -12,9 +12,7 @@
   similarity to @git config@ and <http://weechat.org Weechat>'s settings
   system, but isn't identical.
   .
-  NOTE: The API is probably not documented well enough. Sorry for that. I'm
-  releasing like this because I want to release packages which depend on this
-  library. Full docs will be written.
+  To get started, see the tutorial in the "Data.Settings" module.
 homepage:            http://rel4tion.org/projects/settings/
 bug-reports:         http://rel4tion.org/projects/settings/tickets/
 license:             PublicDomain
diff --git a/src/Data/Settings.hs b/src/Data/Settings.hs
--- a/src/Data/Settings.hs
+++ b/src/Data/Settings.hs
@@ -13,6 +13,299 @@
  - <http://creativecommons.org/publicdomain/zero/1.0/>.
  -}
 
+-- | This top-level module contains just a tutorial, which you can read below.
+-- It will help you figure out which of the sub-modules you need, and how to
+-- use them.
+--
+-- = Tutorial
+--
+-- == Concepts
+--
+-- For a real usage example, see the /funbot/ package.
+--
+-- This library works with 2 components of your application state:
+--
+-- 1. Application settings value, of any type you like. Usually this is a
+--    record of a type you define specifically for your application. It can be
+--    a value just for settings, or, if modifiable settings are stored in
+--    various parts of your state, it can be the state value itself.
+-- 2. A settings tree, of type @Section@ (defined in "Data.Settings.Types").
+--    This is a user interface component for accessing the settings values as a
+--    tree with labeled nodes. If your settings tree never changes, you can use
+--    a Haskell value directly for it. It if changes, add it to your
+--    application state so that it can be modified as needed during run time.
+--
+-- The idea is that you freely use whatever you like for the settings values,
+-- and the settings tree is a UI component added on top without interfering
+-- with your program logic code. Persistence using periodic exports to JSON is
+-- provided in the "Data.Settings.Persist" module, but you can use any other
+-- solution as needed, e.g. the acid-state package. The persistence module is
+-- unrelated to the settings tree, and should probably move into its own
+-- package and get some extra features missing right now, like version control.
+--
+-- == Settings Tree Basics
+--
+-- In order to understand the layers of the API, we'll examine it bottom-up.
+-- We'll start with the generic flexible parts and move towards the more
+-- specific but simpler and more convenient ones. You'll likely need a bit of
+-- both sides, so it's probably best to taste both.
+--
+-- Suppose we're writing a terminal based text editor, like /nano/ or /vim/.
+-- The UI allows the user to enter commands like @get x.y.z@ or @set x.y.z val@
+-- which manipulate the settings.
+--
+-- Let's define a type for settings. It may look like this:
+--
+-- > data Settings = Settings
+-- >     { setsTabWidth    :: Int
+-- >     , setsFont        :: String
+-- >     , setsTextSize    :: Int
+-- >     , setsColorScheme :: String
+-- >     }
+--
+-- For simplicity, suppose the settings tree won't be changing, so all we need
+-- in our application state is the settings. Let's use this:
+--
+-- > data AppState = AppState
+-- >     { appOpenFiles :: [String]
+-- >     , appUI        :: Widget
+-- >     , appSettings  :: Settings
+-- >     }
+--
+-- If we wanted to allow the settings tree structure to change, we'd have a
+-- field for it too in the app state record.
+--
+-- This will be our monad:
+--
+-- > type App = StateT AppState IO
+--
+-- Now let's define a settings tree. A settings tree is the top-level /section/
+-- of it. Each such section consists of two things: A set of settings options,
+-- and a set of subsections. An empty tree looks like this:
+--
+-- > import Data.Settings.Section (empty)
+-- >
+-- > stree :: Section App
+-- > stree = empty
+--
+-- Which is equivalent to:
+--
+-- > import qualified Data.HashMap.Lazy as M
+-- >
+-- > stree :: Section App
+-- > stree = Section
+-- >     { secOpts = M.empty
+-- >     , secSubs = M.empty
+-- >     }
+--
+-- The 'secOpts' field is a map between option names and 'Option' values. The
+-- 'secSubs' field is a map between subsection names and 'Section' values. We
+-- can then refer to a specific tree node using period-separated syntax. For
+-- example, if we have a tree with a single top-level option @\"a\"@, we can
+-- refer to it in the UI simply a @\"a\"@. If we have a tree with a subsection
+-- @\"s\"@ and under it an option @\"a\"@, we refer to that section as @\"a\"@
+-- and to the option under it as @\"s.a\"@. And so on, we can have arbitrarily
+-- deep nesting of sections and options, e.g. @\"s.t.u.v.w.x.a\"@.
+--
+-- The low-level flexible way to define a settings tree is by using 'Option'
+-- value contructors directly. Let's define a simple flat tree with 4 options
+-- and no subsections.
+--
+-- The 'Option' fields are monadic actions in our application monad, @App@.
+--
+-- > import Control.Monad.Trans.State
+-- > import qualified Data.HashMap.Lazy as M
+-- > import Data.Settings.Types
+-- > import Text.Read (readMaybe)
+-- >
+-- > -- Convenience wrappers to make the code shorter
+-- > -- Perhaps a good chance to use lens?
+-- > getS = gets appSettings
+-- > putS sets = modify $ \ app -> app { appSettings = sets }
+-- > modifyS f = modify $ \ app -> app { appSettings = f $ appSettings app }
+-- >
+-- > stree :: Section App
+-- > stree = Section
+-- >     { secOpts = M.fromList
+-- >         [ ( "tab-width"
+-- >           , Option
+-- >               { optGet   = liftM (show . setsTabWidth) getS
+-- >               , optSet   = \ val ->
+-- >                     case readMaybe val of
+-- >                         Just n -> do
+-- >                             modifyS $ \ s -> s { setsTabWidth = n }
+-- >                             return Nothing
+-- >                         Nothing -> return $ Just $ InvalidValueForType val
+-- >               , optReset = modifyS $ \ s -> s { setsTabWidth = 4 }
+-- >               }
+-- >           )
+-- >         , ( "font"
+-- >           , Option {- ... similar fashion ... -}
+-- >           )
+-- >         , ( "text-size"
+-- >           , Option {- ... similar fashion ... -}
+-- >           )
+-- >         , ( "color-scheme"
+-- >           , Option {- ... similar fashion ... -}
+-- >           )
+-- >         ]
+-- >     , secSubs = M.empty
+-- >     }
+--
+-- == Building a Settings UI
+--
+-- We'll see higher level alternatives later. Let's see how to contruct the
+-- settings UI now. The "Data.Settings.Iterface" provides a set of high-level
+-- functions you can use on your UI code. You just need to wrap them with UI
+-- actions like error message (e.g. invalid value) and feedback for successful
+-- operations.
+--
+-- Before we can use those functions, we need to make our application monad an
+-- instance of the 'MonadSettings' (multi-parameter) typeclass:
+--
+-- > instance MonadSettings App Settings where
+-- >     getSettings = getS
+-- >     putSettings = putS
+-- >     modifySettings = modifyS
+-- >     getSTree = return stree
+--
+-- Now, suppose the user enters the command @get x.y.z@ in our text editor's
+-- command input line. This should return a friendly result. If @x.y.z@ is a
+-- valid path in our settings tree leading to an option value, display that
+-- value. If it's a section, display a list of the options and subsections it
+-- contains. If it's neither, i.e. the path is invalid, report the error.
+--
+-- Such a UI can easily be constructed using functions in
+-- "Data.Settings.Interface", e.g. see the 'Data.Settings.Interface.query'
+-- function. Using the values it returns, you can construct UI strings to
+-- display on the screen.
+--
+-- For example, in our case we'd want @get@ to display the top-level tree
+-- contents, @get tab-width@ to display a number (4 by default) and @get foo@
+-- to display an error /no such option or section/.
+--
+-- == Settings Tree Definition Tools
+--
+-- Let's go back to defining the settings tree. Some things we could improve:
+--
+-- * We defined @getS@ and related small functions, and used them when we
+--   defined the 'MonadSettings' instance. Instead, we can first define the
+--   instance and then just use its methods in our settings free definition if
+--   needed.
+-- * The usage of @readMaybe@ and @show@ allowed us to easily and quickly wrap
+--   the tab width, an 'Int' value, by the string-based interface. But with
+--   larger settings records and more value types, we'd want something more
+--   robust and appropriate for UI. For example, if we did this for a 'Bool'
+--   field, the user would have to type in @set x.y.z True@ while
+--   @set x.y.z yes@ wouldn't work. Why tie the UI to the way booleans are
+--   written in Haskell? We can have /true, TRUE, True, yes, Yes, 1/ etc. all
+--   mean 'True'. Be flexible and user friendly.
+-- * Once we write the 'MonadSettings' instance, instead of using its methods
+--   directly (like we used @getS@ etc.) we can have wrappers do it for us, so
+--   that we only need to write functions operating over the @Settings@ type
+--   directly, making our code simple and readable and easy to tweak.
+--
+-- Let's start with the second point, wrapping typed settings values with UI,
+-- e.g. like the example given for booleans above. The "Data.Settings.Option"
+-- module provides the @mkOptionV@ function. This function wraps the type
+-- details for us, if we supply instances of the @OptionValue@ class. Let's
+-- define an instance for 'Int', which is the type of 2 out of the 4 fields in
+-- our @Settings@ type. Generally, you'd want to define instances for all the
+-- relevant field types in your settings type, e.g. perhaps also 'Bool' and
+-- 'Float' and custom enum tyes and so on, depending on your requirements and
+-- UI designs.
+--
+-- > instace OptionValue Int where
+-- >     readOption = readMaybe
+-- >     showOption = show
+-- >     typeName = const "Integer"
+--
+-- And here's an instance for 'Bool':
+--
+-- > instace OptionValue Bool where
+-- >     readOption s
+-- >         | sl `elem` ["true, "yes", "on", "1"]   = Just True
+-- >         | sl `elem` ["false", "no", "off", "0"] = Just False
+-- >         | otherwise                             = Nothing
+-- >         where sl = map toLower s
+-- >     showOption = show
+-- >     typeName = const "Boolean"
+--
+-- Now, using @mkOptionV@, and this time also using the @MonadSettings@
+-- functions, we can redefine the tab width option like this:
+--
+-- > mkOptionV
+-- >     (liftM setsTabWidth getSettings)
+-- >     (\ n -> do
+-- >         modifySettings $ \ s -> s { setsTabWidth = n }
+-- >         return True
+-- >     )
+-- >     (modifySettings $ \ s -> s { setsTabWidth = 4 })
+--
+-- Now let's improve further. This will be the highest level of the API. Given
+-- a @MonadSettings@ instance, the repetitive parts of the code can be cleaned
+-- further, by using the @mkOptionS@ function.
+--
+-- > mkOptionS
+-- >     setsTabWidth
+-- >     (\ n s -> Just s { setsTabWidth = n })
+-- >     (\ s -> (Just 4, s { setsTabWidth = 4 }))
+-- >     (const $ return ())
+--
+-- Perhaps a bit cleaner form removing duplication is this:
+--
+-- > mkOptionS
+-- >     setsTabWidth
+-- >     (\ n s -> Just $ set n s)
+-- >     (\ s -> (Just defval, set defval s))
+-- >     (const $ return ())
+-- >     where
+-- >     set n s = s { setsTabWidth = n }
+-- >     defval = 4
+--
+-- The last argument is a callback action to be run when a successful set or
+-- reset of the value occurs.
+--
+-- We are done with the basics. Another 2 aspects of the library are settings
+-- tree modification and persistence.
+--
+-- == Settings Tree Dynamic Modification
+--
+-- Modification simply requires holding the tree as application state, and
+-- changing as needed. Removing sections, adding options and so on. There is an
+-- API in "Data.Settings.Section" for working with the settings tree, and since
+-- unordered maps are being used, you may also find "Data.HashMap.Lazy" useful
+-- (from unordered-containers package).
+--
+-- == Settings Persistence
+--
+-- Finally, persistence. "Data.Settings.Persist" provides a function for
+-- loading the settings value from a JSON file, and a function which generates
+-- a safe scalable saver function. The JSON files are written using the
+-- @aeson-pretty@ package, so that they are easy to read and modify manually if
+-- needed.
+--
+-- The save function generator, @mkSaveSettings@, returns a function which
+-- saves settings when called, but only at most once in @t@, the time interval
+-- passed to the generator. For example, if you pass an interval of 3 seconds,
+-- you can safely call the generated save function even 100 times a second, and
+-- the JSON file will still get updated just once in 3 seconds, avoiding an
+-- overload of file I/O.
+--
+-- The actual saving happens in a dedicated worker thread, so even when a save
+-- does occur, it won't block the caller thread. You can, for example, call the
+-- save function in the callback you pass to @mkOptionS@. The generator can be
+-- called once at program start, and the returned save function saved in
+-- application state.
+--
+-- Using the persistence module requires that you define @FromJSON@ and
+-- @ToJSON@ instances for your settings type, see the @aeson@ package.
+--
+-- Note that while this simple periodic save-to-file method can serve a simple
+-- standalone application well, it won't work if you wish your settings to be
+-- shared by multiple applications and allow them to read and write settings at
+-- the same time. If that's the case, check out the @acid-state@ package, and
+-- other persistence related packages.
 module Data.Settings
     (
     )
diff --git a/src/Data/Settings/Types.hs b/src/Data/Settings/Types.hs
--- a/src/Data/Settings/Types.hs
+++ b/src/Data/Settings/Types.hs
@@ -30,9 +30,15 @@
 
 import qualified Data.HashMap.Lazy as M
 
+-- | A settings option. The option value itself is held as usual in regular
+-- application state, not here. What is held here is /functions/ applied to
+-- that state to get or set the value.
 data Option m = Option
-    { optGet   :: m String
+    { -- |
+      optGet   :: m String
+      -- |
     , optSet   :: String -> m (Maybe SettingsError)
+      -- |
     , optReset :: m ()
     }
 
