diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,26 +1,16 @@
 # QR Imager Library
+
 [![Build Status](https://travis-ci.org/vmchale/QR-writer.svg?branch=master)](https://travis-ci.org/vmchale/QR-writer)
 
 This is a library to generate `.png` files from QR codes.
 
 ## Dependencies
-The library depends on the C library [libqrencode](https://github.com/fukuchi/libqrencode) which you will need to install separately, as well as the C library `Zbar` from [here](https://github.com/ZBar/ZBar). You should also be able to get them from your distro. 
+The library depends on the C library [libqrencode](https://github.com/fukuchi/libqrencode) which you will need to install separately, as well as the command-line tool `Zbar` from [here](https://github.com/ZBar/ZBar). You should also be able to get them from your distro. 
 
 ## Library
 The library can be used via the exported functions `createQRCode`, `byteStringToQR` and `readQRString`, plus their signed counterparts. The first two export to ".png" while the third can be used on any image format `Zbar` supports.
 
 The functions `bsToImg` and `objToImg` output JuicyPixels images for your further manipulation.
-
-## 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 to your path. 
 
 ### Use
 
diff --git a/cabal.project.local b/cabal.project.local
new file mode 100644
--- /dev/null
+++ b/cabal.project.local
@@ -0,0 +1,3 @@
+-- constraints: qr-imager +development
+tests: true
+documentation: true
diff --git a/qr-imager.cabal b/qr-imager.cabal
--- a/qr-imager.cabal
+++ b/qr-imager.cabal
@@ -1,6 +1,6 @@
-cabal-version: >=1.10
+cabal-version: 1.18
 name: qr-imager
-version: 1.0.1.8
+version: 2.0.0.0
 license: BSD3
 license-file: LICENSE
 copyright: Copyright: (c) 2016-2018 Vanessa McHale
@@ -8,14 +8,15 @@
 author: Vanessa McHale
 stability: stable
 homepage: https://github.com/vmchale/QRImager#readme
-synopsis: Library to generate QR codes from bytestrings and objects
+synopsis: Library to generate images.
 description:
-    Please see README.md
-category: Data
+    Library for generating images containing QR codes, from bytestrings and objects.
+category: Data, QR, Image
 build-type: Simple
 extra-source-files:
-    README.md
     stack.yaml
+    cabal.project.local
+extra-doc-files: README.md
 
 source-repository head
     type: git
@@ -24,7 +25,6 @@
 library
     exposed-modules:
         Data.QRCodes
-        Data.QRCodes.Exe
         Data.QRCodes.Image
         Data.QRCodes.Signature
     pkgconfig-depends: libqrencode -any
@@ -33,8 +33,8 @@
         Data.QRCodes.Utils
     default-language: Haskell2010
     build-depends:
-        base >=4.9 && <5,
-        aeson -any,
+        base >=4.8 && <5,
+        binary -any,
         JuicyPixels -any,
         vector -any,
         bytestring -any,
@@ -44,7 +44,6 @@
         directory -any,
         haskell-qrencode -any,
         process -any,
-        optparse-applicative -any,
         split -any
 
 test-suite test-lib
diff --git a/src/Data/QRCodes.hs b/src/Data/QRCodes.hs
--- a/src/Data/QRCodes.hs
+++ b/src/Data/QRCodes.hs
@@ -17,7 +17,7 @@
 import           Codec.Picture.Png          (writePng)
 import           Control.Applicative        ((<$>))
 import           Crypto.PubKey.RSA
-import           Data.Aeson
+import           Data.Binary
 import qualified Data.ByteString.Char8      as BS
 import           Data.ByteString.Lazy       (toStrict)
 import qualified Data.ByteString.Lazy.Char8 as BSL
@@ -47,17 +47,17 @@
 byteStringToQRSec' string key filepath = flip byteStringToQR filepath =<< (fmap preserveUpper . flip mkSig key) string
 
 -- | Creates a signed QR code from an object that is part of the ToJSON class
-createSecureQRCode :: (ToJSON a) => a -> FilePath -> FilePath -> IO ()
+createSecureQRCode :: (Binary a) => a -> FilePath -> FilePath -> IO ()
 createSecureQRCode object = byteStringToQRSec (toStrict $ encode object)
 
 -- | Creates a signed QR code from an object that is part of the ToJSON class
-createSecureQRCode' :: (ToJSON a) => a -> (PublicKey, PrivateKey) -> FilePath -> IO ()
+createSecureQRCode' :: (Binary a) => a -> (PublicKey, PrivateKey) -> FilePath -> IO ()
 createSecureQRCode' object = byteStringToQRSec' (toStrict $ encode object)
 
 -- | Creates a QR code from an object that is part of the ToJSON class
 --
 -- > createQRCode userRecord "user-231.png"
-createQRCode :: (ToJSON a) => a -> FilePath -> IO ()
+createQRCode :: (Binary a) => a -> FilePath -> IO ()
 createQRCode object filepath = let input = toStrict $ encode object in byteStringToQR input filepath
 
 -- | Create a QR code, writing an image to the given 'FilePath'
@@ -73,13 +73,13 @@
 -- | given a filepath pointing to a QR code, get the contents & verify signature with the keyfile
 --
 -- > readQRStrSec "output.png" ".key.hk"
-readQRStrSec :: (FromJSON a) => FilePath -> FilePath -> IO a
-readQRStrSec filepath keyfile = fromJust . decode . BSL.pack <$> do
+readQRStrSec :: (Binary a) => FilePath -> FilePath -> IO a
+readQRStrSec filepath keyfile = decode . BSL.pack <$> do
     enc <- map toLower . init . drop 8 . view _2 <$> readCreateProcessWithExitCode (shell $ "zbarimg " ++ filepath) ""
     fmap (liftEither BS.unpack) . flip checkSigFile keyfile . resolveUpper $ BS.pack enc
 
 -- | Read an image containing a QR code, decode and verify the signature using the given key.
-readQRStrSec' :: (FromJSON a) => FilePath -> (PublicKey, PrivateKey) -> IO a
-readQRStrSec' filepath key = fromJust . decode . BSL.pack <$> do
+readQRStrSec' :: (Binary a) => FilePath -> (PublicKey, PrivateKey) -> IO a
+readQRStrSec' filepath key = decode . BSL.pack <$> do
     enc <- map toLower . init . drop 8 . view _2 <$> readCreateProcessWithExitCode (shell $ "zbarimg " ++ filepath) ""
     fmap (liftEither BS.unpack) . flip checkSig key . resolveUpper $ BS.pack enc
diff --git a/src/Data/QRCodes/Exe.hs b/src/Data/QRCodes/Exe.hs
deleted file mode 100644
--- a/src/Data/QRCodes/Exe.hs
+++ /dev/null
@@ -1,66 +0,0 @@
--- | Parse options applicatively and read or write secure or non-secure QR codes.
-module Data.QRCodes.Exe where
-
-import           Data.Aeson
-import qualified Data.ByteString     as B
-import           Data.QRCodes
-import           Data.Semigroup
-import           Options.Applicative
-import           System.Environment  (getArgs)
-
--- | Data type for the executable comprising the command, whether to sign, whether to verify it worked, and the output filename
-data Prog = Prog { cmd     :: Com
-                 , secured :: Bool
-                 , verify  :: Bool
-                 , file    :: String}
-
--- | Command is either read or write
-data Com = Input | Output
-
--- | main exec function
-exec :: IO ()
-exec = execParser full >>= act
-    where
-        full = info (helper <*> program)
-            ( fullDesc
-            <> progDesc "Read/Write QR Codes with files"
-            <> header "qrpipe - QR utilities made in Haskell" )
-
--- | Takes a `Prog` and returns the appropriate IO action
-act :: Prog -> IO ()
-act (Prog Output True True filepath) = do
-    pipeIn <- getContents
-    createSecureQRCode pipeIn ".key.hk" filepath
-    (readQRStrSec filepath ".key.hk" :: IO String) >>= print
-act (Prog Output False True filepath) = do
-    pipeIn <- B.getContents
-    byteStringToQR pipeIn filepath
-    readQRString filepath >>= print
-act (Prog Output True False filepath) = do
-    pipeIn <- getContents
-    createSecureQRCode pipeIn ".key.hk" filepath
-act (Prog Output False False filepath) = do
-    pipeIn <- B.getContents
-    byteStringToQR pipeIn filepath
-act (Prog Input True _ filepath) =
-    (readQRStrSec filepath ".key.hk" :: IO String) >>= print
-act (Prog Input False _ filepath) =
-    readQRString filepath >>= print
-
--- | Parser for the command line
-program :: Parser Prog
-program = Prog
-    <$> subparser
-        ( command "write" (info (pure Output)
-            ( progDesc "Create a QR Code from stdin" ))
-        <> command "read" (info (pure Input)
-            ( progDesc "Read a QR code from file" )))
-    <*> switch
-        ( long "signed"
-        <> short 's'
-        <> help "Whether to sign the QR code" )
-    <*> switch
-        ( long "verify"
-        <> short 'v'
-        <> help "Attempt to read the resultant file?" )
-    <*> argument str (metavar "FILE")
diff --git a/src/Data/QRCodes/Image.hs b/src/Data/QRCodes/Image.hs
--- a/src/Data/QRCodes/Image.hs
+++ b/src/Data/QRCodes/Image.hs
@@ -1,6 +1,6 @@
 -- | A few functions to deal with the image itself
-module Data.QRCodes.Image (-- * Functions to convert to JuicyPixels `Image`
-                          bsToImg
+module Data.QRCodes.Image ( -- * Functions to convert to JuicyPixels `Image`
+                            bsToImg
                           , objToImg
                           -- * Functions to sign and convert to `Image`
                           , bsToImgSec
@@ -11,8 +11,9 @@
                           ) where
 
 import           Codec.Picture.Types    as T
+import           Control.Monad
 import           Crypto.PubKey.RSA
-import           Data.Aeson
+import           Data.Binary
 import qualified Data.ByteString        as BS
 import           Data.ByteString.Lazy   (toStrict)
 import           Data.QRCode
@@ -36,11 +37,11 @@
 bsToImgSec' string key = bsToImg =<< (fmap preserveUpper . flip mkSig key) string
 
 -- | Encode an object as a JuicyPixels `Image` with a key in a given file.
-objToImgSec :: (ToJSON a) => a -> FilePath -> IO (T.Image Word8)
+objToImgSec :: (Binary a) => a -> FilePath -> IO (T.Image Word8)
 objToImgSec obj = bsToImgSec (toStrict $ encode obj)
 
 -- | Encode an object as a JuicyPixels `Image` with a key.
-objToImgSec' :: (ToJSON a) => a -> (PublicKey, PrivateKey) -> IO (T.Image Word8)
+objToImgSec' :: (Binary a) => a -> (PublicKey, PrivateKey) -> IO (T.Image Word8)
 objToImgSec' obj = bsToImgSec' (toStrict $ encode obj)
 
 -- | Create a JuicyPixels `Image` from a `ByteString`
@@ -51,14 +52,14 @@
     pure $ encodePng qrMatrix
 
 -- | Encode an object as a JuicyPixels `Image`
-objToImg :: (ToJSON a) => a -> IO (T.Image Word8)
+objToImg :: (Binary a) => a -> IO (T.Image Word8)
 objToImg obj = let input = toStrict $ encode obj in bsToImg input
 
 -- | Encode a JuicyPixels `Image` given a matrix
 encodePng :: [[Word8]] -> T.Image Word8
 encodePng matrix = Image dim dim vector
     where dim    = P.length matrix
-          vector = V.map ((*255) . swapWord) $ V.fromList $ P.concat matrix
+          vector = V.map ((*255) . swapWord) $ V.fromList $ join matrix
 
 -- | To help scale the image up, e.g.
 --
@@ -66,4 +67,4 @@
 --
 -- to scale @smallMatrix :: [[Word8]]@ by a factor of 8
 fattenList :: Int -> [a] -> [a]
-fattenList i l = P.concat $ P.foldr ((:) . P.replicate i) [] l
+fattenList = (=<<) . replicate
diff --git a/src/Data/QRCodes/Utils.hs b/src/Data/QRCodes/Utils.hs
--- a/src/Data/QRCodes/Utils.hs
+++ b/src/Data/QRCodes/Utils.hs
@@ -1,5 +1,5 @@
 -- | Miscellaneous helper functions that don't fit anywhere else
-module Data.QRCodes.Utils where
+module Data.QRCodes.Utils (preserveUpper, resolveUpper, swapWord, liftEither) where
 
 import qualified Data.ByteString.Char8 as BS
 import           Data.Char             (toLower, toUpper)
@@ -24,7 +24,7 @@
 lift :: (String -> String) -> (BS.ByteString -> BS.ByteString)
 lift f = BS.pack . f . BS.unpack
 
--- | helper function to life Either values to IO in our case
+-- | helper function to lift Either values to IO in our case
 liftEither :: (Show b, Monad m) => (t -> m a) -> Either b t -> m a
 liftEither = either (error . show)
 
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,75 +1,4 @@
-# This file was automatically generated by 'stack init'
-#
-# Some commonly used options have been documented as comments in this file.
-# For advanced use and comprehensive documentation of the format, please see:
-# http://docs.haskellstack.org/en/stable/yaml_configuration/
-
-# A warning or info to be displayed to the user on config load.
-user-message: ! 'Warning (added by new or init): Specified resolver could not satisfy
-  all dependencies. Some external packages have been added as dependencies.
-
-  You can suppress this message by removing it from stack.yaml
-
-'
-
-# Resolver to choose a 'specific' stackage snapshot or a compiler version.
-# A snapshot resolver dictates the compiler version and the set of packages
-# to be used for project dependencies. For example:
-#
-# resolver: lts-3.5
-# resolver: nightly-2015-09-21
-# resolver: ghc-7.10.2
-# resolver: ghcjs-0.1.0_ghc-7.10.2
-# resolver:
-#  name: custom-snapshot
-#  location: "./custom-snapshot.yaml"
-resolver: lts-8.15
-
-# User packages to be built.
-# Various formats can be used as shown in the example below.
-#
-# packages:
-# - some-directory
-# - https://example.com/foo/bar/baz-0.0.2.tar.gz
-# - location:
-#    git: https://github.com/commercialhaskell/stack.git
-#    commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
-# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a
-#   extra-dep: true
-#  subdirs:
-#  - auto-update
-#  - wai
-#
-# A package marked 'extra-dep: true' will only be built if demanded by a
-# non-dependency (i.e. a user package), and its test suites and benchmarks
-# will not be run. This is useful for tweaking upstream packages.
-packages:
-- '.'
-# Dependency packages to be pulled from upstream that are not in the resolver
-# (e.g., acme-missiles-0.3)
+---
+resolver: lts-11.4
 extra-deps:
-- haskell-qrencode-1.0.4
-
-# Override default flag values for local packages and extra-deps
-flags: {}
-
-# Extra package databases containing global packages
-extra-package-dbs: []
-
-# Control whether we use the GHC we find on the path
-# system-ghc: true
-#
-# Require a specific version of stack, using version ranges
-# require-stack-version: -any # Default
-# require-stack-version: ">=1.4"
-#
-# Override the architecture used by stack, especially useful on Windows
-# arch: i386
-# arch: x86_64
-#
-# Extra directories used by stack for building
-# extra-include-dirs: [/path/to/dir]
-# extra-lib-dirs: [/path/to/dir]
-#
-# Allow a newer minor version of GHC than the snapshot specifies
-# compiler-check: newer-minor
+  - haskell-qrencode-1.0.4
