diff --git a/calamity.cabal b/calamity.cabal
--- a/calamity.cabal
+++ b/calamity.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 508df452f0143768a08aa0154d0b2fdb542f78f4238b4e028793ba91a6865923
+-- hash: 0b61f91df75a0a06757763a207ce83d2a9597c059dadd7798a155ace29013568
 
 name:           calamity
-version:        0.1.6.2
+version:        0.1.7.0
 synopsis:       A library for writing discord bots
 description:    Please see the README on GitHub at <https://github.com/nitros12/calamity#readme>
 category:       Network, Web
@@ -63,11 +63,11 @@
       Calamity.Internal.SnowflakeMap
       Calamity.Internal.Updateable
       Calamity.Internal.Utils
-      Calamity.LogEff
       Calamity.Metrics.Eff
       Calamity.Metrics.Internal
       Calamity.Metrics.Noop
       Calamity.Types
+      Calamity.Types.LogEff
       Calamity.Types.Model
       Calamity.Types.Model.Channel
       Calamity.Types.Model.Channel.Attachment
diff --git a/src/Calamity/Client/Client.hs b/src/Calamity/Client/Client.hs
--- a/src/Calamity/Client/Client.hs
+++ b/src/Calamity/Client/Client.hs
@@ -2,14 +2,13 @@
 
 -- | The client
 module Calamity.Client.Client
-    ( Client(..)
-    , CalamityEvent(Dispatch, ShutDown)
-    , react
+    ( react
     , runBotIO
     , stopBot
     , sendPresence
     , events
     , fire
+    , CalamityEvent(Dispatch, ShutDown)
     , customEvt ) where
 
 import           Calamity.Cache.Eff
@@ -77,6 +76,10 @@
                 inc
                 outc
 
+-- | Create a bot, run your setup action, and then loop until the bot closes.
+--
+-- This method has a 'P.Fail' effect to handle fatal errors that happen during
+-- setup (bad token, etc).
 runBotIO :: (P.Members '[P.Embed IO, P.Final IO, P.Fail, CacheEff, MetricEff] r, Typeable r) => Token -> SetupEff r -> P.Sem r ()
 runBotIO token setup = do
   client <- P.embed $ newClient token
@@ -87,30 +90,83 @@
     Di.push "calamity-loop" clientLoop
     Di.push "calamity-stop" finishUp
 
-react :: forall s r. (BotC r, InsertEventHandler s (P.Sem r)) => EHType s (P.Sem r) -> P.Sem r ()
+-- | Register an event handler.
+--
+-- Refer to 'EventType' for what events you can register, and 'EHType' for the
+-- parameters the event handlers they receive.
+--
+-- You'll probably want @TypeApplications@ and need @DataKinds@ enabled to
+-- specify the type of @s@.
+--
+-- ==== Examples
+--
+-- Reacting to every message:
+--
+-- @
+-- 'react' @\''MessageCreateEvt' '$' \msg -> 'print' '$' "Got message: " '<>' 'show' msg
+-- @
+--
+-- Reacting to a custom event:
+--
+-- @
+-- 'react' @(\''CustomEvt' "my-event" ('Data.Text.Text', 'Message')) $ \(s, m) ->
+--    'void' $ 'Calamity.Tellable.tell' @'Data.Text.Text' m ("Somebody told me to tell you about: " '<>' s)
+-- @
+--
+-- ==== Notes
+--
+-- This function is pretty bad for giving nasty type errors,
+-- since if something doesn't match then 'EHType' might not get substituted,
+-- which will result in errors about parameter counts mismatching.
+react :: forall (s :: EventType) r. (BotC r, InsertEventHandler s (P.Sem r)) => EHType s (P.Sem r) -> P.Sem r ()
 react handler = let handlers = makeEventHandlers (Proxy @s) (Proxy @(P.Sem r)) handler
                 in P.atomicModify (handlers <>)
 
+-- | Fire an event that the bot will then handle.
+--
+-- ==== Examples
+--
+-- Firing an event named \"my-event\":
+--
+-- @
+-- 'fire' '$' 'customEvt' @"my-event" ("aha" :: 'Data.Text.Text', msg)
+-- @
 fire :: BotC r => CalamityEvent -> P.Sem r ()
 fire e = do
   inc <- P.asks (^. #eventsIn)
   P.embed $ writeChan inc e
 
 -- | Build a Custom CalamityEvent
+--
+-- You'll probably want @TypeApplications@ to specify the type of @s@.
+--
+-- The types of @s@ and @a@ must match up with the event handler you want to
+-- receive it.
+--
+-- ==== Examples
+--
+-- Building an event named \"my-event\":
+--
+-- @
+-- 'customEvt' @"my-event" ("aha" :: 'Data.Text.Text', msg)
+-- @
 customEvt :: forall s a. (Typeable s, Typeable a) => a -> CalamityEvent
 customEvt x = Custom (typeRep $ Proxy @s) (toDyn x)
 
+-- | Get a copy of the event stream.
 events :: BotC r => P.Sem r (OutChan CalamityEvent)
 events = do
   inc <- P.asks (^. #eventsIn)
   P.embed $ dupChan inc
 
+-- | Set the bot's presence on all shards.
 sendPresence :: BotC r => StatusUpdateData -> P.Sem r ()
 sendPresence s = do
   shards <- P.asks (^. #shards) >>= P.embed . readTVarIO
   for_ shards $ \(inc, _) ->
     P.embed $ writeChan inc (SendPresence s)
 
+-- | Initiate shutting down the bot.
 stopBot :: BotC r => P.Sem r ()
 stopBot = do
   debug "stopping bot"
@@ -127,8 +183,8 @@
   for_ shards $ \(_, shardThread) -> P.await shardThread
   debug "bot has stopped"
 
--- | main loop of the client, handles fetching the next event, processing the event
--- and invoking it's handler functions
+-- | main loop of the client, handles fetching the next event, processing the
+-- event and invoking it's handler functions
 clientLoop :: BotC r => P.Sem r ()
 clientLoop = do
   outc <- P.asks (^. #eventsOut)
diff --git a/src/Calamity/Client/Types.hs b/src/Calamity/Client/Types.hs
--- a/src/Calamity/Client/Types.hs
+++ b/src/Calamity/Client/Types.hs
@@ -1,22 +1,21 @@
 -- | Types for the client
 module Calamity.Client.Types
     ( Client(..)
+    , EventType(..)
+    , EHType
     , BotC
     , SetupEff
-    , EHType
     , EventHandlers(..)
-    , EventHandler(..)
     , InsertEventHandler(..)
-    , GetEventHandlers(..)
-    , EventType(..)
+    , getEventHandlers
     , getCustomEventHandlers ) where
 
 import           Calamity.Cache.Eff
 import           Calamity.Gateway.DispatchEvents ( CalamityEvent(..), ReadyData )
 import           Calamity.Gateway.Types          ( ControlMessage )
 import           Calamity.HTTP.Internal.Types
-import           Calamity.LogEff
 import           Calamity.Metrics.Eff
+import           Calamity.Types.LogEff
 import           Calamity.Types.Model.Channel
 import           Calamity.Types.Model.Guild
 import           Calamity.Types.Model.User
@@ -62,6 +61,7 @@
   P.AtomicState EventHandlers, P.Embed IO, P.Final IO, P.Async] r
   , Typeable r)
 
+-- | A concrete effect stack used inside the bot
 type SetupEff r = P.Sem (LogEff ': P.Reader Client ': P.AtomicState EventHandlers ': P.Async ': r) ()
 
 -- | A Data Kind used to fire custom events
@@ -95,7 +95,10 @@
   | TypingStartEvt
   | UserUpdateEvt
   | forall s a. CustomEvt s a
+  -- ^ A custom event, @s@ is the name and @a@ is the data sent to the handler
 
+-- | A type family to decide what the parameters for an event handler should be
+-- determined by the type of event it is handling.
 type family EHType (d :: EventType) m where
   EHType 'ReadyEvt                    m = ReadyData                                   -> m ()
   EHType 'ChannelCreateEvt            m = Channel                                     -> m ()
@@ -218,6 +221,8 @@
   EHInstanceSelector ('CustomEvt _ _) = 'True
   EHInstanceSelector _                = 'False
 
+-- | A helper typeclass that is used to decide how to register regular
+-- events, and custom events which require storing in a map at runtime.
 class InsertEventHandler a m where
   makeEventHandlers :: Proxy a -> Proxy m -> EHType a m -> EventHandlers
 
diff --git a/src/Calamity/Gateway/Shard.hs b/src/Calamity/Gateway/Shard.hs
--- a/src/Calamity/Gateway/Shard.hs
+++ b/src/Calamity/Gateway/Shard.hs
@@ -9,24 +9,25 @@
 import           Calamity.Gateway.DispatchEvents
 import           Calamity.Gateway.Types
 import           Calamity.Internal.Utils
-import           Calamity.LogEff
 import           Calamity.Metrics.Eff
+import           Calamity.Types.LogEff
 import           Calamity.Types.Token
 
 import           Control.Concurrent
 import           Control.Concurrent.Async
-import qualified Control.Concurrent.Chan.Unagi as UC
+import qualified Control.Concurrent.Chan.Unagi   as UC
 import           Control.Concurrent.STM
 import           Control.Concurrent.STM.TBMQueue
 import           Control.Exception
+import qualified Control.Exception.Safe          as Ex
 import           Control.Lens
 import           Control.Monad
 import           Control.Monad.State.Lazy
 
 import qualified Data.Aeson                      as A
 import           Data.Functor
-import           Data.Maybe
 import           Data.IORef
+import           Data.Maybe
 import           Data.Text.Lazy                  ( Text, stripPrefix )
 import           Data.Text.Lazy.Lens
 import           Data.Void
@@ -44,7 +45,7 @@
 import qualified Polysemy.AtomicState            as P
 import qualified Polysemy.Error                  as P
 import qualified Polysemy.Resource               as P
-import qualified Control.Exception.Safe as Ex
+
 import           Prelude                         hiding ( error )
 
 import           TextShow
diff --git a/src/Calamity/Gateway/Types.hs b/src/Calamity/Gateway/Types.hs
--- a/src/Calamity/Gateway/Types.hs
+++ b/src/Calamity/Gateway/Types.hs
@@ -17,8 +17,8 @@
 
 import           Calamity.Gateway.DispatchEvents
 import           Calamity.Internal.AesonThings
-import           Calamity.LogEff
 import           Calamity.Metrics.Eff
+import           Calamity.Types.LogEff
 import           Calamity.Types.Model.Guild.Guild
 import           Calamity.Types.Model.Voice
 import           Calamity.Types.Snowflake
diff --git a/src/Calamity/Internal/Utils.hs b/src/Calamity/Internal/Utils.hs
--- a/src/Calamity/Internal/Utils.hs
+++ b/src/Calamity/Internal/Utils.hs
@@ -12,7 +12,7 @@
     , Calamity.Internal.Utils.error
     , swap ) where
 
-import           Calamity.LogEff
+import           Calamity.Types.LogEff
 
 import           Data.Default.Class
 import qualified Data.HashMap.Lazy   as LH
diff --git a/src/Calamity/LogEff.hs b/src/Calamity/LogEff.hs
deleted file mode 100644
--- a/src/Calamity/LogEff.hs
+++ /dev/null
@@ -1,16 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-
--- | The logging effect we use
-module Calamity.LogEff
-    ( LogEff
-    , LogC ) where
-
-import qualified Df1
-
-import           DiPolysemy
-
-import qualified Polysemy   as P
-
-type LogEff = Di Df1.Level Df1.Path Df1.Message
-
-type LogC r = P.Member LogEff r
diff --git a/src/Calamity/Types/LogEff.hs b/src/Calamity/Types/LogEff.hs
new file mode 100644
--- /dev/null
+++ b/src/Calamity/Types/LogEff.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
+-- | The logging effect we use
+module Calamity.Types.LogEff
+    ( LogEff
+    , LogC ) where
+
+import qualified Df1
+
+import           DiPolysemy
+
+import qualified Polysemy   as P
+
+type LogEff = Di Df1.Level Df1.Path Df1.Message
+
+type LogC r = P.Member LogEff r
diff --git a/src/Calamity/Types/Tellable.hs b/src/Calamity/Types/Tellable.hs
--- a/src/Calamity/Types/Tellable.hs
+++ b/src/Calamity/Types/Tellable.hs
@@ -36,6 +36,7 @@
 -- 'intoMsg' @'Text' "A message" '<>' 'intoMsg' @'Embed' ('def' '&' #description '?~' "Embed description")
 -- @
 class ToMessage a where
+  -- | Turn @a@ into a 'CreateMessageOptions' builder
   intoMsg :: a -> Endo CreateMessageOptions
 
 -- | Message content, '(<>)' concatenates the content
@@ -66,6 +67,17 @@
 runToMessage = flip appEndo def . intoMsg
 
 -- | Send a message to something that is messageable
+--
+-- To send a string literal you'll probably want to use @TypeApplication@ to
+-- specify the type of @msg@
+--
+-- ==== Examples
+--
+-- Sending a string:
+--
+-- @
+-- 'void' $ 'tell' @'Text' m ("Somebody told me to tell you about: " '<>' s)
+-- @
 tell :: forall msg r t. (BotC r, ToMessage msg, Tellable t) => t -> msg -> P.Sem r (Either RestError Message)
 tell target (runToMessage -> msg) = P.runError $ do
   cid <- getChannel target
