diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Joe Vargas (c) 2017
+
+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 Author name here 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/Main.hs b/Main.hs
new file mode 100644
--- /dev/null
+++ b/Main.hs
@@ -0,0 +1,81 @@
+module Main where
+
+import qualified SDL
+import qualified SDL.Image as Image
+import qualified Data.Animate as Ani
+
+import Control.Monad (unless)
+import Control.Concurrent (threadDelay)
+import Data.StateVar (($=))
+import Foreign.C.Types
+import SDL.Vect
+
+data DinoKey
+  = DinoKey'Idle
+  | DinoKey'Move
+  | DinoKey'Kick
+  | DinoKey'Hurt
+  | DinoKey'Sneak
+  deriving (Show, Eq, Ord, Bounded, Enum)
+
+instance Ani.Key DinoKey
+instance Ani.KeyName DinoKey where
+  keyName = \case
+    DinoKey'Idle -> "Idle"
+    DinoKey'Move -> "Move"
+    DinoKey'Kick -> "Kick"
+    DinoKey'Hurt -> "Hurt"
+    DinoKey'Sneak -> "Sneak"
+
+loadSurface :: FilePath -> Maybe Ani.Color -> IO SDL.Surface
+loadSurface path alpha = do
+  surface <- Image.load path
+  case alpha of
+    Just (r,g,b) -> SDL.surfaceColorKey surface $= (Just $ V4 r g b 0x00)
+    Nothing -> return ()
+  return surface
+
+main :: IO ()
+main = do
+  putStrLn "Press Space to iterate through animation keys"
+  SDL.initialize [SDL.InitVideo]
+  window <- SDL.createWindow "Animate Example" SDL.defaultWindow { SDL.windowInitialSize = V2 320 180 }
+  SDL.showWindow window
+  screen <- SDL.getWindowSurface window
+  spriteSheet <- Ani.readSpriteSheetJSON loadSurface "dino.json" :: IO (Ani.SpriteSheet DinoKey SDL.Surface)
+  loop window screen spriteSheet (Ani.initPosition DinoKey'Idle)
+  SDL.destroyWindow window
+  SDL.quit
+
+detectSpacePressed :: SDL.EventPayload -> Bool
+detectSpacePressed event = case event of
+  SDL.KeyboardEvent SDL.KeyboardEventData{keyboardEventKeysym = SDL.Keysym{keysymKeycode = code}, keyboardEventKeyMotion = motion, keyboardEventRepeat = repeated} ->
+    code == SDL.KeycodeSpace &&
+    motion == SDL.Pressed &&
+    not repeated
+  _ -> False
+
+loop :: SDL.Window -> SDL.Surface -> Ani.SpriteSheet DinoKey SDL.Surface -> Ani.Position DinoKey -> IO ()
+loop window screen ss@Ani.SpriteSheet{ssAnimations, ssImage} pos = do
+  events <- map SDL.eventPayload <$> SDL.pollEvents
+  let quit = elem SDL.QuitEvent events
+  let toNextKey = any detectSpacePressed events
+  let pos' = Ani.stepPosition ssAnimations pos frameDeltaSeconds
+  let loc = Ani.currentLocation ssAnimations pos'
+  SDL.surfaceFillRect screen Nothing (V4 0 0 0 0) -- Clear screen
+  _ <- SDL.surfaceBlit ssImage (Just $ rectFromClip loc) screen Nothing
+  SDL.updateWindowSurface window
+  delayMilliseconds frameDeltaMilliseconds
+  let pos'' = if toNextKey then Ani.initPosition (Ani.nextKey (Ani.pKey pos')) else pos'
+  unless quit $ loop window screen ss pos''
+  where
+    frameDeltaSeconds = 0.016667
+    frameDeltaMilliseconds = 16
+
+rectFromClip :: Ani.SpriteClip -> SDL.Rectangle CInt
+rectFromClip Ani.SpriteClip{scX,scY,scW,scH} = SDL.Rectangle (SDL.P (V2 (num scX) (num scY))) (V2 (num scW) (num scH))
+  where
+    num = fromIntegral
+
+delayMilliseconds :: Int -> IO ()
+delayMilliseconds ms = threadDelay (10000 * ms)
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,1 @@
+Thanks to [@ScissorMarks](https://twitter.com/ScissorMarks) for the Dino sprites.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/animate-example.cabal b/animate-example.cabal
new file mode 100644
--- /dev/null
+++ b/animate-example.cabal
@@ -0,0 +1,43 @@
+-- This file has been generated from package.yaml by hpack version 0.17.1.
+--
+-- see: https://github.com/sol/hpack
+
+name:           animate-example
+version:        0.0.0
+synopsis:       Animation for sprites
+description:    Prototypical sprite animation with type-safety.
+category:       Game
+homepage:       https://github.com/jxv/animate#readme
+bug-reports:    https://github.com/jxv/animate/issues
+maintainer:     Joe Vargas
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
+
+extra-source-files:
+    package.yaml
+    README.md
+    stack.yaml
+
+source-repository head
+  type: git
+  location: https://github.com/jxv/animate
+
+executable animate-example
+  main-is: Main.hs
+  hs-source-dirs:
+      ./.
+  default-extensions: DuplicateRecordFields FlexibleContexts FlexibleInstances GeneralizedNewtypeDeriving LambdaCase NamedFieldPuns ScopedTypeVariables OverloadedStrings
+  ghc-options: -Wall -rtsopts -threaded -with-rtsopts=-N
+  build-depends:
+      base >=4.7 && <5
+    , animate
+    , sdl2
+    , containers
+    , text
+    , aeson
+    , sdl2-image
+    , bytestring
+    , StateVar
+  default-language: Haskell2010
diff --git a/package.yaml b/package.yaml
new file mode 100644
--- /dev/null
+++ b/package.yaml
@@ -0,0 +1,40 @@
+name: animate-example
+version: '0.0.0'
+category: Game
+synopsis: Animation for sprites
+description: Prototypical sprite animation with type-safety.
+maintainer: Joe Vargas
+extra-source-files:
+- package.yaml
+- README.md
+- stack.yaml
+ghc-options: -Wall
+default-extensions:
+- DuplicateRecordFields
+- FlexibleContexts
+- FlexibleInstances
+- GeneralizedNewtypeDeriving
+- LambdaCase
+- NamedFieldPuns
+- ScopedTypeVariables
+- OverloadedStrings
+executables:
+  animate-example:
+    dependencies:
+    - base >=4.7 && <5
+    - animate
+    - sdl2
+    - containers
+    - text
+    - aeson
+    - sdl2-image
+    - bytestring
+    - StateVar
+    ghc-options:
+    - -rtsopts
+    - -threaded
+    - -with-rtsopts=-N
+    main: Main.hs
+    source-dirs: .
+github: jxv/animate
+license: BSD3
diff --git a/stack.yaml b/stack.yaml
new file mode 100644
--- /dev/null
+++ b/stack.yaml
@@ -0,0 +1,8 @@
+resolver: lts-9.14
+packages:
+- '.'
+- '..'
+extra-deps:
+- 'animate-0.2.0'
+flags: {}
+extra-package-dbs: []
