diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,10 @@
 Changelog
 =========
+    3.1.2  Apr 2020
+        * Future-proof nested code gen interface
+          with parametric `CodeFrag`ment that can
+          refer to thing that is not a type.
+
     3.1.1  Apr 2020
         * Expose Data.Aeson.AutoType.Nested
 
diff --git a/json-autotype.cabal b/json-autotype.cabal
--- a/json-autotype.cabal
+++ b/json-autotype.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 1f3b5938078282c1d5d432d27afdc61b719195bd936f167412da2cc5cca230d3
+-- hash: 284ee102820ec2e6f94fe118266cdb759c0049a5e95f88fd6c42a73e39aeff04
 
 name:                json-autotype
-version:             3.1.1
+version:             3.1.2
 synopsis:            Automatic type declaration for JSON input data
 description:         Generates datatype declarations with Aeson''s ''Data.Aeson.FromJSON''
                      .
diff --git a/src/Data/Aeson/AutoType/CodeGen/Haskell.hs b/src/Data/Aeson/AutoType/CodeGen/Haskell.hs
--- a/src/Data/Aeson/AutoType/CodeGen/Haskell.hs
+++ b/src/Data/Aeson/AutoType/CodeGen/Haskell.hs
@@ -11,6 +11,7 @@
   , importedModules
   , requiredPackages
   , generateModuleImports
+  , ModuleImport
   ) where
 
 import qualified Data.Text           as Text
@@ -40,6 +41,7 @@
 defaultHaskellFilename :: FilePath
 defaultHaskellFilename = "JSONTypes.hs"
 
+-- | Generate module header
 header :: Text -> Text
 header moduleName = [src|
 {-# LANGUAGE TemplateHaskell     #-}
@@ -50,12 +52,13 @@
 {-# LANGUAGE DeriveGeneric       #-}
 -- | DO NOT EDIT THIS FILE MANUALLY!
 --   It was automatically generated by `json-autotype`.
-
 module |] <> capitalize moduleName <> [src| where
 |] <> generateModuleImports importedModules
 
+-- | Alias for indicating that this is item in module imports list.
 type ModuleImport = Text
 
+-- | Given a list of imports, generate source code.
 generateModuleImports :: [ModuleImport] -> Text
 generateModuleImports  = Text.unlines
                        . fmap ("import " <>)
@@ -81,8 +84,14 @@
   , "qualified GHC.Generics"
   ]
 
+-- | Epilogue for generated code:
+--
+--   * function to use parser to get data from `Text`
+--   * main function in case we use `runghc` for testing parser immediately
 epilogue :: Text -> Text
 epilogue toplevelName = [src|
+
+-- | Use parser to get |] <> toplevelName <> [src| object
 parse :: FilePath -> IO |] <> toplevelName <> [src|
 parse filename = do
     input <- BSL.readFile filename
@@ -97,6 +106,7 @@
     fatal msg = do hPutStrLn stderr msg
                    exitFailure
 
+-- | For quick testing
 main :: IO ()
 main = do
   filenames <- getArgs
@@ -122,13 +132,18 @@
          else outputFilename
     normalizeTypeName' = Text.unpack . normalizeTypeName . Text.pack
 
+-- | Function to run Haskell module
+--
+--   FIXME: just rely on `run-haskell-module` exports
 runHaskellModule :: FilePath -> [String] -> IO ExitCode
 runHaskellModule = Run.runHaskellModule
 
+-- | Options to be used when running Haskell module
 defaultHaskellOpts :: Run.RunOptions
 defaultHaskellOpts  = def { Run.additionalPackages = ["json-alt", "aeson"]
                           }
 
+-- | Run Haskell module with strict warning options (each warning is an error)
 runHaskellModuleStrict :: FilePath -> [String] -> IO ExitCode
 runHaskellModuleStrict = Run.runHaskellModule' opts
   where
diff --git a/src/Data/Aeson/AutoType/Nested.hs b/src/Data/Aeson/AutoType/Nested.hs
--- a/src/Data/Aeson/AutoType/Nested.hs
+++ b/src/Data/Aeson/AutoType/Nested.hs
@@ -1,5 +1,7 @@
-{-# language DeriveGeneric     #-}
-{-# language OverloadedStrings #-}
+{-# language DeriveGeneric        #-}
+{-# language OverloadedStrings    #-}
+{-# language TypeSynonymInstances #-}
+{-# language FlexibleInstances    #-}
 -- | Simple interface for using AutoType inference
 --   in other code generators.
 --
@@ -12,17 +14,21 @@
 --   Note that while we can put more code in the module,
 --   it is recommended to avoid multiple automatically
 --   generated types in order to avoid name conflicts.
+--
+--   NOTE: this interface is yet unstable
 module Data.Aeson.AutoType.Nested(
     defaultImportedModules
   , generateModuleImports
   , inferType
-  , CodeFragment
+  , CodeFrag(..)
   , TypeName
-  , DeclaredType(..)
+  , TypeFrag
+  , ModuleImport
+  , PackageName
   ) where
 
 import Data.Aeson
-import Data.Aeson.AutoType.CodeGen.Haskell(generateModuleImports, requiredPackages, importedModules)
+import Data.Aeson.AutoType.CodeGen.Haskell(generateModuleImports, requiredPackages, importedModules, ModuleImport)
 import Data.Aeson.AutoType.CodeGen.HaskellFormat(displaySplitTypes)
 import Data.Aeson.AutoType.Extract(extractType, unifyTypes)
 import Data.Aeson.AutoType.Split(splitTypeByLabel)
@@ -34,43 +40,43 @@
 -- FIXME: general type to compose generated types
 -- move to JSON Autotype as library interface?
 -- * API Response Structures
-type CodeFragment   = Text
+type Code           = Text
 type TypeName       = Text
-type ImportedModule = Text
 type PackageName    = Text
 
--- | Type declaration and its requirements
+-- | Generated code reference and its requirements
 --   Content to embed in an autogenerated module:
---   * name of the type to reference
+--
+--   * name of the reference
 --   * declarations to describe it
 --   * module imports necessary for declarations
 --     to work
-data DeclaredType = DeclaredType
+data CodeFrag a = CodeFrag
   {
     -- | Code fragment to be inserted in generated module
-    typeCodeFragment    ::  CodeFragment
+    codeFragCode     ::  Code
     -- | Toplevel type name to refer to
-  , typeName            ::  TypeName
+  , codeFragName     ::  a
     -- | List of clauses to add to imports list
-  , typeImportedModules :: [ImportedModule]
+  , codeFragImports  :: [ModuleImport]
     -- | List of packages to add to generated package dependencies
-  , typePackages        :: [PackageName]
-  }
-  deriving
-    ( Eq
-    , Show
-    , Generic
-    , Typeable
-    )
+  , codeFragPackages :: [PackageName]
+  } deriving
+      ( Eq
+      , Show
+      , Generic
+      , Typeable
+      )
 
+type TypeFrag = CodeFrag TypeName
 
-instance Default DeclaredType where
+instance Default TypeFrag where
   -- Minimal placeholder to use in case we cannot infer proper type
-  def = DeclaredType {
-            typeCodeFragment    =  ""
-          , typeName            =  "Data.Aeson.Value"
-          , typeImportedModules = ["qualified Data.Aeson"]
-          , typePackages        = ["aeson"]
+  def = CodeFrag {
+            codeFragCode     =  ""
+          , codeFragName     =  "Data.Aeson.Value"
+          , codeFragImports  = ["qualified Data.Aeson"]
+          , codeFragPackages = ["aeson"]
           }
 
 -- | List of modules imported for Autotyped declarations
@@ -81,14 +87,14 @@
 --   either an error, or an `EndpointResponse`
 --   that allows to declare and use this type
 --   in generated module.
-inferType :: Text -> [Value] -> DeclaredType
+inferType :: Text -> [Value] -> TypeFrag
 inferType typeName []         = def
 inferType typeName jsonValues =
-    DeclaredType {
-          typeImportedModules = defaultImportedModules
-        , typeCodeFragment    = displaySplitTypes splitTypeDescriptors
-        , typeName            = typeName
-        , typePackages        = requiredPackages
+    CodeFrag {
+          codeFragImports  = defaultImportedModules
+        , codeFragCode     = displaySplitTypes splitTypeDescriptors
+        , codeFragName     = typeName
+        , codeFragPackages = requiredPackages
         }
   where
     valueTypes           = map extractType jsonValues
