diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,13 @@
+Change log
+==========
+
+`aeson-options` uses [PVP Versioning][1].
+The change log is available [on GitHub][2].
+
+0.0.0
+=====
+
+* Initially created.
+
+[1]: https://pvp.haskell.org
+[2]: https://github.com/serokell/aeson-options/releases
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2018 Serokell
+
+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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+aeson-options
+=============
+
+[![Build Status](https://travis-ci.org/serokell/aeson-options.svg)](https://travis-ci.org/serokell/aeson-options)
+[![Hackage](https://img.shields.io/hackage/v/aeson-options.svg)](https://hackage.haskell.org/package/aeson-options)
+[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
diff --git a/aeson-options.cabal b/aeson-options.cabal
new file mode 100644
--- /dev/null
+++ b/aeson-options.cabal
@@ -0,0 +1,34 @@
+name:                aeson-options
+version:             0.0.0
+synopsis:            Options to derive FromJSON/ToJSON instances
+description:         Options to derive FromJSON/ToJSON instances.
+homepage:            https://github.com/serokell/aeson-options
+bug-reports:         https://github.com/serokell/aeson-options/issues
+license:             MIT
+license-file:        LICENSE
+category:            Data, JSON
+author:              Serokell
+maintainer:          Serokell <hi@serokell.io>
+copyright:           2018 Serokell
+build-type:          Simple
+
+extra-source-files:  CHANGELOG.md
+                   , README.md
+cabal-version:       >=2.0
+
+
+source-repository head
+  type:                git
+  location:            https://github.com/serokell/aeson-options.git
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Data.Aeson.Options
+
+  build-depends:       base >= 4.9 && < 5
+                     , aeson >= 1.0 && < 1.4
+
+  ghc-options:         -Wall -fno-warn-orphans
+  default-language:    Haskell2010
+  default-extensions:  OverloadedStrings
+                       RecordWildCards
diff --git a/src/Data/Aeson/Options.hs b/src/Data/Aeson/Options.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Aeson/Options.hs
@@ -0,0 +1,60 @@
+-- | Options used to derive FromJSON/ToJSON instance. These options
+-- generally comply to our style regarding names. Of course sometimes
+-- they don't fit one's needs, so treat them as just sensible
+-- defaults.
+
+module Data.Aeson.Options
+       ( defaultOptions
+       , leaveTagOptions
+       , defaultOptionsPS
+       ) where
+
+import Data.Char (isLower, isPunctuation, isUpper, toLower)
+import Data.List (findIndex)
+
+import qualified Data.Aeson.TH as A
+
+headToLower :: String -> String
+headToLower []     = error "Can not use headToLower on empty String"
+headToLower (x:xs) = toLower x : xs
+
+stripFieldPrefix :: String -> String
+stripFieldPrefix = dropWhile (not . isUpper)
+
+dropPunctuation :: String -> String
+dropPunctuation = filter (not . isPunctuation)
+
+stripConstructorPrefix :: String -> String
+stripConstructorPrefix t =
+    maybe t (flip drop t . decrementSafe) $ findIndex isLower t
+  where
+    decrementSafe 0 = 0
+    decrementSafe i = i - 1
+
+-- | These options do the following transformations:
+-- 1. Names of field
+-- records are assumed to be camelCased, `camel` part is removed,
+-- `Cased` part is converted to `cased`. So `camelCased` becomes
+-- `cased`. Also all punctuation symbols are dropped before doing it.
+-- 2. Constructors are assumed to start with some capitalized prefix
+-- (which finished right before the last capital letter). This prefix
+-- is dropped and then the first letter is lowercased.
+defaultOptions :: A.Options
+defaultOptions =
+    A.defaultOptions
+    { A.fieldLabelModifier = headToLower . stripFieldPrefix . dropPunctuation
+    , A.constructorTagModifier = headToLower . stripConstructorPrefix
+    , A.sumEncoding = A.ObjectWithSingleField
+    }
+
+-- | These options are the same as `defaultOptions`, but they don't
+-- modify constructor tags.
+leaveTagOptions :: A.Options
+leaveTagOptions = defaultOptions { A.constructorTagModifier = id }
+
+-- | Options used for communication with PureScript by default.
+defaultOptionsPS :: A.Options
+defaultOptionsPS =
+    A.defaultOptions
+    { A.constructorTagModifier = headToLower . stripConstructorPrefix
+    }
