diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2016, Nikita Volkov
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
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/json-bytes-builder.cabal b/json-bytes-builder.cabal
new file mode 100644
--- /dev/null
+++ b/json-bytes-builder.cabal
@@ -0,0 +1,62 @@
+name:
+  json-bytes-builder
+version:
+  0.2
+synopsis:
+  Direct-to-bytes JSON Builder
+description:
+  An API for encoding of arbitrary data-structures into JSON byte-arrays,
+  which is faster than \"aeson\".
+category:
+  JSON, Codecs
+homepage:
+  https://github.com/nikita-volkov/json-bytes-builder
+bug-reports:
+  https://github.com/nikita-volkov/json-bytes-builder/issues 
+author:
+  Nikita Volkov <nikita.y.volkov@mail.ru>
+maintainer:
+  Nikita Volkov <nikita.y.volkov@mail.ru>
+copyright:
+  (c) 2016, Nikita Volkov
+license:
+  MIT
+license-file:
+  LICENSE
+build-type:
+  Simple
+cabal-version:
+  >=1.10
+
+
+source-repository head
+  type:
+    git
+  location:
+    git://github.com/nikita-volkov/json-bytes-builder.git
+
+
+library
+  hs-source-dirs:
+    library
+  default-extensions:
+    Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples
+  default-language:
+    Haskell2010
+  other-modules:
+    JSONBytesBuilder.Prelude
+    JSONBytesBuilder.BoundedPrims
+    JSONBytesBuilder.Builders
+  exposed-modules:
+    JSONBytesBuilder.Builder
+    JSONBytesBuilder.Interpreters.ByteStringBuilder
+    JSONBytesBuilder.Interpreters.ByteString
+    JSONBytesBuilder.Interpreters.LazyByteString
+  build-depends:
+    scientific == 0.3.*,
+    text == 1.*,
+    bytestring == 0.10.*,
+    semigroups >= 0.16 && < 0.20,
+    base-prelude < 2,
+    base >= 4.6 && < 5
+
diff --git a/library/JSONBytesBuilder/BoundedPrims.hs b/library/JSONBytesBuilder/BoundedPrims.hs
new file mode 100644
--- /dev/null
+++ b/library/JSONBytesBuilder/BoundedPrims.hs
@@ -0,0 +1,72 @@
+module JSONBytesBuilder.BoundedPrims
+where
+
+import JSONBytesBuilder.Prelude
+import Data.ByteString.Builder.Prim
+
+
+{-# INLINE null #-}
+null :: BoundedPrim ()
+null =
+  ascii4 ('n', ('u', ('l', 'l')))
+
+{-# INLINE boolean #-}
+boolean :: BoundedPrim Bool
+boolean =
+  condB id (ascii4 ('t', ('r', ('u', 'e')))) (ascii5 ('f', ('a', ('l', ('s', 'e')))))
+
+{-# INLINE emptyArray #-}
+emptyArray :: BoundedPrim ()
+emptyArray =
+  ascii2 ('[', ']')
+
+{-# INLINE emptyObject #-}
+emptyObject :: BoundedPrim ()
+emptyObject =
+  ascii2 ('{', '}')
+
+{-# INLINE stringEncodedByte #-}
+stringEncodedByte :: BoundedPrim Word8
+stringEncodedByte =
+  condB (== (fromIntegral . ord) '\\') (ascii2 ('\\', '\\')) $
+  condB (== (fromIntegral . ord) '\"') (ascii2 ('\\', '"')) $
+  condB (>= (fromIntegral . ord) '\x20') (liftFixedToBounded word8) $
+  condB (== (fromIntegral . ord) '\n') (ascii2 ('\\', 'n')) $
+  condB (== (fromIntegral . ord) '\r') (ascii2 ('\\', 'r')) $
+  condB (== (fromIntegral . ord) '\t') (ascii2 ('\\', 't')) $
+  hexEncodedByte
+
+{-# INLINE hexEncodedByte #-}
+hexEncodedByte :: BoundedPrim Word8
+hexEncodedByte =
+  liftFixedToBounded ((\c -> ('\\', ('u', fromIntegral c))) >$< char8 >*< char8 >*< word16HexFixed)
+
+{-# INLINE ascii2 #-}
+ascii2 :: (Char, Char) -> BoundedPrim a
+ascii2 cs =
+  liftFixedToBounded $
+  const cs >$< char8 >*< char8
+
+{-# INLINE ascii4 #-}
+ascii4 :: (Char, (Char, (Char, Char))) -> BoundedPrim a
+ascii4 cs =
+  liftFixedToBounded $
+  const cs >$< char8 >*< char8 >*< char8 >*< char8
+
+{-# INLINE ascii5 #-}
+ascii5 :: (Char, (Char, (Char, (Char, Char)))) -> BoundedPrim a
+ascii5 cs =
+  liftFixedToBounded $
+  const cs >$< char8 >*< char8 >*< char8 >*< char8 >*< char8
+
+{-# INLINE ascii6 #-}
+ascii6 :: (Char, (Char, (Char, (Char, (Char, Char))))) -> BoundedPrim a
+ascii6 cs =
+  liftFixedToBounded $ 
+  const cs >$< char8 >*< char8 >*< char8 >*< char8 >*< char8 >*< char8
+
+{-# INLINE ascii8 #-}
+ascii8 :: (Char, (Char, (Char, (Char, (Char, (Char, (Char, Char))))))) -> BoundedPrim a
+ascii8 cs =
+  liftFixedToBounded $
+  const cs >$< char8 >*< char8 >*< char8 >*< char8 >*< char8 >*< char8 >*< char8 >*< char8
diff --git a/library/JSONBytesBuilder/Builder.hs b/library/JSONBytesBuilder/Builder.hs
new file mode 100644
--- /dev/null
+++ b/library/JSONBytesBuilder/Builder.hs
@@ -0,0 +1,114 @@
+module JSONBytesBuilder.Builder
+(
+  JSON,
+  null,
+  boolean,
+  number_int,
+  number_double,
+  number_scientific,
+  string,
+  object,
+  array,
+  Object,
+  row,
+  Array,
+  element,
+)
+where
+
+import JSONBytesBuilder.Prelude hiding (null)
+import qualified Data.ByteString.Builder as A
+import qualified JSONBytesBuilder.Builders as E
+
+
+newtype JSON =
+  JSON A.Builder
+
+newtype Object =
+  Object (Maybe A.Builder)
+
+instance Monoid Object where
+  {-# INLINE mempty #-}
+  mempty =
+    Object Nothing
+  {-# INLINE mappend #-}
+  mappend =
+    \case
+      Object (Just left) ->
+        \case
+          Object (Just right) ->
+            Object (Just (left <> A.char8 ',' <> right))
+          _ ->
+            Object (Just left)
+      Object Nothing ->
+        id
+
+newtype Array =
+  Array (Maybe A.Builder)
+
+instance Monoid Array where
+  {-# INLINE mempty #-}
+  mempty =
+    Array Nothing
+  {-# INLINE mappend #-}
+  mappend =
+    \case
+      Array (Just left) ->
+        \case
+          Array (Just right) ->
+            Array (Just (left <> A.char8 ',' <> right))
+          _ ->
+            Array (Just left)
+      Array Nothing ->
+        id
+
+{-# INLINE null #-}
+null :: JSON
+null =
+  JSON (inline E.null)
+
+{-# INLINE boolean #-}
+boolean :: Bool -> JSON
+boolean =
+  JSON . inline E.boolean
+
+{-# INLINE number_int #-}
+number_int :: Int -> JSON
+number_int =
+  JSON . inline A.intDec
+
+{-# INLINE number_double #-}
+number_double :: Double -> JSON
+number_double =
+  JSON . inline A.doubleDec
+
+{-# INLINE number_scientific #-}
+number_scientific :: Scientific -> JSON
+number_scientific =
+  JSON . inline E.scientific
+
+{-# INLINE string #-}
+string :: Text -> JSON
+string =
+  JSON . inline E.string
+
+{-# INLINE object #-}
+object :: Object -> JSON
+object (Object x) =
+  JSON (maybe E.emptyObject (inline E.inCurlies) x)
+
+{-# INLINE array #-}
+array :: Array -> JSON
+array (Array x) =
+  JSON (maybe E.emptyArray (inline E.inCurlies) x)
+
+{-# INLINE row #-}
+row :: Text -> JSON -> Object
+row key (JSON value) =
+  Object (Just (inline E.row key value))
+
+{-# INLINE element #-}
+element :: JSON -> Array
+element (JSON value) =
+  Array (Just value)
+
diff --git a/library/JSONBytesBuilder/Builders.hs b/library/JSONBytesBuilder/Builders.hs
new file mode 100644
--- /dev/null
+++ b/library/JSONBytesBuilder/Builders.hs
@@ -0,0 +1,66 @@
+module JSONBytesBuilder.Builders
+where
+
+import JSONBytesBuilder.Prelude hiding (length, null)
+import Data.ByteString.Builder
+import qualified JSONBytesBuilder.BoundedPrims as A
+import qualified Data.ByteString.Builder.Prim as A
+import qualified Data.Text.Encoding as B
+import qualified Data.Scientific as C
+import qualified Data.ByteString.Builder.Scientific as D
+
+
+{-# INLINABLE null #-}
+null :: Builder
+null =
+  A.primBounded A.null ()
+
+{-# INLINABLE boolean #-}
+boolean :: Bool -> Builder
+boolean =
+  A.primBounded A.boolean
+
+{-# INLINABLE string #-}
+string :: Text -> Builder
+string x =
+  char8 '"' <> B.encodeUtf8BuilderEscaped A.stringEncodedByte x <> char8 '"'
+
+{-# INLINABLE scientific #-}
+scientific :: Scientific -> Builder
+scientific n =
+  if e < 0
+    then D.scientificBuilder n
+    else integerDec (C.coefficient n * 10 ^ e)
+  where
+    e =
+      C.base10Exponent n
+
+{-# INLINABLE inCurlies #-}
+inCurlies :: Builder -> Builder
+inCurlies x =
+  char8 '{' <> x <> char8 '}'
+
+{-# INLINABLE row #-}
+row :: Text -> Builder -> Builder
+row key value =
+  string key <> char8 ':' <> value
+
+{-# INLINABLE inSquarlies #-}
+inSquarlies :: Builder -> Builder
+inSquarlies x =
+  char8 '[' <> x <> char8 ']'
+
+{-# INLINABLE commaSeparated #-}
+commaSeparated :: Builder -> Builder -> Builder
+commaSeparated left right =
+  left <> char8 ',' <> right
+
+{-# INLINABLE emptyObject #-}
+emptyObject :: Builder
+emptyObject =
+  A.primBounded A.emptyObject ()
+
+{-# INLINABLE emptyArray #-}
+emptyArray :: Builder
+emptyArray =
+  A.primBounded A.emptyArray ()
diff --git a/library/JSONBytesBuilder/Interpreters/ByteString.hs b/library/JSONBytesBuilder/Interpreters/ByteString.hs
new file mode 100644
--- /dev/null
+++ b/library/JSONBytesBuilder/Interpreters/ByteString.hs
@@ -0,0 +1,18 @@
+module JSONBytesBuilder.Interpreters.ByteString
+(
+  compactJSON,
+)
+where
+
+import JSONBytesBuilder.Prelude hiding (length, null)
+import JSONBytesBuilder.Builder
+import qualified JSONBytesBuilder.Interpreters.LazyByteString as A
+import qualified Data.ByteString.Lazy as B
+
+
+-- |
+-- Produce a strict JSON ByteString with compact syntax
+{-# INLINE compactJSON #-}
+compactJSON :: JSON -> ByteString
+compactJSON =
+  B.toStrict . A.compactJSON
diff --git a/library/JSONBytesBuilder/Interpreters/ByteStringBuilder.hs b/library/JSONBytesBuilder/Interpreters/ByteStringBuilder.hs
new file mode 100644
--- /dev/null
+++ b/library/JSONBytesBuilder/Interpreters/ByteStringBuilder.hs
@@ -0,0 +1,17 @@
+module JSONBytesBuilder.Interpreters.ByteStringBuilder
+(
+  compactJSON,
+)
+where
+
+import JSONBytesBuilder.Prelude hiding (length, null)
+import JSONBytesBuilder.Builder
+import Data.ByteString.Builder
+
+
+-- |
+-- Produce a JSON ByteString builder with compact syntax
+{-# INLINE compactJSON #-}
+compactJSON :: JSON -> Builder
+compactJSON =
+  unsafeCoerce
diff --git a/library/JSONBytesBuilder/Interpreters/LazyByteString.hs b/library/JSONBytesBuilder/Interpreters/LazyByteString.hs
new file mode 100644
--- /dev/null
+++ b/library/JSONBytesBuilder/Interpreters/LazyByteString.hs
@@ -0,0 +1,19 @@
+module JSONBytesBuilder.Interpreters.LazyByteString
+(
+  compactJSON,
+)
+where
+
+import JSONBytesBuilder.Prelude hiding (length, null)
+import JSONBytesBuilder.Builder
+import Data.ByteString.Builder
+import qualified JSONBytesBuilder.Interpreters.ByteStringBuilder as A
+import qualified Data.ByteString.Lazy as B
+
+
+-- |
+-- Produce a lazy JSON ByteString with compact syntax
+{-# INLINE compactJSON #-}
+compactJSON :: JSON -> B.ByteString
+compactJSON =
+  toLazyByteString . A.compactJSON
diff --git a/library/JSONBytesBuilder/Prelude.hs b/library/JSONBytesBuilder/Prelude.hs
new file mode 100644
--- /dev/null
+++ b/library/JSONBytesBuilder/Prelude.hs
@@ -0,0 +1,11 @@
+module JSONBytesBuilder.Prelude
+(
+  module Exports,
+)
+where
+
+import BasePrelude as Exports hiding ((<>))
+import Data.Semigroup as Exports (Semigroup(..))
+import Data.Text as Exports (Text)
+import Data.ByteString as Exports (ByteString)
+import Data.Scientific as Exports (Scientific)
