diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Richard Lupton (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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,24 @@
+# tyro
+
+`tyro` is a dependently type JSON parsing library, that provides a quick way to create JSON parsers by deriving them from a type level description of the position of the value to be obtained.
+
+## Example
+
+```Haskell
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+
+import Data.Tyro
+import Data.Aeson (decode)
+import Data.Text (Text)
+
+json = "{\"key1\":[{\"key2\":41},{\"key2\":42}]}" :: Text
+
+-- Extract [41, 42] inside the Tyro types
+parsed = decode json :: Maybe ("key1" |>| List ("key2" |>| Parse Integer))
+
+-- We can dispose of the types using unwrap
+values :: Maybe [Integer]
+values = fmap unwrap parsed
+```
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/src/Data/Tyro.hs b/src/Data/Tyro.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Tyro.hs
@@ -0,0 +1,119 @@
+{-|
+Module      : Data.Tyro
+Description : A library for automatically deriving JSON parsers from types
+Copyright   : (c) Richard Lupton, 2017
+License     : BSD-3
+Stability   : experimental
+Portability : POSIX
+-}
+{-# LANGUAGE DataKinds, GADTs, KindSignatures, TypeOperators #-}
+{-# LANGUAGE InstanceSigs #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
+module Data.Tyro (
+  -- * Introduction
+  -- $example
+
+  -- * Building types
+  Parse
+, type( |>| )
+, List
+, unwrap
+
+-- * Internal types
+, JSBranch ) where
+
+
+import           Data.Aeson ((.:))
+import qualified Data.Aeson as A
+import           Data.Aeson.Types (Parser)
+import           Data.Singletons (Sing, SingI(..))
+import           Data.Singletons.Prelude.List (Sing(SNil, SCons))
+import           Data.Singletons.TypeLits ( Symbol, SSymbol, KnownSymbol
+                                          , withKnownSymbol, symbolVal )
+import           Data.String (String)
+import           Data.Text (pack)
+
+import           Lib.Prelude
+
+
+-- $example
+-- A small (artificial) example demonstrating how to use the types defined here.
+--
+-- > {-# LANGUAGE OverloadedStrings #-}
+-- > {-# LANGUAGE DataKinds #-}
+-- > {-# LANGUAGE TypeOperators #-}
+-- > import Data.Tyro
+-- > import Data.Aeson (decode)
+-- > import Data.Text (Text)
+-- >
+-- > json = "{\"key1\":[{\"key2\":41},{\"key2\":42}]}" :: Text
+-- >
+-- > -- Extract [41, 42] inside the Tyro types
+-- > parsed = decode json :: Maybe ("key1" |>| List ("key2" |>| Parse Integer))
+-- >
+-- > -- We can dispose of the types using unwrap: 'values' will have the value
+-- > -- Just [41, 42]
+-- > values :: Maybe [Integer]
+-- > values = fmap unwrap parsed
+
+
+
+--------------------------------------------------------------------------------
+-- Type level API using a type family to mirror JSON structure
+--------------------------------------------------------------------------------
+
+-- | @Parse a@ represents trying to parse JSON to an @a@.
+type Parse a = JSBranch '[] a
+
+-- | The type operator '|>|' provides a way of describing how to walk
+-- down a JSON tree.
+type family (x :: Symbol) |>| (b :: *) :: *
+type instance (x :: Symbol) |>| JSBranch xs a = JSBranch (x ': xs) a
+
+-- | The 'List' type operator constructs a parsing type for parsing
+-- a list of JSON objects.
+type family List (x :: *) :: *
+type instance List (JSBranch xs a) = Parse [JSBranch xs a]
+
+
+--------------------------------------------------------------------------------
+-- Basic dependent structure
+--------------------------------------------------------------------------------
+
+-- | 'JSBranch' is a dependent datatype which represents a walk down a JSON
+-- tree. @JSBranch ["key1", "key2"] a@ represents the walk "take the value at
+-- @key1@ and then the value at @key2@, and (try to) interpret that as an @a@".
+data JSBranch :: [Symbol] -> * -> * where
+  JSNil :: a -> JSBranch '[] a
+  JSCons :: JSBranch xs a -> JSBranch (t ': xs) a
+
+
+-- | 'unwrap' unwraps a value from it's parsing type.
+unwrap :: JSBranch xs a -> a
+unwrap b = case b of
+  JSNil x -> x
+  JSCons b' -> unwrap b'
+
+
+instance (A.FromJSON a, SingI xs) => A.FromJSON (JSBranch xs a) where
+  parseJSON :: (A.FromJSON a, SingI xs) => A.Value -> Parser (JSBranch xs a)
+  parseJSON = parseSing sing
+    where
+      parseSing :: (A.FromJSON a) => Sing xs -> A.Value -> Parser (JSBranch xs a)
+      parseSing s o = case s of
+        SNil -> JSNil <$> A.parseJSON o
+        x `SCons` xs -> case o of
+          A.Object v -> let key = pack (reflectSym x) in
+            JSCons <$> (v .: key >>= parseSing xs)
+          _ -> empty
+
+
+-- | 'reflectSym' reflects a type level symbol into a value level string
+reflectSym :: SSymbol s -> String
+reflectSym s = withKnownSymbol s $ proxySym s Proxy
+  where
+    proxySym :: (KnownSymbol n) => SSymbol n -> Proxy n -> String
+    proxySym _ = symbolVal
+
+
diff --git a/src/Lib/Prelude.hs b/src/Lib/Prelude.hs
new file mode 100644
--- /dev/null
+++ b/src/Lib/Prelude.hs
@@ -0,0 +1,11 @@
+{-
+Welcome to your custom Prelude
+Export here everything that should always be in your library scope
+For more info on what is exported by Protolude check:
+https://github.com/sdiehl/protolude/blob/master/Symbols.md
+-}
+module Lib.Prelude
+    ( module Exports
+    ) where
+
+import Protolude as Exports
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,65 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+import Test.Framework as TF
+import Test.Framework.Providers.HUnit (hUnitTestToTests)
+import Test.HUnit as HU
+import Test.HUnit ((~:),(@=?))
+
+import Protolude
+import Data.Tyro
+
+import qualified Data.Aeson as A
+import Data.Text (Text)
+
+main :: IO ()
+main = defaultMain tests
+
+tests :: [ TF.Test ]
+tests = [ genericJSONParserTests ]
+
+
+genericJSONParserTests :: TF.Test
+genericJSONParserTests = testGroup "\nGeneric JSON Parser tests" . hUnitTestToTests $
+  HU.TestList [ canExtractTextInJSBranch
+              , canExtractIntegerInJSBranch
+              , canExtractListInJSBranch
+              , canExtractListInJSBranchWithTypeFamily ]
+
+
+--------------------------------------------------------------------------------
+-- Generic JSON Parser tests
+--------------------------------------------------------------------------------
+
+canExtractTextInJSBranch :: HU.Test
+canExtractTextInJSBranch = "Can extract JSBranch on Text" ~:
+  let json = "{\"key1\":{\"key2\":{\"key3\":\"Some text\"}}}"
+      expected = Just "Some text"
+      decoded = A.decode json :: Maybe (JSBranch '["key1", "key2", "key3"] Text)
+  in
+    expected @=? fmap unwrap decoded
+
+canExtractIntegerInJSBranch :: HU.Test
+canExtractIntegerInJSBranch = "Can extract JSBranch on Integer" ~:
+  let json = "{\"key1\":{\"key2\":{\"key3\":42}}}"
+      expected = Just 42
+      decoded = A.decode json :: Maybe (JSBranch '["key1", "key2", "key3"] Integer)
+  in
+    expected @=? fmap unwrap decoded
+
+canExtractListInJSBranch :: HU.Test
+canExtractListInJSBranch = "Can extract JSBranch on List" ~:
+  let json = "{\"key1\":[{\"key2\":41},{\"key2\":42}]}"
+      expected = Just [41,42]
+      decoded = A.decode json :: Maybe (JSBranch '["key1"] [JSBranch '["key2"] Integer])
+  in
+    expected @=? (fmap (fmap unwrap) . (fmap unwrap) $ decoded)
+
+
+canExtractListInJSBranchWithTypeFamily :: HU.Test
+canExtractListInJSBranchWithTypeFamily = "Can extract JSBranch on List with type family" ~:
+  let json = "{\"key1\":[{\"key2\":41},{\"key2\":42}]}"
+      expected = Just [41,42]
+      decoded = A.decode json :: Maybe ("key1" |>| List ("key2" |>| Parse Integer))
+  in
+    expected @=? (fmap (fmap unwrap) . (fmap unwrap) $ decoded)
diff --git a/tyro.cabal b/tyro.cabal
new file mode 100644
--- /dev/null
+++ b/tyro.cabal
@@ -0,0 +1,49 @@
+name:                tyro
+version:             0.1.1.0
+synopsis:            Type derived JSON parsing using Aeson
+description:
+    A library for deriving JSON parsers (using Aeson) by indicating
+    JSON structure at the type level.
+homepage:            https://github.com/rlupton20/tyro#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Richard Lupton
+maintainer:          example@example.com
+copyright:           2017 Richard Lupton
+category:            Text, Web, JSON
+build-type:          Simple
+extra-source-files:  README.md
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  ghc-options:         -Wall
+  exposed-modules:     Data.Tyro
+  other-modules:       Lib.Prelude
+  build-depends:       base >= 4.7 && < 5
+                     , protolude >= 0.1.6 && < 0.2
+                     , aeson
+                     , text
+                     , singletons
+  default-language:    Haskell2010
+  default-extensions:  OverloadedStrings, NoImplicitPrelude
+
+test-suite tyro-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Spec.hs
+  build-depends:       base
+                     , tyro
+                     , protolude >= 0.1.6 && < 0.2
+                     , test-framework
+                     , test-framework-hunit
+                     , HUnit
+                     , text
+                     , aeson
+  ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-N
+  default-language:    Haskell2010
+  default-extensions:  OverloadedStrings, NoImplicitPrelude
+
+source-repository head
+  type:     git
+  location: https://github.com/rlupton20/tyro
