diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Vanessa McHale (c) 2016
+
+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 Vanessa McHale 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,25 @@
+#QR Imager Library
+This is a library to generate `.png` files from QR codes.
+
+##Dependencies
+The library depends on the C library [https://github.com/fukuchi/libqrencode](libqrencode) which you will need to install separately.
+
+##Usage
+The library exports main functions - `createQRCode` and `byteStringToQR` - and their secured/signed versions. The first takes any object that is an instance of `ToJSON` and writes an image to file, while the second takes a (strict) bytestring and writes it to file.
+
+##Executable
+
+###Installation
+For building haskell, the best tool is currently [http://haskellstack.org](stack). Install it, and then type
+
+```
+stack install --install-ghc
+```
+
+in the appropriate directory, and it will be installed on your path. 
+
+###Use
+
+Compiling will generate an executable called `QRPipe` which reads from `stdin` and outputs a file as the second argument, e.g.
+
+```echo 'My name is:" | qrpipe "nametag.png"```
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/app/Main.hs b/app/Main.hs
new file mode 100644
--- /dev/null
+++ b/app/Main.hs
@@ -0,0 +1,11 @@
+{-#LANGUAGE OverloadedStrings #-}
+
+import Data.QRCodes.Repa
+import qualified Data.ByteString as B
+import System.Environment (getArgs)
+
+main :: IO ()
+main = do
+    pipeIn <- B.getContents
+    filepath <- fmap (flip (!!) 0) getArgs
+    byteStringToQRSec pipeIn filepath
diff --git a/qr-repa.cabal b/qr-repa.cabal
new file mode 100644
--- /dev/null
+++ b/qr-repa.cabal
@@ -0,0 +1,44 @@
+name:                qr-repa
+version:             0.1.0.0
+synopsis:            Library to generate QR codes from bytestrings and objects and scale image files
+description:         Please see README.md
+homepage:            https://github.com/vmchale/QRRepa#readme
+license:             BSD3
+license-file:        LICENSE
+author:              Vanessa McHale
+maintainer:          tmchale@wisc.edu
+copyright:           Copyright: (c) 2016 Vanessa McHale
+category:            Data
+build-type:          Simple
+stability:           stable
+extra-source-files:  README.md
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Data.QRCodes.Repa
+  build-depends:       base >= 4.7 && < 5
+                     , aeson
+                     , bytestring
+                     , lens
+                     , cryptonite
+                     , jose-jwt
+                     , directory
+                     , haskell-qrencode
+                     , repa
+                     , vector
+                     , repa-devil
+  default-language:    Haskell2010
+
+executable qrpipe
+  hs-source-dirs:      app
+  main-is:             Main.hs
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -O3
+  build-depends:       base
+                     , qr-repa
+                     , bytestring
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/vmchale/QRRepa
diff --git a/src/Data/QRCodes/Repa.hs b/src/Data/QRCodes/Repa.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/QRCodes/Repa.hs
@@ -0,0 +1,123 @@
+{-# LANGUAGE GADTs            #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Module exports functions to sign, create, and manipulate QR codes with repa
+module Data.QRCodes.Repa ( checkSig
+                         -- * Functions on objects that are members of the ToJSON class
+                         , createQRCode
+                         , createSecureQRCode
+                         -- * Functions on byteStrings
+                         , byteStringToQRSec
+                         , byteStringToQR
+                         -- * Functions for QR codes as Repa arrays
+                         , byteStringToRepa
+                         , scale
+                         ) where
+
+import Data.Aeson
+import Data.QRCode
+import Data.Word (Word8)
+import Data.ByteString.Lazy (toStrict)
+import qualified Data.ByteString as BS
+import Data.List (replicate)
+import Data.Char (toLower)
+import Prelude as P
+import Crypto.PubKey.RSA as Cr
+import Jose.Jws
+import System.Directory (doesFileExist)
+import Control.Lens.Tuple
+import Control.Lens (view)
+import Jose.Jwt (unJwt)
+import Jose.Jwa (JwsAlg (RS512))
+import Data.Either (either)
+import Jose.Jwt (JwtError)
+import Jose.Jws (rsaDecode)
+import Data.Bits ((.&.))
+import Data.Array.Repa as R
+import Data.Array.Repa.IO.DevIL
+import Data.Array.Repa.Repr.Vector
+import Data.Array.Repa.Eval (fromList)
+import Data.Array.Repa.Repr.ForeignPtr (F)
+import Data.Array.Repa.Repr.ByteString (fromByteString)
+import Control.Monad ((>=>))
+
+-- | Check signature of a token
+checkSig :: BS.ByteString -> IO (Either JwtError BS.ByteString)
+checkSig tok = do
+    key <- fmap read $ readFile ".key.hk"
+    let jws = rsaDecode key tok
+    return $ (fmap (view _2)) jws
+
+-- | Create a QR code from an object that is a member of the ToJSON class
+createQRCode :: (ToJSON a) => a -> FilePath -> IO ()
+createQRCode object = byteStringToQR (toStrict $ encode object)
+
+-- | Create a signed QR code from an object that is a member of the ToJSON class
+createSecureQRCode :: (ToJSON a) => a -> FilePath -> IO ()
+createSecureQRCode object = byteStringToQRSec (toStrict $ encode object)
+
+-- | Write signed/encrypted QR code to file, with content from a bytestring
+byteStringToQRSec :: BS.ByteString -> FilePath -> IO ()
+byteStringToQRSec string filepath = make
+    where make = do
+                    switch <- doesFileExist ".key.hk"
+                    if not switch then do
+                        putStrLn "generating key..."
+                        key <- Cr.generate 512 0x10001
+                        writeFile ".key.hk" (show key)
+                    else
+                        return ()
+                    key' <- fmap read $ readFile ".key.hk" :: IO (Cr.PublicKey, Cr.PrivateKey)
+                    signedToken <- rsaEncode RS512 (view _2 key') string
+                    let signed = fmap (unJwt) signedToken
+                    output <- liftEither id $ fmap (flip byteStringToQR filepath) signed
+                    putStrLn $ show output
+
+-- | Lifts IO Either to plain IO and throws exception on a `Left` value.
+liftEither :: (Show b, Monad m) => (t -> m a) -> Either b t -> m a
+liftEither = either (fail . show)
+
+-- | Enables quick switching between parallel/sequential computations
+--consider making this controllable with a command-line flag? i.e. -s for sequential idk --sign to sign it obvi
+compute = return . computeS
+
+-- | Converts a byteString to the Repa array representing what we want to write to .png
+byteStringToRepa :: BS.ByteString -> IO (R.Array D DIM2 Word8)
+byteStringToRepa input = do
+    qrMatrix <- toMatrix' <$> encodeByteString input Nothing QR_ECLEVEL_H QR_MODE_EIGHT False
+    return $ (scale . fatten . flipper) qrMatrix
+
+-- | Actually compute it (non-lazy)
+fullRepa :: BS.ByteString -> IO (R.Array F DIM2 Word8)
+fullRepa = (flip (>>= ) compute) . byteStringToRepa
+
+-- | Write a byteString to file as a .png qr code
+byteStringToQR :: BS.ByteString -> FilePath -> IO ()
+byteStringToQR input filepath = do
+    toWrite <- fullRepa input
+    runIL $ writeImage filepath (Grey toWrite)
+
+-- | Scales our array by an integer factor to make the .png useful
+scale :: R.Array D DIM2 Word8 -> R.Array D DIM2 Word8
+scale smol = fromFunction sh (\(Z:.x:.y) -> ((view _2) (toFunction smol)) (Z:.(x `div` 8):.(y `div` 8)))
+    where sh = (\(Z:.x:.y) -> Z:.((*8) x):.((*8) y)) (extent smol)
+
+-- | Swap black and white, plus make them dark enough ('fatten' the color?)
+fatten :: R.Array D DIM2 Word8 -> R.Array D DIM2 Word8
+fatten = (R.map ((*255) . swapWord))
+
+-- | Reflects vertically; since otherwise our QR code is upside down
+flipper :: R.Array D DIM2 Word8 ->  R.Array D DIM2 Word8
+flipper = (\arr -> let l = head . listOfShape $ extent arr in backpermute (extent arr) (\(Z:.x:.y) -> (Z:.(l-x-1):.y)) arr)
+
+-- | Given an object of type QRCode, return an array
+--QRCode -> Array D DIM2 Word8
+toMatrix' code = delay $ fromByteString sh (BS.map tobin (getQRCodeString code))
+    where sh      = (Z:.dim:.dim)
+          dim     = (getQRCodeWidth code)
+          tobin c = c .&. 1
+
+-- | Helper function that swaps words so we don't have black/white inverted
+swapWord :: Word8 -> Word8
+swapWord 1 = 0
+swapWord 0 = 1
