diff --git a/README.markdown b/README.markdown
new file mode 100644
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,404 @@
+# Evoke
+
+:crystal_ball: Evoke is a GHC plugin that automatically derives type class
+instances without using generics or Template Haskell.
+
+- [Motivation](#motivation)
+- [Installation](#installation)
+- [Usage](#usage)
+- [Options](#options)
+- [Type Classes](#type-classes)
+  - [Arbitrary](#arbitrary)
+  - [FromJSON](#fromjson)
+  - [ToJSON](#tojson)
+  - [ToSchema](#toschema)
+- [Performance](#performance)
+- [Benefits](#benefits)
+- [Drawbacks](#drawbacks)
+
+## Motivation
+
+In Haskell there are many ways to provide type class instances for data types.
+As a motivating example, let's say you have the following data type:
+
+``` hs
+data Person = Person
+  { name :: String
+  , age :: Int
+  }
+```
+
+And let's also say that you want to send and receive this data type over the
+wire as JSON. Typically in Haskell you would use the Aeson library and
+implement the `FromJSON` and `ToJSON` instances. The simplest and easiest way
+to do that is to write the instances by hand, like this:
+
+``` hs
+instance FromJSON Person where
+  parseJSON = withObject "Person" $ \ object -> do
+    theirName <- object .: "name"
+    theirAge <- object .: "age"
+    pure Person
+      { name = theirName
+      , age = theirAge
+      }
+
+instance ToJSON Person where
+  toJSON person = object
+    [ "name" .= name person
+    , "age" .= age person
+    ]
+```
+
+This is not difficult, but it's tedious and error prone. It's tedious because
+the instance isn't doing anything interesting --- it's all boilerplate. (What's
+worse: We haven't even written all the boilerplate! We should have implemented
+`toEncoding` for better performance, but we didn't.) And it's error prone
+because we have to type all the key names correctly, get them matched up to the
+correct fields, and make sure that `FromJSON` and `ToJSON` agree with each
+other.
+
+Thankfully GHC has a couple ways to make this easier. The first is Template
+Haskell (TH), and thankfully the Aeson library provides some TH functions for
+generating instances. Instead of writing the above instances, we could simply
+write this:
+
+``` hs
+$( deriveJSON defaultOptions ''Person )
+```
+
+The generated instance would be similar to what we wrote by hand, but we don't
+have to actually write it. And if we update the data type, the instance will be
+updated automatically to match.
+
+Unfortunately this approach has one major problem: It forces the module to be
+recompiled more often. If any of this module's transitive dependencies changes,
+this module will be recompiled. For a small project that's not too bad, but for
+a large project that means TH forces you to recompile way more often.
+
+Fortunately there's another approach that supports generating the instances
+without causing unnecessary recompilations: generics. It's also simple to use:
+
+``` hs
+data Person = Person
+  { name :: String
+  , age :: Int
+  } deriving (Generic, FromJSON, ToJSON)
+```
+
+Again the generated instances will behavior similarly to our hand-written
+instances, but we don't have to worry about keeping everything in sync. This
+feels like the best of all worlds, so what's the problem?
+
+Generics has one major problem: It's slow to compile. Unlike TH, it avoids
+recompiling more often, but when it does recompile it's much slower. And just
+like TH, this is fine for small projects but for large projects it means you'll
+spend a lot of time waiting for generic type class instances to compile.
+
+So what can you do? Ideally we could fix the recompilation checking for TH
+and/or fix the compile time performance for generics. Doing either of those
+things feels daunting to me, so I looked for alternative approaches. I saw that
+it was technically possible for GHC plugins to generate instances, so I created
+Evoke to explore that option.
+
+## Installation
+
+Currently Evoke only supports GHC 8.10. It is possible to support a wider range
+of versions, but I haven't put in the legwork necessary to make that possible.
+Please let me know if you'd like to use Evoke with a different version of GHC.
+
+You can install Evoke by adding it to the `build-depends` section of your
+`*.cabal` file. For example:
+
+``` cabal
+name: example
+version: 0
+library
+  build-depends: evoke, whatever-else
+--               ^^^^^
+```
+
+## Usage
+
+Since Evoke is a GHC plugin, you must enable it before you can use it. To
+enable it on a per-file basis, add the following pragma to the top of a Haskell
+file:
+
+``` hs
+{-# OPTIONS_GHC -fplugin=Evoke #-}
+--              ^^^^^^^^^^^^^^
+```
+
+It can be tedious to add that pragma to each file that needs it. Instead you
+can enable Evoke for every file in a package by adding it to the `ghc-options`
+section of your `*.cabal` file. For example:
+
+``` cabal
+name: example
+version: 0
+library
+  ghc-options: -fplugin=Evoke -whatever-else
+--             ^^^^^^^^^^^^^^
+```
+
+The performance impact of enabling Evoke for an entire package is negligible.
+In practice I recommend enabling Evoke once in the `*.cabal` file rather than
+with a pragma in each source file.
+
+Enabling Evoke will not change the behavior of any modules that previously
+compiled. In order to convince Evoke to derive an instance for you, you must
+write a deriving clause like this:
+
+``` hs
+newtype Person = Person
+  { name :: String
+  } deriving SomeTypeClass via "Evoke"
+--                         ^^^^^^^^^^^
+```
+
+Note that `"Evoke"` is a literal string. You do not need to have any language
+extensions, such as `DerivingVia` or `DerivingStrategies`, enabled in order to
+use Evoke.
+
+## Options
+
+The Evoke plugin itself accepts options, which you can pass using GHC's
+`-fplugin-opt` option. For example, this will output the generated instances:
+
+``` hs
+{-# OPTIONS_GHC -fplugin=Evoke -fplugin-opt=Evoke:--verbose #-}
+--                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+```
+
+Evoke will also output the instances that it generates when you pass the
+`-ddump-deriv` flag to GHC. For example:
+
+``` hs
+{-# OPTIONS_GHC -fplugin=Evoke -ddump-deriv #-}
+--                             ^^^^^^^^^^^^
+```
+
+Each type class can accept its own options, which you can pass by adding them
+to the `"Evoke"` string used. For example:
+
+``` hs
+newtype Person = Person
+  { name :: String
+  } deriving SomeTypeClass via "Evoke --some-option"
+--                                    ^^^^^^^^^^^^^
+```
+
+## Type Classes
+
+These type classes accept the following options:
+
+- `--kebab`: Convert field names into `kebab-case`. For example `firstName`
+  would become `first-name`.
+
+- `--camel`: Convert field names into `camelCase`. For example `FirstName`
+  would become `firstName`. This is usually combined with `--strip PREFIX`.
+
+- `--snake`: Convert field names into `snake_case`. For example `firstName`
+  would become `first_name`.
+
+- `--strip PREFIX`: Removes the given prefix from field names. If the field
+  name doesn't begin with the prefix, an error will be thrown. For example,
+  with `--strip person` the field name `personFirstName` would become
+  `FirstName`.
+
+- `--title`: Convert field names into `TitleCase`. For example `firstName`
+  would become `FirstName`.
+
+Options are processed in order. So for example `--strip person --kebab` would
+change `personFirstName` into `first-name`.
+
+### Arbitrary
+
+Here's an example of how to derive `Arbitrary` using Evoke:
+
+``` hs
+{-# OPTIONS_GHC -fplugin=Evoke #-}
+data Person = Person
+  { name :: String
+  , age :: Int
+  } deriving Arbitrary via "Evoke"
+```
+
+And here's what the generated instance might look like:
+
+``` hs
+instance Test.QuickCheck.Arbitrary Person where
+  arbitrary = do
+    name_1 <- Test.QuickCheck.arbitrary
+    age_2 <- Test.QuickCheck.arbitrary
+    Control.Applicative.pure Person
+      { name = name_1
+      , age = age_2
+      }
+```
+
+### FromJSON
+
+Here's an example of how to derive `FromJSON` using Evoke:
+
+``` hs
+{-# OPTIONS_GHC -fplugin=Evoke #-}
+data Person = Person
+  { name :: String
+  , age :: Int
+  } deriving FromJSON via "Evoke"
+```
+
+And here's what the generated instance might look like:
+
+``` hs
+instance Data.Aeson.FromJSON Person where
+  parseJSON = Data.Aeson.withObject "Main.Person" (\ object_1 -> do
+    name_2 <- object_1 Data.Aeson..: Data.Text.pack "name"
+    age_3 <- object_1 Data.Aeson..: Data.Text.pack "age"
+    Control.Applicative.pure Person
+      { name = name_2
+      , age = age_3
+      })
+```
+
+### ToJSON
+
+Here's an example of how to derive `ToJSON` using Evoke:
+
+``` hs
+{-# OPTIONS_GHC -fplugin=Evoke #-}
+data Person = Person
+  { name :: String
+  , age :: Int
+  } deriving ToJSON via "Evoke"
+```
+
+And here's what the generated instance might look like:
+
+``` hs
+instance Data.Aeson.ToJSON Person where
+  toJSON var_1 = Data.Aeson.object
+    [ Data.Text.pack "name" Data.Aeson..= name var_1
+    , Data.Text.pack "age" Data.Aeson..= age var_1
+    ]
+  toEncoding var_2 = Data.Aeson.pairs (Data.Monoid.mconcat
+    [ Data.Text.pack "name" Data.Aeson..= name var_2
+    , Data.Text.pack "age" Data.Aeson..= age var_2
+    ])
+```
+
+### ToSchema
+
+Here's an example of how to derive `ToSchema` using Evoke:
+
+``` hs
+{-# OPTIONS_GHC -fplugin=Evoke #-}
+data Person = Person
+  { name :: String
+  , age :: Int
+  } deriving ToSchema via "Evoke"
+```
+
+And here's what the generated instance might look like:
+
+``` hs
+instance Data.Swagger.ToSchema Person where
+  declareNamedSchema _proxy_1 = do
+    name_2 <- Data.Swagger.declareSchemaRef (Data.Proxy.Proxy :: Data.Proxy.Proxy String)
+    age_3 <- Data.Swagger.declareSchemaRef (Data.Proxy.Proxy :: Data.Proxy.Proxy Int)
+    Control.Applicative.pure (Data.Swagger.NamedSchema
+      (Data.Maybe.Just (Data.Text.pack "Main.Person"))
+      (Data.Monoid.mempty
+          Control.Lens.& Data.Swagger.type_ Control.Lens.?~ Data.Swagger.SwaggerObject
+          Control.Lens.& Data.Swagger.properties Control.Lens..~ Data.HashMap.Strict.InsOrd.fromList
+            [ (Data.Text.pack "name", name_2)
+            , (Data.Text.pack "age", age_3)
+            ]
+          Control.Lens.& Data.Swagger.required Control.Lens..~
+            [ Data.Text.pack "name"
+            , Data.Text.pack "age"
+            ]))
+```
+
+Note that this instance will require the `ScopedTypeVariables` extension if the
+type has any type variables that are used in any of the fields.
+
+## Performance
+
+There are several answers to the question: "How fast is Evoke?"
+
+The first answer relates to the plugin itself. How long does it take the plugin
+to run? If the plugin is enabled for a module that doesn't actually derive any
+instances, it's basically instantaneous. In that case Evoke just has to walk
+over the parsed module and make sure that nothing needs to be done. If the
+module does derive some instances, it's still very fast. Generating the code
+for the instances does not take an appreciable amount of time. I hesitate to
+call it instantaneous, but you probably won't notice how long it takes.
+
+The second answer relates to the code generated by the plugin. How long does it
+take GHC to compile the generated code? Since this plugin generates code and
+then hands it off to GHC, it's just as fast as manually writing the code
+yourself. It turns out that TH has the same performance characteristics, except
+that using TH causes more frequent recompiles. And compared to generic deriving
+this plugin is much faster.
+
+The last answer relates to the runtime performance of the code generated by the
+plugin. How fast is the generated code? The answer here is practically the same
+as the last one: Just as fast as if you wrote it manually. That's the same as
+TH and quite a bit better than generics.
+
+And now for some specific numbers. At [ACI Learning][] we have a Haskell
+codebase with just over 400 data types that use Evoke for deriving at least one
+type class instance. Previously we used generic deriving for those instances.
+By switching from generics to Evoke, our compilation time improved by at least
+20%! Here's a table summarizing the build times:
+
+[ACI Learning]: https://www.acilearning.com
+
+Flags | Generic | Evoke | Change | Percent
+--- | --- | --- | --- | ---
+`-O1 -j1` | 922s | 750s | -172s | 81%
+`-O0 -j1`  | 372s | 229s | -143s | 62%
+`-O0 -j8`  | 139s | 94s | -45s | 68%
+
+Our runtime also improved slightly, along with lowered CPU and memory usage.
+Those numbers are harder to quantify, but we definitely saw an improvement.
+
+## Benefits
+
+Compared to TH and generics, why might you prefer Evoke?
+
+- It's fast to compile. Generating the instances is basically instantaneous.
+  Compiling the instances takes just as long as if you wrote them manually.
+
+- It doesn't affect recompilation checks. You can generate instances without
+  forcing the module to be recompiled more frequently like you would with TH.
+
+- It's easy to debug. The entire plugin operates as a source-to-source
+  conversion process. You can output the generated source to remove the plugin
+  entirely if you'd like. Or you can run it as a standalone executable.
+
+- It doesn't require any language extensions. Obviously it requires a plugin
+  instead.
+
+## Drawbacks
+
+Compared to TH and generics, why might you avoid Evoke?
+
+- It operates syntactically. Things that are equivalent to the type checker,
+  like `a` and `(a)`, typically confuse Evoke.
+
+- It's tightly coupled to GHC. Since it operates on GHC's view of a parsed
+  module, it naturally depends on that representation.
+
+- It only supports a subset of possible data types. Currently it doesn't
+  support types with multiple constructors or GADTs.
+
+- Each type class must be supported explicitly. And this support must be
+  provided by the plugin itself rather than by various other libraries like
+  Aeson.
+
+- Some things are uncomfortably magical. For instance a field with type
+  `Maybe a` will be optional, but if its type is `Prelude.Maybe a` then it
+  won't be optional.
diff --git a/evoke.cabal b/evoke.cabal
--- a/evoke.cabal
+++ b/evoke.cabal
@@ -1,12 +1,13 @@
 cabal-version: >= 1.10
 
 name: evoke
-version: 0.2021.8.25
+version: 0.2021.9.14
 synopsis: A GHC plugin to derive instances.
 description: Evoke is a GHC plugin to derive instances.
 
 build-type: Simple
 category: Plugin
+extra-source-files: README.markdown
 license-file: LICENSE.txt
 license: MIT
 maintainer: Taylor Fausak
@@ -17,9 +18,8 @@
 
 library
   build-depends:
-    base >= 4.14.1 && < 4.15
-    , ghc >= 8.10.4 && < 8.11
-    , random >= 1.2.0 && < 1.3
+    base >= 4.14 && < 4.15
+    , ghc >= 8.10.1 && < 8.11
   default-language: Haskell2010
   exposed-modules:
     Evoke
@@ -55,12 +55,12 @@
     base
     , aeson
     , evoke
-    , HUnit >= 1.6.2 && < 1.7
-    , insert-ordered-containers >= 0.2.5 && < 0.3
+    , HUnit >= 1.6.1 && < 1.7
+    , insert-ordered-containers >= 0.2.3 && < 0.3
     , lens >= 4.19.2 && < 4.20
     , QuickCheck >= 2.14.2 && < 2.15
     , swagger2 >= 2.6 && < 2.7
-    , text >= 1.2.4 && < 1.3
+    , text >= 1.2.3 && < 1.3
   default-language: Haskell2010
   ghc-options: -rtsopts -threaded
   hs-source-dirs: src/test
diff --git a/src/lib/Evoke.hs b/src/lib/Evoke.hs
--- a/src/lib/Evoke.hs
+++ b/src/lib/Evoke.hs
@@ -349,7 +349,8 @@
         generate moduleName lIdP lHsQTyVars lConDecls options srcSpan
       Nothing -> Hsc.throwError srcSpan $ Ghc.text "unsupported type class"
 
-    Monad.when (Config.verbose config) $ do
+    verbose <- isVerbose config
+    Monad.when verbose $ do
       dynFlags <- Ghc.getDynFlags
       IO.liftIO $ do
         putStrLn $ replicate 80 '-'
@@ -357,6 +358,11 @@
         mapM_ (putStrLn . Ghc.showSDocDump dynFlags . Ghc.ppr) lHsDecls
 
     pure (lImportDecls, lHsDecls)
+
+isVerbose :: Config.Config -> Ghc.Hsc Bool
+isVerbose config = do
+  dynFlags <- Ghc.getDynFlags
+  pure $ Config.verbose config || Ghc.dopt Ghc.Opt_D_dump_deriv dynFlags
 
 getGenerator :: Ghc.LHsSigType Ghc.GhcPs -> Maybe Common.Generator
 getGenerator lHsSigType = do
diff --git a/src/lib/Evoke/Constant/Module.hs b/src/lib/Evoke/Constant/Module.hs
--- a/src/lib/Evoke/Constant/Module.hs
+++ b/src/lib/Evoke/Constant/Module.hs
@@ -1,46 +1,44 @@
-{- hlint ignore "Use camelCase" -}
-
 module Evoke.Constant.Module
-  ( control_applicative
-  , control_lens
-  , data_aeson
-  , data_hashMap_strict_insOrd
-  , data_maybe
-  , data_monoid
-  , data_proxy
-  , data_swagger
-  , data_text
-  , test_quickCheck
+  ( controlApplicative
+  , controlLens
+  , dataAeson
+  , dataHashMapStrictInsOrd
+  , dataMaybe
+  , dataMonoid
+  , dataProxy
+  , dataSwagger
+  , dataText
+  , testQuickCheck
   ) where
 
 import qualified Module as Ghc
 
-control_applicative :: Ghc.ModuleName
-control_applicative = Ghc.mkModuleName "Control.Applicative"
+controlApplicative :: Ghc.ModuleName
+controlApplicative = Ghc.mkModuleName "Control.Applicative"
 
-control_lens :: Ghc.ModuleName
-control_lens = Ghc.mkModuleName "Control.Lens"
+controlLens :: Ghc.ModuleName
+controlLens = Ghc.mkModuleName "Control.Lens"
 
-data_aeson :: Ghc.ModuleName
-data_aeson = Ghc.mkModuleName "Data.Aeson"
+dataAeson :: Ghc.ModuleName
+dataAeson = Ghc.mkModuleName "Data.Aeson"
 
-data_hashMap_strict_insOrd :: Ghc.ModuleName
-data_hashMap_strict_insOrd = Ghc.mkModuleName "Data.HashMap.Strict.InsOrd"
+dataHashMapStrictInsOrd :: Ghc.ModuleName
+dataHashMapStrictInsOrd = Ghc.mkModuleName "Data.HashMap.Strict.InsOrd"
 
-data_maybe :: Ghc.ModuleName
-data_maybe = Ghc.mkModuleName "Data.Maybe"
+dataMaybe :: Ghc.ModuleName
+dataMaybe = Ghc.mkModuleName "Data.Maybe"
 
-data_monoid :: Ghc.ModuleName
-data_monoid = Ghc.mkModuleName "Data.Monoid"
+dataMonoid :: Ghc.ModuleName
+dataMonoid = Ghc.mkModuleName "Data.Monoid"
 
-data_proxy :: Ghc.ModuleName
-data_proxy = Ghc.mkModuleName "Data.Proxy"
+dataProxy :: Ghc.ModuleName
+dataProxy = Ghc.mkModuleName "Data.Proxy"
 
-data_swagger :: Ghc.ModuleName
-data_swagger = Ghc.mkModuleName "Data.Swagger"
+dataSwagger :: Ghc.ModuleName
+dataSwagger = Ghc.mkModuleName "Data.Swagger"
 
-data_text :: Ghc.ModuleName
-data_text = Ghc.mkModuleName "Data.Text"
+dataText :: Ghc.ModuleName
+dataText = Ghc.mkModuleName "Data.Text"
 
-test_quickCheck :: Ghc.ModuleName
-test_quickCheck = Ghc.mkModuleName "Test.QuickCheck"
+testQuickCheck :: Ghc.ModuleName
+testQuickCheck = Ghc.mkModuleName "Test.QuickCheck"
diff --git a/src/lib/Evoke/Generator/Arbitrary.hs b/src/lib/Evoke/Generator/Arbitrary.hs
--- a/src/lib/Evoke/Generator/Arbitrary.hs
+++ b/src/lib/Evoke/Generator/Arbitrary.hs
@@ -2,6 +2,7 @@
   ( generate
   ) where
 
+import qualified Data.List as List
 import qualified Evoke.Constant.Module as Module
 import qualified Evoke.Generator.Common as Common
 import qualified Evoke.Hs as Hs
@@ -19,16 +20,18 @@
     [x] -> pure x
     _ -> Hsc.throwError srcSpan $ Ghc.text "requires exactly one constructor"
   fields <-
-    mapM (fromField srcSpan) . concatMap Constructor.fields $ Type.constructors
-      type_
+    mapM (fromField srcSpan)
+    . List.sortOn Field.name
+    . concatMap Constructor.fields
+    $ Type.constructors type_
 
-  applicative <- Common.makeRandomModule Module.control_applicative
-  quickCheck <- Common.makeRandomModule Module.test_quickCheck
+  applicative <- Common.makeRandomModule Module.controlApplicative
+  quickCheck <- Common.makeRandomModule Module.testQuickCheck
   let
     lImportDecls = Hs.importDecls
       srcSpan
-      [ (Module.control_applicative, applicative)
-      , (Module.test_quickCheck, quickCheck)
+      [ (Module.controlApplicative, applicative)
+      , (Module.testQuickCheck, quickCheck)
       ]
 
     bindStmts = fmap
diff --git a/src/lib/Evoke/Generator/Common.hs b/src/lib/Evoke/Generator/Common.hs
--- a/src/lib/Evoke/Generator/Common.hs
+++ b/src/lib/Evoke/Generator/Common.hs
@@ -9,10 +9,11 @@
   ) where
 
 import qualified Bag as Ghc
+import qualified Control.Monad.IO.Class as IO
 import qualified Data.Char as Char
+import qualified Data.IORef as IORef
 import qualified Data.List as List
 import qualified Data.Maybe as Maybe
-import qualified Data.Word as Word
 import qualified Evoke.Hs as Hs
 import qualified Evoke.Hsc as Hsc
 import qualified Evoke.Type.Constructor as Constructor
@@ -21,7 +22,7 @@
 import qualified GHC.Hs as Ghc
 import qualified GhcPlugins as Ghc
 import qualified System.Console.GetOpt as Console
-import qualified System.Random as Random
+import qualified System.IO.Unsafe as Unsafe
 import qualified Text.Printf as Printf
 
 type Generator
@@ -198,27 +199,24 @@
 -- | Makes a random variable name using the given prefix.
 makeRandomVariable :: Ghc.SrcSpan -> String -> Ghc.Hsc (Ghc.LIdP Ghc.GhcPs)
 makeRandomVariable srcSpan prefix = do
-  word16 <- randomWord16
+  n <- bumpCounter
   pure . Ghc.L srcSpan . Ghc.Unqual . Ghc.mkVarOcc $ Printf.printf
-    "%s%04x"
+    "%s%d"
     prefix
-    word16
-
-randomWord16 :: Ghc.Hsc Word.Word16
-randomWord16 = Random.randomIO
+    n
 
 -- | Makes a random module name. This will convert any periods to underscores
 -- and add a unique suffix.
 --
 -- >>> makeRandomModule "Data.Aeson"
--- "Data_Aeson_01ef"
+-- "Data_Aeson_1"
 makeRandomModule :: Ghc.ModuleName -> Ghc.Hsc Ghc.ModuleName
 makeRandomModule moduleName = do
-  word16 <- randomWord16
+  n <- bumpCounter
   pure . Ghc.mkModuleName $ Printf.printf
-    "%s_%04x"
+    "%s_%d"
     (underscoreAll moduleName)
-    word16
+    n
 
 underscoreAll :: Ghc.ModuleName -> String
 underscoreAll = fmap underscoreOne . Ghc.moduleNameString
@@ -302,3 +300,10 @@
   Ghc.GRHSs Ghc.noExtField [Hs.grhs srcSpan hsExpr]
     . Ghc.L srcSpan
     $ Ghc.EmptyLocalBinds Ghc.noExtField
+
+bumpCounter :: IO.MonadIO m => m Word
+bumpCounter = IO.liftIO . IORef.atomicModifyIORef' counterRef $ \ n -> (n + 1, n)
+
+counterRef :: IORef.IORef Word
+counterRef = Unsafe.unsafePerformIO $ IORef.newIORef 0
+{-# NOINLINE counterRef #-}
diff --git a/src/lib/Evoke/Generator/FromJSON.hs b/src/lib/Evoke/Generator/FromJSON.hs
--- a/src/lib/Evoke/Generator/FromJSON.hs
+++ b/src/lib/Evoke/Generator/FromJSON.hs
@@ -2,6 +2,7 @@
   ( generate
   ) where
 
+import qualified Data.List as List
 import qualified Evoke.Constant.Module as Module
 import qualified Evoke.Generator.Common as Common
 import qualified Evoke.Hs as Hs
@@ -25,19 +26,20 @@
 
   fields <-
     mapM (fromField srcSpan modifyFieldName)
+    . List.sortOn Field.name
     . concatMap Constructor.fields
     $ Type.constructors type_
 
-  applicative <- Common.makeRandomModule Module.control_applicative
-  aeson <- Common.makeRandomModule Module.data_aeson
-  text <- Common.makeRandomModule Module.data_text
+  applicative <- Common.makeRandomModule Module.controlApplicative
+  aeson <- Common.makeRandomModule Module.dataAeson
+  text <- Common.makeRandomModule Module.dataText
   object <- Common.makeRandomVariable srcSpan "object_"
   let
     lImportDecls = Hs.importDecls
       srcSpan
-      [ (Module.control_applicative, applicative)
-      , (Module.data_aeson, aeson)
-      , (Module.data_text, text)
+      [ (Module.controlApplicative, applicative)
+      , (Module.dataAeson, aeson)
+      , (Module.dataText, text)
       ]
 
     bindStmts = fmap
diff --git a/src/lib/Evoke/Generator/ToJSON.hs b/src/lib/Evoke/Generator/ToJSON.hs
--- a/src/lib/Evoke/Generator/ToJSON.hs
+++ b/src/lib/Evoke/Generator/ToJSON.hs
@@ -2,6 +2,7 @@
   ( generate
   ) where
 
+import qualified Data.List as List
 import qualified Evoke.Constant.Module as Module
 import qualified Evoke.Generator.Common as Common
 import qualified Evoke.Hs as Hs
@@ -25,21 +26,22 @@
 
   fieldNames <-
     mapM (fromField modifyFieldName)
+    . List.sort
     . fmap Field.name
     . concatMap Constructor.fields
     $ Type.constructors type_
 
-  aeson <- Common.makeRandomModule Module.data_aeson
-  monoid <- Common.makeRandomModule Module.data_monoid
-  text <- Common.makeRandomModule Module.data_text
+  aeson <- Common.makeRandomModule Module.dataAeson
+  monoid <- Common.makeRandomModule Module.dataMonoid
+  text <- Common.makeRandomModule Module.dataText
   var1 <- Common.makeRandomVariable srcSpan "var_"
   var2 <- Common.makeRandomVariable srcSpan "var_"
   let
     lImportDecls = Hs.importDecls
       srcSpan
-      [ (Module.data_aeson, aeson)
-      , (Module.data_monoid, monoid)
-      , (Module.data_text, text)
+      [ (Module.dataAeson, aeson)
+      , (Module.dataMonoid, monoid)
+      , (Module.dataText, text)
       ]
 
     toPair lRdrName (occName, fieldName) =
diff --git a/src/lib/Evoke/Generator/ToSchema.hs b/src/lib/Evoke/Generator/ToSchema.hs
--- a/src/lib/Evoke/Generator/ToSchema.hs
+++ b/src/lib/Evoke/Generator/ToSchema.hs
@@ -2,6 +2,7 @@
   ( generate
   ) where
 
+import qualified Data.List as List
 import qualified Evoke.Constant.Module as Module
 import qualified Evoke.Generator.Common as Common
 import qualified Evoke.Hs as Hs
@@ -26,29 +27,30 @@
 
   fields <-
     mapM (fromField srcSpan modifyFieldName)
+    . List.sortOn Field.name
     . concatMap Constructor.fields
     $ Type.constructors type_
 
-  applicative <- Common.makeRandomModule Module.control_applicative
-  lens <- Common.makeRandomModule Module.control_lens
-  hashMap <- Common.makeRandomModule Module.data_hashMap_strict_insOrd
-  dataMaybe <- Common.makeRandomModule Module.data_maybe
-  monoid <- Common.makeRandomModule Module.data_monoid
-  proxy <- Common.makeRandomModule Module.data_proxy
-  swagger <- Common.makeRandomModule Module.data_swagger
-  text <- Common.makeRandomModule Module.data_text
+  applicative <- Common.makeRandomModule Module.controlApplicative
+  lens <- Common.makeRandomModule Module.controlLens
+  hashMap <- Common.makeRandomModule Module.dataHashMapStrictInsOrd
+  dataMaybe <- Common.makeRandomModule Module.dataMaybe
+  monoid <- Common.makeRandomModule Module.dataMonoid
+  proxy <- Common.makeRandomModule Module.dataProxy
+  swagger <- Common.makeRandomModule Module.dataSwagger
+  text <- Common.makeRandomModule Module.dataText
   ignored <- Common.makeRandomVariable srcSpan "_proxy_"
   let
     lImportDecls = Hs.importDecls
       srcSpan
-      [ (Module.control_applicative, applicative)
-      , (Module.control_lens, lens)
-      , (Module.data_hashMap_strict_insOrd, hashMap)
-      , (Module.data_maybe, dataMaybe)
-      , (Module.data_monoid, monoid)
-      , (Module.data_proxy, proxy)
-      , (Module.data_swagger, swagger)
-      , (Module.data_text, text)
+      [ (Module.controlApplicative, applicative)
+      , (Module.controlLens, lens)
+      , (Module.dataHashMapStrictInsOrd, hashMap)
+      , (Module.dataMaybe, dataMaybe)
+      , (Module.dataMonoid, monoid)
+      , (Module.dataProxy, proxy)
+      , (Module.dataSwagger, swagger)
+      , (Module.dataText, text)
       ]
 
     toBind field var =
