diff --git a/morpheus-graphql-client.cabal b/morpheus-graphql-client.cabal
--- a/morpheus-graphql-client.cabal
+++ b/morpheus-graphql-client.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.34.4.
+-- This file has been generated from package.yaml by hpack version 0.35.0.
 --
 -- see: https://github.com/sol/hpack
 
 name:           morpheus-graphql-client
-version:        0.21.0
+version:        0.22.0
 synopsis:       Morpheus GraphQL Client
 description:    Build GraphQL APIs with your favorite functional language!
 category:       web, graphql, client
@@ -57,10 +57,6 @@
       Data.Morpheus.Client
   other-modules:
       Data.Morpheus.Client.Declare
-      Data.Morpheus.Client.Declare.Aeson
-      Data.Morpheus.Client.Declare.Client
-      Data.Morpheus.Client.Declare.RequestType
-      Data.Morpheus.Client.Declare.Type
       Data.Morpheus.Client.Fetch
       Data.Morpheus.Client.Fetch.GQLClient
       Data.Morpheus.Client.Fetch.Http
@@ -70,6 +66,7 @@
       Data.Morpheus.Client.Internal.TH
       Data.Morpheus.Client.Internal.Types
       Data.Morpheus.Client.Internal.Utils
+      Data.Morpheus.Client.Printing.TH
       Data.Morpheus.Client.QuasiQuoter
       Data.Morpheus.Client.Schema.JSON.Parse
       Data.Morpheus.Client.Schema.JSON.TypeKind
@@ -91,8 +88,8 @@
     , containers >=0.4.2.1 && <0.7.0
     , file-embed >=0.0.10 && <1.0.0
     , modern-uri >=0.1.0.0 && <1.0.0
-    , morpheus-graphql-code-gen >=0.21.0 && <0.22.0
-    , morpheus-graphql-core >=0.21.0 && <0.22.0
+    , morpheus-graphql-code-gen-utils
+    , morpheus-graphql-core >=0.22.0 && <0.23.0
     , morpheus-graphql-subscriptions
     , mtl >=2.0.0 && <3.0.0
     , relude >=0.3.0 && <2.0.0
@@ -132,8 +129,8 @@
     , file-embed >=0.0.10 && <1.0.0
     , modern-uri >=0.1.0.0 && <1.0.0
     , morpheus-graphql-client
-    , morpheus-graphql-code-gen >=0.21.0 && <0.22.0
-    , morpheus-graphql-core >=0.21.0 && <0.22.0
+    , morpheus-graphql-code-gen-utils
+    , morpheus-graphql-core >=0.22.0 && <0.23.0
     , morpheus-graphql-subscriptions
     , mtl >=2.0.0 && <3.0.0
     , relude >=0.3.0 && <2.0.0
diff --git a/src/Data/Morpheus/Client/Declare.hs b/src/Data/Morpheus/Client/Declare.hs
--- a/src/Data/Morpheus/Client/Declare.hs
+++ b/src/Data/Morpheus/Client/Declare.hs
@@ -12,23 +12,23 @@
   )
 where
 
-import Data.Morpheus.Client.Declare.Client (declareTypes)
-import Data.Morpheus.Client.Declare.RequestType (declareRequestType)
 import Data.Morpheus.Client.Internal.Types
   ( ExecutableSource,
     SchemaSource,
   )
 import Data.Morpheus.Client.Internal.Utils (getFile, getSource, handleResult)
+import Data.Morpheus.Client.Printing.TH
+  ( printDeclarations,
+  )
 import Data.Morpheus.Client.QuasiQuoter (raw)
 import Data.Morpheus.Client.Schema.Parse (parseSchema)
 import Data.Morpheus.Client.Transform
   ( toGlobalDefinitions,
     toLocalDefinitions,
   )
-import Data.Morpheus.CodeGen.Internal.AST
 import Data.Morpheus.Core (parseRequest)
 import Data.Morpheus.Types.IO (GQLRequest (..))
-import Data.Set
+import Data.Morpheus.Types.Internal.AST (TypeName)
 import qualified Data.Set as S
 import Language.Haskell.TH (Dec, Q, runIO)
 import Relude
@@ -46,16 +46,12 @@
     ( do
         schemaDoc <- parseSchema schemaText
         executableDoc <- parseRequest request
-        toLocalDefinitions executableDoc schemaDoc
-    )
-    ( \(fetch, types) ->
-        (<>)
-          <$> declareRequestType query fetch
-          <*> declareTypes types
+        toLocalDefinitions (query, executableDoc) schemaDoc
     )
+    printDeclarations
 
 globalTypeDeclarations :: SchemaSource -> (TypeName -> Bool) -> Q [Dec]
-globalTypeDeclarations src f = handleResult (toGlobalDefinitions f <$> parseSchema src) declareTypes
+globalTypeDeclarations src f = handleResult (toGlobalDefinitions f <$> parseSchema src) printDeclarations
 
 -- | declares global or local types, depending
 -- on whether the second argument is specified or not
@@ -93,7 +89,7 @@
 declareGlobalTypesByName :: FilePath -> [TypeName] -> Q [Dec]
 declareGlobalTypesByName path names = do
   schema <- getSource path
-  globalTypeDeclarations schema (`member` S.fromList names)
+  globalTypeDeclarations schema (`S.member` S.fromList names)
 
 {- ORMOLU_DISABLE -}
 -- | declares object, interface and union types for
diff --git a/src/Data/Morpheus/Client/Declare/Aeson.hs b/src/Data/Morpheus/Client/Declare/Aeson.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Client/Declare/Aeson.hs
+++ /dev/null
@@ -1,264 +0,0 @@
-{-# LANGUAGE ConstrainedClassMethods #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TemplateHaskellQuotes #-}
-{-# LANGUAGE TupleSections #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Client.Declare.Aeson
-  ( aesonDeclarations,
-  )
-where
-
-import Data.Aeson
-import Data.Aeson.Types
-import Data.Morpheus.Client.Internal.TH
-  ( decodeObjectE,
-    destructRecord,
-    failExp,
-    hasInstance,
-    isTypeDeclared,
-    matchWith,
-    mkFieldsE,
-  )
-import Data.Morpheus.Client.Internal.Types
-  ( ClientConstructorDefinition (..),
-    ClientTypeDefinition (..),
-    TypeNameTH (..),
-  )
-import Data.Morpheus.CodeGen.Internal.TH
-  ( applyCons,
-    camelCaseTypeName,
-    funDSimple,
-    toCon,
-    toName,
-    toString,
-    v',
-    _',
-  )
-import Data.Morpheus.Internal.Utils (IsMap (lookup))
-import Data.Morpheus.Types.GQLScalar
-  ( scalarFromJSON,
-    scalarToJSON,
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( FieldName,
-    GQLError,
-    Msg (msg),
-    TypeKind (..),
-    TypeName,
-    internal,
-    isResolverType,
-  )
-import qualified Data.Text as T
-import Language.Haskell.TH
-  ( DecQ,
-    Exp (..),
-    ExpQ,
-    Name,
-    PatQ,
-    Q,
-    appE,
-    conP,
-    cxt,
-    instanceD,
-    tupP,
-  )
-import Language.Haskell.TH.Syntax (Dec)
-import Relude hiding (toString)
-
-aesonDeclarations :: TypeKind -> ClientTypeDefinition -> Q [Dec]
-aesonDeclarations KindEnum clientDef = do
-  a <- deriveIfNotDefined deriveFromJSON ''FromJSON clientDef
-  b <- deriveIfNotDefined deriveToJSON ''ToJSON clientDef
-  pure (a <> b)
-aesonDeclarations KindScalar clientDef = deriveScalarJSON clientDef
-aesonDeclarations kind clientDef
-  | isResolverType kind = deriveIfNotDefined deriveFromJSON ''FromJSON clientDef
-  | otherwise = deriveIfNotDefined deriveToJSON ''ToJSON clientDef
-
-deriveIfNotDefined :: (ClientTypeDefinition -> Q Dec) -> Name -> ClientTypeDefinition -> Q [Dec]
-deriveIfNotDefined derivation typeClass clientDef = do
-  exists <- isTypeDeclared clientDef
-  if exists
-    then do
-      has <- hasInstance typeClass clientDef
-      if has
-        then pure []
-        else mkDerivation
-    else mkDerivation
-  where
-    mkDerivation :: Q [Dec]
-    mkDerivation = do
-      derived <- derivation clientDef
-      pure [derived]
-
-failure :: GQLError -> Q a
-failure = fail . show
-
-deriveScalarJSON :: ClientTypeDefinition -> Q [Dec]
-deriveScalarJSON clientDef = do
-  a <- deriveIfNotDefined deriveScalarFromJSON ''FromJSON clientDef
-  b <- deriveIfNotDefined deriveScalarToJSON ''ToJSON clientDef
-  pure (a <> b)
-
-deriveScalarFromJSON :: ClientTypeDefinition -> DecQ
-deriveScalarFromJSON ClientTypeDefinition {clientTypeName} =
-  defineFromJSON clientTypeName [|scalarFromJSON|]
-
-deriveScalarToJSON :: ClientTypeDefinition -> DecQ
-deriveScalarToJSON
-  ClientTypeDefinition
-    { clientTypeName = TypeNameTH {typename}
-    } = instanceD (cxt []) typeDef body
-    where
-      typeDef = applyCons ''ToJSON [typename]
-      body = [funDSimple 'toJSON [] [|scalarToJSON|]]
-
--- FromJSON
-deriveFromJSON :: ClientTypeDefinition -> DecQ
-deriveFromJSON ClientTypeDefinition {clientCons = [], clientTypeName} =
-  failure $
-    internal $
-      "Type "
-        <> msg (typename clientTypeName)
-        <> " Should Have at least one Constructor"
-deriveFromJSON ClientTypeDefinition {clientTypeName, clientCons, clientKind = KindEnum} =
-  defineFromJSON clientTypeName $
-    aesonFromJSONEnumBody clientTypeName clientCons
-deriveFromJSON
-  ClientTypeDefinition
-    { clientTypeName = clientTypeName@TypeNameTH {namespace},
-      clientCons = [cons]
-    } =
-    defineFromJSON clientTypeName $
-      aesonObject namespace cons
-deriveFromJSON typeD@ClientTypeDefinition {clientTypeName} =
-  defineFromJSON clientTypeName $
-    aesonUnionObject typeD
-
-aesonObject :: [FieldName] -> ClientConstructorDefinition -> ExpQ
-aesonObject tNamespace con@ClientConstructorDefinition {cName} =
-  withBody
-    <$> aesonObjectBody tNamespace con
-  where
-    withBody body =
-      AppE
-        (AppE (VarE 'withObject) name)
-        (LamE [v'] body)
-    name :: Exp
-    name = toString (camelCaseTypeName tNamespace cName)
-
-aesonObjectBody :: [FieldName] -> ClientConstructorDefinition -> ExpQ
-aesonObjectBody namespace ClientConstructorDefinition {cName, cFields} =
-  decodeObjectE
-    entry
-    (camelCaseTypeName namespace cName)
-    cFields
-
-entry :: Bool -> Name
-entry nullable
-  | nullable = '(.:?)
-  | otherwise = '(.:)
-
-aesonUnionObject :: ClientTypeDefinition -> ExpQ
-aesonUnionObject
-  ClientTypeDefinition
-    { clientCons,
-      clientTypeName = TypeNameTH {namespace, typename}
-    } =
-    appE [|takeValueType|] $
-      matchWith elseCondition f clientCons
-    where
-      elseCondition =
-        (tupP [_', v'],)
-          . aesonObjectBody
-            namespace
-          <$> find ((typename ==) . cName) clientCons
-      f cons@ClientConstructorDefinition {cName, cFields} =
-        ( tupP [toString cName, if null cFields then _' else v'],
-          aesonObjectBody namespace cons
-        )
-
-takeValueType :: ((String, Object) -> Parser a) -> Value -> Parser a
-takeValueType f (Object hMap) = case lookup "__typename" hMap of
-  Nothing -> fail "key \"__typename\" not found on object"
-  Just (String x) -> f (T.unpack x, hMap)
-  Just val ->
-    fail $ "key \"__typename\" should be string but found: " <> show val
-takeValueType _ _ = fail "expected Object"
-
-namespaced :: TypeNameTH -> TypeName
-namespaced TypeNameTH {namespace, typename} =
-  camelCaseTypeName namespace typename
-
-defineFromJSON :: TypeNameTH -> ExpQ -> DecQ
-defineFromJSON name expr = instanceD (cxt []) typeDef body
-  where
-    typeDef = applyCons ''FromJSON [namespaced name]
-    body = [funDSimple 'parseJSON [] expr]
-
-aesonFromJSONEnumBody :: TypeNameTH -> [ClientConstructorDefinition] -> ExpQ
-aesonFromJSONEnumBody TypeNameTH {typename} = matchWith (Just (v', failExp)) f
-  where
-    f :: ClientConstructorDefinition -> (PatQ, ExpQ)
-    f ClientConstructorDefinition {cName} =
-      ( toString cName,
-        appE [|pure|] $ toCon $ camelCaseTypeName [typename] cName
-      )
-
-aesonToJSONEnumBody :: TypeNameTH -> [ClientConstructorDefinition] -> ExpQ
-aesonToJSONEnumBody TypeNameTH {typename} = matchWith Nothing f
-  where
-    f :: ClientConstructorDefinition -> (PatQ, ExpQ)
-    f ClientConstructorDefinition {cName} =
-      ( conP (toName $ camelCaseTypeName [typename] cName) [],
-        toString cName
-      )
-
--- ToJSON
-deriveToJSON :: ClientTypeDefinition -> DecQ
-deriveToJSON
-  ClientTypeDefinition
-    { clientCons = []
-    } =
-    fail "Type Should Have at least one Constructor"
-deriveToJSON
-  ClientTypeDefinition
-    { clientTypeName = clientTypeName@TypeNameTH {typename},
-      clientCons,
-      clientKind = KindEnum
-    } = instanceD (cxt []) typeDef body
-    where
-      typeDef = applyCons ''ToJSON [typename]
-      body = [funDSimple 'toJSON [] (aesonToJSONEnumBody clientTypeName clientCons)]
-deriveToJSON
-  ClientTypeDefinition
-    { clientTypeName = TypeNameTH {typename},
-      clientCons = [ClientConstructorDefinition {cFields}]
-    } =
-    instanceD (cxt []) appHead methods
-    where
-      appHead = applyCons ''ToJSON [typename]
-      ------------------------------------------------------------------
-      -- defines: toJSON (User field1 field2 ...)= object ["name" .= name, "age" .= age, ...]
-      methods = [funDSimple 'toJSON args body]
-        where
-          args = [destructRecord typename cFields]
-          body =
-            pure $
-              AppE
-                (VarE 'omitNulls)
-                (mkFieldsE typename '(.=) cFields)
-deriveToJSON _ = fail "Input Unions are not yet supported"
-
-omitNulls :: [Pair] -> Value
-omitNulls = object . filter notNull
-  where
-    notNull (_, Null) = False
-    notNull _ = True
diff --git a/src/Data/Morpheus/Client/Declare/Client.hs b/src/Data/Morpheus/Client/Declare/Client.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Client/Declare/Client.hs
+++ /dev/null
@@ -1,30 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Client.Declare.Client
-  ( declareTypes,
-  )
-where
-
-import Data.Morpheus.Client.Declare.Aeson
-  ( aesonDeclarations,
-  )
-import Data.Morpheus.Client.Declare.Type
-  ( typeDeclarations,
-  )
-import Data.Morpheus.Client.Internal.Types
-  ( ClientTypeDefinition (..),
-  )
-import Language.Haskell.TH
-import Relude hiding (Type)
-
-declareTypes :: [ClientTypeDefinition] -> Q [Dec]
-declareTypes subTypes = concat <$> traverse declareType subTypes
-
-declareType :: ClientTypeDefinition -> Q [Dec]
-declareType clientType@ClientTypeDefinition {clientKind} = do
-  types <- typeDeclarations clientKind clientType
-  instances <- aesonDeclarations clientKind clientType
-  pure (types <> instances)
diff --git a/src/Data/Morpheus/Client/Declare/RequestType.hs b/src/Data/Morpheus/Client/Declare/RequestType.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Client/Declare/RequestType.hs
+++ /dev/null
@@ -1,55 +0,0 @@
-{-# LANGUAGE ConstrainedClassMethods #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes #-}
-{-# LANGUAGE TemplateHaskellQuotes #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Client.Declare.RequestType
-  ( declareRequestType,
-  )
-where
-
-import Data.Morpheus.Client.Fetch.RequestType
-  ( RequestType (..),
-  )
-import Data.Morpheus.Client.Internal.Types
-  ( FetchDefinition (..),
-    TypeNameTH (..),
-  )
-import Data.Morpheus.CodeGen.Internal.TH
-  ( applyCons,
-    funDSimple,
-    toCon,
-    typeInstanceDec,
-    _',
-  )
-import qualified Data.Text as T
-import Language.Haskell.TH
-  ( Dec,
-    Q,
-    Type,
-    cxt,
-    instanceD,
-  )
-import Relude hiding (ByteString, Type)
-
-declareRequestType :: Text -> FetchDefinition -> Q [Dec]
-declareRequestType query FetchDefinition {clientArgumentsTypeName, rootTypeName, fetchOperationType} =
-  pure <$> instanceD (cxt []) iHead methods
-  where
-    queryString = T.unpack query
-    typeName = typename rootTypeName
-    iHead = applyCons ''RequestType [typeName]
-    methods =
-      [ funDSimple '__name [_'] [|typeName|],
-        funDSimple '__query [_'] [|queryString|],
-        funDSimple '__type [_'] [|fetchOperationType|],
-        pure $ typeInstanceDec ''RequestArgs (toCon typeName) (argumentType clientArgumentsTypeName)
-      ]
-
-argumentType :: Maybe TypeNameTH -> Type
-argumentType Nothing = toCon ("()" :: String)
-argumentType (Just clientTypeName) = toCon (typename clientTypeName)
diff --git a/src/Data/Morpheus/Client/Declare/Type.hs b/src/Data/Morpheus/Client/Declare/Type.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Client/Declare/Type.hs
+++ /dev/null
@@ -1,85 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TemplateHaskellQuotes #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Client.Declare.Type
-  ( typeDeclarations,
-  )
-where
-
-import Data.Morpheus.Client.Internal.TH (isTypeDeclared)
-import Data.Morpheus.Client.Internal.Types
-  ( ClientConstructorDefinition (..),
-    ClientTypeDefinition (..),
-    TypeNameTH (..),
-  )
-import Data.Morpheus.Client.Internal.Utils
-  ( isEnum,
-  )
-import Data.Morpheus.CodeGen.Internal.TH
-  ( camelCaseTypeName,
-    declareTypeRef,
-    toCon,
-    toName,
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( ANY,
-    FieldDefinition (..),
-    FieldName,
-    TypeKind (..),
-    TypeName,
-    VALID,
-  )
-import Language.Haskell.TH
-import Relude hiding (Type)
-
-typeDeclarations :: TypeKind -> ClientTypeDefinition -> Q [Dec]
-typeDeclarations KindScalar _ = pure []
-typeDeclarations _ c = do
-  exists <- isTypeDeclared c
-  if exists
-    then pure []
-    else pure [declareType c]
-
-declareType :: ClientTypeDefinition -> Dec
-declareType
-  ClientTypeDefinition
-    { clientTypeName = thName@TypeNameTH {namespace, typename},
-      clientCons
-    } =
-    DataD
-      []
-      (mkConName namespace typename)
-      []
-      Nothing
-      (declareCons thName clientCons)
-      (map derive [''Generic, ''Show, ''Eq])
-    where
-      derive className = DerivClause Nothing [ConT className]
-
-declareCons :: TypeNameTH -> [ClientConstructorDefinition] -> [Con]
-declareCons TypeNameTH {namespace, typename} clientCons
-  | isEnum clientCons = map consE clientCons
-  | otherwise = map consR clientCons
-  where
-    consE ClientConstructorDefinition {cName} = NormalC (mkTypeName namespace typename cName) []
-    consR ClientConstructorDefinition {cName, cFields} =
-      RecC
-        (mkConName namespace cName)
-        (map declareField cFields)
-
-declareField :: FieldDefinition ANY VALID -> (Name, Bang, Type)
-declareField FieldDefinition {fieldName, fieldType} =
-  ( toName fieldName,
-    Bang NoSourceUnpackedness NoSourceStrictness,
-    declareTypeRef toCon fieldType
-  )
-
-mkTypeName :: [FieldName] -> TypeName -> TypeName -> Name
-mkTypeName namespace typename = mkConName namespace . camelCaseTypeName [typename]
-
-mkConName :: [FieldName] -> TypeName -> Name
-mkConName namespace = toName . camelCaseTypeName namespace
diff --git a/src/Data/Morpheus/Client/Internal/TH.hs b/src/Data/Morpheus/Client/Internal/TH.hs
--- a/src/Data/Morpheus/Client/Internal/TH.hs
+++ b/src/Data/Morpheus/Client/Internal/TH.hs
@@ -7,6 +7,7 @@
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TemplateHaskellQuotes #-}
 {-# LANGUAGE NoImplicitPrelude #-}
@@ -15,29 +16,31 @@
   ( matchWith,
     decodeObjectE,
     mkFieldsE,
-    destructRecord,
     failExp,
-    isTypeDeclared,
-    hasInstance,
+    deriveIfNotDefined,
+    declareIfNotDeclared,
   )
 where
 
+import Data.Aeson ((.:))
+import Data.Aeson.Types ((.:?))
 import Data.Foldable (foldr1)
-import Data.Morpheus.Client.Internal.Types (ClientTypeDefinition (..), TypeNameTH (..))
-import Data.Morpheus.CodeGen.Internal.TH
-  ( camelCaseFieldName,
-    camelCaseTypeName,
-    toCon,
+import Data.Morpheus.CodeGen.Internal.AST
+  ( CodeGenConstructor (..),
+    CodeGenField (..),
+    CodeGenType (cgTypeName),
+    CodeGenTypeName (..),
+    getFullName,
+  )
+import Data.Morpheus.CodeGen.TH
+  ( toCon,
     toName,
     toString,
     toVar,
     v',
-    vars,
   )
-import Data.Morpheus.Types.Internal.AST
-  ( FieldDefinition (..),
-    TypeName,
-    isNullable,
+import Data.Morpheus.CodeGen.Utils
+  ( camelCaseFieldName,
   )
 import Language.Haskell.TH
 import Relude hiding (toString)
@@ -65,20 +68,26 @@
         (stringE " is Not Valid Union Constructor")
     )
 
-decodeObjectE :: (Bool -> Name) -> TypeName -> [FieldDefinition cat s] -> ExpQ
-decodeObjectE _ conName [] = appE [|pure|] (toCon conName)
-decodeObjectE funName conName fields =
-  uInfixE
-    (toCon conName)
-    [|(<$>)|]
-    (foldr1 withApplicative $ map (defField funName) fields)
+decodeObjectE :: CodeGenConstructor -> ExpQ
+decodeObjectE CodeGenConstructor {..}
+  | null constructorFields = appE [|pure|] (toCon constructorName)
+  | otherwise =
+      uInfixE
+        (toCon constructorName)
+        [|(<$>)|]
+        (foldr1 withApplicative $ map defField constructorFields)
 
+defField :: CodeGenField -> ExpQ
+defField CodeGenField {..} = uInfixE v' (varE $ bindField fieldIsNullable) (toString fieldName)
+
+bindField :: Bool -> Name
+bindField nullable
+  | nullable = '(.:?)
+  | otherwise = '(.:)
+
 withApplicative :: ExpQ -> ExpQ -> ExpQ
 withApplicative x = uInfixE x [|(<*>)|]
 
-defField :: (Bool -> Name) -> FieldDefinition cat s -> ExpQ
-defField f field@FieldDefinition {fieldName} = uInfixE v' (varE $ f (isNullable field)) (toString fieldName)
-
 -- | 'mkFieldsE'
 --
 --  input :
@@ -92,50 +101,49 @@
 --    ..
 --    ]
 -- >>>
-mkFieldsE :: TypeName -> Name -> [FieldDefinition cat s] -> Exp
+mkFieldsE :: CodeGenTypeName -> Name -> [CodeGenField] -> Exp
 mkFieldsE conName name = ListE . map (mkEntryWith conName name)
 
 --  input : mkFieldWith 'mkValue (FieldDefinition { fieldName = "field1", ..})
 --  expression: mkValue "field1"  field1
 mkEntryWith ::
-  TypeName ->
+  CodeGenTypeName ->
   Name ->
-  FieldDefinition cat s ->
+  CodeGenField ->
   Exp
-mkEntryWith conName f FieldDefinition {fieldName} =
+mkEntryWith conName f CodeGenField {fieldName} =
   AppE
     (AppE (VarE f) (toString fieldName))
-    (toVar $ camelCaseFieldName conName fieldName)
-
--- |
--- input:
--- >>>
--- WAS WAS destructRecord "User" ["name","id"]
--- >>>
---
--- expression:
--- >>>
--- WAS WAS (User name id)
--- >>>
-destructRecord :: TypeName -> [FieldDefinition cat s] -> PatQ
-destructRecord conName fields = conP (toName conName) (vars names)
-  where
-    names = map (camelCaseFieldName conName . fieldName) fields
+    (toVar $ camelCaseFieldName (getFullName conName) fieldName)
 
-isTypeDeclared :: ClientTypeDefinition -> Q Bool
-isTypeDeclared clientDef = do
-  let name = mkTypeName clientDef
+isTypeDeclared :: CodeGenTypeName -> Q Bool
+isTypeDeclared clientTypeName = do
+  let name = toName clientTypeName
   m <- lookupTypeName (show name)
   case m of
     Nothing -> pure False
     _ -> pure True
 
-hasInstance :: Name -> ClientTypeDefinition -> Q Bool
-hasInstance typeClass clientDef = do
-  isInstance typeClass [ConT (mkTypeName clientDef)]
+hasInstance :: Name -> CodeGenType -> Q Bool
+hasInstance typeClass clientDef = isInstance typeClass [ConT (toName (cgTypeName clientDef))]
 
-mkTypeName :: ClientTypeDefinition -> Name
-mkTypeName ClientTypeDefinition {clientTypeName = TypeNameTH namespace typeName} =
-  toType typeName
+deriveIfNotDefined :: (CodeGenType -> Q Dec) -> Name -> CodeGenType -> Q [Dec]
+deriveIfNotDefined derivation typeClass clientDef = do
+  exists <- isTypeDeclared (cgTypeName clientDef)
+  if exists
+    then do
+      has <- hasInstance typeClass clientDef
+      if has
+        then pure []
+        else mkDerivation
+    else mkDerivation
   where
-    toType = toName . camelCaseTypeName namespace
+    mkDerivation :: Q [Dec]
+    mkDerivation = pure <$> derivation clientDef
+
+declareIfNotDeclared :: (CodeGenType -> a) -> CodeGenType -> Q [a]
+declareIfNotDeclared f c = do
+  exists <- isTypeDeclared (cgTypeName c)
+  if exists
+    then pure []
+    else pure [f c]
diff --git a/src/Data/Morpheus/Client/Internal/Types.hs b/src/Data/Morpheus/Client/Internal/Types.hs
--- a/src/Data/Morpheus/Client/Internal/Types.hs
+++ b/src/Data/Morpheus/Client/Internal/Types.hs
@@ -5,52 +5,50 @@
 
 module Data.Morpheus.Client.Internal.Types
   ( ClientTypeDefinition (..),
-    TypeNameTH (..),
-    FetchDefinition (..),
-    ClientConstructorDefinition (..),
+    RequestTypeDefinition (..),
     FetchError (..),
     SchemaSource (..),
     ExecutableSource,
     GQLClientResult,
+    ClientDeclaration (..),
+    DERIVING_MODE (..),
   )
 where
 
 import Data.ByteString.Lazy (ByteString)
+import Data.Morpheus.CodeGen.Internal.AST
+  ( CodeGenConstructor (..),
+    CodeGenType,
+    CodeGenTypeName,
+  )
 import Data.Morpheus.Types.Internal.AST
-  ( ANY,
-    FieldDefinition,
-    FieldName,
-    GQLErrors,
+  ( GQLErrors,
     OperationType,
     TypeKind,
     TypeName,
-    VALID,
   )
 import Relude hiding (ByteString)
 
-data TypeNameTH = TypeNameTH
-  { namespace :: [FieldName],
-    typename :: TypeName
-  }
-  deriving (Show)
+data DERIVING_MODE = SCALAR_MODE | ENUM_MODE | TYPE_MODE
 
-data ClientConstructorDefinition = ClientConstructorDefinition
-  { cName :: TypeName,
-    cFields :: [FieldDefinition ANY VALID]
-  }
-  deriving (Show)
+data ClientDeclaration
+  = ToJSONClass DERIVING_MODE CodeGenType
+  | FromJSONClass DERIVING_MODE CodeGenType
+  | RequestTypeClass RequestTypeDefinition
+  | ClientType CodeGenType
 
 data ClientTypeDefinition = ClientTypeDefinition
-  { clientTypeName :: TypeNameTH,
-    clientCons :: [ClientConstructorDefinition],
+  { clientTypeName :: CodeGenTypeName,
+    clientCons :: [CodeGenConstructor],
     clientKind :: TypeKind
   }
   deriving (Show)
 
-data FetchDefinition = FetchDefinition
-  { rootTypeName :: TypeNameTH,
-    clientArgumentsTypeName :: Maybe TypeNameTH,
-    fetchOperationType :: OperationType
+data RequestTypeDefinition = RequestTypeDefinition
+  { requestName :: TypeName,
+    requestArgs :: TypeName,
+    requestType :: OperationType,
+    requestQuery :: String
   }
   deriving (Show)
 
diff --git a/src/Data/Morpheus/Client/Internal/Utils.hs b/src/Data/Morpheus/Client/Internal/Utils.hs
--- a/src/Data/Morpheus/Client/Internal/Utils.hs
+++ b/src/Data/Morpheus/Client/Internal/Utils.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE NoImplicitPrelude #-}
 
 module Data.Morpheus.Client.Internal.Utils
@@ -7,19 +8,27 @@
     getSource,
     handleResult,
     getFile,
+    omitNulls,
+    emptyTypeError,
+    takeValueType,
   )
 where
 
 import Control.Monad.Except (MonadError (catchError))
+import Data.Aeson (Object)
+import Data.Aeson.Types (Pair, Parser, Value (..), object)
 import qualified Data.ByteString.Lazy.Char8 as L
 import Data.FileEmbed (makeRelativeToProject)
 import Data.List (isSuffixOf)
 import Data.Morpheus.Client.Internal.Types
-  ( ClientConstructorDefinition (cFields),
-    SchemaSource (..),
+  ( SchemaSource (..),
   )
+import Data.Morpheus.CodeGen.Internal.AST (CodeGenConstructor (..), CodeGenTypeName (..), getFullName)
 import Data.Morpheus.Error (gqlWarnings, renderGQLErrors)
 import Data.Morpheus.Internal.Ext (GQLResult, Result (..))
+import Data.Morpheus.Internal.Utils (IsMap (lookup))
+import Data.Morpheus.Types.Internal.AST (Msg (msg), internal)
+import qualified Data.Text as T
 import qualified Data.Text.IO as TIO
 import Language.Haskell.TH (Q, runIO)
 import Language.Haskell.TH.Syntax (qAddDependentFile)
@@ -37,8 +46,8 @@
       | x `elem` collected = collectElems (collected, errors <> [x]) xs
       | otherwise = collectElems (collected <> [x], errors) xs
 
-isEnum :: [ClientConstructorDefinition] -> Bool
-isEnum = all (null . cFields)
+isEnum :: [CodeGenConstructor] -> Bool
+isEnum = all (null . constructorFields)
 
 getSource :: FilePath -> Q SchemaSource
 getSource p
@@ -65,3 +74,20 @@
     { result,
       warnings
     } -> gqlWarnings warnings >> f result
+
+omitNulls :: [Pair] -> Value
+omitNulls = object . filter notNull
+  where
+    notNull (_, Null) = False
+    notNull _ = True
+
+emptyTypeError :: MonadFail m => CodeGenTypeName -> m a
+emptyTypeError name = fail $ show $ internal ("Type " <> msg (getFullName name) <> " Should Have at least one Constructor")
+
+takeValueType :: ((String, Object) -> Parser a) -> Value -> Parser a
+takeValueType f (Object hMap) = case lookup "__typename" hMap of
+  Nothing -> fail "key \"__typename\" not found on object"
+  Just (String x) -> f (T.unpack x, hMap)
+  Just val ->
+    fail $ "key \"__typename\" should be string but found: " <> show val
+takeValueType _ _ = fail "expected Object"
diff --git a/src/Data/Morpheus/Client/Printing/TH.hs b/src/Data/Morpheus/Client/Printing/TH.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Client/Printing/TH.hs
@@ -0,0 +1,152 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskellQuotes #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Client.Printing.TH
+  ( printDeclarations,
+  )
+where
+
+import Data.Aeson
+  ( FromJSON (parseJSON),
+    KeyValue ((.=)),
+    ToJSON (toJSON),
+    withObject,
+  )
+import Data.Morpheus.Client.Fetch.RequestType
+  ( RequestType (..),
+  )
+import Data.Morpheus.Client.Internal.TH
+  ( declareIfNotDeclared,
+    decodeObjectE,
+    deriveIfNotDefined,
+    failExp,
+    matchWith,
+    mkFieldsE,
+  )
+import Data.Morpheus.Client.Internal.Types
+  ( ClientDeclaration (..),
+    DERIVING_MODE (..),
+    RequestTypeDefinition (..),
+  )
+import Data.Morpheus.Client.Internal.Utils
+  ( emptyTypeError,
+    omitNulls,
+    takeValueType,
+  )
+import Data.Morpheus.CodeGen.Internal.AST
+  ( CodeGenConstructor (..),
+    CodeGenType (..),
+    CodeGenTypeName (..),
+    getFullName,
+  )
+import Data.Morpheus.CodeGen.TH
+  ( PrintDec (printDec),
+    ToString (..),
+    destructConstructor,
+    printTypeClass,
+    toCon,
+    toName,
+    toString,
+    toVar,
+    v',
+    _',
+  )
+import Data.Morpheus.Types.GQLScalar
+  ( scalarFromJSON,
+    scalarToJSON,
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( TypeName,
+  )
+import Language.Haskell.TH
+  ( Dec,
+    DecQ,
+    Exp (..),
+    ExpQ,
+    PatQ,
+    Q,
+    appE,
+    tupP,
+  )
+import Relude hiding (ToString, toString)
+
+printDeclarations :: [ClientDeclaration] -> Q [Dec]
+printDeclarations clientType = concat <$> traverse typeDeclarations clientType
+
+typeDeclarations :: ClientDeclaration -> Q [Dec]
+typeDeclarations (FromJSONClass mode clientDef) = deriveIfNotDefined (deriveFromJSON mode) ''FromJSON clientDef
+typeDeclarations (ToJSONClass mode clientDef) = deriveIfNotDefined (deriveToJSON mode) ''ToJSON clientDef
+typeDeclarations (ClientType c) = declareIfNotDeclared printDec c
+typeDeclarations (RequestTypeClass RequestTypeDefinition {..}) =
+  pure <$> printTypeClass [] ''RequestType (toCon requestName) [(''RequestArgs, toCon requestArgs)] methods
+  where
+    methods =
+      [ ('__name, [_'], [|requestName|]),
+        ('__query, [_'], [|requestQuery|]),
+        ('__type, [_'], [|requestType|])
+      ]
+
+-- UTILS
+
+mkFromJSON :: CodeGenTypeName -> ExpQ -> DecQ
+mkFromJSON name expr = printTypeClass [] ''FromJSON (toCon (toName name)) [] [('parseJSON, [], expr)]
+
+mkToJSON :: CodeGenTypeName -> [PatQ] -> ExpQ -> DecQ
+mkToJSON name args expr = printTypeClass [] ''ToJSON (toCon $ toName name) [] [('toJSON, args, expr)]
+
+originalLit :: ToString TypeName a => CodeGenTypeName -> Q a
+originalLit = toString . typename
+
+-- FromJSON
+deriveFromJSON :: DERIVING_MODE -> CodeGenType -> DecQ
+deriveFromJSON SCALAR_MODE CodeGenType {cgTypeName} = mkFromJSON cgTypeName [|scalarFromJSON|]
+deriveFromJSON _ CodeGenType {cgConstructors = [], ..} = emptyTypeError cgTypeName
+deriveFromJSON ENUM_MODE CodeGenType {..} =
+  mkFromJSON cgTypeName (matchWith (Just (v', failExp)) fromJSONEnum cgConstructors)
+deriveFromJSON _ CodeGenType {cgConstructors = [cons], ..} =
+  mkFromJSON cgTypeName (fromJSONObject cons)
+deriveFromJSON _ typeD@CodeGenType {cgTypeName} =
+  mkFromJSON cgTypeName (fromJSONUnion typeD)
+
+fromJSONEnum :: CodeGenConstructor -> (PatQ, ExpQ)
+fromJSONEnum CodeGenConstructor {constructorName} = (originalLit constructorName, appE (toVar 'pure) (toCon constructorName))
+
+fromJSONObject :: CodeGenConstructor -> ExpQ
+fromJSONObject con@CodeGenConstructor {constructorName} = withBody <$> decodeObjectE con
+  where
+    withBody body = AppE (AppE (VarE 'withObject) name) (LamE [v'] body)
+    name :: Exp
+    name = toString (getFullName constructorName)
+
+fromJSONUnion :: CodeGenType -> ExpQ
+fromJSONUnion CodeGenType {..} = appE (toVar 'takeValueType) (matchWith elseCondition f cgConstructors)
+  where
+    elseCondition =
+      (tupP [_', v'],) . decodeObjectE
+        <$> find ((typename cgTypeName ==) . typename . constructorName) cgConstructors
+    f cons@CodeGenConstructor {..} =
+      ( tupP [originalLit constructorName, if null constructorFields then _' else v'],
+        decodeObjectE cons
+      )
+
+-- ToJSON
+deriveToJSON :: DERIVING_MODE -> CodeGenType -> DecQ
+deriveToJSON SCALAR_MODE CodeGenType {..} = mkToJSON cgTypeName [] [|scalarToJSON|]
+deriveToJSON _ CodeGenType {cgConstructors = [], ..} = emptyTypeError cgTypeName
+deriveToJSON ENUM_MODE CodeGenType {..} =
+  mkToJSON cgTypeName [] (matchWith Nothing toJSONEnum cgConstructors)
+deriveToJSON _ CodeGenType {cgConstructors = [cons], ..} =
+  mkToJSON cgTypeName [destructConstructor cons] (toJSONObject cons)
+deriveToJSON _ _ = fail "Input Unions are not yet supported"
+
+toJSONEnum :: CodeGenConstructor -> (PatQ, ExpQ)
+toJSONEnum CodeGenConstructor {constructorName} = (toCon constructorName, originalLit constructorName)
+
+toJSONObject :: CodeGenConstructor -> ExpQ
+toJSONObject CodeGenConstructor {..} = pure $ AppE (VarE 'omitNulls) (mkFieldsE constructorName '(.=) constructorFields)
diff --git a/src/Data/Morpheus/Client/Transform/Core.hs b/src/Data/Morpheus/Client/Transform/Core.hs
--- a/src/Data/Morpheus/Client/Transform/Core.hs
+++ b/src/Data/Morpheus/Client/Transform/Core.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE NoImplicitPrelude #-}
 
@@ -13,13 +14,24 @@
     getType,
     typeFrom,
     deprecationWarning,
+    toCodeGenField,
+    toClientDeclarations,
   )
 where
 
 import Control.Monad.Except (MonadError)
-import Data.Morpheus.CodeGen.Internal.TH
-  ( camelCaseTypeName,
+import Data.Morpheus.Client.Internal.Types
+  ( ClientDeclaration (..),
+    ClientTypeDefinition (..),
+    DERIVING_MODE (..),
   )
+import Data.Morpheus.CodeGen.Internal.AST
+  ( CodeGenField (..),
+    CodeGenType (..),
+    DerivingClass (..),
+    FIELD_TYPE_WRAPPER (..),
+  )
+import Data.Morpheus.CodeGen.Utils (camelCaseTypeName)
 import Data.Morpheus.Error
   ( deprecatedField,
   )
@@ -33,6 +45,7 @@
 import Data.Morpheus.Types.Internal.AST
   ( ANY,
     Directives,
+    FieldDefinition (..),
     FieldName,
     GQLError,
     RAW,
@@ -40,10 +53,14 @@
     Schema (..),
     TypeContent (..),
     TypeDefinition (..),
+    TypeKind (..),
     TypeName,
+    TypeRef (..),
     VALID,
     VariableDefinitions,
     internal,
+    isNullable,
+    isResolverType,
     lookupDeprecated,
     lookupDeprecatedReason,
     msg,
@@ -95,3 +112,29 @@
             (lookupDeprecatedReason deprecation)
         ]
   Nothing -> pure ()
+
+toCodeGenField :: FieldDefinition a b -> CodeGenField
+toCodeGenField FieldDefinition {fieldType = field@TypeRef {..}, ..} =
+  CodeGenField
+    { fieldName,
+      fieldType = typeConName,
+      wrappers = [GQL_WRAPPER typeWrappers],
+      fieldIsNullable = isNullable field
+    }
+
+toClientDeclarations :: ClientTypeDefinition -> [ClientDeclaration]
+toClientDeclarations def@ClientTypeDefinition {clientKind}
+  | KindScalar == clientKind = [FromJSONClass SCALAR_MODE cgType, ToJSONClass SCALAR_MODE cgType]
+  | KindEnum == clientKind = [ClientType cgType, FromJSONClass ENUM_MODE cgType, ToJSONClass ENUM_MODE cgType]
+  | isResolverType clientKind = [ClientType cgType, FromJSONClass TYPE_MODE cgType]
+  | otherwise = [ClientType cgType, ToJSONClass TYPE_MODE cgType]
+  where
+    cgType = printClientType def
+
+printClientType :: ClientTypeDefinition -> CodeGenType
+printClientType ClientTypeDefinition {..} =
+  CodeGenType
+    { cgTypeName = clientTypeName,
+      cgConstructors = clientCons,
+      cgDerivations = [GENERIC, SHOW, CLASS_EQ]
+    }
diff --git a/src/Data/Morpheus/Client/Transform/Global.hs b/src/Data/Morpheus/Client/Transform/Global.hs
--- a/src/Data/Morpheus/Client/Transform/Global.hs
+++ b/src/Data/Morpheus/Client/Transform/Global.hs
@@ -11,10 +11,15 @@
 where
 
 import Data.Morpheus.Client.Internal.Types
-  ( ClientConstructorDefinition (..),
+  ( ClientDeclaration,
     ClientTypeDefinition (..),
-    TypeNameTH (..),
   )
+import Data.Morpheus.Client.Transform.Core (toClientDeclarations, toCodeGenField)
+import Data.Morpheus.CodeGen.Internal.AST
+  ( CodeGenConstructor (..),
+    CodeGenTypeName (..),
+    fromTypeName,
+  )
 import Data.Morpheus.Internal.Utils
   ( empty,
   )
@@ -34,25 +39,24 @@
     VariableDefinitions,
     isNotSystemTypeName,
     isResolverType,
-    toAny,
   )
 import Relude hiding (empty)
 
 toArgumentsType ::
-  TypeName ->
+  CodeGenTypeName ->
   VariableDefinitions RAW ->
   Maybe ClientTypeDefinition
-toArgumentsType cName variables
+toArgumentsType clientTypeName variables
   | null variables = Nothing
   | otherwise =
       Just
         ClientTypeDefinition
-          { clientTypeName = TypeNameTH [] cName,
+          { clientTypeName,
             clientKind = KindInputObject,
             clientCons =
-              [ ClientConstructorDefinition
-                  { cName,
-                    cFields = toFieldDefinition <$> toList variables
+              [ CodeGenConstructor
+                  { constructorName = clientTypeName,
+                    constructorFields = toCodeGenField . toFieldDefinition <$> toList variables
                   }
               ]
           }
@@ -67,10 +71,11 @@
       fieldDirectives = empty
     }
 
-toGlobalDefinitions :: (TypeName -> Bool) -> Schema VALID -> [ClientTypeDefinition]
+toGlobalDefinitions :: (TypeName -> Bool) -> Schema VALID -> [ClientDeclaration]
 toGlobalDefinitions f Schema {types} =
-  mapMaybe generateGlobalType $
-    filter shouldInclude (toList types)
+  concatMap toClientDeclarations $
+    mapMaybe generateGlobalType $
+      filter shouldInclude (toList types)
   where
     shouldInclude t =
       not (isResolverType t)
@@ -82,24 +87,25 @@
   (clientKind, clientCons) <- genContent typeContent
   pure
     ClientTypeDefinition
-      { clientTypeName = TypeNameTH [] typeName,
+      { clientTypeName = fromTypeName typeName,
         clientKind,
         clientCons
       }
   where
-    genContent :: TypeContent TRUE ANY VALID -> Maybe (TypeKind, [ClientConstructorDefinition])
-    genContent (DataInputObject inputFields) = do
+    genContent :: TypeContent TRUE ANY VALID -> Maybe (TypeKind, [CodeGenConstructor])
+    genContent (DataInputObject inputFields) =
       pure
         ( KindInputObject,
-          [ ClientConstructorDefinition
-              { cName = typeName,
-                cFields = toAny <$> toList inputFields
+          [ CodeGenConstructor
+              { constructorName = fromTypeName typeName,
+                constructorFields = toCodeGenField <$> toList inputFields
               }
           ]
         )
-    genContent (DataEnum enumTags) = pure (KindEnum, mkConsEnum <$> enumTags)
+    genContent (DataEnum enumTags) = pure (KindEnum, mkConsEnum typeName <$> enumTags)
     genContent DataScalar {} = pure (KindScalar, [])
     genContent _ = Nothing
 
-mkConsEnum :: DataEnumValue s -> ClientConstructorDefinition
-mkConsEnum DataEnumValue {enumName} = ClientConstructorDefinition enumName []
+mkConsEnum :: TypeName -> DataEnumValue s -> CodeGenConstructor
+mkConsEnum typename DataEnumValue {enumName} =
+  CodeGenConstructor (CodeGenTypeName [coerce typename] [] enumName) []
diff --git a/src/Data/Morpheus/Client/Transform/Local.hs b/src/Data/Morpheus/Client/Transform/Local.hs
--- a/src/Data/Morpheus/Client/Transform/Local.hs
+++ b/src/Data/Morpheus/Client/Transform/Local.hs
@@ -14,13 +14,13 @@
 
 import Control.Monad.Except (MonadError (throwError))
 import Data.Morpheus.Client.Internal.Types
-  ( ClientConstructorDefinition (..),
+  ( ClientDeclaration (..),
     ClientTypeDefinition (..),
-    FetchDefinition (..),
-    TypeNameTH (..),
+    RequestTypeDefinition (..),
   )
-import Data.Morpheus.Client.Transform.Core (Converter (..), compileError, deprecationWarning, getType, typeFrom)
+import Data.Morpheus.Client.Transform.Core (Converter (..), compileError, deprecationWarning, getType, toClientDeclarations, toCodeGenField, typeFrom)
 import Data.Morpheus.Client.Transform.Global (toArgumentsType)
+import Data.Morpheus.CodeGen.Internal.AST (CodeGenConstructor (..), CodeGenTypeName (..), fromTypeName)
 import Data.Morpheus.Core (Config (..), VALIDATION_MODE (WITHOUT_VARIABLES), validateRequest)
 import Data.Morpheus.Internal.Ext
   ( GQLResult,
@@ -56,6 +56,7 @@
     msg,
     toAny,
   )
+import qualified Data.Text as T
 import Relude hiding (empty, show)
 import Prelude (show)
 
@@ -66,24 +67,16 @@
       validationMode = WITHOUT_VARIABLES
     }
 
-toLocalDefinitions ::
-  ExecutableDocument ->
-  Schema VALID ->
-  GQLResult
-    ( FetchDefinition,
-      [ClientTypeDefinition]
-    )
-toLocalDefinitions request schema = do
+toLocalDefinitions :: (Text, ExecutableDocument) -> Schema VALID -> GQLResult [ClientDeclaration]
+toLocalDefinitions (query, request) schema = do
   validOperation <- validateRequest clientConfig schema request
-  flip runReaderT (schema, operationArguments $ operation request) $
-    runConverter $
-      genOperation validOperation
+  flip runReaderT (schema, operationArguments $ operation request) $ runConverter $ genLocalDeclarations query validOperation
 
-genOperation :: Operation VALID -> Converter (FetchDefinition, [ClientTypeDefinition])
-genOperation op@Operation {operationName, operationSelection, operationType} = do
+genLocalDeclarations :: Text -> Operation VALID -> Converter [ClientDeclaration]
+genLocalDeclarations query op@Operation {operationName, operationSelection, operationType} = do
   (schema, varDefs) <- asks id
   datatype <- getOperationDataType op schema
-  let argumentsType = toArgumentsType (getOperationName operationName <> "Args") varDefs
+  let argumentsType = toArgumentsType (fromTypeName $ getOperationName operationName <> "Args") varDefs
   (rootType :| localTypes) <-
     genLocalTypes
       []
@@ -91,12 +84,14 @@
       (toAny datatype)
       operationSelection
   pure
-    ( FetchDefinition
-        { clientArgumentsTypeName = fmap clientTypeName argumentsType,
-          rootTypeName = clientTypeName rootType,
-          fetchOperationType = operationType
-        },
-      rootType : (localTypes <> maybeToList argumentsType)
+    ( RequestTypeClass
+        RequestTypeDefinition
+          { requestArgs = maybe "()" (typename . clientTypeName) argumentsType,
+            requestName = typename (clientTypeName rootType),
+            requestType = operationType,
+            requestQuery = T.unpack query
+          }
+        : concatMap toClientDeclarations (rootType : (localTypes <> maybeToList argumentsType))
     )
 
 -------------------------------------------------------------------------
@@ -107,11 +102,12 @@
   TypeDefinition ANY VALID ->
   SelectionSet VALID ->
   Converter (NonEmpty ClientTypeDefinition)
-genLocalTypes path tName dataType recordSelSet = do
-  (con, subTypes) <- toConstructorDefinition (if null path then [coerce tName] else path) tName dataType recordSelSet
+genLocalTypes namespace tName dataType recordSelSet = do
+  let clientTypeName = CodeGenTypeName {namespace, typeParameters = [], typename = tName}
+  (con, subTypes) <- toConstructorDefinition (if null namespace then [coerce tName] else namespace) clientTypeName dataType recordSelSet
   pure $
     ClientTypeDefinition
-      { clientTypeName = TypeNameTH path tName,
+      { clientTypeName,
         clientCons = [con],
         clientKind = KindObject Nothing
       }
@@ -119,13 +115,13 @@
 
 toConstructorDefinition ::
   [FieldName] ->
-  TypeName ->
+  CodeGenTypeName ->
   TypeDefinition ANY VALID ->
   SelectionSet VALID ->
-  Converter (ClientConstructorDefinition, [ClientTypeDefinition])
-toConstructorDefinition path cName datatype selSet = do
-  (cFields, subTypes) <- unzip <$> traverse genField (toList selSet)
-  pure (ClientConstructorDefinition {cName, cFields}, concat subTypes)
+  Converter (CodeGenConstructor, [ClientTypeDefinition])
+toConstructorDefinition path name datatype selSet = do
+  (fields, subTypes) <- unzip <$> traverse genField (toList selSet)
+  pure (CodeGenConstructor {constructorName = name, constructorFields = map toCodeGenField fields}, concat subTypes)
   where
     genField :: Selection VALID -> Converter (FieldDefinition ANY VALID, [ClientTypeDefinition])
     genField sel = do
@@ -151,25 +147,25 @@
   Selection VALID ->
   Converter [ClientTypeDefinition]
 subTypesBySelection _ _ Selection {selectionContent = SelectionField} = pure []
-subTypesBySelection path dType Selection {selectionContent = SelectionSet selectionSet} = do
+subTypesBySelection path dType Selection {selectionContent = SelectionSet selectionSet} =
   toList <$> genLocalTypes path (typeFrom [] dType) dType selectionSet
-subTypesBySelection path dType Selection {selectionContent = UnionSelection interface unionSelections} =
+subTypesBySelection namespace dType Selection {selectionContent = UnionSelection interface unionSelections} =
   do
     let variants = UnionTag (typeName dType) interface : toList unionSelections
-    (clientCons, subTypes) <- unzip <$> traverse (getVariantType path) variants
+    (clientCons, subTypes) <- unzip <$> traverse (getVariantType namespace) variants
     pure
       ( ClientTypeDefinition
-          { clientTypeName = TypeNameTH path (typeFrom [] dType),
+          { clientTypeName = CodeGenTypeName {namespace, typeParameters = [], typename = typeFrom [] dType},
             clientCons,
             clientKind = KindUnion
           }
           : concat subTypes
       )
 
-getVariantType :: [FieldName] -> UnionTag -> Converter (ClientConstructorDefinition, [ClientTypeDefinition])
+getVariantType :: [FieldName] -> UnionTag -> Converter (CodeGenConstructor, [ClientTypeDefinition])
 getVariantType path (UnionTag selectedTyName selectionVariant) = do
   conDatatype <- getType selectedTyName
-  toConstructorDefinition path selectedTyName conDatatype selectionVariant
+  toConstructorDefinition path (CodeGenTypeName path [] selectedTyName) conDatatype selectionVariant
 
 getFieldType ::
   [FieldName] ->
