diff --git a/FRP/Helm.hs b/FRP/Helm.hs
--- a/FRP/Helm.hs
+++ b/FRP/Helm.hs
@@ -12,6 +12,7 @@
   module FRP.Helm.Graphics,
 ) where
 
+import Control.Monad (void)
 import Data.IORef
 import Foreign.Ptr (castPtr)
 import FRP.Elerea.Simple
@@ -25,7 +26,6 @@
 {-| Attempt to change the window dimensions (and initialize the video mode if not already).
     Will try to get a hardware accelerated window and then fallback to a software one.
     Throws an exception if the software mode can't be used as a fallback. -}
--- TODO: userland version of this
 requestDimensions :: Int -> Int -> IO SDL.Surface
 requestDimensions w h =	do
   mayhaps <- SDL.trySetVideoMode w h 32 [SDL.HWSurface, SDL.DoubleBuf, SDL.Resizable]
@@ -83,7 +83,7 @@
     >   return $ fmap render dims
  -}
 run :: SignalGen (Signal Element) -> IO ()
-run gen = SDL.init [SDL.InitVideo] >> requestDimensions 800 600 >> start gen >>= newEngineState >>= run'
+run gen = SDL.init [SDL.InitVideo, SDL.InitJoystick] >> requestDimensions 800 600 >> start gen >>= newEngineState >>= run'
 
 {-| A utility function called by 'run' that samples the element
     or quits the entire engine if SDL events say to do so. -}
@@ -160,7 +160,7 @@
 
 {-| A utility function for rendering a specific element. -}
 renderElement :: EngineState -> Element -> Cairo.Render ()
-renderElement state (CollageElement _ _ forms) = mapM (renderForm state) forms >> return ()
+renderElement state (CollageElement _ _ forms) = void $ mapM_ (renderForm state) forms
 renderElement state (ImageElement (sx, sy) sw sh src stretch) = do
   (surface, w, h) <- Cairo.liftIO $ getSurface state (normalise src)
 
@@ -178,6 +178,12 @@
   Cairo.fill
   Cairo.restore
 
+renderElement _ (TextElement (Text { textColor = (Color r g b a), .. })) = do
+  Cairo.setSourceRGBA r g b a
+  Cairo.selectFontFace fontTypeface fontSlant fontWeight
+  Cairo.setFontSize fontSize
+  Cairo.showText textUTF8
+
 {-| A utility function that goes into a state of transformation and then pops it when finished. -}
 withTransform :: Double -> Double -> Double -> Double -> Cairo.Render () -> Cairo.Render ()
 withTransform s t x y f = Cairo.save >> Cairo.scale s s >> Cairo.rotate t >> Cairo.translate x y >> f >> Cairo.restore
@@ -212,31 +218,31 @@
 setFillStyle :: EngineState -> FillStyle -> Cairo.Render ()
 setFillStyle _ (Solid (Color r g b a)) = Cairo.setSourceRGBA r g b a >> Cairo.fill
 setFillStyle state (Texture src) = do
-  (surface, w, h) <- Cairo.liftIO $ getSurface state (normalise src)
+  (surface, _, _) <- Cairo.liftIO $ getSurface state (normalise src)
 
-  Cairo.setSourceSurface surface 0 0 >> Cairo.getSource >>= (flip Cairo.patternSetExtend) Cairo.ExtendRepeat
+  Cairo.setSourceSurface surface 0 0 >> Cairo.getSource >>= flip Cairo.patternSetExtend Cairo.ExtendRepeat
   Cairo.fill
 
-setFillStyle _ (Gradient (Linear (sx, sy) (ex, ey) points)) = do
-  Cairo.withLinearPattern sx sy ex ey $ \pattern -> do
-    Cairo.setSource pattern >> mapM (\(o, (Color r g b a)) -> Cairo.patternAddColorStopRGBA pattern o r g b a) points >> Cairo.fill
+setFillStyle _ (Gradient (Linear (sx, sy) (ex, ey) points)) =
+  Cairo.withLinearPattern sx sy ex ey $ \pattern ->
+    Cairo.setSource pattern >> mapM (\(o, Color r g b a) -> Cairo.patternAddColorStopRGBA pattern o r g b a) points >> Cairo.fill
 
-setFillStyle _ (Gradient (Radial (sx, sy) sr (ex, ey) er points)) = do
-  Cairo.withRadialPattern sx sy sr ex ey er $ \pattern -> do
-    Cairo.setSource pattern >> mapM (\(o, (Color r g b a)) -> Cairo.patternAddColorStopRGBA pattern o r g b a) points >> Cairo.fill
+setFillStyle _ (Gradient (Radial (sx, sy) sr (ex, ey) er points)) =
+  Cairo.withRadialPattern sx sy sr ex ey er $ \pattern ->
+    Cairo.setSource pattern >> mapM (\(o, Color r g b a) -> Cairo.patternAddColorStopRGBA pattern o r g b a) points >> Cairo.fill
 
 {-| A utility that renders a form. -}
 renderForm :: EngineState -> Form -> Cairo.Render ()
 renderForm _ (Form { style = PathForm style p, .. }) =
   withTransform scalar theta x y $ 
-      setLineStyle style >> Cairo.moveTo hx hy >> mapM (\(x_, y_) -> Cairo.lineTo x_ y_) p >> return ()
+      void $ setLineStyle style >> Cairo.moveTo hx hy >> mapM (uncurry Cairo.lineTo) p
 
     where
       (hx, hy) = head p
 
 renderForm state (Form { style = ShapeForm style (PolygonShape points), .. }) =
   withTransform scalar theta x y $ do
-      Cairo.newPath >> Cairo.moveTo hx hy >> mapM (\(x_, y_) -> Cairo.lineTo x_ y_) points >> Cairo.closePath
+      Cairo.newPath >> Cairo.moveTo hx hy >> mapM (uncurry Cairo.lineTo) points >> Cairo.closePath
 
       case style of
         Left lineStyle -> setLineStyle lineStyle
@@ -264,4 +270,4 @@
       Right fillStyle -> setFillStyle state fillStyle
 
 renderForm state (Form { style = ElementForm element, .. }) = withTransform scalar theta x y $ renderElement state element
-renderForm state (Form { style = GroupForm m forms, .. }) = withTransform scalar theta x y $ Cairo.setMatrix m >> mapM (renderForm state) forms >> return ()
+renderForm state (Form { style = GroupForm m forms, .. }) = withTransform scalar theta x y $ void $ Cairo.setMatrix m >> mapM (renderForm state) forms
diff --git a/FRP/Helm/Automaton.hs b/FRP/Helm/Automaton.hs
new file mode 100644
--- /dev/null
+++ b/FRP/Helm/Automaton.hs
@@ -0,0 +1,78 @@
+{-| Contains all data structures and functions for composing, calculating and creating automatons. -}
+module FRP.Helm.Automaton (
+  -- * Types
+  Automaton(..),
+  -- * Composing
+  pure,
+  stateful,
+  combine,
+  (>>>),
+  (<<<),
+  -- * Computing
+  step,
+  run,
+  counter
+) where
+
+import FRP.Elerea.Simple (Signal, SignalGen, transfer)
+
+{-| A data structure describing an automaton.
+    An automaton is essentially a high-level way to package piped behavior
+    between an input signal and an output signal. Automatons can also
+    be composed, allowing you to connect one automaton to another
+    and pipe data between them. Automatons are an easy and powerful way
+    to create composable dynamic behavior, like animation systems. -}
+data Automaton a b = Step (a -> (Automaton a b, b))
+
+{-| Creates a pure automaton that has no accumulated state. It applies input to
+    a function at each step. -}
+pure :: (a -> b) -> Automaton a b
+pure f = Step (\x -> (pure f, f x))
+
+{-| Creates an automaton that has an initial and accumulated state. It applies
+    input and the last state to a function at each step. -}
+stateful :: b -> (a -> b -> b) -> Automaton a b
+stateful s f = Step (\x -> let s' = f x s
+                           in (stateful s' f, s'))
+
+{-| Steps an automaton forward, returning the next automaton to step
+    and output of the step in a tuple. -}
+step :: a -> Automaton a b -> (Automaton a b, b)
+step auto (Step f) = f auto
+
+{-| Combines a list of automatons that take some input
+    and turns it into an automaton that takes
+    the same input and outputs a list of all outputs
+    from each separate automaton. -}
+combine :: [Automaton a b] -> Automaton a [b]
+combine autos =
+  Step (\a -> let (autos', bs) = unzip $ map (step a) autos
+              in  (combine autos', bs))
+
+{-| Pipes two automatons together. It essentially
+    returns an automaton that takes the input of the first
+    automaton and outputs the output of the second automaton,
+    with the directly connected values being discarded. -}
+(>>>) :: Automaton a b -> Automaton b c -> Automaton a c
+f >>> g =
+  Step (\a -> let (f', b) = step a f
+                  (g', c) = step b g
+              in (f' >>> g', c))
+
+{-| Pipes two automatons in the opposite order of '>>>'. -}
+(<<<) :: Automaton b c -> Automaton a b -> Automaton a c
+g <<< f = f >>> g
+
+{-| A useful automaton that outputs the amount of times it has been stepped,
+    discarding its input value. -}
+counter :: Automaton a Int
+counter = stateful 0 (\_ c -> c + 1)
+
+{-| Runs an automaton with an initial output value and input signal generator
+    and creates an output signal generator that contains a signal that can be
+    sampled for the output value. -}
+run :: Automaton a b -> b -> SignalGen (Signal a) -> SignalGen (Signal b)
+run auto initial feeder = do
+  stepper <- feeder >>= transfer (auto, initial) (\a (Step f, _) -> f a)
+
+  return $ fmap snd stepper
diff --git a/FRP/Helm/Color.hs b/FRP/Helm/Color.hs
--- a/FRP/Helm/Color.hs
+++ b/FRP/Helm/Color.hs
@@ -1,34 +1,34 @@
 {-| Contains all data structures and functions for composing colors. -}
 module FRP.Helm.Color (
-	-- * Types
-	Color(..),
-	Gradient(..),
-	-- * Composing
-	rgba,
-	rgb,
+  -- * Types
+  Color(..),
+  Gradient(..),
+  -- * Composing
+  rgba,
+  rgb,
   hsva,
   hsv,
   complement,
-	linear,
-	radial,
-	-- * Constants
-	red,
-	lime,
-	blue,
-	yellow,
-	cyan,
-	magenta,
-	black,
-	white,
-	gray,
-	grey,
-	maroon,
-	navy,
-	green,
-	teal,
-	purple,
-	violet,
-	forestGreen
+  linear,
+  radial,
+  -- * Constants
+  red,
+  lime,
+  blue,
+  yellow,
+  cyan,
+  magenta,
+  black,
+  white,
+  gray,
+  grey,
+  maroon,
+  navy,
+  green,
+  teal,
+  purple,
+  violet,
+  forestGreen
 ) where
 
 {-| A data structure describing a color. It is represented interally as an RGBA
@@ -138,7 +138,7 @@
 
   where
     h' = h / 60
-    h'' = (floor h') `mod` 6 :: Int
+    h'' = floor h' `mod` 6 :: Int
     f = h' - fromIntegral h''
     p = v * (1 - s)
     q = v * (1 - f * s)
diff --git a/FRP/Helm/Graphics.hs b/FRP/Helm/Graphics.hs
--- a/FRP/Helm/Graphics.hs
+++ b/FRP/Helm/Graphics.hs
@@ -3,6 +3,7 @@
 module FRP.Helm.Graphics (
   -- * Types
   Element(..),
+  Text(..),
   Form(..),
   FormStyle(..),
   FillStyle(..),
@@ -49,8 +50,9 @@
   ngon
 ) where
 
-import FRP.Helm.Color as Color
+import FRP.Helm.Color (Color, black, Gradient)
 import Graphics.Rendering.Cairo.Matrix (Matrix, identity)
+import qualified Graphics.Rendering.Cairo as Cairo
 
 {-| A data structure describing something that can be rendered
     to the screen. Elements are the most important structure
@@ -60,8 +62,19 @@
     off to the 'collage' function, which essentially
     renders a collection of forms together. -}
 data Element = CollageElement Int Int [Form] |
-               ImageElement (Int, Int) Int Int FilePath Bool
+               ImageElement (Int, Int) Int Int FilePath Bool |
+               TextElement Text
 
+{-| A data structure describing a piece of formatted text. -}
+data Text = Text {
+  textUTF8 :: String,
+  textColor :: Color,
+  fontTypeface :: String,
+  fontSize :: Double,
+  fontWeight :: Cairo.FontWeight,
+  fontSlant :: Cairo.FontSlant
+}
+
 {-| Create an element from an image with a given width, height and image file path.
     If the image dimensions are not the same as given, then it will stretch/shrink to fit.
     Only PNG files are supported currently. -}
@@ -116,7 +129,7 @@
     flat caps and regular sharp joints. -}
 defaultLine :: LineStyle
 defaultLine = LineStyle {
-  color = Color.black,
+  color = black,
   width = 1,
   cap = Flat,
   join = Sharp 10,
@@ -153,15 +166,15 @@
 
 {-| Creates a form from a shape by filling it with a specific color. -}
 filled :: Color -> Shape -> Form
-filled color shape = fill (Solid color) shape
+filled color = fill (Solid color)
 
 {-| Creates a form from a shape with a tiled texture and image file path. -}
 textured :: String -> Shape -> Form
-textured src shape = fill (Texture src) shape
+textured src = fill (Texture src)
 
 {-| Creates a form from a shape filled with a gradient. -}
 gradient :: Gradient -> Shape -> Form
-gradient grad shape = fill (Gradient grad) shape
+gradient grad = fill (Gradient grad)
 
 {-| Creates a form from a shape by outlining it with a specific line style. -}
 outlined :: LineStyle -> Shape -> Form
@@ -202,11 +215,11 @@
 
 {-| Moves a form's x-coordinate relative to its current position. -}
 moveX :: Double -> Form -> Form
-moveX x f = move (x, 0) f
+moveX x = move (x, 0)
 
 {-| Moves a form's y-coordinate relative to its current position. -}
 moveY :: Double -> Form -> Form
-moveY y f = move (0, y) f
+moveY y = move (0, y)
 
 {-| Create an element from a collection of forms, with width and height arguments.
     Can be used to directly render a collection of forms.
@@ -215,7 +228,7 @@
     >                  move (100, 100) $ outlined (solid white) $ circle 50]
  -}
 collage :: Int -> Int -> [Form] -> Element
-collage w h forms = CollageElement w h forms
+collage = CollageElement
 
 {-| A data type made up a collection of points that form a path when joined. -}
 type Path = [(Double, Double)]
@@ -234,7 +247,7 @@
 
 {-| Creates a shape from a path (a set of points). -}
 polygon :: Path -> Shape
-polygon points = PolygonShape points
+polygon = PolygonShape
 
 {-| Creates a rectangular shape with a width and height. -}
 rect :: Double -> Double -> Shape
diff --git a/FRP/Helm/Joystick.hs b/FRP/Helm/Joystick.hs
new file mode 100644
--- /dev/null
+++ b/FRP/Helm/Joystick.hs
@@ -0,0 +1,105 @@
+{-| Contains signals that sample input from joysticks. -}
+module FRP.Helm.Joystick (
+  -- * Types
+  Joystick,
+  -- * Probing
+  available,
+  name,
+  open,
+  index,
+  availableAxes,
+  availableBalls,
+  availableHats,
+  availableButtons,
+  -- * Joystick State
+  axis,
+  hat,
+  button,
+  ball
+) where
+
+import Control.Applicative
+import Data.Int (Int16)
+import FRP.Elerea.Simple
+import qualified Graphics.UI.SDL as SDL
+
+{-| A type describing a joystick. -}
+type Joystick = SDL.Joystick
+
+{-| The amount of joysticks available. -}
+available :: SignalGen (Signal Int)
+available = effectful SDL.countAvailable
+
+{-| The name of a joystick. -}
+name :: Int -> SignalGen (Signal String)
+name i = effectful $ SDL.name i
+
+{-| The joystick at a certain slot. -}
+open :: Int -> SignalGen (Signal Joystick)
+open i = effectful $ SDL.open i
+
+{-| The index of a joystick. -}
+index :: Joystick -> SignalGen (Signal Int)
+index j = return $ return $ SDL.index j
+
+{-| The amount of axes available for a joystick. -}
+availableAxes :: Joystick -> SignalGen (Signal Int)
+availableAxes j = return $ return $ SDL.axesAvailable j
+
+{-| The amount of balls available for a joystick. -}
+availableBalls :: Joystick -> SignalGen (Signal Int)
+availableBalls j = return $ return $ SDL.ballsAvailable j
+
+{-| The amount of hats available for a joystick. -}
+availableHats :: Joystick -> SignalGen (Signal Int)
+availableHats j = return $ return $ SDL.hatsAvailable j
+
+{-| The amount of buttons available for a joystick. -}
+availableButtons :: Joystick -> SignalGen (Signal Int)
+availableButtons j = return $ return $ SDL.buttonsAvailable j
+
+{-| The current state of the axis of the joystick. -}
+axis :: Joystick -> Int -> SignalGen (Signal Int)
+axis j i = effectful $ SDL.update >> fromIntegral <$> SDL.getAxis j (fromIntegral i)
+
+{-| The current state of the hat of the joystick, returned
+    as a directional tuple. For example, up is /(0, -1)/,
+    left /(-1, 0)/, bottom-right is /(1, 1)/, etc. -}
+hat :: Joystick -> Int -> SignalGen (Signal (Int, Int))
+hat j i = effectful $ SDL.update >> hat' <$> SDL.getHat j (fromIntegral i)
+
+{-| A utility function for mapping a list of hat states to an averaged directional tuple. -}
+hat' :: [SDL.Hat] -> (Int, Int)
+hat' hats = if l > 0 then (round $ fromIntegral hx / l, round $ fromIntegral hy / l) else (0, 0)
+  where
+    l = realToFrac $ length hats :: Double
+    (hx, hy) = foldl hat'' (0, 0) hats
+
+{-| A utility function for accumulating the total directional tuple. -}
+hat'' :: (Int, Int) -> SDL.Hat -> (Int, Int)
+hat'' (x, y) h =
+  case h of
+    SDL.HatCentered -> (x, y)
+    SDL.HatUp -> (x, y - 1)
+    SDL.HatRight -> (x + 1, y)
+    SDL.HatDown -> (x, y + 1)
+    SDL.HatLeft -> (x - 1, y)
+    SDL.HatRightUp -> (x + 1, y - 1)
+    SDL.HatRightDown -> (x + 1, y + 1)
+    SDL.HatLeftUp -> (x - 1, x - 1)
+    SDL.HatLeftDown -> (x - 1, y + 1)
+
+{-| The current state of the button of the joystick. -}
+button :: Joystick -> Int -> SignalGen (Signal Bool)
+button j i = effectful $ SDL.update >> SDL.getButton j (fromIntegral i)
+
+{-| The current state of the ball of the joystick. -}
+ball :: Joystick -> Int -> SignalGen (Signal (Int, Int))
+ball j i = effectful $ SDL.update >> ball' <$> SDL.getBall j (fromIntegral i)
+
+{-| A utility function for mapping the optional value to a null tuple or the actual tuple. -}
+ball' :: Maybe (Int16, Int16) -> (Int, Int)
+ball' mayhaps =
+  case mayhaps of
+    Just (x, y) -> (fromIntegral x, fromIntegral y)
+    Nothing -> (0, 0)
diff --git a/FRP/Helm/Keyboard.hs b/FRP/Helm/Keyboard.hs
--- a/FRP/Helm/Keyboard.hs
+++ b/FRP/Helm/Keyboard.hs
@@ -25,7 +25,7 @@
 getKeyState = alloca $ \numkeysPtr -> do
   keysPtr <- sdlGetKeyState numkeysPtr
   numkeys <- peek numkeysPtr
-  (map fromIntegral . findIndices (== 1)) <$> peekArray (fromIntegral numkeys) keysPtr
+  (map fromIntegral . elemIndices 1) <$> peekArray (fromIntegral numkeys) keysPtr
 
 {-| A data structure describing a physical key on a keyboard. -}
 data Key = BackspaceKey | TabKey | ClearKey | EnterKey | PauseKey | EscapeKey |
@@ -329,15 +329,15 @@
 
 {-| Whether either shift key is pressed. -}
 shift :: SignalGen (Signal Bool)
-shift = effectful $ (elem SDL.KeyModShift) <$> SDL.getModState
+shift = effectful $ elem SDL.KeyModShift <$> SDL.getModState
 
 {-| Whether either control key is pressed. -}
 ctrl :: SignalGen (Signal Bool)
-ctrl = effectful $ (elem SDL.KeyModCtrl) <$> SDL.getModState
+ctrl = effectful $ elem SDL.KeyModCtrl <$> SDL.getModState
 
 {-| Whether a key is pressed. -}
 isDown :: Key -> SignalGen (Signal Bool)
-isDown k = effectful $ (elem $ fromEnum k) <$> getKeyState
+isDown k = effectful $ elem (fromEnum k) <$> getKeyState
 
 {-| Whether the enter (a.k.a. return) key is pressed. -}
 enter :: SignalGen (Signal Bool)
@@ -349,7 +349,7 @@
 
 {-| A list of keys that are currently being pressed. -}
 keysDown :: SignalGen (Signal [Key])
-keysDown = effectful $ (map toEnum) <$> getKeyState
+keysDown = effectful $ map toEnum <$> getKeyState
 
 {-| A directional tuple combined from the arrow keys. When none of the arrow keys
     are being pressed this signal samples to /(0, 0)/, otherwise it samples to a
diff --git a/FRP/Helm/Mouse.hs b/FRP/Helm/Mouse.hs
--- a/FRP/Helm/Mouse.hs
+++ b/FRP/Helm/Mouse.hs
@@ -1,20 +1,32 @@
 {-| Contains signals that sample input from the mouse. -}
 module FRP.Helm.Mouse (
-	-- * Types
-	Mouse(..),
-	-- * Position
-	isDown,
-	-- * Mouse State
-	position, x, y
+  -- * Types
+  Mouse(..),
+  -- * Position
+  isDown,
+  -- * Mouse State
+  position, x, y
 ) where
 
 import Control.Applicative
 import FRP.Elerea.Simple
 import qualified Graphics.UI.SDL as SDL
+import qualified Graphics.UI.SDL.Utilities as Util
 
 {-| A data structure describing a button on a mouse. -}
 data Mouse = LeftMouse | MiddleMouse | RightMouse
 
+{- All integer values of this enum are equivalent to the SDL key enum. -}
+instance Enum Mouse where
+  fromEnum LeftMouse = 1
+  fromEnum MiddleMouse = 2
+  fromEnum RightMouse = 3
+
+  toEnum 1 = LeftMouse
+  toEnum 2 = MiddleMouse
+  toEnum 3 = RightMouse
+  toEnum _ = error "FRP.Helm.Mouse.Mouse.toEnum: bad argument"
+
 {-| The current position of the mouse. -}
 position :: SignalGen (Signal (Int, Int))
 position = effectful $ (\(x_, y_, _) -> (x_, y_)) <$> SDL.getMouseState
@@ -27,15 +39,7 @@
 y :: SignalGen (Signal Int)
 y = effectful $ (\(_, y_, _) -> y_) <$> SDL.getMouseState
 
-{-| Maps our mouse type into SDL's one. -}
-mapMouse :: Mouse -> SDL.MouseButton
-mapMouse m =
-  case m of
-    LeftMouse -> SDL.ButtonLeft
-    MiddleMouse -> SDL.ButtonMiddle
-    RightMouse -> SDL.ButtonRight
-
 {-| The current state of a certain mouse button.
     True if the mouse is down, false otherwise. -}
 isDown :: Mouse -> SignalGen (Signal Bool)
-isDown m = effectful $ (\(_, _, b_) -> elem (mapMouse m) b_) <$> SDL.getMouseState
+isDown m = effectful $ (\(_, _, b_) -> elem (Util.toEnum $ fromIntegral $ fromEnum m) b_) <$> SDL.getMouseState
diff --git a/FRP/Helm/Text.hs b/FRP/Helm/Text.hs
new file mode 100644
--- /dev/null
+++ b/FRP/Helm/Text.hs
@@ -0,0 +1,91 @@
+{-| Contains all the data structures and functions for composing
+    pieces of formatted text. -}
+module FRP.Helm.Text (
+  -- * Elements
+  plainText,
+  asText,
+  text,
+  -- * Composing
+  defaultText,
+  toText,
+  -- * Formatting
+  bold,
+  italic,
+  color,
+  monospace,
+  typeface,
+  header,
+  height
+) where
+
+import FRP.Helm.Color (Color, black)
+import FRP.Helm.Graphics (Element(TextElement), Text(..))
+import qualified Graphics.Rendering.Cairo as Cairo
+
+{-| Creates the default text. By default the text is black sans-serif
+    with a height of 14px. -}
+defaultText :: Text
+defaultText = Text {
+  textUTF8 = "",
+  textColor = black,
+  fontTypeface = "sans-serif",
+  fontSize = 14,
+  fontWeight = Cairo.FontWeightNormal,
+  fontSlant = Cairo.FontSlantNormal
+}
+
+{-| Creates a text from a string. -}
+toText :: String -> Text
+toText utf8 = defaultText { textUTF8 = utf8 }
+
+{-| Creates a text element from a string. -}
+plainText :: String -> Element
+plainText utf8 = text $ toText utf8
+
+{-| Creates a text element from any showable type, defaulting to
+    the monospace typeface. -}
+asText :: Show a => a -> Element
+asText val = text $ monospace $ toText $ show val
+
+{-| Creates an element from a text. -}
+text :: Text -> Element
+text = TextElement
+
+{- TODO:
+centered
+justified
+righted
+underline
+strikeThrough
+overline
+-}
+
+{-| Sets the weight of a piece of text to bold. -}
+bold :: Text -> Text
+bold txt = txt { fontWeight = Cairo.FontWeightBold }
+
+{-| Sets the slant of a piece of text to italic. -}
+italic :: Text -> Text
+italic txt = txt { fontSlant = Cairo.FontSlantItalic }
+
+{-| Sets the color of a piece of text. -}
+color :: Color -> Text -> Text
+color col txt = txt { textColor = col }
+
+{-| Sets the typeface of the text to monospace. -}
+monospace :: Text -> Text
+monospace txt = txt { fontTypeface = "monospace" }
+
+{-| Sets the typeface of the text. Only fonts
+    supported by Cairo's toy font API are currently
+    supported. -}
+typeface :: String -> Text -> Text
+typeface face txt = txt { fontTypeface = face }
+
+{-| Sets the size of a text noticeably large. -}
+header :: Text -> Text
+header = height 32
+
+{-| Sets the size of a piece of text. -}
+height :: Double -> Text -> Text
+height size txt = txt { fontSize = size }
diff --git a/FRP/Helm/Window.hs b/FRP/Helm/Window.hs
--- a/FRP/Helm/Window.hs
+++ b/FRP/Helm/Window.hs
@@ -5,17 +5,18 @@
 ) where
 
 import Control.Applicative
+import Control.Arrow
 import FRP.Elerea.Simple
 import qualified Graphics.UI.SDL as SDL
 
--- |The current dimensions of the window.
+{-| The current dimensions of the window. -}
 dimensions :: SignalGen (Signal (Int, Int))
-dimensions = effectful $ (\s -> (SDL.surfaceGetWidth s, SDL.surfaceGetHeight s)) <$> SDL.getVideoSurface
+dimensions = effectful $ (SDL.surfaceGetWidth &&& SDL.surfaceGetHeight) <$> SDL.getVideoSurface
 
--- |The current width of the window.
+{-| The current width of the window. -}
 width :: SignalGen (Signal Int)
 width = effectful $ SDL.surfaceGetWidth <$> SDL.getVideoSurface
 
--- |The current height of the window.
+{-| The current height of the window. -}
 height :: SignalGen (Signal Int)
 height = effectful $ SDL.surfaceGetHeight <$> SDL.getVideoSurface
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -3,10 +3,10 @@
 ## Introduction
 
 Helm is a functionally reactive game engine written in Haskell and built around
-the [Elerea](https://github.com/cobbpg/elerea) FRP framework. Helm is
+the [Elerea FRP framework](https://github.com/cobbpg/elerea). Helm is
 heavily inspired by the [Elm programming language](http://elm-lang.org) (especially the API).
 All rendering is done through a vector-graphics based API. At the core, Helm is
-built on SDL and the Cairo vector graphics library. This may change to a more
+built on SDL and the Cairo vector graphics library. The plan is to change to a more
 robust setup in the future, such as a lightweight homebrewed renderer built on OpenGL.
 But for now, Cairo performs pretty well.
 
@@ -18,45 +18,66 @@
 ## Features
 
 * Allows you to express game logic dependent on input in a straightforward manner,
-  treating events as (almost) first class objects (the essence of FRP).
+  treating events as first class values (the essence of FRP).
+
 * Vector graphics based rendering, allow you to either write art
   designed for any resolution or still load generic images and render
   those as you would with any pixel-based direct blitting game engine.
-* Straightforward API heavily inspired by the Elm programming language.
 
-## Future Work
+* Straightforward API heavily inspired by the Elm programming language. The API
+  is broken up into the following areas:
 
-* Improve the API. There's a few API calls from Elm that would work
-  just as nicely in Helm. These are marked inside TODOs in the code.
-  There also other important things that it's missing,
-  such as audio, text rendering, joysticks and loading a larger range of
-  image formats.
-* Backend wise, it would be nice to use OpenGL instead of Cairo.
-  Cairo isn't particuarly that well performing for graphic intensive games,
-  although work is done being towards to fix that. However, using
-  OpenGL would make the engine more lightweight, easier to port
-  and be incredibly easier to accelerate. This means I have
-  to write the full vector graphics stack myself, but the worse part
-  will probably just be line styles, the rest should be moderately easy.
-  This will also allow loading of multiple image formats, as the current
-  reason for not using SDL_image is that it's annoying as fuck
-  to integrate with Cairo.
-* Optimizations and testing. This is the first release of the engine so
-  obviously little testing or optimizations have been done.
-  It's a little hard to set up a test framework for a game engine,
-  but I have a few ideas, such as writing a dummy version of the backend
-  that simply renders to a PNG file that is fed fake (but predictable) input,
-  which is then compared to a static PNG file to see if the final expected
-  rendering outcome was achieved.
-* Port and support multiple platforms. I've only been testing it on
-  Linux, but there's really no reason that it wouldn't work out of the box
-  on Windows or OSX after setting up the dependencies. But I'd definitely
-  also like to investigate Android and iOS.
+  * `FRP.Helm` contains the main code for interfacing with the game engine but
+    also includes some utility functions and the modules `FRP.Helm.Color` and `FRP.Helm.Graphics`
+    in the style of a sort of prelude library, allowing it to be included and readily
+    make the most basic of games.
 
+  * `FRP.Helm.Automaton` contains the `Automaton` data structure and functions
+    for composing, creating and calculating them. Automatons are a useful
+    abstraction of a dynamic process that is fed input from a signal
+    and feeds output through a signal. This is really useful for things
+    like animation systems, accumulating network packets and other
+    stateful but input dependent things.
+
+  * `FRP.Helm.Color` contains the `Color` data structure, functions for composing
+    colors and a few pre-defined colors that are usually used in games.
+
+  * `FRP.Helm.Graphics` contains all the graphics data structures, functions
+    for composing these structures and other general graphical utilities.
+
+  * `FRP.Helm.Joystick` contains signals for working with joystick state.
+
+  * `FRP.Helm.Keyboard` contains signals for working with keyboard state.
+
+  * `FRP.Helm.Mouse` contains signals for working with mouse state.
+
+  * `FRP.Helm.Text` contains functions for composing text, formatting it
+    and then turning it into an element.
+
+  * `FRP.Helm.Window` contains signals for working with the game window state.
+
 ## Example
 
-The following examples is the barebones of a game. It shows how to create
-an accumulated state that depends on the values sampled from signals (e.g. mouse input and such).
+The simplest example of a Helm game that doesn't require any input from the user is the following:
+
+```haskell
+import FRP.Helm
+import qualified FRP.Helm.Window as Window
+
+render :: (Int, Int) -> Element
+render (w, h) = collage w h [move (100, 100) $ filled red $ square 64]
+
+main :: IO ()
+main = run $ do
+  dims <- Window.dimensions
+
+  return $ fmap render dims
+```
+
+It renders a red square at the position `(100, 100)` with a side length of 64px.  
+  
+The next example is the barebones of a game that depends on input. It shows how to create
+an accumulated state that depends on the values sampled from signals (e.g. mouse input).
 You should see a white square on the screen and pressing the arrow keys allows you to move it.
 
 ```haskell
@@ -71,7 +92,8 @@
 data State = State { mx :: Double, my :: Double }
 
 step :: (Int, Int) -> State -> State
-step (dx, dy) state = state { mx = (realToFrac dx) + mx state, my = (realToFrac dy) + my state }
+step (dx, dy) state = state { mx = (realToFrac dx) + mx state,
+                              my = (realToFrac dy) + my state }
 
 render :: (Int, Int) -> State -> Element
 render (w, h) (State { .. }) = collage w h [move (mx, my) $ filled white $ square 100]
@@ -106,3 +128,51 @@
 ## License
 
 Helm is licensed under the MIT license. See the `LICENSE` file for more details.
+
+## Contributing
+
+Helm would benefit from either of the following contributions:
+
+1. Try out the engine, reporting any issues or suggestions you have.
+
+2. Look through the source, get a feel for the code and then
+   contribute some features or fixes. If you plan on contributing
+   code please submit a pull request and follow the formatting
+   styles set out in the current code: 2 space indents, documentation
+   on every top-level function, favouring monad operators over
+   do blocks, etc.
+
+The following is a list of areas I want to tackle in the future, 
+and possible targets that others could try for:
+
+* Improve the API. There's a few API calls from Elm that would work
+  just as nicely in Helm. These are marked inside TODOs in the code.
+  There also other important things that it's missing,
+  such as audio, joysticks and loading a larger range of
+  image formats.
+
+* Backend wise, it would be nice to use OpenGL instead of Cairo.
+  Cairo isn't particuarly that well performing for graphic intensive games,
+  although work is done being towards to fix that. However, using
+  OpenGL would make the engine more lightweight, easier to port
+  and be incredibly easier to accelerate. This means I have
+  to write the full vector graphics stack myself, but the worse part
+  will probably just be line styles, the rest should be moderately easy.
+  This will also allow loading of multiple image formats, as the current
+  reason for not using SDL_image is that it's annoying as fuck
+  to integrate with Cairo. Helm also currently uses the Cairo toy text
+  API for rendering, which isn't suppose to be used in production. If switched
+  to OpenGL, SDL_ttf would be a better fit.
+
+* Optimizations and testing. This is a early release of the engine so
+  obviously little testing or optimizations have been done.
+  It's a little hard to set up a test framework for a game engine,
+  but I have a few ideas, such as writing a dummy version of the backend
+  that simply renders to a PNG file that is fed fake (but predictable) input,
+  which is then compared to a static PNG file to see if the final expected
+  rendering outcome was achieved.
+
+* Port and support multiple platforms. I've only been testing it on
+  Linux, but there's really no reason that it wouldn't work out of the box
+  on Windows or OSX after setting up the dependencies. But I'd definitely
+  also like to investigate Android and iOS.
diff --git a/helm.cabal b/helm.cabal
--- a/helm.cabal
+++ b/helm.cabal
@@ -1,5 +1,5 @@
 name: helm
-version: 0.2.0
+version: 0.3.0
 synopsis: A functionally reactive game engine.
 description: A functionally reactive game engine, with headgear to protect you
              from the headache of game development provided.
@@ -12,7 +12,7 @@
 author: Zack Corr
 maintainer: Zack Corr <zack@z0w0.me>
 copyright: (c) 2013, Zack Corr
-category: Game Engine
+category: Game Engine, FRP
 build-type: Simple
 cabal-version: >=1.10
 
@@ -23,10 +23,13 @@
 library
   exposed-modules:
     FRP.Helm
+    FRP.Helm.Automaton
     FRP.Helm.Color
     FRP.Helm.Graphics
+    FRP.Helm.Joystick
     FRP.Helm.Keyboard
     FRP.Helm.Mouse
+    FRP.Helm.Text
     FRP.Helm.Window
   build-depends:
     base >= 4 && < 5,
