diff --git a/morpheus-graphql-server.cabal b/morpheus-graphql-server.cabal
--- a/morpheus-graphql-server.cabal
+++ b/morpheus-graphql-server.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           morpheus-graphql-server
-version:        0.27.0
+version:        0.27.1
 synopsis:       Morpheus GraphQL
 description:    Build GraphQL APIs with your favourite functional language!
 category:       web, graphql
@@ -312,35 +312,38 @@
       Data.Morpheus.Server.Types
   other-modules:
       Data.Morpheus.Server.Deriving.App
-      Data.Morpheus.Server.Deriving.Channels
-      Data.Morpheus.Server.Deriving.Decode
-      Data.Morpheus.Server.Deriving.Encode
-      Data.Morpheus.Server.Deriving.Named.Encode
-      Data.Morpheus.Server.Deriving.Named.EncodeType
-      Data.Morpheus.Server.Deriving.Named.EncodeValue
+      Data.Morpheus.Server.Deriving.Internal.Decode.Rep
+      Data.Morpheus.Server.Deriving.Internal.Decode.Utils
+      Data.Morpheus.Server.Deriving.Internal.Resolve.Explore
+      Data.Morpheus.Server.Deriving.Internal.Schema.Directive
+      Data.Morpheus.Server.Deriving.Internal.Schema.Enum
+      Data.Morpheus.Server.Deriving.Internal.Schema.Internal
+      Data.Morpheus.Server.Deriving.Internal.Schema.Object
+      Data.Morpheus.Server.Deriving.Internal.Schema.Type
+      Data.Morpheus.Server.Deriving.Internal.Schema.Union
+      Data.Morpheus.Server.Deriving.Kinded.Arguments
+      Data.Morpheus.Server.Deriving.Kinded.Channels
+      Data.Morpheus.Server.Deriving.Kinded.NamedResolver
+      Data.Morpheus.Server.Deriving.Kinded.NamedResolverFun
+      Data.Morpheus.Server.Deriving.Kinded.Resolver
+      Data.Morpheus.Server.Deriving.Kinded.Type
+      Data.Morpheus.Server.Deriving.Kinded.Value
+      Data.Morpheus.Server.Deriving.Resolvers
       Data.Morpheus.Server.Deriving.Schema
-      Data.Morpheus.Server.Deriving.Schema.DeriveKinded
-      Data.Morpheus.Server.Deriving.Schema.Directive
-      Data.Morpheus.Server.Deriving.Schema.Enum
-      Data.Morpheus.Server.Deriving.Schema.Internal
-      Data.Morpheus.Server.Deriving.Schema.Object
-      Data.Morpheus.Server.Deriving.Schema.TypeContent
-      Data.Morpheus.Server.Deriving.Schema.Union
-      Data.Morpheus.Server.Deriving.Utils
-      Data.Morpheus.Server.Deriving.Utils.Decode
-      Data.Morpheus.Server.Deriving.Utils.DeriveGType
-      Data.Morpheus.Server.Deriving.Utils.GTraversable
+      Data.Morpheus.Server.Deriving.Utils.AST
+      Data.Morpheus.Server.Deriving.Utils.Gmap
+      Data.Morpheus.Server.Deriving.Utils.GRep
+      Data.Morpheus.Server.Deriving.Utils.GScan
       Data.Morpheus.Server.Deriving.Utils.Kinded
       Data.Morpheus.Server.Deriving.Utils.Proxy
-      Data.Morpheus.Server.Deriving.Utils.Types
       Data.Morpheus.Server.Deriving.Utils.Use
-      Data.Morpheus.Server.NamedResolvers
       Data.Morpheus.Server.Playground
       Data.Morpheus.Server.Types.DirectiveDefinitions
       Data.Morpheus.Server.Types.Directives
       Data.Morpheus.Server.Types.GQLType
       Data.Morpheus.Server.Types.Internal
       Data.Morpheus.Server.Types.Kind
+      Data.Morpheus.Server.Types.NamedResolvers
       Data.Morpheus.Server.Types.SchemaT
       Data.Morpheus.Server.Types.TypeName
       Data.Morpheus.Server.Types.Types
@@ -359,7 +362,7 @@
     , mtl >=2.0.0 && <3.0.0
     , relude >=0.3.0 && <2.0.0
     , template-haskell >=2.0.0 && <3.0.0
-    , text >=1.2.3 && <1.3.0
+    , text >=1.2.3 && <2.1.0
     , transformers >=0.3.0 && <0.6.0
     , unordered-containers >=0.2.8 && <0.3.0
     , vector >=0.12.0.1 && <0.13.0
@@ -418,7 +421,7 @@
     , tasty >=0.1.0 && <1.5.0
     , tasty-hunit >=0.1.0 && <1.0.0
     , template-haskell >=2.0.0 && <3.0.0
-    , text >=1.2.3 && <1.3.0
+    , text >=1.2.3 && <2.1.0
     , transformers >=0.3.0 && <0.6.0
     , unordered-containers >=0.2.8 && <0.3.0
     , vector >=0.12.0.1 && <0.13.0
diff --git a/src/Data/Morpheus/Server/Deriving/App.hs b/src/Data/Morpheus/Server/Deriving/App.hs
--- a/src/Data/Morpheus/Server/Deriving/App.hs
+++ b/src/Data/Morpheus/Server/Deriving/App.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
 {-# LANGUAGE KindSignatures #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE TupleSections #-}
@@ -22,33 +23,31 @@
 import Data.Morpheus.App.Internal.Resolving
   ( resultOr,
   )
-import Data.Morpheus.Server.Deriving.Encode
-  ( EncodeConstraints,
-    deriveModel,
-  )
-import Data.Morpheus.Server.Deriving.Named.Encode
-  ( EncodeNamedConstraints,
-    deriveNamedModel,
+import Data.Morpheus.Server.Deriving.Resolvers
+  ( DERIVE_NAMED_RESOLVERS,
+    DERIVE_RESOLVERS,
+    deriveNamedResolvers,
+    deriveResolvers,
   )
 import Data.Morpheus.Server.Deriving.Schema
-  ( SchemaConstraints,
+  ( SCHEMA,
     deriveSchema,
   )
 import Data.Morpheus.Server.Resolvers
   ( NamedResolvers,
-    RootResolver (..),
   )
+import Data.Morpheus.Server.Types
 import Relude
 
 type RootResolverConstraint m e query mutation subscription =
-  ( EncodeConstraints e m query mutation subscription,
-    SchemaConstraints e m query mutation subscription,
+  ( DERIVE_RESOLVERS (Resolver QUERY e m) query mutation subscription,
+    SCHEMA query mutation subscription,
     Monad m
   )
 
 type NamedResolversConstraint m e query mutation subscription =
-  ( EncodeNamedConstraints e m query mutation subscription,
-    SchemaConstraints e m query mutation subscription,
+  ( DERIVE_NAMED_RESOLVERS (Resolver QUERY e m) query,
+    SCHEMA query mutation subscription,
     Monad m
   )
 
@@ -65,10 +64,8 @@
 
 instance RootResolverConstraint m e query mut sub => DeriveApp RootResolver m e query mut sub where
   deriveApp root =
-    resultOr FailApp (uncurry mkApp) $
-      (,) <$> deriveSchema (Identity root) <*> deriveModel root
+    resultOr FailApp (uncurry mkApp) $ (,) <$> deriveSchema (Identity root) <*> deriveResolvers root
 
 instance NamedResolversConstraint m e query mut sub => DeriveApp NamedResolvers m e query mut sub where
   deriveApp root =
-    resultOr FailApp (uncurry mkApp) $
-      (,deriveNamedModel root) <$> deriveSchema (Identity root)
+    resultOr FailApp (uncurry mkApp) $ (,deriveNamedResolvers root) <$> deriveSchema (Identity root)
diff --git a/src/Data/Morpheus/Server/Deriving/Channels.hs b/src/Data/Morpheus/Server/Deriving/Channels.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Channels.hs
+++ /dev/null
@@ -1,151 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Channels
-  ( channelResolver,
-    ChannelsConstraint,
-  )
-where
-
-import Control.Monad.Except (throwError)
-import qualified Data.HashMap.Lazy as HM
-import Data.Morpheus.App.Internal.Resolving
-  ( Channel,
-    Resolver,
-    ResolverState,
-    SubscriptionField (..),
-  )
-import Data.Morpheus.Internal.Utils
-  ( selectBy,
-  )
-import Data.Morpheus.Server.Deriving.Decode
-  ( Decode,
-    decodeArguments,
-  )
-import Data.Morpheus.Server.Deriving.Schema.Directive (toFieldRes)
-import Data.Morpheus.Server.Deriving.Utils
-  ( ConsRep (..),
-    DataType (..),
-  )
-import Data.Morpheus.Server.Deriving.Utils.DeriveGType
-  ( DeriveValueOptions (..),
-    DeriveWith,
-    deriveValue,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Kinded (CatType (..), outputType)
-import Data.Morpheus.Server.Types.GQLType (GQLType, deriveTypename, withDir, __typeData)
-import Data.Morpheus.Server.Types.Types (Undefined)
-import Data.Morpheus.Types.Internal.AST
-  ( FieldName,
-    OUT,
-    SUBSCRIPTION,
-    Selection (..),
-    SelectionContent (..),
-    VALID,
-    internal,
-  )
-import GHC.Generics
-import Relude hiding (Undefined)
-
-newtype DerivedChannel e = DerivedChannel
-  { _unpackChannel :: Channel e
-  }
-
-type ChannelRes (e :: Type) = Selection VALID -> ResolverState (DerivedChannel e)
-
-type ChannelsConstraint e m (subs :: (Type -> Type) -> Type) =
-  ExploreChannels (IsUndefined (subs (Resolver SUBSCRIPTION e m))) e (subs (Resolver SUBSCRIPTION e m))
-
-channelResolver ::
-  forall e m subs.
-  ChannelsConstraint e m subs =>
-  subs (Resolver SUBSCRIPTION e m) ->
-  Selection VALID ->
-  ResolverState (Channel e)
-channelResolver value = fmap _unpackChannel . channelSelector
-  where
-    channelSelector ::
-      Selection VALID ->
-      ResolverState (DerivedChannel e)
-    channelSelector =
-      selectBySelection
-        ( exploreChannels
-            (Proxy @(IsUndefined (subs (Resolver SUBSCRIPTION e m))))
-            value
-        )
-
-selectBySelection ::
-  HashMap FieldName (ChannelRes e) ->
-  Selection VALID ->
-  ResolverState (DerivedChannel e)
-selectBySelection channels = withSubscriptionSelection >=> selectSubscription channels
-
-selectSubscription ::
-  HashMap FieldName (ChannelRes e) ->
-  Selection VALID ->
-  ResolverState (DerivedChannel e)
-selectSubscription channels sel@Selection {selectionName} =
-  selectBy
-    (internal "invalid subscription: no channel is selected.")
-    selectionName
-    channels
-    >>= (sel &)
-
-withSubscriptionSelection :: Selection VALID -> ResolverState (Selection VALID)
-withSubscriptionSelection Selection {selectionContent = SelectionSet selSet} =
-  case toList selSet of
-    [sel] -> pure sel
-    _ -> throwError (internal "invalid subscription: there can be only one top level selection")
-withSubscriptionSelection _ = throwError (internal "invalid subscription: expected selectionSet")
-
-class GetChannel e a | a -> e where
-  getChannel :: a -> ChannelRes e
-
-instance GetChannel e (SubscriptionField (Resolver SUBSCRIPTION e m a)) where
-  getChannel x = const $ pure $ DerivedChannel $ channel x
-
-instance
-  Decode arg =>
-  GetChannel e (arg -> SubscriptionField (Resolver SUBSCRIPTION e m a))
-  where
-  getChannel f sel@Selection {selectionArguments} =
-    decodeArguments selectionArguments
-      >>= (`getChannel` sel)
-        . f
-
-------------------------------------------------------
-
-type family IsUndefined a :: Bool where
-  IsUndefined (Undefined m) = 'True
-  IsUndefined a = 'False
-
-class ExploreChannels (t :: Bool) e a where
-  exploreChannels :: f t -> a -> HashMap FieldName (ChannelRes e)
-
-instance (GQLType a, Generic a, DeriveWith GQLType (GetChannel e) (ChannelRes e) (Rep a)) => ExploreChannels 'False e a where
-  exploreChannels _ =
-    HM.fromList
-      . map (toFieldRes withDir (Proxy @a))
-      . consFields
-      . tyCons
-      . deriveValue
-        ( DeriveValueOptions
-            { __valueApply = getChannel,
-              __valueTypeName = deriveTypename (OutputType :: CatType OUT a),
-              __valueGetType = __typeData . outputType
-            } ::
-            DeriveValueOptions OUT GQLType (GetChannel e) (ChannelRes e)
-        )
-
-instance ExploreChannels 'True e (Undefined m) where
-  exploreChannels _ = pure HM.empty
diff --git a/src/Data/Morpheus/Server/Deriving/Decode.hs b/src/Data/Morpheus/Server/Deriving/Decode.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Decode.hs
+++ /dev/null
@@ -1,205 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Decode
-  ( decodeArguments,
-    Decode,
-    decode,
-  )
-where
-
-import Control.Monad.Except (MonadError (throwError))
-import qualified Data.Map as M
-import Data.Morpheus.App.Internal.Resolving
-  ( ResolverState,
-  )
-import Data.Morpheus.Server.Deriving.Schema.Directive (visitEnumName, visitFieldName)
-import Data.Morpheus.Server.Deriving.Utils
-  ( selNameProxy,
-    symbolName,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Decode
-  ( Context (..),
-    DecoderT,
-    DescribeCons,
-    DescribeFields (countFields),
-    decodeFieldWith,
-    getFieldName,
-    getUnionInfos,
-    handleEither,
-    setVariantRef,
-    withInputObject,
-    withInputUnion,
-    withScalar,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Kinded
-  ( CatType (..),
-  )
-import Data.Morpheus.Server.Types.GQLType
-  ( GQLType (..),
-    deriveTypename,
-    withDir,
-  )
-import Data.Morpheus.Server.Types.Kind
-  ( CUSTOM,
-    DerivingKind,
-    SCALAR,
-    TYPE,
-    WRAPPER,
-  )
-import Data.Morpheus.Server.Types.Types (Arg (Arg))
-import Data.Morpheus.Types.GQLScalar
-  ( DecodeScalar (..),
-  )
-import Data.Morpheus.Types.GQLWrapper
-  ( DecodeWrapper (..),
-    DecodeWrapperConstraint,
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( Argument (..),
-    Arguments,
-    IN,
-    Object,
-    ObjectEntry (..),
-    TypeName,
-    VALID,
-    ValidObject,
-    ValidValue,
-    Value (..),
-    internal,
-    msg,
-  )
-import GHC.Generics
-import GHC.TypeLits (KnownSymbol)
-import Relude
-
--- GENERIC
-decodeArguments :: forall a. Decode a => Arguments VALID -> ResolverState a
-decodeArguments = decode . Object . fmap toEntry
-  where
-    toEntry Argument {..} = ObjectEntry argumentName argumentValue
-
-type Decode a = (DecodeKind (KIND a) a)
-
-decode :: forall a. Decode a => ValidValue -> ResolverState a
-decode = decodeKind (Proxy @(KIND a))
-
--- | Decode GraphQL type with Specific Kind
-class DecodeKind (kind :: DerivingKind) a where
-  decodeKind :: Proxy kind -> ValidValue -> ResolverState a
-
--- SCALAR
-instance (DecodeScalar a, GQLType a) => DecodeKind SCALAR a where
-  decodeKind _ = withScalar (deriveTypename (InputType :: CatType IN a)) decodeScalar
-
--- INPUT_OBJECT and  INPUT_UNION
-instance (Generic a, GQLType a, DecodeRep (Rep a)) => DecodeKind TYPE a where
-  decodeKind _ = fmap to . (`runReaderT` context) . decodeRep
-    where
-      context =
-        Context
-          { isVariantRef = False,
-            typeName = deriveTypename (InputType :: CatType IN a),
-            enumVisitor = visitEnumName withDir proxy,
-            fieldVisitor = visitFieldName withDir proxy
-          }
-        where
-          proxy = Proxy @a
-
-instance (Decode a, DecodeWrapperConstraint f a, DecodeWrapper f) => DecodeKind WRAPPER (f a) where
-  decodeKind _ value =
-    runExceptT (decodeWrapper decode value)
-      >>= handleEither
-
-instance (Decode a, KnownSymbol name) => DecodeKind CUSTOM (Arg name a) where
-  decodeKind _ value = Arg <$> withInputObject fieldDecoder value
-    where
-      fieldDecoder = decodeFieldWith decode fieldName
-      fieldName = symbolName (Proxy @name)
-
---  Map
-instance (Ord k, Decode (k, v)) => DecodeKind CUSTOM (Map k v) where
-  decodeKind _ v = M.fromList <$> (decode v :: ResolverState [(k, v)])
-
-decideEither ::
-  (DecodeRep f, DecodeRep g) =>
-  ([TypeName], [TypeName]) ->
-  TypeName ->
-  ValidValue ->
-  DecoderT ((f :+: g) a)
-decideEither (left, right) name value
-  | name `elem` left = L1 <$> decodeRep value
-  | name `elem` right = R1 <$> decodeRep value
-  | otherwise =
-      throwError $
-        internal $
-          "Constructor \""
-            <> msg name
-            <> "\" could not find in Union"
-
-decodeInputUnionObject ::
-  (DecodeRep f, DecodeRep g) =>
-  ([TypeName], [TypeName]) ->
-  TypeName ->
-  Object VALID ->
-  ValidObject ->
-  DecoderT ((f :+: g) a)
-decodeInputUnionObject (l, r) name unions object
-  | [name] == l = L1 <$> decodeRep (Object object)
-  | [name] == r = R1 <$> decodeRep (Object object)
-  | otherwise = decideEither (l, r) name (Object unions)
-
-class DecodeRep (f :: Type -> Type) where
-  decodeRep :: ValidValue -> DecoderT (f a)
-
-instance (Datatype d, DecodeRep f) => DecodeRep (M1 D d f) where
-  decodeRep value = M1 <$> decodeRep value
-
-instance (DescribeCons a, DescribeCons b, DecodeRep a, DecodeRep b) => DecodeRep (a :+: b) where
-  decodeRep (Object obj) =
-    do
-      (kind, lr) <- getUnionInfos (Proxy @(a :+: b))
-      setVariantRef kind $ withInputUnion (decodeInputUnionObject lr) obj
-  decodeRep (Enum name) = do
-    (_, (l, r)) <- getUnionInfos (Proxy @(a :+: b))
-    visitor <- asks enumVisitor
-    decideEither (map visitor l, map visitor r) name (Enum name)
-  decodeRep _ = throwError (internal "lists and scalars are not allowed in Union")
-
-instance (Constructor c, DecodeFields a) => DecodeRep (M1 C c a) where
-  decodeRep = fmap M1 . decodeFields 0
-
-class DecodeFields (f :: Type -> Type) where
-  decodeFields :: Int -> ValidValue -> DecoderT (f a)
-
-instance (DecodeFields f, DecodeFields g, DescribeFields g) => DecodeFields (f :*: g) where
-  decodeFields index gql =
-    (:*:)
-      <$> decodeFields index gql
-      <*> decodeFields (index + countFields (Proxy @g)) gql
-
-instance (Selector s, GQLType a, Decode a) => DecodeFields (M1 S s (K1 i a)) where
-  decodeFields index value =
-    M1 . K1 <$> do
-      Context {isVariantRef, fieldVisitor} <- ask
-      if isVariantRef
-        then lift (decode value)
-        else
-          let fieldName = fieldVisitor $ getFieldName (selNameProxy (Proxy @s)) index
-              fieldDecoder = decodeFieldWith (lift . decode) fieldName
-           in withInputObject fieldDecoder value
-
-instance DecodeFields U1 where
-  decodeFields _ _ = pure U1
diff --git a/src/Data/Morpheus/Server/Deriving/Encode.hs b/src/Data/Morpheus/Server/Deriving/Encode.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Encode.hs
+++ /dev/null
@@ -1,261 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Encode
-  ( deriveModel,
-    EncodeConstraints,
-    ContextValue (..),
-  )
-where
-
-import Control.Monad.Except (MonadError)
-import qualified Data.Map as M
-import Data.Morpheus.App.Internal.Resolving
-  ( LiftOperation,
-    ObjectTypeResolver,
-    Resolver,
-    ResolverState,
-    ResolverValue (..),
-    RootResolverValue (..),
-    getArguments,
-    liftResolverState,
-    mkEnum,
-    mkObject,
-    mkUnion,
-    requireObject,
-  )
-import Data.Morpheus.Internal.Ext (GQLResult)
-import Data.Morpheus.Server.Deriving.Channels
-  ( ChannelsConstraint,
-    channelResolver,
-  )
-import Data.Morpheus.Server.Deriving.Decode
-  ( Decode,
-    decodeArguments,
-  )
-import Data.Morpheus.Server.Deriving.Schema.Directive (toFieldRes, visitEnumName)
-import Data.Morpheus.Server.Deriving.Utils
-  ( ConsRep (..),
-    DataType (..),
-    FieldRep (..),
-    isUnionRef,
-  )
-import Data.Morpheus.Server.Deriving.Utils.DeriveGType
-  ( DeriveValueOptions (..),
-    DeriveWith,
-    deriveValue,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Kinded
-  ( CatType (..),
-    inputType,
-  )
-import Data.Morpheus.Server.Resolvers
-  ( RootResolver (..),
-  )
-import Data.Morpheus.Server.Types.GQLType
-  ( GQLType,
-    KIND,
-    deriveTypename,
-    withDir,
-    __isEmptyType,
-    __typeData,
-  )
-import Data.Morpheus.Server.Types.Kind
-  ( CUSTOM,
-    DerivingKind,
-    SCALAR,
-    TYPE,
-    WRAPPER,
-  )
-import Data.Morpheus.Server.Types.Types
-  ( TypeGuard (..),
-  )
-import Data.Morpheus.Types.GQLScalar
-  ( EncodeScalar (..),
-  )
-import Data.Morpheus.Types.GQLWrapper (EncodeWrapper (..))
-import Data.Morpheus.Types.Internal.AST
-  ( GQLError,
-    IN,
-    MUTATION,
-    OperationType,
-    QUERY,
-    SUBSCRIPTION,
-    TypeRef (..),
-  )
-import GHC.Generics
-  ( Generic (..),
-  )
-import Relude
-
-newtype ContextValue (kind :: DerivingKind) a = ContextValue
-  { unContextValue :: a
-  }
-
-class Encode (m :: Type -> Type) resolver where
-  encode :: resolver -> m (ResolverValue m)
-
-instance (EncodeKind (KIND a) m a) => Encode m a where
-  encode resolver = encodeKind (ContextValue resolver :: ContextValue (KIND a) a)
-
--- ENCODE GQL KIND
-class EncodeKind (kind :: DerivingKind) (m :: Type -> Type) (a :: Type) where
-  encodeKind :: ContextValue kind a -> m (ResolverValue m)
-
-instance
-  ( EncodeWrapper f,
-    Encode m a,
-    Monad m
-  ) =>
-  EncodeKind WRAPPER m (f a)
-  where
-  encodeKind = encodeWrapper encode . unContextValue
-
-instance
-  ( EncodeScalar a,
-    Monad m
-  ) =>
-  EncodeKind SCALAR m a
-  where
-  encodeKind = pure . ResScalar . encodeScalar . unContextValue
-
-instance
-  ( EncodeConstraint m a,
-    MonadError GQLError m
-  ) =>
-  EncodeKind TYPE m a
-  where
-  encodeKind = pure . exploreResolvers . unContextValue
-
---  Map
-instance (Monad m, Encode m [(k, v)]) => EncodeKind CUSTOM m (Map k v) where
-  encodeKind = encode . M.toList . unContextValue
-
---  INTERFACE Types
-instance (MonadError GQLError m, EncodeConstraint m guard, EncodeConstraint m union) => EncodeKind CUSTOM m (TypeGuard guard union) where
-  encodeKind (ContextValue (ResolveType value)) = pure (exploreResolvers value)
-  encodeKind (ContextValue (ResolveInterface value)) = pure (exploreResolvers value)
-
---  GQL a -> Resolver b, MUTATION, SUBSCRIPTION, QUERY
-instance
-  ( Decode a,
-    Generic a,
-    Monad m,
-    Encode (Resolver o e m) b,
-    LiftOperation o
-  ) =>
-  EncodeKind CUSTOM (Resolver o e m) (a -> b)
-  where
-  encodeKind (ContextValue f) =
-    getArguments
-      >>= liftResolverState . decodeArguments
-      >>= encode . f
-
---  GQL a -> Resolver b, MUTATION, SUBSCRIPTION, QUERY
-instance
-  (Monad m, Encode (Resolver o e m) b, LiftOperation o) =>
-  EncodeKind CUSTOM (Resolver o e m) (Resolver o e m b)
-  where
-  encodeKind (ContextValue value) = value >>= encode
-
-convertNode ::
-  forall m f a.
-  (MonadError GQLError m, GQLType a) =>
-  f a ->
-  DataType (m (ResolverValue m)) ->
-  ResolverValue m
-convertNode
-  proxy
-  DataType
-    { dataTypeName,
-      tyIsUnion,
-      tyCons = cons@ConsRep {consFields, consName}
-    } = encodeTypeFields consFields
-    where
-      -- ENUM
-      encodeTypeFields ::
-        [FieldRep (m (ResolverValue m))] ->
-        ResolverValue m
-      encodeTypeFields [] = mkEnum (visitEnumName withDir proxy consName)
-      encodeTypeFields fields
-        | not tyIsUnion = mkObject dataTypeName (toFieldRes withDir proxy <$> fields)
-      -- Type References --------------------------------------------------------------
-      encodeTypeFields [FieldRep {fieldTypeRef, fieldValue}]
-        | isUnionRef dataTypeName cons = ResLazy (ResObject (Just (typeConName fieldTypeRef)) <$> (fieldValue >>= requireObject))
-      -- Inline Union Types ----------------------------------------------------------------------------
-      encodeTypeFields fields = mkUnion consName (toFieldRes withDir proxy <$> fields)
-
--- Types & Constrains -------------------------------------------------------
-
-exploreResolvers ::
-  forall m a.
-  ( EncodeConstraint m a,
-    MonadError GQLError m
-  ) =>
-  a ->
-  ResolverValue m
-exploreResolvers =
-  convertNode (Proxy @a)
-    . deriveValue
-      ( DeriveValueOptions
-          { __valueApply = encode,
-            __valueTypeName = deriveTypename (InputType :: CatType IN a),
-            __valueGetType = __typeData . inputType
-          } ::
-          DeriveValueOptions IN GQLType (Encode m) (m (ResolverValue m))
-      )
-
------ HELPERS ----------------------------
-objectResolvers ::
-  ( EncodeConstraint m a,
-    MonadError GQLError m
-  ) =>
-  a ->
-  ResolverState (ObjectTypeResolver m)
-objectResolvers value = requireObject (exploreResolvers value)
-
-type EncodeConstraint (m :: Type -> Type) a =
-  ( GQLType a,
-    Generic a,
-    DeriveWith GQLType (Encode m) (m (ResolverValue m)) (Rep a)
-  )
-
-type EncodeObjectConstraint (o :: OperationType) e (m :: Type -> Type) a =
-  EncodeConstraint (Resolver o e m) (a (Resolver o e m))
-
-type EncodeConstraints e m query mut sub =
-  ( ChannelsConstraint e m sub,
-    EncodeObjectConstraint QUERY e m query,
-    EncodeObjectConstraint MUTATION e m mut,
-    EncodeObjectConstraint SUBSCRIPTION e m sub
-  )
-
-deriveModel ::
-  forall e m query mut sub.
-  (Monad m, EncodeConstraints e m query mut sub) =>
-  RootResolver m e query mut sub ->
-  GQLResult (RootResolverValue e m)
-deriveModel RootResolver {..} =
-  pure
-    RootResolverValue
-      { queryResolver = objectResolvers queryResolver,
-        mutationResolver = objectResolvers mutationResolver,
-        subscriptionResolver = objectResolvers subscriptionResolver,
-        channelMap
-      }
-  where
-    channelMap
-      | __isEmptyType (Proxy :: Proxy (sub (Resolver SUBSCRIPTION e m))) = Nothing
-      | otherwise = Just (channelResolver subscriptionResolver)
diff --git a/src/Data/Morpheus/Server/Deriving/Internal/Decode/Rep.hs b/src/Data/Morpheus/Server/Deriving/Internal/Decode/Rep.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Internal/Decode/Rep.hs
@@ -0,0 +1,121 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Internal.Decode.Rep
+  ( DecodeRep (..),
+  )
+where
+
+import Control.Monad.Except (MonadError (throwError))
+import Data.Morpheus.Server.Deriving.Internal.Decode.Utils
+  ( Context (..),
+    CountFields (..),
+    DecoderT,
+    DescribeCons,
+    decodeFieldWith,
+    getFieldName,
+    getUnionInfos,
+    setVariantRef,
+    withInputObject,
+    withInputUnion,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Proxy
+  ( selNameProxy,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Use
+  ( UseDeriving (..),
+    UseValue (..),
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( Object,
+    TypeName,
+    VALID,
+    ValidObject,
+    ValidValue,
+    Value (..),
+    internal,
+    msg,
+  )
+import GHC.Generics
+import Relude
+
+decideEither ::
+  (DecodeRep gql args f, DecodeRep gql args g) =>
+  UseDeriving gql args ->
+  ([TypeName], [TypeName]) ->
+  TypeName ->
+  ValidValue ->
+  DecoderT ((f :+: g) a)
+decideEither dir (left, right) name value
+  | name `elem` left = L1 <$> decodeRep dir value
+  | name `elem` right = R1 <$> decodeRep dir value
+  | otherwise =
+      throwError $
+        internal $
+          "Constructor \""
+            <> msg name
+            <> "\" could not find in Union"
+
+decodeInputUnionObject ::
+  (DecodeRep gql args f, DecodeRep gql args g) =>
+  UseDeriving gql args ->
+  ([TypeName], [TypeName]) ->
+  TypeName ->
+  Object VALID ->
+  ValidObject ->
+  DecoderT ((f :+: g) a)
+decodeInputUnionObject dir (l, r) name unions object
+  | [name] == l = L1 <$> decodeRep dir (Object object)
+  | [name] == r = R1 <$> decodeRep dir (Object object)
+  | otherwise = decideEither dir (l, r) name (Object unions)
+
+class DecodeRep gql args (f :: Type -> Type) where
+  decodeRep :: UseDeriving gql args -> ValidValue -> DecoderT (f a)
+
+instance (Datatype d, DecodeRep gql args f) => DecodeRep gql args (M1 D d f) where
+  decodeRep dir value = M1 <$> decodeRep dir value
+
+instance (DescribeCons gql a, DescribeCons gql b, DecodeRep gql args a, DecodeRep gql args b) => DecodeRep gql args (a :+: b) where
+  decodeRep dir (Object obj) =
+    do
+      (kind, lr) <- getUnionInfos (dirGQL dir) (Proxy @(a :+: b))
+      setVariantRef kind $ withInputUnion (decodeInputUnionObject dir lr) obj
+  decodeRep dir (Enum name) = do
+    (_, (l, r)) <- getUnionInfos (dirGQL dir) (Proxy @(a :+: b))
+    visitor <- asks enumVisitor
+    decideEither dir (map visitor l, map visitor r) name (Enum name)
+  decodeRep _ _ = throwError (internal "lists and scalars are not allowed in Union")
+
+instance (Constructor c, DecodeFields gql args a) => DecodeRep gql args (M1 C c a) where
+  decodeRep dir = fmap M1 . decodeFields dir 0
+
+class DecodeFields gql args (f :: Type -> Type) where
+  decodeFields :: UseDeriving gql args -> Int -> ValidValue -> DecoderT (f a)
+
+instance (DecodeFields gql args f, DecodeFields gql args g, CountFields g) => DecodeFields gql args (f :*: g) where
+  decodeFields dir index gql =
+    (:*:)
+      <$> decodeFields dir index gql
+      <*> decodeFields dir (index + countFields (Proxy @g)) gql
+
+instance (Selector s, args a) => DecodeFields gql args (M1 S s (K1 i a)) where
+  decodeFields UseDeriving {dirArgs} index value =
+    M1 . K1 <$> do
+      Context {isVariantRef, fieldVisitor} <- ask
+      if isVariantRef
+        then lift (useDecodeValue dirArgs value)
+        else
+          let fieldName = fieldVisitor $ getFieldName (selNameProxy (Proxy @s)) index
+              fieldDecoder = decodeFieldWith (lift . useDecodeValue dirArgs) fieldName
+           in withInputObject fieldDecoder value
+
+instance DecodeFields gql args U1 where
+  decodeFields _ _ _ = pure U1
diff --git a/src/Data/Morpheus/Server/Deriving/Internal/Decode/Utils.hs b/src/Data/Morpheus/Server/Deriving/Internal/Decode/Utils.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Internal/Decode/Utils.hs
@@ -0,0 +1,239 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Internal.Decode.Utils
+  ( withInputObject,
+    withEnum,
+    withInputUnion,
+    decodeFieldWith,
+    withScalar,
+    handleEither,
+    getFieldName,
+    DecoderT,
+    setVariantRef,
+    Context (..),
+    getUnionInfos,
+    DescribeCons,
+    CountFields (..),
+    RefType (..),
+    repValue,
+    useDecodeArguments,
+  )
+where
+
+import Control.Monad.Except (MonadError (throwError))
+import Data.Morpheus.App.Internal.Resolving (ResolverState)
+import Data.Morpheus.Internal.Ext (GQLResult)
+import Data.Morpheus.Internal.Utils
+  ( fromElems,
+    selectOr,
+  )
+import Data.Morpheus.Server.Deriving.Utils.AST (argumentsToObject)
+import Data.Morpheus.Server.Deriving.Utils.GRep
+  ( ConsRep (..),
+    FieldRep (..),
+    TypeRep (..),
+  )
+import Data.Morpheus.Server.Deriving.Utils.Kinded
+  ( CatType (..),
+  )
+import Data.Morpheus.Server.Deriving.Utils.Proxy
+  ( conNameProxy,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Use (UseDeriving, UseGQLType (useTypename), UseValue (..), dirArgs)
+import Data.Morpheus.Types.GQLScalar
+  ( toScalar,
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( Arguments,
+    CONST,
+    FieldName,
+    GQLError,
+    IN,
+    Msg (msg),
+    ObjectEntry (..),
+    ScalarValue,
+    Token,
+    TypeName,
+    VALID,
+    ValidObject,
+    ValidValue,
+    Value (..),
+    getInputUnionValue,
+    internal,
+  )
+import GHC.Generics
+import Relude
+
+repValue ::
+  TypeRep (GQLResult (Value CONST)) ->
+  GQLResult (Value CONST)
+repValue
+  TypeRep
+    { tyIsUnion,
+      tyCons = ConsRep {consFields, consName}
+    } = encodeTypeFields consFields
+    where
+      encodeTypeFields ::
+        [FieldRep (GQLResult (Value CONST))] -> GQLResult (Value CONST)
+      encodeTypeFields [] = pure $ Enum consName
+      encodeTypeFields fields | not tyIsUnion = Object <$> (traverse fromField fields >>= fromElems)
+        where
+          fromField FieldRep {fieldSelector, fieldValue} = do
+            entryValue <- fieldValue
+            pure ObjectEntry {entryName = fieldSelector, entryValue}
+      -- Type References --------------------------------------------------------------
+      encodeTypeFields _ = throwError (internal "input unions are not supported")
+
+withInputObject ::
+  MonadError GQLError m =>
+  (ValidObject -> m a) ->
+  ValidValue ->
+  m a
+withInputObject f (Object object) = f object
+withInputObject _ isType = throwError (typeMismatch "InputObject" isType)
+
+-- | Useful for more restrictive instances of lists (non empty, size indexed etc)
+withEnum :: MonadError GQLError m => (TypeName -> m a) -> Value VALID -> m a
+withEnum decode (Enum value) = decode value
+withEnum _ isType = throwError (typeMismatch "Enum" isType)
+
+withInputUnion ::
+  (MonadError GQLError m, Monad m) =>
+  (TypeName -> ValidObject -> ValidObject -> m a) ->
+  ValidObject ->
+  m a
+withInputUnion decoder unions =
+  either onFail onSuccess (getInputUnionValue unions)
+  where
+    onSuccess (name, value) = withInputObject (decoder name unions) value
+    onFail = throwError . internal . msg
+
+withScalar ::
+  (Applicative m, MonadError GQLError m) =>
+  TypeName ->
+  (ScalarValue -> Either Token a) ->
+  Value VALID ->
+  m a
+withScalar typename decodeScalar value = case toScalar value >>= decodeScalar of
+  Right scalar -> pure scalar
+  Left message ->
+    throwError
+      ( typeMismatch
+          ("SCALAR(" <> msg typename <> ")" <> msg message)
+          value
+      )
+
+decodeFieldWith :: (Value VALID -> m a) -> FieldName -> ValidObject -> m a
+decodeFieldWith decoder = selectOr (decoder Null) (decoder . entryValue)
+
+handleEither :: MonadError GQLError m => Either GQLError a -> m a
+handleEither = either throwError pure
+
+-- if value is already validated but value has different type
+typeMismatch :: GQLError -> Value s -> GQLError
+typeMismatch text jsType =
+  internal $
+    "Type mismatch! expected:"
+      <> text
+      <> ", got: "
+      <> msg jsType
+
+getFieldName :: FieldName -> Int -> FieldName
+getFieldName "" index = "_" <> show index
+getFieldName label _ = label
+
+data VariantKind = InlineVariant | VariantRef deriving (Eq, Ord)
+
+data Info = Info
+  { kind :: VariantKind,
+    tagName :: [TypeName]
+  }
+
+instance Semigroup Info where
+  Info VariantRef t1 <> Info _ t2 = Info VariantRef (t1 <> t2)
+  Info _ t1 <> Info VariantRef t2 = Info VariantRef (t1 <> t2)
+  Info InlineVariant t1 <> Info InlineVariant t2 = Info InlineVariant (t1 <> t2)
+
+data Context = Context
+  { isVariantRef :: Bool,
+    typeName :: TypeName,
+    enumVisitor :: TypeName -> TypeName,
+    fieldVisitor :: FieldName -> FieldName
+  }
+
+type DecoderT = ReaderT Context ResolverState
+
+setVariantRef :: Bool -> DecoderT a -> DecoderT a
+setVariantRef isVariantRef = local (\ctx -> ctx {isVariantRef})
+
+class DescribeCons gql (f :: Type -> Type) where
+  tags :: UseGQLType gql -> Proxy f -> Context -> Info
+
+instance (Datatype d, DescribeCons gql f) => DescribeCons gql (M1 D d f) where
+  tags ctx _ = tags ctx (Proxy @f)
+
+instance (DescribeCons gql a, DescribeCons gql b) => DescribeCons gql (a :+: b) where
+  tags ctx _ = tags ctx (Proxy @a) <> tags ctx (Proxy @b)
+
+instance (Constructor c, CountFields a, RefType gql a) => DescribeCons gql (M1 C c a) where
+  tags ctx _ Context {typeName} = getTag (refType ctx (Proxy @a))
+    where
+      getTag (Just memberRef)
+        | isUnionRef memberRef = Info {kind = VariantRef, tagName = [memberRef]}
+        | otherwise = Info {kind = InlineVariant, tagName = [consName]}
+      getTag Nothing = Info {kind = InlineVariant, tagName = [consName]}
+      --------
+      consName = conNameProxy (Proxy @c)
+      ----------
+      isUnionRef x = typeName <> x == consName
+
+getUnionInfos ::
+  forall f a b gql.
+  (DescribeCons gql a, DescribeCons gql b) =>
+  UseGQLType gql ->
+  f (a :+: b) ->
+  DecoderT (Bool, ([TypeName], [TypeName]))
+getUnionInfos ctx _ = do
+  context <- ask
+  let l = tags ctx (Proxy @a) context
+  let r = tags ctx (Proxy @b) context
+  let k = kind (l <> r)
+  pure (k == VariantRef, (tagName l, tagName r))
+
+class RefType gql (f :: Type -> Type) where
+  refType :: UseGQLType gql -> Proxy f -> Maybe TypeName
+
+instance (RefType gql f, RefType gql g) => RefType gql (f :*: g) where
+  refType _ _ = Nothing
+
+instance (Selector s, gql a) => RefType gql (M1 S s (K1 i a)) where
+  refType dir _ = Just $ useTypename dir (InputType :: CatType IN a)
+
+instance RefType gql U1 where
+  refType _ _ = Nothing
+
+class CountFields (f :: Type -> Type) where
+  countFields :: Proxy f -> Int
+
+instance (CountFields f, CountFields g) => CountFields (f :*: g) where
+  countFields _ = countFields (Proxy @f) + countFields (Proxy @g)
+
+instance (Selector s) => CountFields (M1 S s (K1 i a)) where
+  countFields _ = 1
+
+instance CountFields U1 where
+  countFields _ = 0
+
+useDecodeArguments :: val a => UseDeriving gql val -> Arguments VALID -> ResolverState a
+useDecodeArguments drv = useDecodeValue (dirArgs drv) . argumentsToObject
diff --git a/src/Data/Morpheus/Server/Deriving/Internal/Resolve/Explore.hs b/src/Data/Morpheus/Server/Deriving/Internal/Resolve/Explore.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Internal/Resolve/Explore.hs
@@ -0,0 +1,112 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Internal.Resolve.Explore
+  ( useExploreResolvers,
+    useObjectResolvers,
+    EXPLORE,
+  )
+where
+
+import Control.Monad.Except (MonadError)
+import Data.Morpheus.App.Internal.Resolving
+  ( ObjectTypeResolver (..),
+    ResolverState,
+    ResolverValue (..),
+    mkEnum,
+    mkObject,
+    mkUnion,
+    requireObject,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Schema.Directive
+  ( toFieldRes,
+    visitEnumName,
+  )
+import Data.Morpheus.Server.Deriving.Utils.GRep
+  ( ConsRep (..),
+    FieldRep (..),
+    GRep,
+    RepContext (..),
+    TypeRep (..),
+    deriveValue,
+    isUnionRef,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Kinded (inputType)
+import Data.Morpheus.Server.Deriving.Utils.Use
+  ( UseDeriving (..),
+    UseGQLType (..),
+    UseResolver (..),
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( GQLError,
+    TypeRef (..),
+  )
+import GHC.Generics (Generic (Rep))
+import Relude
+
+convertNode ::
+  gql a =>
+  (MonadError GQLError m) =>
+  UseDeriving gql val ->
+  f a ->
+  TypeRep (m (ResolverValue m)) ->
+  ResolverValue m
+convertNode
+  drv
+  proxy
+  TypeRep
+    { dataTypeName,
+      tyIsUnion,
+      tyCons = cons@ConsRep {consFields, consName}
+    } = encodeTypeFields consFields
+    where
+      -- ENUM
+      encodeTypeFields :: (MonadError GQLError m) => [FieldRep (m (ResolverValue m))] -> ResolverValue m
+      encodeTypeFields [] = mkEnum (visitEnumName drv proxy consName)
+      encodeTypeFields fields
+        | not tyIsUnion = mkObject dataTypeName (toFieldRes drv proxy <$> fields)
+      -- Type References --------------------------------------------------------------
+      encodeTypeFields [FieldRep {fieldTypeRef, fieldValue}]
+        | isUnionRef dataTypeName cons = ResLazy (ResObject (Just (typeConName fieldTypeRef)) <$> (fieldValue >>= requireObject))
+      -- Inline Union Types ----------------------------------------------------------------------------
+      encodeTypeFields fields = mkUnion consName (toFieldRes drv proxy <$> fields)
+
+toOptions :: UseResolver res gql val -> RepContext gql (res m) Identity (m (ResolverValue m))
+toOptions UseResolver {..} =
+  RepContext
+    { optApply = useEncodeResolver . runIdentity,
+      optTypeData = useTypeData (dirGQL resDrv) . inputType
+    }
+
+useExploreResolvers ::
+  (MonadError GQLError m, EXPLORE gql res m a) =>
+  UseResolver res gql val ->
+  a ->
+  ResolverValue m
+useExploreResolvers res v = convertNode (resDrv res) proxy (deriveValue (toOptions res) v)
+  where
+    proxy = Identity v
+
+useObjectResolvers ::
+  (MonadError GQLError m, EXPLORE gql res m a) =>
+  UseResolver res gql val ->
+  a ->
+  ResolverState (ObjectTypeResolver m)
+useObjectResolvers ctx value = requireObject (useExploreResolvers ctx value)
+
+type EXPLORE gql res (m :: Type -> Type) a =
+  ( Generic a,
+    GRep gql (res m) (m (ResolverValue m)) (Rep a),
+    gql a
+  )
diff --git a/src/Data/Morpheus/Server/Deriving/Internal/Schema/Directive.hs b/src/Data/Morpheus/Server/Deriving/Internal/Schema/Directive.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Internal/Schema/Directive.hs
@@ -0,0 +1,220 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Internal.Schema.Directive
+  ( deriveFieldDirectives,
+    deriveTypeDirectives,
+    deriveEnumDirectives,
+    visitEnumValueDescription,
+    visitFieldDescription,
+    visitTypeDescription,
+    visitFieldDefaultValue,
+    visitFieldContent,
+    visitEnumName,
+    visitFieldName,
+    toFieldRes,
+    UseDeriving (..),
+  )
+where
+
+import Control.Monad.Except
+import qualified Data.HashMap.Lazy as HM
+import Data.Morpheus.Internal.Ext (resultOr, unsafeFromList)
+import Data.Morpheus.Internal.Utils (Empty (..), fromElems)
+import Data.Morpheus.Server.Deriving.Internal.Schema.Internal
+  ( CatType,
+    deriveTypeAsArguments,
+  )
+import Data.Morpheus.Server.Deriving.Utils.GRep (FieldRep (..))
+import Data.Morpheus.Server.Deriving.Utils.Kinded
+  ( CatType (..),
+    inputType,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Use
+  ( UseDeriving (..),
+    UseGQLType (..),
+    UseValue (..),
+  )
+import Data.Morpheus.Server.Types.Directives
+  ( GDirectiveUsage (..),
+    GDirectiveUsages (..),
+    GQLDirective (..),
+    applyEnumDescription,
+    applyEnumName,
+    applyFieldDefaultValue,
+    applyFieldDescription,
+    applyFieldName,
+    applyTypeDescription,
+    applyTypeEnumNames,
+    applyTypeFieldNames,
+    getLocations,
+  )
+import Data.Morpheus.Server.Types.SchemaT
+  ( SchemaT,
+    insertDirectiveDefinition,
+    outToAny,
+    withInput,
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( Argument (..),
+    Arguments,
+    CONST,
+    Description,
+    Directive (..),
+    DirectiveDefinition (..),
+    Directives,
+    FieldContent (..),
+    FieldName,
+    IN,
+    OUT,
+    ObjectEntry (..),
+    Position (Position),
+    TRUE,
+    TypeName,
+    Value (..),
+    internal,
+  )
+import GHC.Generics ()
+import GHC.TypeLits ()
+import Relude hiding (empty)
+
+deriveDirectiveDefinition ::
+  (gql a, GQLDirective a, args a) =>
+  UseDeriving gql args ->
+  a ->
+  b ->
+  SchemaT kind (DirectiveDefinition CONST)
+deriveDirectiveDefinition options arg _ = do
+  directiveDefinitionArgs <- outToAny (withInput $ deriveTypeAsArguments (dirGQL options) proxy)
+  pure
+    ( DirectiveDefinition
+        { directiveDefinitionName = deriveDirectiveName (dirGQL options) proxy,
+          directiveDefinitionDescription = visitTypeDescription options proxy Nothing,
+          directiveDefinitionArgs,
+          directiveDefinitionLocations = getLocations proxy
+        }
+    )
+  where
+    proxy = Identity arg
+
+deriveDirectiveUsages :: UseDeriving gql args -> [GDirectiveUsage gql args] -> SchemaT kind (Directives CONST)
+deriveDirectiveUsages options = fmap unsafeFromList . traverse (toDirectiveTuple options)
+
+encodeDirectiveArguments :: val a => UseValue val -> a -> SchemaT OUT (Arguments CONST)
+encodeDirectiveArguments val x = resultOr (const $ throwError err) pure (useEncodeValue val x) >>= unpackValue
+  where
+    err = internal "could not encode arguments. Arguments should be an object like type!"
+    unpackValue (Object v) = pure $ fmap toArgument v
+    unpackValue _ = throwError err
+    toArgument ObjectEntry {..} = Argument (Position 0 0) entryName entryValue
+
+toDirectiveTuple ::
+  UseDeriving gql args ->
+  GDirectiveUsage gql args ->
+  SchemaT kind (FieldName, Directive CONST)
+toDirectiveTuple options (GDirectiveUsage x) = do
+  insertDirective options (deriveDirectiveDefinition options x) x
+  let directiveName = deriveDirectiveName (dirGQL options) (Identity x)
+  args <- toList <$> outToAny (encodeDirectiveArguments (dirArgs options) x)
+  directiveArgs <- fromElems (map editArg args)
+  pure
+    ( directiveName,
+      Directive
+        { directivePosition = Position 0 0,
+          directiveName,
+          directiveArgs
+        }
+    )
+  where
+    editArg Argument {..} = Argument {argumentName = applyGQLFieldOptions options (Identity x) argumentName, ..}
+
+insertDirective ::
+  forall gql args a k.
+  gql a =>
+  UseDeriving gql args ->
+  (CatType IN a -> SchemaT k (DirectiveDefinition CONST)) ->
+  a ->
+  SchemaT k ()
+insertDirective ops f _ = insertDirectiveDefinition (useFingerprint (dirGQL ops) proxy) f proxy
+  where
+    proxy = InputType :: CatType IN a
+
+getDirHM :: (Ord k, Hashable k, Empty a) => k -> HashMap k a -> a
+getDirHM name xs = fromMaybe empty $ name `HM.lookup` xs
+
+isIncluded :: GDirectiveUsage gql args -> Bool
+isIncluded (GDirectiveUsage x) = not $ excludeFromSchema (Identity x)
+
+getEnumDirectiveUsages :: gql a => UseDeriving gql args -> f a -> TypeName -> [GDirectiveUsage gql args]
+getEnumDirectiveUsages UseDeriving {..} proxy name = getDirHM name $ enumValueDirectives $ __directives proxy
+
+getFieldDirectiveUsages :: gql a => UseDeriving gql args -> FieldName -> f a -> [GDirectiveUsage gql args]
+getFieldDirectiveUsages UseDeriving {..} name proxy = getDirHM name $ fieldDirectives $ __directives proxy
+
+-- derive directives
+deriveEnumDirectives :: gql a => UseDeriving gql args -> f a -> TypeName -> SchemaT k (Directives CONST)
+deriveEnumDirectives options proxy name = deriveDirectiveUsages options $ filter isIncluded $ getEnumDirectiveUsages options proxy name
+
+deriveFieldDirectives :: gql a => UseDeriving gql args -> f a -> FieldName -> SchemaT kind (Directives CONST)
+deriveFieldDirectives options proxy name = deriveDirectiveUsages options $ filter isIncluded $ getFieldDirectiveUsages options name proxy
+
+deriveTypeDirectives :: gql a => UseDeriving gql args -> f a -> SchemaT kind (Directives CONST)
+deriveTypeDirectives options proxy = deriveDirectiveUsages options $ filter isIncluded $ typeDirectives $ __directives options proxy
+
+-- visit
+
+visitEnumValueDescription :: gql a => UseDeriving gql args -> f a -> TypeName -> Maybe Description -> Maybe Description
+visitEnumValueDescription options proxy name desc = foldr applyEnumDescription desc (getEnumDirectiveUsages options proxy name)
+
+visitEnumName :: gql a => UseDeriving gql args -> f a -> TypeName -> TypeName
+visitEnumName options proxy name = foldr applyEnumName (withTypeDirectives name) (getEnumDirectiveUsages options proxy name)
+  where
+    withTypeDirectives dirName = foldr applyTypeEnumNames dirName (typeDirectives $ __directives options proxy)
+
+visitFieldDescription :: gql a => UseDeriving gql args -> f a -> FieldName -> Maybe Description -> Maybe Description
+visitFieldDescription options proxy name desc = foldr applyFieldDescription desc (getFieldDirectiveUsages options name proxy)
+
+visitFieldDefaultValue :: gql a => UseDeriving gql args -> f a -> FieldName -> Maybe (Value CONST) -> Maybe (Value CONST)
+visitFieldDefaultValue options proxy name desc = foldr applyFieldDefaultValue desc (getFieldDirectiveUsages options name proxy)
+
+visitFieldContent ::
+  gql a =>
+  UseDeriving gql args ->
+  CatType kind a ->
+  FieldName ->
+  Maybe (FieldContent TRUE kind CONST) ->
+  Maybe (FieldContent TRUE kind CONST)
+visitFieldContent options proxy@InputType name x =
+  DefaultInputValue
+    <$> visitFieldDefaultValue options proxy name (defaultInputValue <$> x)
+visitFieldContent _ OutputType _ x = x
+
+applyGQLFieldOptions :: gql a => UseDeriving gql args -> f a -> FieldName -> FieldName
+applyGQLFieldOptions options proxy = withTypeDirectives
+  where
+    withTypeDirectives name = foldr applyTypeFieldNames name (typeDirectives $ __directives options proxy)
+
+visitFieldName :: gql a => UseDeriving gql args -> f a -> FieldName -> FieldName
+visitFieldName options proxy name = foldr applyFieldName (applyGQLFieldOptions options proxy name) (getFieldDirectiveUsages options name proxy)
+
+visitTypeDescription :: gql a => UseDeriving gql args -> f a -> Maybe Description -> Maybe Description
+visitTypeDescription options proxy desc = foldr applyTypeDescription desc (typeDirectives $ __directives options proxy)
+
+toFieldRes :: gql a => UseDeriving gql args -> f a -> FieldRep v -> (FieldName, v)
+toFieldRes options proxy FieldRep {..} = (visitFieldName options proxy fieldSelector, fieldValue)
+
+deriveDirectiveName :: gql a => UseGQLType gql -> f a -> FieldName
+deriveDirectiveName options = coerce . useTypename options . inputType
diff --git a/src/Data/Morpheus/Server/Deriving/Internal/Schema/Enum.hs b/src/Data/Morpheus/Server/Deriving/Internal/Schema/Enum.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Internal/Schema/Enum.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE RecordWildCards #-}
+
+module Data.Morpheus.Server.Deriving.Internal.Schema.Enum
+  ( buildEnumTypeContent,
+    defineEnumUnit,
+  )
+where
+
+import Data.Morpheus.Server.Deriving.Internal.Schema.Directive
+  ( UseDeriving,
+    deriveEnumDirectives,
+    visitEnumName,
+    visitEnumValueDescription,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Kinded
+  ( CatType (..),
+  )
+import Data.Morpheus.Server.Types.SchemaT
+  ( SchemaT,
+    insertType,
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( CONST,
+    DataEnumValue (..),
+    LEAF,
+    TRUE,
+    TypeContent (..),
+    TypeDefinition,
+    TypeName,
+    mkEnumContent,
+    mkType,
+    unitTypeName,
+  )
+
+buildEnumTypeContent :: gql a => UseDeriving gql args -> CatType kind a -> [TypeName] -> SchemaT k (TypeContent TRUE kind CONST)
+buildEnumTypeContent options p@InputType enumCons = DataEnum <$> traverse (mkEnumValue options p) enumCons
+buildEnumTypeContent options p@OutputType enumCons = DataEnum <$> traverse (mkEnumValue options p) enumCons
+
+mkEnumValue :: gql a => UseDeriving gql args -> f a -> TypeName -> SchemaT k (DataEnumValue CONST)
+mkEnumValue options proxy enumName = do
+  enumDirectives <- deriveEnumDirectives options proxy enumName
+  pure
+    DataEnumValue
+      { enumName = visitEnumName options proxy enumName,
+        enumDescription = visitEnumValueDescription options proxy enumName Nothing,
+        ..
+      }
+
+defineEnumUnit :: SchemaT cat ()
+defineEnumUnit =
+  insertType
+    ( mkType unitTypeName (mkEnumContent [unitTypeName]) ::
+        TypeDefinition LEAF CONST
+    )
diff --git a/src/Data/Morpheus/Server/Deriving/Internal/Schema/Internal.hs b/src/Data/Morpheus/Server/Deriving/Internal/Schema/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Internal/Schema/Internal.hs
@@ -0,0 +1,75 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE TemplateHaskellQuotes #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Internal.Schema.Internal
+  ( CatType (..),
+    fromSchema,
+    withObject,
+    deriveTypeAsArguments,
+  )
+where
+
+-- MORPHEUS
+
+import Control.Monad.Except (throwError)
+import Data.Morpheus.Internal.Ext
+  ( GQLResult,
+    Result (Failure, Success, errors),
+  )
+import Data.Morpheus.Server.Deriving.Utils.Kinded
+  ( CatType (..),
+    inputType,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Use (UseGQLType (..))
+import Data.Morpheus.Server.Types.SchemaT (SchemaT)
+import Data.Morpheus.Types.Internal.AST
+  ( ArgumentsDefinition,
+    CONST,
+    FieldsDefinition,
+    IN,
+    Msg (..),
+    Schema (..),
+    TRUE,
+    TypeContent (..),
+    TypeDefinition (..),
+    VALID,
+    fieldsToArguments,
+  )
+import Language.Haskell.TH (Exp, Q)
+import Relude hiding (empty)
+
+fromSchema :: GQLResult (Schema VALID) -> Q Exp
+fromSchema Success {} = [|()|]
+fromSchema Failure {errors} = fail (show errors)
+
+withObject :: (gql a) => UseGQLType gql -> CatType c a -> TypeContent TRUE any s -> SchemaT c (FieldsDefinition c s)
+withObject _ InputType DataInputObject {inputObjectFields} = pure inputObjectFields
+withObject _ OutputType DataObject {objectFields} = pure objectFields
+withObject gql x _ = failureOnlyObject gql x
+
+failureOnlyObject :: (gql a) => UseGQLType gql -> CatType c a -> SchemaT c b
+failureOnlyObject gql proxy = throwError $ msg (useTypename gql proxy) <> " should have only one nonempty constructor"
+
+deriveTypeAsArguments :: gql a => UseGQLType gql -> f a -> SchemaT IN (ArgumentsDefinition CONST)
+deriveTypeAsArguments gql arg =
+  fieldsToArguments
+    <$> ( useDeriveType gql (inputType arg)
+            >>= withObject gql (inputType arg) . typeContent
+        )
diff --git a/src/Data/Morpheus/Server/Deriving/Internal/Schema/Object.hs b/src/Data/Morpheus/Server/Deriving/Internal/Schema/Object.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Internal/Schema/Object.hs
@@ -0,0 +1,102 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+
+module Data.Morpheus.Server.Deriving.Internal.Schema.Object
+  ( buildObjectTypeContent,
+    defineObjectType,
+  )
+where
+
+import Data.Morpheus.Internal.Utils
+  ( empty,
+    singleton,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Schema.Directive
+  ( UseDeriving,
+    deriveFieldDirectives,
+    visitFieldContent,
+    visitFieldDescription,
+    visitFieldName,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Schema.Enum
+  ( defineEnumUnit,
+  )
+import Data.Morpheus.Server.Deriving.Utils.GRep
+  ( ConsRep (..),
+    FieldRep (..),
+  )
+import Data.Morpheus.Server.Deriving.Utils.Kinded
+  ( CatType (..),
+  )
+import Data.Morpheus.Server.Types.SchemaT
+  ( SchemaT,
+    insertType,
+  )
+import Data.Morpheus.Types.Internal.AST (ArgumentsDefinition, CONST, FieldContent (..), FieldDefinition (..), FieldsDefinition, TRUE, TypeContent (..), mkField, mkType, mkTypeRef, unitFieldName, unitTypeName, unsafeFromFields)
+import Relude hiding (empty)
+
+defineObjectType ::
+  CatType kind a ->
+  ConsRep (Maybe (ArgumentsDefinition CONST)) ->
+  SchemaT cat ()
+defineObjectType proxy ConsRep {consName, consFields} = insertType . mkType consName . mkObjectTypeContent proxy =<< fields
+  where
+    fields
+      | null consFields = defineEnumUnit $> singleton unitFieldName mkFieldUnit
+      | otherwise = pure $ unsafeFromFields $ map (repToFieldDefinition proxy) consFields
+
+mkFieldUnit :: FieldDefinition cat s
+mkFieldUnit = mkField Nothing unitFieldName (mkTypeRef unitTypeName)
+
+buildObjectTypeContent ::
+  gql a =>
+  UseDeriving gql args ->
+  CatType cat a ->
+  [FieldRep (Maybe (ArgumentsDefinition CONST))] ->
+  SchemaT k (TypeContent TRUE cat CONST)
+buildObjectTypeContent options scope consFields = do
+  xs <- traverse (setGQLTypeProps options scope . repToFieldDefinition scope) consFields
+  pure $ mkObjectTypeContent scope $ unsafeFromFields xs
+
+repToFieldDefinition ::
+  CatType c a ->
+  FieldRep (Maybe (ArgumentsDefinition CONST)) ->
+  FieldDefinition c CONST
+repToFieldDefinition
+  x
+  FieldRep
+    { fieldSelector = fieldName,
+      fieldTypeRef = fieldType,
+      fieldValue
+    } =
+    FieldDefinition
+      { fieldDescription = mempty,
+        fieldDirectives = empty,
+        fieldContent = toFieldContent x fieldValue,
+        ..
+      }
+
+toFieldContent :: CatType c a -> Maybe (ArgumentsDefinition CONST) -> Maybe (FieldContent TRUE c CONST)
+toFieldContent OutputType (Just x) = Just (FieldArgs x)
+toFieldContent _ _ = Nothing
+
+mkObjectTypeContent :: CatType kind a -> FieldsDefinition kind CONST -> TypeContent TRUE kind CONST
+mkObjectTypeContent InputType = DataInputObject
+mkObjectTypeContent OutputType = DataObject []
+
+setGQLTypeProps :: gql a => UseDeriving gql args -> CatType kind a -> FieldDefinition kind CONST -> SchemaT k (FieldDefinition kind CONST)
+setGQLTypeProps options proxy FieldDefinition {..} = do
+  dirs <- deriveFieldDirectives options proxy fieldName
+  pure
+    FieldDefinition
+      { fieldName = visitFieldName options proxy fieldName,
+        fieldDescription = visitFieldDescription options proxy fieldName Nothing,
+        fieldContent = visitFieldContent options proxy fieldName fieldContent,
+        fieldDirectives = dirs,
+        ..
+      }
diff --git a/src/Data/Morpheus/Server/Deriving/Internal/Schema/Type.hs b/src/Data/Morpheus/Server/Deriving/Internal/Schema/Type.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Internal/Schema/Type.hs
@@ -0,0 +1,166 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Data.Morpheus.Server.Deriving.Internal.Schema.Type
+  ( fillTypeContent,
+    deriveTypeDefinition,
+    deriveScalarDefinition,
+    deriveInterfaceDefinition,
+    deriveTypeGuardUnions,
+    useDeriveObject,
+    injectType,
+  )
+where
+
+import Control.Monad.Except
+import Data.Foldable
+import Data.Morpheus.Server.Deriving.Internal.Schema.Directive
+  ( UseDeriving (..),
+    deriveTypeDirectives,
+    visitTypeDescription,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Schema.Enum
+  ( buildEnumTypeContent,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Schema.Internal
+  ( CatType,
+    withObject,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Schema.Object
+  ( buildObjectTypeContent,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Schema.Union (buildUnionTypeContent)
+import Data.Morpheus.Server.Deriving.Utils.GRep
+  ( ConsRep (..),
+    GRep,
+    RepContext (..),
+    deriveTypeWith,
+    isEmptyConstraint,
+    unpackMonad,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Kinded (CatContext, addContext, getCatContext, mkScalar, outputType)
+import Data.Morpheus.Server.Deriving.Utils.Use
+  ( UseGQLType (..),
+  )
+import Data.Morpheus.Server.Types.SchemaT
+  ( SchemaT,
+    updateSchema,
+  )
+import Data.Morpheus.Types.Internal.AST
+import GHC.Generics (Rep)
+import Relude
+
+buildTypeContent ::
+  (gql a) =>
+  UseDeriving gql args ->
+  CatType kind a ->
+  [ConsRep (Maybe (ArgumentsDefinition CONST))] ->
+  SchemaT kind (TypeContent TRUE kind CONST)
+buildTypeContent options scope cons | all isEmptyConstraint cons = buildEnumTypeContent options scope (consName <$> cons)
+buildTypeContent options scope [ConsRep {consFields}] = buildObjectTypeContent options scope consFields
+buildTypeContent options scope cons = buildUnionTypeContent (dirGQL options) scope cons
+
+deriveTypeContentWith ::
+  (gql a, GRep gql gql (SchemaT kind (Maybe (ArgumentsDefinition CONST))) (Rep a)) =>
+  UseDeriving gql args ->
+  CatType kind a ->
+  SchemaT kind (TypeContent TRUE kind CONST)
+deriveTypeContentWith dir proxy =
+  unpackMonad (deriveTypeWith (toFieldContent (getCatContext proxy) dir) proxy)
+    >>= buildTypeContent dir proxy
+
+deriveTypeGuardUnions ::
+  ( gql a,
+    GRep gql gql (SchemaT OUT (Maybe (ArgumentsDefinition CONST))) (Rep a)
+  ) =>
+  UseDeriving gql args ->
+  CatType OUT a ->
+  SchemaT OUT [TypeName]
+deriveTypeGuardUnions dir proxy = do
+  content <- deriveTypeContentWith dir proxy
+  getUnionNames content
+  where
+    getUnionNames :: TypeContent TRUE OUT CONST -> SchemaT OUT [TypeName]
+    getUnionNames DataUnion {unionMembers} = pure $ toList $ memberName <$> unionMembers
+    getUnionNames DataObject {} = pure [useTypename (dirGQL dir) proxy]
+    getUnionNames _ = throwError "guarded type must be an union or object"
+
+insertType ::
+  forall c gql a args.
+  (gql a) =>
+  UseDeriving gql args ->
+  (UseDeriving gql args -> CatType c a -> SchemaT c (TypeDefinition c CONST)) ->
+  CatType c a ->
+  SchemaT c ()
+insertType dir f proxy = updateSchema (useFingerprint (dirGQL dir) proxy) (f dir) proxy
+
+deriveScalarDefinition ::
+  gql a =>
+  (CatType cat a -> ScalarDefinition) ->
+  UseDeriving gql args ->
+  CatType cat a ->
+  SchemaT kind (TypeDefinition cat CONST)
+deriveScalarDefinition f dir p = fillTypeContent dir p (mkScalar p (f p))
+
+deriveTypeDefinition ::
+  (gql a, GRep gql gql (SchemaT c (Maybe (ArgumentsDefinition CONST))) (Rep a)) =>
+  UseDeriving gql args ->
+  CatType c a ->
+  SchemaT c (TypeDefinition c CONST)
+deriveTypeDefinition dir proxy = deriveTypeContentWith dir proxy >>= fillTypeContent dir proxy
+
+deriveInterfaceDefinition ::
+  (gql a, GRep gql gql (SchemaT OUT (Maybe (ArgumentsDefinition CONST))) (Rep a)) =>
+  UseDeriving gql args ->
+  CatType OUT a ->
+  SchemaT OUT (TypeDefinition OUT CONST)
+deriveInterfaceDefinition dir proxy = do
+  fields <- deriveFields dir proxy
+  fillTypeContent dir proxy (DataInterface fields)
+
+fillTypeContent ::
+  gql a =>
+  UseDeriving gql args ->
+  CatType c a ->
+  TypeContent TRUE cat CONST ->
+  SchemaT kind (TypeDefinition cat CONST)
+fillTypeContent options@UseDeriving {dirGQL = UseGQLType {..}} proxy content = do
+  dirs <- deriveTypeDirectives options proxy
+  pure $
+    TypeDefinition
+      (visitTypeDescription options proxy Nothing)
+      (useTypename proxy)
+      dirs
+      content
+
+deriveFields ::
+  ( gql a,
+    GRep gql gql (SchemaT cat (Maybe (ArgumentsDefinition CONST))) (Rep a)
+  ) =>
+  UseDeriving gql args ->
+  CatType cat a ->
+  SchemaT cat (FieldsDefinition cat CONST)
+deriveFields dirs kindedType = deriveTypeContentWith dirs kindedType >>= withObject (dirGQL dirs) kindedType
+
+toFieldContent :: CatContext cat -> UseDeriving gql dir -> RepContext gql gql Proxy (SchemaT cat (Maybe (ArgumentsDefinition CONST)))
+toFieldContent ctx dir@UseDeriving {..} =
+  RepContext
+    { optTypeData = useTypeData dirGQL . addContext ctx,
+      optApply = \proxy -> injectType dir (addContext ctx proxy) *> useDeriveFieldArguments dirGQL (addContext ctx proxy)
+    }
+
+injectType :: gql a => UseDeriving gql args -> CatType c a -> SchemaT c ()
+injectType dir = insertType dir (\_ y -> useDeriveType (dirGQL dir) y)
+
+useDeriveObject :: gql a => UseGQLType gql -> f a -> SchemaT OUT (TypeDefinition OBJECT CONST)
+useDeriveObject gql pr = do
+  fields <- useDeriveType gql proxy >>= withObject gql proxy . typeContent
+  pure $ mkType (useTypename gql (outputType proxy)) (DataObject [] fields)
+  where
+    proxy = outputType pr
diff --git a/src/Data/Morpheus/Server/Deriving/Internal/Schema/Union.hs b/src/Data/Morpheus/Server/Deriving/Internal/Schema/Union.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Internal/Schema/Union.hs
@@ -0,0 +1,82 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE GADTs #-}
+
+module Data.Morpheus.Server.Deriving.Internal.Schema.Union
+  ( buildUnionTypeContent,
+  )
+where
+
+import Data.List (partition)
+import Data.Morpheus.Internal.Utils (fromElems)
+import Data.Morpheus.Server.Deriving.Internal.Schema.Enum
+  ( defineEnumUnit,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Schema.Object
+  ( defineObjectType,
+  )
+import Data.Morpheus.Server.Deriving.Utils.GRep
+  ( ConsRep (..),
+    FieldRep (fieldTypeRef),
+    isEmptyConstraint,
+    isUnionRef,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Kinded
+  ( CatType (..),
+  )
+import Data.Morpheus.Server.Deriving.Utils.Use (UseGQLType (..), useTypename)
+import Data.Morpheus.Server.Types.SchemaT
+  ( SchemaT,
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( ArgumentsDefinition,
+    CONST,
+    IN,
+    TRUE,
+    TypeContent (..),
+    TypeName,
+    TypeRef (..),
+    UnionMember (..),
+    mkNullaryMember,
+    mkUnionMember,
+  )
+import Relude
+
+buildUnionTypeContent ::
+  (gql a) =>
+  UseGQLType gql ->
+  CatType kind a ->
+  [ConsRep (Maybe (ArgumentsDefinition CONST))] ->
+  SchemaT k (TypeContent TRUE kind CONST)
+buildUnionTypeContent gql scope cons = mkUnionType scope unionRef unionCons
+  where
+    unionRef = typeConName . fieldTypeRef <$> concatMap consFields unionRefRep
+    (unionRefRep, unionCons) = partition (isUnionRef (useTypename gql scope)) cons
+
+mkUnionType ::
+  CatType kind a ->
+  [TypeName] ->
+  [ConsRep (Maybe (ArgumentsDefinition CONST))] ->
+  SchemaT c (TypeContent TRUE kind CONST)
+mkUnionType p@InputType unionRef unionCons = DataInputUnion <$> (typeMembers >>= fromElems)
+  where
+    (nullaryCons, cons) = partition isEmptyConstraint unionCons
+    nullaryMembers :: [UnionMember IN CONST]
+    nullaryMembers = mkNullaryMember . consName <$> nullaryCons
+    defineEnumEmpty
+      | null nullaryCons = pure ()
+      | otherwise = defineEnumUnit
+    typeMembers =
+      (<> nullaryMembers) . withRefs
+        <$> ( defineEnumEmpty *> buildUnions p cons
+            )
+      where
+        withRefs = fmap mkUnionMember . (unionRef <>)
+mkUnionType p@OutputType unionRef unionCons =
+  DataUnion <$> (buildUnions p unionCons >>= fromElems . map mkUnionMember . (unionRef <>))
+
+buildUnions ::
+  CatType kind a ->
+  [ConsRep (Maybe (ArgumentsDefinition CONST))] ->
+  SchemaT c [TypeName]
+buildUnions proxy cons =
+  traverse_ (defineObjectType proxy) cons $> fmap consName cons
diff --git a/src/Data/Morpheus/Server/Deriving/Kinded/Arguments.hs b/src/Data/Morpheus/Server/Deriving/Kinded/Arguments.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Kinded/Arguments.hs
@@ -0,0 +1,61 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Kinded.Arguments
+  ( DeriveFieldArguments (..),
+    HasArguments,
+  )
+where
+
+import Data.Morpheus.Internal.Ext ((<:>))
+import Data.Morpheus.Server.Deriving.Internal.Schema.Internal
+  ( CatType,
+    deriveTypeAsArguments,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Kinded
+  ( CatType (..),
+  )
+import Data.Morpheus.Server.Deriving.Utils.Use
+  ( UseDeriving (..),
+    UseGQLType (..),
+  )
+import Data.Morpheus.Server.Types.SchemaT
+  ( SchemaT,
+    withInput,
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( ArgumentsDefinition,
+    CONST,
+    OUT,
+  )
+import Relude
+
+type family HasArguments a where
+  HasArguments (a -> b) = (a -> b)
+  HasArguments a = ()
+
+class DeriveFieldArguments gql a where
+  deriveFieldArguments :: UseDeriving gql val -> f a -> SchemaT OUT (Maybe (ArgumentsDefinition CONST))
+
+instance DeriveFieldArguments gql () where
+  deriveFieldArguments _ _ = pure Nothing
+
+instance (gql b, gql a) => DeriveFieldArguments gql (a -> b) where
+  deriveFieldArguments UseDeriving {..} _ = do
+    a <- withInput $ deriveTypeAsArguments dirGQL (Proxy @a)
+    b <- useDeriveFieldArguments dirGQL (OutputType :: CatType OUT b)
+    case b of
+      Just x -> Just <$> (a <:> x)
+      Nothing -> pure $ Just a
diff --git a/src/Data/Morpheus/Server/Deriving/Kinded/Channels.hs b/src/Data/Morpheus/Server/Deriving/Kinded/Channels.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Kinded/Channels.hs
@@ -0,0 +1,139 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Kinded.Channels
+  ( resolverChannels,
+    CHANNELS,
+  )
+where
+
+import Control.Monad.Except (throwError)
+import qualified Data.HashMap.Lazy as HM
+import Data.Morpheus.App.Internal.Resolving
+  ( Channel,
+    MonadResolver (..),
+    ResolverState,
+    SubscriptionField (..),
+  )
+import Data.Morpheus.Internal.Utils
+  ( selectBy,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Decode.Utils (useDecodeArguments)
+import Data.Morpheus.Server.Deriving.Internal.Schema.Directive (UseDeriving (..), toFieldRes)
+import Data.Morpheus.Server.Deriving.Utils.GRep
+  ( ConsRep (..),
+    GRep,
+    RepContext (..),
+    TypeRep (..),
+    deriveValue,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Kinded (outputType)
+import Data.Morpheus.Server.Deriving.Utils.Use (UseGQLType (useTypeData))
+import Data.Morpheus.Server.Types.Types (Undefined)
+import Data.Morpheus.Types.Internal.AST
+  ( FALSE,
+    FieldName,
+    SUBSCRIPTION,
+    Selection (..),
+    SelectionContent (..),
+    TRUE,
+    VALID,
+    internal,
+  )
+import GHC.Generics (Rep)
+import Relude hiding (Undefined)
+
+newtype DerivedChannel e = DerivedChannel
+  { _unpackChannel :: Channel e
+  }
+
+type ChannelRes (e :: Type) = Selection VALID -> ResolverState (DerivedChannel e)
+
+type CHANNELS gql val (subs :: (Type -> Type) -> Type) m =
+  ( MonadResolver m,
+    MonadOperation m ~ SUBSCRIPTION,
+    ExploreChannels gql val (IsUndefined (subs m)) (MonadEvent m) (subs m)
+  )
+
+resolverChannels ::
+  forall m subs gql val.
+  CHANNELS gql val subs m =>
+  UseDeriving gql val ->
+  subs m ->
+  Selection VALID ->
+  ResolverState (Channel (MonadEvent m))
+resolverChannels drv value = fmap _unpackChannel . channelSelector
+  where
+    channelSelector :: Selection VALID -> ResolverState (DerivedChannel (MonadEvent m))
+    channelSelector = selectBySelection (exploreChannels drv (Proxy @(IsUndefined (subs m))) value)
+
+selectBySelection ::
+  HashMap FieldName (ChannelRes e) ->
+  Selection VALID ->
+  ResolverState (DerivedChannel e)
+selectBySelection channels = withSubscriptionSelection >=> selectSubscription channels
+
+selectSubscription ::
+  HashMap FieldName (ChannelRes e) ->
+  Selection VALID ->
+  ResolverState (DerivedChannel e)
+selectSubscription channels sel@Selection {selectionName} =
+  selectBy
+    (internal "invalid subscription: no channel is selected.")
+    selectionName
+    channels
+    >>= (sel &)
+
+withSubscriptionSelection :: Selection VALID -> ResolverState (Selection VALID)
+withSubscriptionSelection Selection {selectionContent = SelectionSet selSet} =
+  case toList selSet of
+    [sel] -> pure sel
+    _ -> throwError (internal "invalid subscription: there can be only one top level selection")
+withSubscriptionSelection _ = throwError (internal "invalid subscription: expected selectionSet")
+
+class GetChannel val e a where
+  getChannel :: UseDeriving gql val -> a -> ChannelRes e
+
+instance (MonadResolver m, MonadOperation m ~ SUBSCRIPTION, MonadEvent m ~ e) => GetChannel val e (SubscriptionField (m a)) where
+  getChannel _ x = const $ pure $ DerivedChannel $ channel x
+
+instance (MonadResolver m, MonadOperation m ~ SUBSCRIPTION, MonadEvent m ~ e, val arg) => GetChannel val e (arg -> SubscriptionField (m a)) where
+  getChannel drv f sel@Selection {selectionArguments} =
+    useDecodeArguments drv selectionArguments
+      >>= flip (getChannel drv) sel . f
+
+------------------------------------------------------
+
+type family IsUndefined a :: Bool where
+  IsUndefined (Undefined m) = TRUE
+  IsUndefined a = FALSE
+
+class ExploreChannels gql val (t :: Bool) e a where
+  exploreChannels :: UseDeriving gql val -> f t -> a -> HashMap FieldName (ChannelRes e)
+
+instance (gql a, Generic a, GRep gql (GetChannel val e) (ChannelRes e) (Rep a)) => ExploreChannels gql val FALSE e a where
+  exploreChannels drv _ =
+    HM.fromList
+      . map (toFieldRes drv (Proxy @a))
+      . consFields
+      . tyCons
+      . deriveValue
+        ( RepContext
+            { optApply = getChannel drv . runIdentity,
+              optTypeData = useTypeData (dirGQL drv) . outputType
+            } ::
+            RepContext gql (GetChannel val e) Identity (ChannelRes e)
+        )
+
+instance ExploreChannels drv val TRUE e (Undefined m) where
+  exploreChannels _ _ = pure HM.empty
diff --git a/src/Data/Morpheus/Server/Deriving/Kinded/NamedResolver.hs b/src/Data/Morpheus/Server/Deriving/Kinded/NamedResolver.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Kinded/NamedResolver.hs
@@ -0,0 +1,112 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Kinded.NamedResolver
+  ( KindedNamedResolver (..),
+  )
+where
+
+import Data.Morpheus.App.Internal.Resolving
+  ( MonadResolver (..),
+    NamedResolver (..),
+    NamedResolverResult (..),
+    ResolverValue,
+  )
+import Data.Morpheus.Server.Deriving.Kinded.NamedResolverFun
+  ( deriveNamedResolverFun,
+  )
+import Data.Morpheus.Server.Deriving.Utils.GRep (GRep)
+import Data.Morpheus.Server.Deriving.Utils.GScan (ScanRef (..))
+import Data.Morpheus.Server.Deriving.Utils.Gmap (Gmap)
+import Data.Morpheus.Server.Deriving.Utils.Kinded (outputType)
+import Data.Morpheus.Server.Deriving.Utils.Use (UseDeriving (..), UseGQLType (useFingerprint, useTypename), UseNamedResolver (..), UseValue (useDecodeValue))
+import Data.Morpheus.Server.Types.Kind
+  ( CUSTOM,
+    DerivingKind,
+    SCALAR,
+    TYPE,
+    WRAPPER,
+  )
+import Data.Morpheus.Server.Types.NamedResolvers (Dependency, NamedResolverT (..), ResolveNamed (..))
+import Data.Morpheus.Types.GQLScalar (EncodeScalar (..))
+import Data.Morpheus.Types.Internal.AST
+  ( ValidValue,
+  )
+import GHC.Generics (Rep)
+import Relude
+
+type DECODE_VALUES val m a = (ResolveNamed m a, val (Dependency a), MonadResolver m)
+
+decodeValues :: DECODE_VALUES val m a => UseDeriving gql val -> Proxy a -> [ValidValue] -> m [Maybe a]
+decodeValues ctx _ xs = traverse (liftState . useDecodeValue (dirArgs ctx)) xs >>= resolveBatched
+
+class KindedNamedResolver namedRes resFun gql val (m :: Type -> Type) (k :: DerivingKind) a where
+  kindedNamedResolver :: UseNamedResolver namedRes resFun gql val -> f k a -> [NamedResolver m]
+  kindedNamedRefs :: UseNamedResolver namedRes resFun gql val -> f k a -> [ScanRef (namedRes m)]
+
+instance
+  ( DECODE_VALUES val m a,
+    gql a,
+    namedRes m a,
+    EncodeScalar a
+  ) =>
+  KindedNamedResolver namedRes resFun gql val m SCALAR a
+  where
+  kindedNamedResolver ctx _ =
+    [ NamedResolver
+        { resolverName = useTypename (dirGQL $ namedDrv ctx) (outputType proxy),
+          resolverFun = decodeValues (namedDrv ctx) proxy >=> pure . map (maybe NamedNullResolver (NamedScalarResolver . encodeScalar))
+        }
+    ]
+    where
+      proxy = Proxy @a
+  kindedNamedRefs ctx _ = [ScanType fp proxy]
+    where
+      fp = useFingerprint (dirGQL $ namedDrv ctx) (outputType proxy)
+      proxy = Proxy @a
+
+instance
+  ( DECODE_VALUES val m a,
+    gql a,
+    namedRes m a,
+    Generic a,
+    gql [Maybe a],
+    GRep gql (resFun m) (m (ResolverValue m)) (Rep a),
+    Gmap (namedRes m) (Rep a)
+  ) =>
+  KindedNamedResolver namedRes resFun gql val m TYPE (a :: Type)
+  where
+  kindedNamedResolver ctx _ =
+    [ NamedResolver
+        { resolverName = useTypename (dirGQL $ namedDrv ctx) (outputType proxy),
+          resolverFun = decodeValues (namedDrv ctx) proxy >=> deriveNamedResolverFun ctx
+        }
+    ]
+    where
+      proxy = Proxy @a
+
+  kindedNamedRefs ctx _ = [ScanObject (useFingerprint (dirGQL $ namedDrv ctx) (outputType proxy)) proxy]
+    where
+      proxy = Proxy @a
+
+instance namedRes m a => KindedNamedResolver namedRes resFun gql val m CUSTOM (NamedResolverT m a) where
+  kindedNamedResolver ctx _ = useDeriveNamedResolvers ctx (Proxy @a)
+  kindedNamedRefs ctx _ = useDeriveNamedRefs ctx (Proxy @a)
+
+instance namedRes m a => KindedNamedResolver namedRes resFun gql val m CUSTOM (input -> a) where
+  kindedNamedResolver ctx _ = useDeriveNamedResolvers ctx (Proxy @a)
+  kindedNamedRefs ctx _ = useDeriveNamedRefs ctx (Proxy @a)
+
+instance namedRes m a => KindedNamedResolver namedRes resFun gql val m WRAPPER (f a) where
+  kindedNamedResolver ctx _ = useDeriveNamedResolvers ctx (Proxy @a)
+  kindedNamedRefs ctx _ = useDeriveNamedRefs ctx (Proxy @a)
diff --git a/src/Data/Morpheus/Server/Deriving/Kinded/NamedResolverFun.hs b/src/Data/Morpheus/Server/Deriving/Kinded/NamedResolverFun.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Kinded/NamedResolverFun.hs
@@ -0,0 +1,172 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Kinded.NamedResolverFun
+  ( deriveNamedResolverFun,
+    KindedNamedFunValue (..),
+  )
+where
+
+import Control.Monad.Except (MonadError (..))
+import Data.Aeson (ToJSON (..))
+import Data.Morpheus.App.Internal.Resolving
+  ( MonadResolver (..),
+    NamedResolverRef (..),
+    NamedResolverResult (..),
+    ObjectTypeResolver (..),
+    ResolverValue (..),
+    getArguments,
+    mkList,
+    mkNull,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Decode.Utils (useDecodeArguments)
+import Data.Morpheus.Server.Deriving.Internal.Schema.Directive (UseDeriving, toFieldRes)
+import Data.Morpheus.Server.Deriving.Utils.GRep
+  ( ConsRep (..),
+    FieldRep (..),
+    GRep,
+    RepContext (..),
+    TypeRep (..),
+    deriveValue,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Kinded
+  ( CatType (..),
+    outputType,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Proxy
+  ( ContextValue (..),
+  )
+import Data.Morpheus.Server.Deriving.Utils.Use
+  ( UseDeriving (..),
+    UseGQLType (..),
+    UseNamedResolver (..),
+  )
+import Data.Morpheus.Server.Types.Kind
+  ( CUSTOM,
+    DerivingKind,
+    SCALAR,
+    TYPE,
+    WRAPPER,
+  )
+import Data.Morpheus.Server.Types.NamedResolvers
+  ( NamedRef,
+    NamedResolverT (..),
+  )
+import Data.Morpheus.Types.GQLScalar
+  ( EncodeScalar (..),
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( GQLError,
+    OUT,
+    TypeName,
+    ValidValue,
+    Value (List),
+    internal,
+    replaceValue,
+  )
+import qualified GHC.Exts as HM
+import GHC.Generics
+  ( Generic (..),
+  )
+import Relude hiding (empty)
+
+deriveNamedResolverFun ::
+  ( Generic a,
+    gql [Maybe a],
+    gql a,
+    MonadError GQLError m,
+    GRep gql (res m) (m (ResolverValue m)) (Rep a)
+  ) =>
+  UseNamedResolver namedRes res gql val ->
+  [Maybe a] ->
+  m [NamedResolverResult m]
+deriveNamedResolverFun ctx x = traverse encodeNode x
+  where
+    encodeNode (Just v) = convertNamedNode (namedDrv ctx) (Identity x) (deriveValue (getOptions ctx) v)
+    encodeNode Nothing = pure NamedNullResolver
+
+class KindedNamedFunValue res gql val (k :: DerivingKind) (m :: Type -> Type) (a :: Type) where
+  kindedNamedFunValue :: UseNamedResolver namedRes res gql val -> ContextValue k a -> m (ResolverValue m)
+
+instance (EncodeScalar a, Monad m) => KindedNamedFunValue res gql val SCALAR m a where
+  kindedNamedFunValue _ = pure . ResScalar . encodeScalar . unContextValue
+
+instance (MonadError GQLError m) => KindedNamedFunValue res gql val TYPE m a where
+  kindedNamedFunValue _ (ContextValue _) = throwError (internal "types are resolved by Refs")
+
+instance (Applicative m, res m a) => KindedNamedFunValue res gql val WRAPPER m [a] where
+  kindedNamedFunValue ctx = fmap ResList . traverse (useNamedFieldResolver ctx) . unContextValue
+
+instance (gql a, res m a, Applicative m) => KindedNamedFunValue res gql val WRAPPER m (Maybe a) where
+  kindedNamedFunValue ctx (ContextValue (Just x)) = useNamedFieldResolver ctx x
+  kindedNamedFunValue _ (ContextValue Nothing) = pure mkNull
+
+instance (Monad m, gql a, ToJSON (NamedRef a)) => KindedNamedFunValue res gql val CUSTOM m (NamedResolverT m a) where
+  kindedNamedFunValue ctx = encodeRef . unContextValue
+    where
+      name :: TypeName
+      name = useTypename (dirGQL (namedDrv ctx)) (OutputType :: CatType OUT a)
+      encodeRef :: Monad m => NamedResolverT m a -> m (ResolverValue m)
+      encodeRef (NamedResolverT ref) = do
+        value <- replaceValue . toJSON <$> ref
+        case value of
+          (List ls) -> pure $ mkList $ map (packRef name) ls
+          _ -> pure $ packRef name value
+
+packRef :: Applicative m => TypeName -> ValidValue -> ResolverValue m
+packRef name v = ResRef $ pure $ NamedResolverRef name [v]
+
+instance (Monad m, val a, MonadResolver m, res m b) => KindedNamedFunValue res gql val CUSTOM m (a -> b) where
+  kindedNamedFunValue ctx (ContextValue f) =
+    getArguments
+      >>= liftState . useDecodeArguments (namedDrv ctx)
+      >>= useNamedFieldResolver ctx . f
+
+getOptions :: UseNamedResolver namedRes res gql val -> RepContext gql (res m) Identity (m (ResolverValue m))
+getOptions UseNamedResolver {..} =
+  RepContext
+    { optApply = useNamedFieldResolver . runIdentity,
+      optTypeData = useTypeData (dirGQL namedDrv) . outputType
+    }
+
+convertNamedNode ::
+  (gql a, MonadError GQLError m) =>
+  UseDeriving gql val ->
+  f a ->
+  TypeRep (m (ResolverValue m)) ->
+  m (NamedResolverResult m)
+convertNamedNode
+  drv
+  proxy
+  TypeRep
+    { tyIsUnion,
+      tyCons = ConsRep {consFields, consName}
+    }
+    | null consFields = pure $ NamedEnumResolver consName
+    | tyIsUnion = deriveUnion consFields
+    | otherwise =
+        pure $
+          NamedObjectResolver
+            ObjectTypeResolver
+              { objectFields = HM.fromList (toFieldRes drv proxy <$> consFields)
+              }
+
+deriveUnion :: (MonadError GQLError m) => [FieldRep (m (ResolverValue m))] -> m (NamedResolverResult m)
+deriveUnion [FieldRep {..}] = NamedUnionResolver <$> (fieldValue >>= getRef)
+deriveUnion _ = throwError "only union references are supported!"
+
+getRef :: MonadError GQLError m => ResolverValue m -> m NamedResolverRef
+getRef (ResRef x) = x
+getRef _ = throwError "only resolver references are supported!"
diff --git a/src/Data/Morpheus/Server/Deriving/Kinded/Resolver.hs b/src/Data/Morpheus/Server/Deriving/Kinded/Resolver.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Kinded/Resolver.hs
@@ -0,0 +1,83 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Kinded.Resolver
+  ( KindedResolver (..),
+  )
+where
+
+import Control.Monad.Except (MonadError)
+import qualified Data.Map as M
+import Data.Morpheus.App.Internal.Resolving
+  ( MonadResolver (..),
+    ResolverValue (..),
+    getArguments,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Resolve.Explore
+import Data.Morpheus.Server.Deriving.Utils.AST
+import Data.Morpheus.Server.Deriving.Utils.Proxy
+  ( ContextValue (..),
+  )
+import Data.Morpheus.Server.Deriving.Utils.Use
+  ( UseDeriving (dirArgs),
+    UseResolver (..),
+    UseValue (useDecodeValue),
+  )
+import Data.Morpheus.Server.Types.Kind
+  ( CUSTOM,
+    DerivingKind,
+    SCALAR,
+    TYPE,
+    WRAPPER,
+  )
+import Data.Morpheus.Server.Types.Types
+  ( TypeGuard (..),
+  )
+import Data.Morpheus.Types.GQLScalar
+  ( EncodeScalar (..),
+  )
+import Data.Morpheus.Types.GQLWrapper (EncodeWrapper (..))
+import Data.Morpheus.Types.Internal.AST
+  ( GQLError,
+  )
+import Relude
+
+-- ENCODE GQL KIND
+class KindedResolver gql res val (kind :: DerivingKind) (m :: Type -> Type) (a :: Type) where
+  kindedResolver :: UseResolver res gql val -> ContextValue kind a -> m (ResolverValue m)
+
+instance (EncodeWrapper f, Monad m, res m a) => KindedResolver gql res val WRAPPER m (f a) where
+  kindedResolver res = encodeWrapper (useEncodeResolver res) . unContextValue
+
+instance (EncodeScalar a, Monad m) => KindedResolver gql res val SCALAR m a where
+  kindedResolver _ = pure . ResScalar . encodeScalar . unContextValue
+
+instance (MonadError GQLError m, EXPLORE gql res m a) => KindedResolver gql res val TYPE m a where
+  kindedResolver ctx = pure . useExploreResolvers ctx . unContextValue
+
+--  Map
+instance (Monad m, res m [(k, v)]) => KindedResolver gql res val CUSTOM m (Map k v) where
+  kindedResolver res = useEncodeResolver res . M.toList . unContextValue
+
+--  INTERFACE Types
+instance (MonadError GQLError m, EXPLORE gql res m guard, EXPLORE gql res m union) => KindedResolver gql res val CUSTOM m (TypeGuard guard union) where
+  kindedResolver ctx (ContextValue (ResolveType value)) = pure (useExploreResolvers ctx value)
+  kindedResolver ctx (ContextValue (ResolveInterface value)) = pure (useExploreResolvers ctx value)
+
+instance (Generic a, res m b, MonadResolver m, val a) => KindedResolver gql res val CUSTOM m (a -> b) where
+  kindedResolver res (ContextValue f) =
+    getArguments
+      >>= liftState . useDecodeValue (dirArgs $ resDrv res) . argumentsToObject
+      >>= useEncodeResolver res . f
+
+instance (MonadResolver m, res m a) => KindedResolver gql res val CUSTOM m (m a) where
+  kindedResolver res (ContextValue value) = value >>= useEncodeResolver res
diff --git a/src/Data/Morpheus/Server/Deriving/Kinded/Type.hs b/src/Data/Morpheus/Server/Deriving/Kinded/Type.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Kinded/Type.hs
@@ -0,0 +1,78 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Kinded.Type
+  ( DeriveKindedType (..),
+    DERIVE_TYPE,
+    deriveInterfaceDefinition,
+    deriveScalarDefinition,
+    deriveTypeGuardUnions,
+  )
+where
+
+import Data.Morpheus.Server.Deriving.Internal.Schema.Type
+  ( deriveInterfaceDefinition,
+    deriveScalarDefinition,
+    deriveTypeDefinition,
+    deriveTypeGuardUnions,
+  )
+import Data.Morpheus.Server.Deriving.Utils.GRep
+  ( GRep,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Kinded
+  ( CatType,
+    catMap,
+    unliftKind,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Use
+  ( UseDeriving (..),
+    UseGQLType (..),
+  )
+import Data.Morpheus.Server.Types.Kind
+  ( DerivingKind,
+    SCALAR,
+    TYPE,
+    WRAPPER,
+  )
+import Data.Morpheus.Server.Types.SchemaT
+  ( SchemaT,
+  )
+import Data.Morpheus.Types.GQLScalar
+  ( DecodeScalar (..),
+    scalarValidator,
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( ArgumentsDefinition,
+    CONST,
+    TypeCategory,
+    TypeDefinition (..),
+  )
+import GHC.Generics
+import Relude
+
+type DERIVE_TYPE gql c a = (gql a, GRep gql gql (SchemaT c (Maybe (ArgumentsDefinition CONST))) (Rep a))
+
+-- | DeriveType With specific Kind: 'kind': object, scalar, enum ...
+class DeriveKindedType gql val (cat :: TypeCategory) (kind :: DerivingKind) a where
+  deriveKindedType :: UseDeriving gql val -> CatType cat (f kind a) -> SchemaT cat (TypeDefinition cat CONST)
+
+instance (gql a) => DeriveKindedType gql val cat WRAPPER (f a) where
+  deriveKindedType UseDeriving {..} = useDeriveType dirGQL . catMap (Proxy @a)
+
+instance (DecodeScalar a, gql a) => DeriveKindedType gql val cat SCALAR a where
+  deriveKindedType drv = deriveScalarDefinition scalarValidator drv . unliftKind
+
+instance DERIVE_TYPE gql cat a => DeriveKindedType gql val cat TYPE a where
+  deriveKindedType drv = deriveTypeDefinition drv . unliftKind
diff --git a/src/Data/Morpheus/Server/Deriving/Kinded/Value.hs b/src/Data/Morpheus/Server/Deriving/Kinded/Value.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Kinded/Value.hs
@@ -0,0 +1,154 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Kinded.Value
+  ( KindedValue (..),
+  )
+where
+
+import Control.Monad.Except
+  ( MonadError (throwError),
+  )
+import qualified Data.Map as M
+import Data.Morpheus.App.Internal.Resolving
+  ( ResolverState,
+  )
+import Data.Morpheus.Internal.Ext
+  ( GQLResult,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Decode.Rep
+  ( DecodeRep (..),
+  )
+import Data.Morpheus.Server.Deriving.Internal.Decode.Utils
+  ( Context (..),
+    decodeFieldWith,
+    handleEither,
+    repValue,
+    withInputObject,
+    withScalar,
+  )
+import Data.Morpheus.Server.Deriving.Internal.Schema.Directive
+  ( visitEnumName,
+    visitFieldName,
+  )
+import Data.Morpheus.Server.Deriving.Utils.GRep
+  ( GRep,
+    RepContext (..),
+    deriveValue,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Kinded
+  ( CatType (..),
+    inputType,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Proxy
+  ( ContextValue,
+    symbolName,
+    unContextValue,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Use
+  ( UseDeriving (..),
+    UseGQLType (..),
+    UseValue (..),
+  )
+import Data.Morpheus.Server.Types.Kind
+  ( CUSTOM,
+    DerivingKind,
+    SCALAR,
+    TYPE,
+    WRAPPER,
+  )
+import Data.Morpheus.Server.Types.Types (Arg (Arg))
+import Data.Morpheus.Types.GQLScalar
+  ( DecodeScalar (..),
+    EncodeScalar (..),
+  )
+import Data.Morpheus.Types.GQLWrapper
+  ( DecodeWrapper (..),
+    DecodeWrapperConstraint,
+    EncodeWrapperValue (encodeWrapperValue),
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( CONST,
+    IN,
+    ObjectEntry (..),
+    VALID,
+    ValidValue,
+    Value (..),
+  )
+import GHC.Generics
+import GHC.TypeLits (KnownSymbol)
+import Relude
+
+class KindedValue gql args (kind :: DerivingKind) (a :: Type) where
+  encodeKindedValue :: UseDeriving gql args -> ContextValue kind a -> GQLResult (Value CONST)
+  decodeKindedValue :: UseDeriving gql args -> Proxy kind -> ValidValue -> ResolverState a
+
+instance (EncodeScalar a, DecodeScalar a, gql a) => KindedValue gql args SCALAR a where
+  encodeKindedValue _ = pure . Scalar . encodeScalar . unContextValue
+  decodeKindedValue dir _ = withScalar (useTypename (dirGQL dir) (InputType :: CatType IN a)) decodeScalar
+
+instance (DecodeWrapperConstraint f a, DecodeWrapper f, EncodeWrapperValue f, args a) => KindedValue gql args WRAPPER (f a) where
+  encodeKindedValue dir = encodeWrapperValue (useEncodeValue (dirArgs dir)) . unContextValue
+  decodeKindedValue dir _ value =
+    runExceptT (decodeWrapper (useDecodeValue (dirArgs dir)) value)
+      >>= handleEither
+
+instance (gql a, Generic a, DecodeRep gql args (Rep a), GRep gql args (GQLResult (Value CONST)) (Rep a)) => KindedValue gql args TYPE a where
+  encodeKindedValue UseDeriving {..} =
+    repValue
+      . deriveValue
+        ( RepContext
+            { optApply = useEncodeValue dirArgs . runIdentity,
+              optTypeData = useTypeData dirGQL . inputType
+            } ::
+            RepContext gql args Identity (GQLResult (Value CONST))
+        )
+      . unContextValue
+  decodeKindedValue dir _ = fmap to . (`runReaderT` context) . decodeRep dir
+    where
+      context =
+        Context
+          { isVariantRef = False,
+            typeName = useTypename (dirGQL dir) (InputType :: CatType IN a),
+            enumVisitor = visitEnumName dir proxy,
+            fieldVisitor = visitFieldName dir proxy
+          }
+        where
+          proxy = Proxy @a
+
+instance KindedValue gql args CUSTOM (Value CONST) where
+  encodeKindedValue _ = pure . unContextValue
+  decodeKindedValue _ _ = pure . toConstValue
+
+toConstValue :: ValidValue -> Value CONST
+toConstValue Null = Null
+toConstValue (Enum x) = Enum x
+toConstValue (Scalar x) = Scalar x
+toConstValue (List xs) = List (map toConstValue xs)
+toConstValue (Object fields) = Object (fmap toEntry fields)
+  where
+    toEntry :: ObjectEntry VALID -> ObjectEntry CONST
+    toEntry ObjectEntry {..} = ObjectEntry {entryValue = toConstValue entryValue, ..}
+
+instance (KnownSymbol name, args a) => KindedValue gql args CUSTOM (Arg name a) where
+  encodeKindedValue _ _ = throwError "directives cant be tagged arguments"
+  decodeKindedValue UseDeriving {dirArgs} _ value = Arg <$> withInputObject fieldDecoder value
+    where
+      fieldDecoder = decodeFieldWith (useDecodeValue dirArgs) fieldName
+      fieldName = symbolName (Proxy @name)
+
+--  Map
+instance (Ord k, val [(k, v)]) => KindedValue gql val CUSTOM (Map k v) where
+  decodeKindedValue dir _ v = M.fromList <$> (useDecodeValue (dirArgs dir) v :: ResolverState [(k, v)])
+  encodeKindedValue dir = useEncodeValue (dirArgs dir) . M.toList . unContextValue
diff --git a/src/Data/Morpheus/Server/Deriving/Named/Encode.hs b/src/Data/Morpheus/Server/Deriving/Named/Encode.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Named/Encode.hs
+++ /dev/null
@@ -1,56 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Named.Encode
-  ( deriveNamedModel,
-    EncodeNamedConstraints,
-  )
-where
-
-import Data.Morpheus.App.Internal.Resolving
-  ( NamedResolver (..),
-    Resolver,
-    RootResolverValue (..),
-  )
-import Data.Morpheus.Server.Deriving.Named.EncodeType
-  ( EncodeTypeConstraint,
-    deriveResolver,
-  )
-import Data.Morpheus.Server.Deriving.Utils.GTraversable
-  ( traverseTypes,
-  )
-import Data.Morpheus.Server.NamedResolvers (NamedResolverT (..))
-import Data.Morpheus.Server.Resolvers
-  ( NamedResolvers (..),
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( QUERY,
-  )
-import qualified GHC.Exts as HM
-import Relude
-
-type EncodeNamedConstraints e m query mut sub =
-  (EncodeTypeConstraint (Resolver QUERY e m) query)
-
-deriveNamedModel ::
-  forall e m query mut sub.
-  (Monad m, EncodeNamedConstraints e m query mut sub) =>
-  NamedResolvers m e query mut sub ->
-  RootResolverValue e m
-deriveNamedModel NamedResolvers =
-  NamedResolversValue $
-    HM.fromList $
-      map (\x -> (resolverName x, x)) $
-        join $
-          toList $
-            traverseTypes deriveResolver (Proxy @(query (NamedResolverT (Resolver QUERY e m))))
diff --git a/src/Data/Morpheus/Server/Deriving/Named/EncodeType.hs b/src/Data/Morpheus/Server/Deriving/Named/EncodeType.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Named/EncodeType.hs
+++ /dev/null
@@ -1,129 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Named.EncodeType
-  ( deriveResolver,
-    EncodeTypeConstraint,
-    DeriveNamedResolver (..),
-  )
-where
-
-import Data.Morpheus.App.Internal.Resolving
-  ( LiftOperation,
-    NamedResolver (..),
-    NamedResolverResult (..),
-    Resolver,
-    liftResolverState,
-  )
-import Data.Morpheus.Server.Deriving.Decode
-  ( Decode,
-    decode,
-  )
-import Data.Morpheus.Server.Deriving.Named.EncodeValue
-  ( EncodeFieldKind,
-    FieldConstraint,
-    encodeResolverValue,
-    getTypeName,
-  )
-import Data.Morpheus.Server.Deriving.Utils.GTraversable
-import Data.Morpheus.Server.Deriving.Utils.Kinded (KindedProxy (KindedProxy))
-import Data.Morpheus.Server.NamedResolvers (Dependency, NamedResolverT (..), ResolveNamed (..))
-import Data.Morpheus.Server.Types.GQLType
-  ( GQLType,
-    KIND,
-  )
-import Data.Morpheus.Server.Types.Kind
-  ( CUSTOM,
-    DerivingKind,
-    SCALAR,
-    TYPE,
-    WRAPPER,
-  )
-import Data.Morpheus.Types.GQLScalar (EncodeScalar (..))
-import Data.Morpheus.Types.Internal.AST
-  ( ValidValue,
-  )
-import Relude
-
-deriveResolver :: Mappable (DeriveNamedResolver m) [NamedResolver m] KindedProxy
-deriveResolver = Mappable deriveNamedResolver
-
-type EncodeTypeConstraint m a =
-  ( GFmap
-      (ScanConstraint (DeriveNamedResolver m))
-      (KIND (a (NamedResolverT m)))
-      (a (NamedResolverT m)),
-    DeriveNamedResolver
-      m
-      (KIND (a (NamedResolverT m)))
-      (a (NamedResolverT m)),
-    GQLType (a (NamedResolverT m))
-  )
-
-class DeriveNamedResolver (m :: Type -> Type) (k :: DerivingKind) a where
-  deriveNamedResolver :: f k a -> [NamedResolver m]
-
-instance
-  ( GQLType a,
-    DecodeValuesConstraint o e m a,
-    EncodeScalar a
-  ) =>
-  DeriveNamedResolver (Resolver o e m) SCALAR a
-  where
-  deriveNamedResolver _ =
-    [ NamedResolver
-        { resolverName = getTypeName proxy,
-          resolverFun = decodeValues proxy >=> pure . map (maybe NamedNullResolver (NamedScalarResolver . encodeScalar))
-        }
-    ]
-    where
-      proxy = Proxy @a
-
-type DecodeValuesConstraint o e m a =
-  ( LiftOperation o,
-    ResolveNamed (Resolver o e m) a,
-    Monad m,
-    Decode (Dependency a)
-  )
-
-decodeValues :: forall o e m a. DecodeValuesConstraint o e m a => Proxy a -> [ValidValue] -> Resolver o e m [Maybe a]
-decodeValues _ xs = traverse decodeArg xs >>= resolveBatched
-  where
-    decodeArg :: ValidValue -> Resolver o e m (Dependency a)
-    decodeArg = liftResolverState . decode
-
-instance
-  ( GQLType a,
-    DecodeValuesConstraint o e m a,
-    EncodeFieldKind (KIND a) (Resolver o e m) a,
-    FieldConstraint (Resolver o e m) a
-  ) =>
-  DeriveNamedResolver (Resolver o e m) TYPE (a :: Type)
-  where
-  deriveNamedResolver _ =
-    [ NamedResolver
-        { resolverName = getTypeName proxy,
-          resolverFun = decodeValues proxy >=> encodeResolverValue
-        }
-    ]
-    where
-      proxy = Proxy @a
-
-instance DeriveNamedResolver m (KIND a) a => DeriveNamedResolver m CUSTOM (NamedResolverT m a) where
-  deriveNamedResolver _ = deriveNamedResolver (KindedProxy :: KindedProxy (KIND a) a)
-
-instance DeriveNamedResolver m (KIND a) a => DeriveNamedResolver m CUSTOM (input -> a) where
-  deriveNamedResolver _ = deriveNamedResolver (KindedProxy :: KindedProxy (KIND a) a)
-
-instance DeriveNamedResolver m (KIND a) a => DeriveNamedResolver m WRAPPER (f a) where
-  deriveNamedResolver _ = deriveNamedResolver (KindedProxy :: KindedProxy (KIND a) a)
diff --git a/src/Data/Morpheus/Server/Deriving/Named/EncodeValue.hs b/src/Data/Morpheus/Server/Deriving/Named/EncodeValue.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Named/EncodeValue.hs
+++ /dev/null
@@ -1,209 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Named.EncodeValue
-  ( EncodeFieldKind,
-    Encode,
-    getTypeName,
-    encodeResolverValue,
-    FieldConstraint,
-  )
-where
-
-import Control.Monad.Except (MonadError (..))
-import Data.Aeson (ToJSON (..))
-import Data.Morpheus.App.Internal.Resolving
-  ( LiftOperation,
-    NamedResolverRef (..),
-    NamedResolverResult (..),
-    ObjectTypeResolver (..),
-    Resolver,
-    ResolverValue (..),
-    getArguments,
-    liftResolverState,
-    mkList,
-    mkNull,
-  )
-import Data.Morpheus.Server.Deriving.Decode
-  ( Decode,
-    decodeArguments,
-  )
-import Data.Morpheus.Server.Deriving.Encode
-  ( ContextValue (..),
-  )
-import Data.Morpheus.Server.Deriving.Schema.Directive (toFieldRes)
-import Data.Morpheus.Server.Deriving.Utils
-  ( ConsRep (..),
-    DataType (..),
-    FieldRep (..),
-  )
-import Data.Morpheus.Server.Deriving.Utils.DeriveGType
-  ( DeriveValueOptions (..),
-    DeriveWith,
-    deriveValue,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Kinded
-import Data.Morpheus.Server.NamedResolvers
-  ( NamedRef,
-    NamedResolverT (..),
-  )
-import Data.Morpheus.Server.Types.GQLType
-  ( GQLType (__type),
-    KIND,
-    deriveTypename,
-    withDir,
-    __typeData,
-  )
-import Data.Morpheus.Server.Types.Internal
-  ( TypeData (gqlTypeName),
-  )
-import Data.Morpheus.Server.Types.Kind
-  ( CUSTOM,
-    DerivingKind,
-    SCALAR,
-    TYPE,
-    WRAPPER,
-  )
-import Data.Morpheus.Types.GQLScalar
-  ( EncodeScalar (..),
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( GQLError,
-    OUT,
-    TypeCategory (OUT),
-    TypeName,
-    ValidValue,
-    Value (List),
-    internal,
-    replaceValue,
-  )
-import qualified GHC.Exts as HM
-import GHC.Generics
-  ( Generic (..),
-  )
-import Relude hiding (empty)
-
-encodeResolverValue :: (MonadError GQLError m, FieldConstraint m a) => [Maybe a] -> m [NamedResolverResult m]
-encodeResolverValue x = traverse encodeNode x
-  where
-    encodeNode (Just v) = convertNamedNode (Identity x) (getFieldValues v)
-    encodeNode Nothing = pure NamedNullResolver
-
-type FieldConstraint m a =
-  ( GQLType a,
-    Generic a,
-    DeriveWith GQLType (Encode m) (m (ResolverValue m)) (Rep a)
-  )
-
-class Encode (m :: Type -> Type) res where
-  encodeField :: res -> m (ResolverValue m)
-
-instance (EncodeFieldKind (KIND a) m a) => Encode m a where
-  encodeField resolver = encodeFieldKind (ContextValue resolver :: ContextValue (KIND a) a)
-
-class EncodeFieldKind (k :: DerivingKind) (m :: Type -> Type) (a :: Type) where
-  encodeFieldKind :: ContextValue k a -> m (ResolverValue m)
-
-instance (EncodeScalar a, Monad m) => EncodeFieldKind SCALAR m a where
-  encodeFieldKind = pure . ResScalar . encodeScalar . unContextValue
-
-instance (FieldConstraint m a, MonadError GQLError m) => EncodeFieldKind TYPE m a where
-  encodeFieldKind (ContextValue _) = throwError (internal "types are resolved by Refs")
-
-instance (GQLType a, Applicative m, EncodeFieldKind (KIND a) m a) => EncodeFieldKind WRAPPER m [a] where
-  encodeFieldKind = fmap ResList . traverse encodeField . unContextValue
-
-instance (GQLType a, EncodeFieldKind (KIND a) m a, Applicative m) => EncodeFieldKind WRAPPER m (Maybe a) where
-  encodeFieldKind (ContextValue (Just x)) = encodeField x
-  encodeFieldKind (ContextValue Nothing) = pure mkNull
-
-instance
-  ( Monad m,
-    GQLType a,
-    EncodeFieldKind (KIND a) m a,
-    ToJSON (NamedRef a)
-  ) =>
-  EncodeFieldKind CUSTOM m (NamedResolverT m a)
-  where
-  encodeFieldKind = encodeRef . unContextValue
-    where
-      name :: TypeName
-      name = getTypeName (Proxy @a)
-      encodeRef :: Monad m => NamedResolverT m a -> m (ResolverValue m)
-      encodeRef (NamedResolverT ref) = do
-        value <- replaceValue . toJSON <$> ref
-        case value of
-          (List ls) -> pure $ mkList $ map (packRef name) ls
-          _ -> pure $ packRef name value
-
-packRef :: Applicative m => TypeName -> ValidValue -> ResolverValue m
-packRef name v = ResRef $ pure $ NamedResolverRef name [v]
-
-instance
-  ( Decode a,
-    Monad m,
-    Encode (Resolver o e m) b,
-    LiftOperation o
-  ) =>
-  EncodeFieldKind CUSTOM (Resolver o e m) (a -> b)
-  where
-  encodeFieldKind (ContextValue f) =
-    getArguments
-      >>= liftResolverState . decodeArguments
-      >>= encodeField . f
-
-getFieldValues :: forall m a. FieldConstraint m a => a -> DataType (m (ResolverValue m))
-getFieldValues =
-  deriveValue
-    ( DeriveValueOptions
-        { __valueApply = encodeField,
-          __valueTypeName = deriveTypename (OutputType :: CatType OUT a),
-          __valueGetType = __typeData . outputType
-        } ::
-        DeriveValueOptions OUT GQLType (Encode m) (m (ResolverValue m))
-    )
-
-convertNamedNode ::
-  (GQLType a, MonadError GQLError m) =>
-  f a ->
-  DataType (m (ResolverValue m)) ->
-  m (NamedResolverResult m)
-convertNamedNode
-  proxy
-  DataType
-    { tyIsUnion,
-      tyCons = ConsRep {consFields, consName}
-    }
-    | null consFields = pure $ NamedEnumResolver consName
-    | tyIsUnion = deriveUnion consFields
-    | otherwise =
-        pure $
-          NamedObjectResolver
-            ObjectTypeResolver
-              { objectFields = HM.fromList (toFieldRes withDir proxy <$> consFields)
-              }
-
-deriveUnion :: (MonadError GQLError m) => [FieldRep (m (ResolverValue m))] -> m (NamedResolverResult m)
-deriveUnion [FieldRep {..}] =
-  NamedUnionResolver <$> (fieldValue >>= getRef)
-deriveUnion _ = throwError "only union references are supported!"
-
-getRef :: MonadError GQLError m => ResolverValue m -> m NamedResolverRef
-getRef (ResRef x) = x
-getRef _ = throwError "only resolver references are supported!"
-
-getTypeName :: GQLType a => f a -> TypeName
-getTypeName proxy = gqlTypeName $ __type proxy OUT
diff --git a/src/Data/Morpheus/Server/Deriving/Resolvers.hs b/src/Data/Morpheus/Server/Deriving/Resolvers.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Resolvers.hs
@@ -0,0 +1,145 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Resolvers
+  ( deriveResolvers,
+    deriveNamedResolvers,
+    DERIVE_RESOLVERS,
+    DERIVE_NAMED_RESOLVERS,
+  )
+where
+
+import Data.Morpheus.App.Internal.Resolving
+  ( MonadResolver (MonadMutation, MonadQuery, MonadSubscription),
+    NamedResolver (..),
+    Resolver,
+    ResolverValue,
+    RootResolverValue (..),
+  )
+import Data.Morpheus.Internal.Ext (GQLResult)
+import Data.Morpheus.Server.Deriving.Internal.Resolve.Explore
+  ( EXPLORE,
+    useObjectResolvers,
+  )
+import Data.Morpheus.Server.Deriving.Kinded.Channels
+  ( CHANNELS,
+    resolverChannels,
+  )
+import Data.Morpheus.Server.Deriving.Kinded.NamedResolver
+  ( KindedNamedResolver (..),
+  )
+import Data.Morpheus.Server.Deriving.Kinded.NamedResolverFun (KindedNamedFunValue (..))
+import Data.Morpheus.Server.Deriving.Utils.GScan
+  ( ScanRef,
+    Scanner (..),
+    scan,
+  )
+import Data.Morpheus.Server.Deriving.Utils.Proxy
+  ( ContextValue (..),
+  )
+import Data.Morpheus.Server.Deriving.Utils.Use (UseNamedResolver (..))
+import Data.Morpheus.Server.Resolvers
+  ( NamedResolverT (..),
+    NamedResolvers (..),
+    RootResolver (..),
+  )
+import Data.Morpheus.Server.Types.GQLType
+  ( GQLResolver,
+    GQLType (..),
+    GQLValue,
+    ignoreUndefined,
+    kindedProxy,
+    withDir,
+    withRes,
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( QUERY,
+  )
+import Relude
+
+class GQLNamedResolverFun (m :: Type -> Type) a where
+  deriveNamedResFun :: a -> m (ResolverValue m)
+
+class GQLType a => GQLNamedResolver (m :: Type -> Type) a where
+  deriveNamedRes :: f a -> [NamedResolver m]
+  deriveNamedRefs :: f a -> [ScanRef (GQLNamedResolver m)]
+
+instance
+  (GQLType a, KindedNamedResolver GQLNamedResolver GQLNamedResolverFun GQLType GQLValue m (KIND a) a) =>
+  GQLNamedResolver m a
+  where
+  deriveNamedRes = kindedNamedResolver withNamed . kindedProxy
+  deriveNamedRefs = kindedNamedRefs withNamed . kindedProxy
+
+instance KindedNamedFunValue GQLNamedResolverFun GQLType GQLValue (KIND a) m a => GQLNamedResolverFun m a where
+  deriveNamedResFun resolver = kindedNamedFunValue withNamed (ContextValue resolver :: ContextValue (KIND a) a)
+
+withNamed :: UseNamedResolver GQLNamedResolver GQLNamedResolverFun GQLType GQLValue
+withNamed =
+  UseNamedResolver
+    { namedDrv = withDir,
+      useNamedFieldResolver = deriveNamedResFun,
+      useDeriveNamedResolvers = deriveNamedRes,
+      useDeriveNamedRefs = deriveNamedRefs
+    }
+
+deriveNamedResolver :: Scanner (GQLNamedResolver m) (NamedResolver m)
+deriveNamedResolver = Scanner {scannerFun = deriveNamedRes, scannerRefs = deriveNamedRefs}
+
+type ROOT (m :: Type -> Type) a = EXPLORE GQLType GQLResolver m (a m)
+
+type DERIVE_RESOLVERS m query mut sub =
+  ( CHANNELS GQLType GQLValue sub (MonadSubscription m),
+    ROOT (MonadQuery m) query,
+    ROOT (MonadMutation m) mut,
+    ROOT (MonadSubscription m) sub
+  )
+
+type DERIVE_NAMED_RESOLVERS m query =
+  ( GQLType (query (NamedResolverT m)),
+    KindedNamedResolver
+      GQLNamedResolver
+      GQLNamedResolverFun
+      GQLType
+      GQLValue
+      m
+      (KIND (query (NamedResolverT m)))
+      (query (NamedResolverT m))
+  )
+
+deriveResolvers ::
+  (Monad m, DERIVE_RESOLVERS (Resolver QUERY e m) query mut sub) =>
+  RootResolver m e query mut sub ->
+  GQLResult (RootResolverValue e m)
+deriveResolvers RootResolver {..} =
+  pure
+    RootResolverValue
+      { queryResolver = useObjectResolvers withRes queryResolver,
+        mutationResolver = useObjectResolvers withRes mutationResolver,
+        subscriptionResolver = useObjectResolvers withRes subscriptionResolver,
+        channelMap =
+          ignoreUndefined (Identity subscriptionResolver)
+            $> resolverChannels withDir subscriptionResolver
+      }
+
+deriveNamedResolvers ::
+  forall e m query mut sub.
+  (Monad m, DERIVE_NAMED_RESOLVERS (Resolver QUERY e m) query) =>
+  NamedResolvers m e query mut sub ->
+  RootResolverValue e m
+deriveNamedResolvers NamedResolvers =
+  NamedResolversValue $
+    scan
+      resolverName
+      deriveNamedResolver
+      (deriveNamedRefs (Proxy @(query (NamedResolverT (Resolver QUERY e m)))))
diff --git a/src/Data/Morpheus/Server/Deriving/Schema.hs b/src/Data/Morpheus/Server/Deriving/Schema.hs
--- a/src/Data/Morpheus/Server/Deriving/Schema.hs
+++ b/src/Data/Morpheus/Server/Deriving/Schema.hs
@@ -14,107 +14,47 @@
 
 module Data.Morpheus.Server.Deriving.Schema
   ( compileTimeSchemaValidation,
-    DeriveType,
     deriveSchema,
-    SchemaConstraints,
-    SchemaT,
+    SCHEMA,
   )
 where
 
-import Data.Morpheus.App.Internal.Resolving
-  ( Resolver,
-  )
 import Data.Morpheus.Core (defaultConfig, validateSchema)
-import Data.Morpheus.Internal.Ext
-import Data.Morpheus.Server.Deriving.Schema.DeriveKinded
-  ( DERIVE_TYPE,
-    toFieldContent,
-  )
-import Data.Morpheus.Server.Deriving.Schema.Internal
+import Data.Morpheus.Internal.Ext (GQLResult)
+import Data.Morpheus.Server.Deriving.Internal.Schema.Internal
   ( fromSchema,
   )
-import Data.Morpheus.Server.Deriving.Schema.Object
-  ( asObjectType,
-  )
-import Data.Morpheus.Server.Deriving.Schema.TypeContent
-import Data.Morpheus.Server.Deriving.Utils.Kinded
-  ( CatContext (OutputContext),
-    outputType,
+import Data.Morpheus.Server.Deriving.Internal.Schema.Type
+  ( useDeriveObject,
   )
 import Data.Morpheus.Server.Types.GQLType
-  ( DeriveType,
-    GQLType (..),
-    withDeriveType,
-    withDir,
+  ( GQLType (..),
+    IgnoredResolver,
+    ignoreUndefined,
     withGQL,
-    __isEmptyType,
   )
 import Data.Morpheus.Server.Types.SchemaT
-  ( SchemaT,
-    toSchema,
+  ( toSchema,
   )
 import Data.Morpheus.Types.Internal.AST
   ( CONST,
-    MUTATION,
-    OBJECT,
-    OUT,
-    QUERY,
-    SUBSCRIPTION,
     Schema (..),
-    TypeDefinition (..),
   )
 import Language.Haskell.TH (Exp, Q)
 import Relude
 
-type SchemaConstraints event (m :: Type -> Type) query mutation subscription =
-  ( DERIVE_TYPE GQLType DeriveType OUT (query (Resolver QUERY event m)),
-    DERIVE_TYPE GQLType DeriveType OUT (mutation (Resolver MUTATION event m)),
-    DERIVE_TYPE GQLType DeriveType OUT (subscription (Resolver SUBSCRIPTION event m))
-  )
+type SCHEMA qu mu su = (GQLType (qu IgnoredResolver), GQLType (mu IgnoredResolver), GQLType (su IgnoredResolver))
 
 -- | normal morpheus server validates schema at runtime (after the schema derivation).
 --   this method allows you to validate it at compile time.
-compileTimeSchemaValidation ::
-  (SchemaConstraints event m qu mu su) =>
-  proxy (root m event qu mu su) ->
-  Q Exp
-compileTimeSchemaValidation =
-  fromSchema . (deriveSchema >=> validateSchema True defaultConfig)
-
-deriveSchema ::
-  forall
-    root
-    proxy
-    m
-    e
-    query
-    mut
-    subs.
-  ( SchemaConstraints e m query mut subs
-  ) =>
-  proxy (root m e query mut subs) ->
-  GQLResult (Schema CONST)
-deriveSchema _ = toSchema schemaT
-  where
-    schemaT ::
-      SchemaT
-        OUT
-        ( TypeDefinition OBJECT CONST,
-          Maybe (TypeDefinition OBJECT CONST),
-          Maybe (TypeDefinition OBJECT CONST)
-        )
-    schemaT =
-      (,,)
-        <$> deriveRoot (Proxy @(query (Resolver QUERY e m)))
-        <*> deriveMaybeRoot (Proxy @(mut (Resolver MUTATION e m)))
-        <*> deriveMaybeRoot (Proxy @(subs (Resolver SUBSCRIPTION e m)))
-
---
-
-deriveMaybeRoot :: DERIVE_TYPE GQLType DeriveType OUT a => f a -> SchemaT OUT (Maybe (TypeDefinition OBJECT CONST))
-deriveMaybeRoot proxy
-  | __isEmptyType proxy = pure Nothing
-  | otherwise = Just <$> asObjectType withGQL (deriveFieldsWith withDir (toFieldContent OutputContext withDir withDeriveType) . outputType) proxy
+compileTimeSchemaValidation :: (SCHEMA qu mu su) => proxy (root m event qu mu su) -> Q Exp
+compileTimeSchemaValidation = fromSchema . (deriveSchema >=> validateSchema True defaultConfig)
 
-deriveRoot :: DERIVE_TYPE GQLType DeriveType OUT a => f a -> SchemaT OUT (TypeDefinition OBJECT CONST)
-deriveRoot = asObjectType withGQL (deriveFieldsWith withDir (toFieldContent OutputContext withDir withDeriveType) . outputType)
+deriveSchema :: forall root f m e qu mu su. SCHEMA qu mu su => f (root m e qu mu su) -> GQLResult (Schema CONST)
+deriveSchema _ =
+  toSchema
+    ( (,,)
+        <$> useDeriveObject withGQL (Proxy @(qu IgnoredResolver))
+        <*> traverse (useDeriveObject withGQL) (ignoreUndefined (Proxy @(mu IgnoredResolver)))
+        <*> traverse (useDeriveObject withGQL) (ignoreUndefined (Proxy @(su IgnoredResolver)))
+    )
diff --git a/src/Data/Morpheus/Server/Deriving/Schema/DeriveKinded.hs b/src/Data/Morpheus/Server/Deriving/Schema/DeriveKinded.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Schema/DeriveKinded.hs
+++ /dev/null
@@ -1,176 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Schema.DeriveKinded
-  ( DeriveKindedType (..),
-    DeriveArgs (..),
-    toFieldContent,
-    DERIVE_TYPE,
-  )
-where
-
-import Control.Monad.Except (throwError)
-import Data.Morpheus.App.Internal.Resolving
-  ( Resolver,
-  )
-import Data.Morpheus.Internal.Ext
-import Data.Morpheus.Internal.Utils (singleton)
-import Data.Morpheus.Server.Deriving.Schema.Internal
-  ( CatType,
-    TyContentM,
-  )
-import Data.Morpheus.Server.Deriving.Schema.TypeContent
-import Data.Morpheus.Server.Deriving.Utils
-  ( DeriveTypeOptions (..),
-    DeriveWith,
-    symbolName,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Kinded
-  ( CatContext (..),
-    CatType (..),
-    addContext,
-    catMap,
-    getCat,
-    getCatContext,
-    inputType,
-    mkScalar,
-    outputType,
-    unliftKind,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Use
-import Data.Morpheus.Server.Types.Internal (TypeData (..))
-import Data.Morpheus.Server.Types.Kind
-  ( CUSTOM,
-    DerivingKind,
-    SCALAR,
-    TYPE,
-    WRAPPER,
-  )
-import Data.Morpheus.Server.Types.SchemaT
-  ( SchemaT,
-    extendImplements,
-  )
-import Data.Morpheus.Server.Types.Types
-  ( Arg (..),
-    TypeGuard,
-  )
-import Data.Morpheus.Types.GQLScalar
-  ( DecodeScalar (..),
-    scalarValidator,
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( ArgumentsDefinition,
-    CONST,
-    FieldContent (..),
-    IN,
-    OUT,
-    ScalarDefinition (..),
-    TRUE,
-    TypeCategory (IN),
-    TypeContent (..),
-    TypeName,
-    TypeRef (..),
-    UnionMember (memberName),
-    Value,
-    fieldsToArguments,
-    mkField,
-  )
-import GHC.Generics
-import GHC.TypeLits
-import Relude
-
-type DERIVE_TYPE gql derive k a = (gql a, DeriveWith gql (derive k) (TyContentM k) (Rep a))
-
-toFieldContent :: CatContext kind -> UseDirective gql dir -> UseDeriveType derive -> DeriveTypeOptions kind gql (derive kind) (TyContentM kind)
-toFieldContent catCtx UseDirective {..} ops =
-  DeriveTypeOptions
-    { __typeGetType = \x -> __useTypeData dirGQL x (getCat catCtx),
-      __typeApply = \proxy -> useDeriveType ops (addContext catCtx proxy) *> useDeriveContent ops (addContext catCtx proxy)
-    }
-
--- | DeriveType With specific Kind: 'kind': object, scalar, enum ...
-class DeriveKindedType gql derive dir (cat :: TypeCategory) (kind :: DerivingKind) a where
-  deriveKindedType :: UseDirective gql dir -> UseDeriveType derive -> CatType cat (f kind a) -> SchemaT cat ()
-  deriveKindedContent :: UseDirective gql dir -> UseDeriveType derive -> CatType cat (f kind a) -> TyContentM cat
-  deriveKindedContent _ _ _ = pure Nothing
-
-instance (derive cat a) => DeriveKindedType gql derive dir cat WRAPPER (f a) where
-  deriveKindedType _ UseDeriveType {..} = useDeriveType . catMap (Proxy @a)
-
-instance (DecodeScalar a, gql a) => DeriveKindedType gql derive dir cat SCALAR a where
-  deriveKindedType dirs _ proxy = insertTypeContent dirs (pure . mkScalar proxy . scalarValidator) (unliftKind proxy)
-
-instance DERIVE_TYPE gql derive cat a => DeriveKindedType gql derive dir cat TYPE a where
-  deriveKindedType dirs ops proxy = insertTypeContent dirs (deriveTypeContentWith dirs (toFieldContent (getCatContext proxy) dirs ops)) (unliftKind proxy)
-
-instance (derive cat a) => DeriveKindedType gql derive dir cat CUSTOM (Resolver o e m a) where
-  deriveKindedType _ UseDeriveType {..} = useDeriveType . catMap (Proxy @a)
-
-instance (gql (Value CONST)) => DeriveKindedType gql derive dir cat CUSTOM (Value CONST) where
-  deriveKindedType dirs _ proxy = insertTypeContent dirs (const $ pure $ mkScalar proxy $ ScalarDefinition pure) (unliftKind proxy)
-
-instance (derive cat [(k, v)]) => DeriveKindedType gql derive dir cat CUSTOM (Map k v) where
-  deriveKindedType _ UseDeriveType {..} = useDeriveType . catMap (Proxy @[(k, v)])
-
-instance
-  ( DERIVE_TYPE gql derive OUT interface,
-    DERIVE_TYPE gql derive OUT union
-  ) =>
-  DeriveKindedType gql derive dir OUT CUSTOM (TypeGuard interface union)
-  where
-  deriveKindedType dir ops OutputType = do
-    insertTypeContent dir (fmap DataInterface . deriveFieldsWith dir (toFieldContent OutputContext dir ops) . outputType) interfaceProxy
-    content <- deriveTypeContentWith dir (toFieldContent OutputContext dir ops) (OutputType :: CatType OUT union)
-    unionNames <- getUnionNames content
-    extendImplements interfaceName unionNames
-    where
-      interfaceName :: TypeName
-      interfaceName = useTypename (dirGQL dir) interfaceProxy
-      interfaceProxy :: CatType OUT interface
-      interfaceProxy = OutputType
-      unionProxy :: CatType OUT union
-      unionProxy = OutputType
-      getUnionNames :: TypeContent TRUE OUT CONST -> SchemaT OUT [TypeName]
-      getUnionNames DataUnion {unionMembers} = pure $ toList $ memberName <$> unionMembers
-      getUnionNames DataObject {} = pure [useTypename (dirGQL dir) unionProxy]
-      getUnionNames _ = throwError "guarded type must be an union or object"
-
-instance (derive OUT b, dir a) => DeriveKindedType gql derive dir OUT CUSTOM (a -> b) where
-  deriveKindedContent dir UseDeriveType {..} OutputType = do
-    a <- useDeriveArguments (dirArgs dir) (Proxy @a)
-    b <- useDeriveContent (OutputType :: CatType OUT b)
-    case b of
-      Just (FieldArgs x) -> Just . FieldArgs <$> (a <:> x)
-      Nothing -> pure $ Just (FieldArgs a)
-  deriveKindedType _ UseDeriveType {..} OutputType = useDeriveType (outputType $ Proxy @b)
-
-class DeriveArgs gql derive (k :: DerivingKind) a where
-  deriveArgs :: UseDirective gql dir -> UseDeriveType derive -> f k a -> SchemaT IN (ArgumentsDefinition CONST)
-
-instance (DERIVE_TYPE gql derive IN a) => DeriveArgs gql derive TYPE a where
-  deriveArgs dir ops = fmap fieldsToArguments . deriveFieldsWith dir (toFieldContent InputContext dir ops) . inputType
-
-instance (KnownSymbol name, derive IN a, gql a) => DeriveArgs gql derive CUSTOM (Arg name a) where
-  deriveArgs dir ops _ = do
-    useDeriveType ops proxy
-    pure $ fieldsToArguments $ singleton argName $ mkField Nothing argName argTypeRef
-    where
-      proxy :: CatType IN a
-      proxy = InputType
-      argName = symbolName (Proxy @name)
-      argTypeRef = TypeRef {typeConName = gqlTypeName, typeWrappers = gqlWrappers}
-      TypeData {gqlTypeName, gqlWrappers} = __useTypeData (dirGQL dir) proxy IN
diff --git a/src/Data/Morpheus/Server/Deriving/Schema/Directive.hs b/src/Data/Morpheus/Server/Deriving/Schema/Directive.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Schema/Directive.hs
+++ /dev/null
@@ -1,204 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Schema.Directive
-  ( deriveFieldDirectives,
-    deriveTypeDirectives,
-    deriveEnumDirectives,
-    visitEnumValueDescription,
-    visitFieldDescription,
-    visitTypeDescription,
-    visitFieldDefaultValue,
-    visitFieldContent,
-    visitEnumName,
-    visitFieldName,
-    toFieldRes,
-    UseDirective (..),
-  )
-where
-
-import qualified Data.HashMap.Lazy as HM
-import Data.Morpheus.Internal.Ext (unsafeFromList)
-import Data.Morpheus.Internal.Utils (Empty (..), fromElems)
-import Data.Morpheus.Server.Deriving.Utils.Kinded
-  ( CatType (..),
-    KindedProxy (..),
-  )
-import Data.Morpheus.Server.Deriving.Utils.Types (FieldRep (..))
-import Data.Morpheus.Server.Deriving.Utils.Use
-  ( UseArguments (..),
-    UseDirective (..),
-    UseGQLType (..),
-  )
-import Data.Morpheus.Server.Types.Directives
-  ( GDirectiveUsage (..),
-    GDirectiveUsages (..),
-    GQLDirective (..),
-    applyEnumDescription,
-    applyEnumName,
-    applyFieldDefaultValue,
-    applyFieldDescription,
-    applyFieldName,
-    applyTypeDescription,
-    applyTypeEnumNames,
-    applyTypeFieldNames,
-    getLocations,
-  )
-import Data.Morpheus.Server.Types.SchemaT
-  ( SchemaT,
-    insertDirectiveDefinition,
-    outToAny,
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( Argument (..),
-    CONST,
-    Description,
-    Directive (..),
-    DirectiveDefinition (..),
-    Directives,
-    FieldContent (..),
-    FieldName,
-    IN,
-    Position (Position),
-    TRUE,
-    TypeCategory (..),
-    TypeName,
-    Value,
-  )
-import GHC.Generics ()
-import GHC.TypeLits ()
-import Relude hiding (empty)
-
-deriveDirectiveDefinition ::
-  forall a b kind gql args.
-  (gql a, GQLDirective a, args a) =>
-  UseDirective gql args ->
-  a ->
-  b ->
-  SchemaT kind (DirectiveDefinition CONST)
-deriveDirectiveDefinition options _ _ = do
-  directiveDefinitionArgs <- outToAny (useDeriveArguments (dirArgs options) (Proxy @a))
-  pure
-    ( DirectiveDefinition
-        { directiveDefinitionName = deriveDirectiveName (dirGQL options) proxy,
-          directiveDefinitionDescription = visitTypeDescription options proxy Nothing,
-          directiveDefinitionArgs,
-          directiveDefinitionLocations = getLocations proxy
-        }
-    )
-  where
-    proxy = Proxy @a
-
-deriveDirectiveUsages :: UseDirective gql args -> [GDirectiveUsage gql args] -> SchemaT kind (Directives CONST)
-deriveDirectiveUsages options = fmap unsafeFromList . traverse (toDirectiveTuple options)
-
-toDirectiveTuple ::
-  UseDirective gql args ->
-  GDirectiveUsage gql args ->
-  SchemaT kind (FieldName, Directive CONST)
-toDirectiveTuple options (GDirectiveUsage x) = do
-  insertDirective options (deriveDirectiveDefinition options x) x
-  let directiveName = deriveDirectiveName (dirGQL options) (Identity x)
-  args <- toList <$> useEncodeArguments (dirArgs options) x
-  directiveArgs <- fromElems (map editArg args)
-  pure
-    ( directiveName,
-      Directive
-        { directivePosition = Position 0 0,
-          directiveName,
-          directiveArgs
-        }
-    )
-  where
-    editArg Argument {..} = Argument {argumentName = applyGQLFieldOptions options (Identity x) argumentName, ..}
-
-insertDirective ::
-  forall gql args a k.
-  gql a =>
-  UseDirective gql args ->
-  (KindedProxy IN a -> SchemaT k (DirectiveDefinition CONST)) ->
-  a ->
-  SchemaT k ()
-insertDirective ops f _ = insertDirectiveDefinition (__useFingerprint (dirGQL ops) IN (Proxy :: Proxy a)) f proxy
-  where
-    proxy = KindedProxy :: KindedProxy IN a
-
-getDirHM :: (Ord k, Hashable k, Empty a) => k -> HashMap k a -> a
-getDirHM name xs = fromMaybe empty $ name `HM.lookup` xs
-
-isIncluded :: GDirectiveUsage gql args -> Bool
-isIncluded (GDirectiveUsage x) = not $ excludeFromSchema (Identity x)
-
-getEnumDirectiveUsages :: gql a => UseDirective gql args -> f a -> TypeName -> [GDirectiveUsage gql args]
-getEnumDirectiveUsages UseDirective {..} proxy name = getDirHM name $ enumValueDirectives $ __directives proxy
-
-getFieldDirectiveUsages :: gql a => UseDirective gql args -> FieldName -> f a -> [GDirectiveUsage gql args]
-getFieldDirectiveUsages UseDirective {..} name proxy = getDirHM name $ fieldDirectives $ __directives proxy
-
--- derive directives
-deriveEnumDirectives :: gql a => UseDirective gql args -> f a -> TypeName -> SchemaT k (Directives CONST)
-deriveEnumDirectives options proxy name = deriveDirectiveUsages options $ filter isIncluded $ getEnumDirectiveUsages options proxy name
-
-deriveFieldDirectives :: gql a => UseDirective gql args -> f a -> FieldName -> SchemaT kind (Directives CONST)
-deriveFieldDirectives options proxy name = deriveDirectiveUsages options $ filter isIncluded $ getFieldDirectiveUsages options name proxy
-
-deriveTypeDirectives :: gql a => UseDirective gql args -> f a -> SchemaT kind (Directives CONST)
-deriveTypeDirectives options proxy = deriveDirectiveUsages options $ filter isIncluded $ typeDirectives $ __directives options proxy
-
--- visit
-
-visitEnumValueDescription :: gql a => UseDirective gql args -> f a -> TypeName -> Maybe Description -> Maybe Description
-visitEnumValueDescription options proxy name desc = foldr applyEnumDescription desc (getEnumDirectiveUsages options proxy name)
-
-visitEnumName :: gql a => UseDirective gql args -> f a -> TypeName -> TypeName
-visitEnumName options proxy name = foldr applyEnumName (withTypeDirectives name) (getEnumDirectiveUsages options proxy name)
-  where
-    withTypeDirectives dirName = foldr applyTypeEnumNames dirName (typeDirectives $ __directives options proxy)
-
-visitFieldDescription :: gql a => UseDirective gql args -> f a -> FieldName -> Maybe Description -> Maybe Description
-visitFieldDescription options proxy name desc = foldr applyFieldDescription desc (getFieldDirectiveUsages options name proxy)
-
-visitFieldDefaultValue :: gql a => UseDirective gql args -> f a -> FieldName -> Maybe (Value CONST) -> Maybe (Value CONST)
-visitFieldDefaultValue options proxy name desc = foldr applyFieldDefaultValue desc (getFieldDirectiveUsages options name proxy)
-
-visitFieldContent ::
-  gql a =>
-  UseDirective gql args ->
-  CatType kind a ->
-  FieldName ->
-  Maybe (FieldContent TRUE kind CONST) ->
-  Maybe (FieldContent TRUE kind CONST)
-visitFieldContent options proxy@InputType name x =
-  DefaultInputValue
-    <$> visitFieldDefaultValue options proxy name (defaultInputValue <$> x)
-visitFieldContent _ OutputType _ x = x
-
-applyGQLFieldOptions :: gql a => UseDirective gql args -> f a -> FieldName -> FieldName
-applyGQLFieldOptions options proxy = withTypeDirectives
-  where
-    withTypeDirectives name = foldr applyTypeFieldNames name (typeDirectives $ __directives options proxy)
-
-visitFieldName :: gql a => UseDirective gql args -> f a -> FieldName -> FieldName
-visitFieldName options proxy name = foldr applyFieldName (applyGQLFieldOptions options proxy name) (getFieldDirectiveUsages options name proxy)
-
-visitTypeDescription :: gql a => UseDirective gql args -> f a -> Maybe Description -> Maybe Description
-visitTypeDescription options proxy desc = foldr applyTypeDescription desc (typeDirectives $ __directives options proxy)
-
-toFieldRes :: gql a => UseDirective gql args -> f a -> FieldRep v -> (FieldName, v)
-toFieldRes options proxy FieldRep {..} = (visitFieldName options proxy fieldSelector, fieldValue)
-
-deriveDirectiveName :: gql a => UseGQLType gql -> f a -> FieldName
-deriveDirectiveName options proxy = coerce $ __useTypename options IN proxy
diff --git a/src/Data/Morpheus/Server/Deriving/Schema/Enum.hs b/src/Data/Morpheus/Server/Deriving/Schema/Enum.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Schema/Enum.hs
+++ /dev/null
@@ -1,56 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE RecordWildCards #-}
-
-module Data.Morpheus.Server.Deriving.Schema.Enum
-  ( buildEnumTypeContent,
-    defineEnumUnit,
-  )
-where
-
-import Data.Morpheus.Server.Deriving.Schema.Directive
-  ( UseDirective,
-    deriveEnumDirectives,
-    visitEnumName,
-    visitEnumValueDescription,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Kinded
-  ( CatType (..),
-  )
-import Data.Morpheus.Server.Types.SchemaT
-  ( SchemaT,
-    insertType,
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( CONST,
-    DataEnumValue (..),
-    LEAF,
-    TRUE,
-    TypeContent (..),
-    TypeDefinition,
-    TypeName,
-    mkEnumContent,
-    mkType,
-    unitTypeName,
-  )
-
-buildEnumTypeContent :: gql a => UseDirective gql args -> CatType kind a -> [TypeName] -> SchemaT k (TypeContent TRUE kind CONST)
-buildEnumTypeContent options p@InputType enumCons = DataEnum <$> traverse (mkEnumValue options p) enumCons
-buildEnumTypeContent options p@OutputType enumCons = DataEnum <$> traverse (mkEnumValue options p) enumCons
-
-mkEnumValue :: gql a => UseDirective gql args -> f a -> TypeName -> SchemaT k (DataEnumValue CONST)
-mkEnumValue options proxy enumName = do
-  enumDirectives <- deriveEnumDirectives options proxy enumName
-  pure
-    DataEnumValue
-      { enumName = visitEnumName options proxy enumName,
-        enumDescription = visitEnumValueDescription options proxy enumName Nothing,
-        ..
-      }
-
-defineEnumUnit :: SchemaT cat ()
-defineEnumUnit =
-  insertType
-    ( mkType unitTypeName (mkEnumContent [unitTypeName]) ::
-        TypeDefinition LEAF CONST
-    )
diff --git a/src/Data/Morpheus/Server/Deriving/Schema/Internal.hs b/src/Data/Morpheus/Server/Deriving/Schema/Internal.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Schema/Internal.hs
+++ /dev/null
@@ -1,57 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE DefaultSignatures #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE TemplateHaskellQuotes #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Schema.Internal
-  ( CatType (..),
-    TyContentM,
-    TyContent,
-    fromSchema,
-  )
-where
-
--- MORPHEUS
-
-import Data.Morpheus.Internal.Ext
-  ( GQLResult,
-    Result (Failure, Success, errors),
-  )
-import Data.Morpheus.Server.Deriving.Utils.Kinded
-  ( CatType (..),
-  )
-import Data.Morpheus.Server.Types.SchemaT
-  ( SchemaT,
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( CONST,
-    FieldContent (..),
-    Schema (..),
-    TRUE,
-    VALID,
-  )
-import Language.Haskell.TH (Exp, Q)
-import Relude hiding (empty)
-
-fromSchema :: GQLResult (Schema VALID) -> Q Exp
-fromSchema Success {} = [|()|]
-fromSchema Failure {errors} = fail (show errors)
-
-type TyContentM kind = SchemaT kind (TyContent kind)
-
-type TyContent kind = Maybe (FieldContent TRUE kind CONST)
diff --git a/src/Data/Morpheus/Server/Deriving/Schema/Object.hs b/src/Data/Morpheus/Server/Deriving/Schema/Object.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Schema/Object.hs
+++ /dev/null
@@ -1,137 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE KindSignatures #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE RecordWildCards #-}
-
-module Data.Morpheus.Server.Deriving.Schema.Object
-  ( asObjectType,
-    withObject,
-    buildObjectTypeContent,
-    defineObjectType,
-  )
-where
-
-import Control.Monad.Except (throwError)
-import Data.Morpheus.Internal.Utils
-  ( empty,
-    singleton,
-  )
-import Data.Morpheus.Server.Deriving.Schema.Directive
-  ( UseDirective,
-    deriveFieldDirectives,
-    visitFieldContent,
-    visitFieldDescription,
-    visitFieldName,
-  )
-import Data.Morpheus.Server.Deriving.Schema.Enum (defineEnumUnit)
-import Data.Morpheus.Server.Deriving.Utils
-  ( ConsRep (..),
-    FieldRep (..),
-  )
-import Data.Morpheus.Server.Deriving.Utils.Kinded
-  ( CatType (..),
-    outputType,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Use (UseGQLType, useTypename)
-import Data.Morpheus.Server.Types.SchemaT
-  ( SchemaT,
-    insertType,
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( CONST,
-    FieldContent (..),
-    FieldDefinition (..),
-    FieldsDefinition,
-    OBJECT,
-    OUT,
-    TRUE,
-    TypeContent (..),
-    TypeDefinition,
-    mkField,
-    mkType,
-    mkTypeRef,
-    msg,
-    unitFieldName,
-    unitTypeName,
-    unsafeFromFields,
-  )
-import Relude hiding (empty)
-
-defineObjectType ::
-  CatType kind a ->
-  ConsRep (Maybe (FieldContent TRUE kind CONST)) ->
-  SchemaT cat ()
-defineObjectType proxy ConsRep {consName, consFields} = insertType . mkType consName . mkObjectTypeContent proxy =<< fields
-  where
-    fields
-      | null consFields = defineEnumUnit $> singleton unitFieldName mkFieldUnit
-      | otherwise = pure $ unsafeFromFields $ map repToFieldDefinition consFields
-
-mkFieldUnit :: FieldDefinition cat s
-mkFieldUnit = mkField Nothing unitFieldName (mkTypeRef unitTypeName)
-
-buildObjectTypeContent ::
-  gql a =>
-  UseDirective gql args ->
-  CatType cat a ->
-  [FieldRep (Maybe (FieldContent TRUE cat CONST))] ->
-  SchemaT k (TypeContent TRUE cat CONST)
-buildObjectTypeContent options scope consFields = do
-  xs <- traverse (setGQLTypeProps options scope . repToFieldDefinition) consFields
-  pure $ mkObjectTypeContent scope $ unsafeFromFields xs
-
-repToFieldDefinition ::
-  FieldRep (Maybe (FieldContent TRUE kind CONST)) ->
-  FieldDefinition kind CONST
-repToFieldDefinition
-  FieldRep
-    { fieldSelector = fieldName,
-      fieldTypeRef = fieldType,
-      fieldValue
-    } =
-    FieldDefinition
-      { fieldDescription = mempty,
-        fieldDirectives = empty,
-        fieldContent = fieldValue,
-        ..
-      }
-
-asObjectType ::
-  (gql a) =>
-  UseGQLType gql ->
-  (f a -> SchemaT kind (FieldsDefinition OUT CONST)) ->
-  f a ->
-  SchemaT kind (TypeDefinition OBJECT CONST)
-asObjectType gql f proxy =
-  mkType
-    (useTypename gql (outputType proxy))
-    . DataObject []
-    <$> f proxy
-
-withObject :: (gql a) => UseGQLType gql -> CatType c a -> TypeContent TRUE any s -> SchemaT c (FieldsDefinition c s)
-withObject _ InputType DataInputObject {inputObjectFields} = pure inputObjectFields
-withObject _ OutputType DataObject {objectFields} = pure objectFields
-withObject gql x _ = failureOnlyObject gql x
-
-failureOnlyObject :: (gql a) => UseGQLType gql -> CatType c a -> SchemaT c b
-failureOnlyObject gql proxy = throwError $ msg (useTypename gql proxy) <> " should have only one nonempty constructor"
-
-mkObjectTypeContent :: CatType kind a -> FieldsDefinition kind CONST -> TypeContent TRUE kind CONST
-mkObjectTypeContent InputType = DataInputObject
-mkObjectTypeContent OutputType = DataObject []
-
-setGQLTypeProps :: gql a => UseDirective gql args -> CatType kind a -> FieldDefinition kind CONST -> SchemaT k (FieldDefinition kind CONST)
-setGQLTypeProps options proxy FieldDefinition {..} = do
-  dirs <- deriveFieldDirectives options proxy fieldName
-  pure
-    FieldDefinition
-      { fieldName = visitFieldName options proxy fieldName,
-        fieldDescription = visitFieldDescription options proxy fieldName Nothing,
-        fieldContent = visitFieldContent options proxy fieldName fieldContent,
-        fieldDirectives = dirs,
-        ..
-      }
diff --git a/src/Data/Morpheus/Server/Deriving/Schema/TypeContent.hs b/src/Data/Morpheus/Server/Deriving/Schema/TypeContent.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Schema/TypeContent.hs
+++ /dev/null
@@ -1,104 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Data.Morpheus.Server.Deriving.Schema.TypeContent
-  ( buildTypeContent,
-    insertTypeContent,
-    deriveTypeContentWith,
-    deriveFieldsWith,
-  )
-where
-
-import Data.Morpheus.Server.Deriving.Schema.Directive (UseDirective (..), deriveTypeDirectives, visitTypeDescription)
-import Data.Morpheus.Server.Deriving.Schema.Enum
-  ( buildEnumTypeContent,
-  )
-import Data.Morpheus.Server.Deriving.Schema.Internal
-  ( CatType,
-    TyContent,
-  )
-import Data.Morpheus.Server.Deriving.Schema.Object
-  ( buildObjectTypeContent,
-    withObject,
-  )
-import Data.Morpheus.Server.Deriving.Schema.Union (buildUnionTypeContent)
-import Data.Morpheus.Server.Deriving.Utils
-  ( ConsRep (..),
-    DeriveTypeOptions,
-    DeriveWith,
-    deriveTypeWith,
-    isEmptyConstraint,
-    unpackMonad,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Kinded (typeCat)
-import Data.Morpheus.Server.Deriving.Utils.Use
-  ( UseGQLType (..),
-  )
-import Data.Morpheus.Server.Types.SchemaT
-  ( SchemaT,
-    updateSchema,
-  )
-import Data.Morpheus.Types.Internal.AST
-import GHC.Generics (Rep)
-
-buildTypeContent ::
-  (gql a) =>
-  UseDirective gql args ->
-  CatType kind a ->
-  [ConsRep (TyContent kind)] ->
-  SchemaT kind (TypeContent TRUE kind CONST)
-buildTypeContent options scope cons | all isEmptyConstraint cons = buildEnumTypeContent options scope (consName <$> cons)
-buildTypeContent options scope [ConsRep {consFields}] = buildObjectTypeContent options scope consFields
-buildTypeContent options scope cons = buildUnionTypeContent (dirGQL options) scope cons
-
-insertTypeContent ::
-  forall k gql args a.
-  (gql a) =>
-  UseDirective gql args ->
-  (CatType k a -> SchemaT k (TypeContent TRUE k CONST)) ->
-  CatType k a ->
-  SchemaT k ()
-insertTypeContent options@UseDirective {dirGQL = UseGQLType {..}} f proxy =
-  updateSchema
-    (__useFingerprint category proxy)
-    deriveD
-    proxy
-  where
-    category = typeCat proxy
-    deriveD x = do
-      content <- f x
-      dirs <- deriveTypeDirectives options proxy
-      pure $
-        TypeDefinition
-          (visitTypeDescription options proxy Nothing)
-          (__useTypename category proxy)
-          dirs
-          content
-
-deriveTypeContentWith ::
-  ( DeriveWith gql derive (SchemaT kind (TyContent kind)) (Rep a),
-    gql a
-  ) =>
-  UseDirective gql args ->
-  DeriveTypeOptions kind gql derive (SchemaT kind (TyContent kind)) ->
-  CatType kind a ->
-  SchemaT kind (TypeContent TRUE kind CONST)
-deriveTypeContentWith options x kindedProxy =
-  unpackMonad
-    ( deriveTypeWith x kindedProxy
-    )
-    >>= buildTypeContent options kindedProxy
-
-deriveFieldsWith ::
-  ( gql a,
-    DeriveWith gql derive (SchemaT cat (TyContent cat)) (Rep a)
-  ) =>
-  UseDirective gql args ->
-  DeriveTypeOptions cat gql derive (SchemaT cat (TyContent cat)) ->
-  CatType cat a ->
-  SchemaT cat (FieldsDefinition cat CONST)
-deriveFieldsWith dirs cont kindedType = deriveTypeContentWith dirs cont kindedType >>= withObject (dirGQL dirs) kindedType
diff --git a/src/Data/Morpheus/Server/Deriving/Schema/Union.hs b/src/Data/Morpheus/Server/Deriving/Schema/Union.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Schema/Union.hs
+++ /dev/null
@@ -1,81 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE GADTs #-}
-
-module Data.Morpheus.Server.Deriving.Schema.Union
-  ( buildUnionTypeContent,
-  )
-where
-
-import Data.List (partition)
-import Data.Morpheus.Internal.Utils (fromElems)
-import Data.Morpheus.Server.Deriving.Schema.Enum
-  ( defineEnumUnit,
-  )
-import Data.Morpheus.Server.Deriving.Schema.Object
-  ( defineObjectType,
-  )
-import Data.Morpheus.Server.Deriving.Utils
-  ( ConsRep (..),
-    fieldTypeName,
-    isEmptyConstraint,
-    isUnionRef,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Kinded
-  ( CatType (..),
-  )
-import Data.Morpheus.Server.Deriving.Utils.Use (UseGQLType (..), useTypename)
-import Data.Morpheus.Server.Types.SchemaT
-  ( SchemaT,
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( CONST,
-    FieldContent (..),
-    IN,
-    TRUE,
-    TypeContent (..),
-    TypeName,
-    UnionMember (..),
-    mkNullaryMember,
-    mkUnionMember,
-  )
-import Relude
-
-buildUnionTypeContent ::
-  (gql a) =>
-  UseGQLType gql ->
-  CatType kind a ->
-  [ConsRep (Maybe (FieldContent TRUE kind CONST))] ->
-  SchemaT k (TypeContent TRUE kind CONST)
-buildUnionTypeContent gql scope cons = mkUnionType scope unionRef unionCons
-  where
-    unionRef = fieldTypeName <$> concatMap consFields unionRefRep
-    (unionRefRep, unionCons) = partition (isUnionRef (useTypename gql scope)) cons
-
-mkUnionType ::
-  CatType kind a ->
-  [TypeName] ->
-  [ConsRep (Maybe (FieldContent TRUE kind CONST))] ->
-  SchemaT c (TypeContent TRUE kind CONST)
-mkUnionType p@InputType unionRef unionCons = DataInputUnion <$> (typeMembers >>= fromElems)
-  where
-    (nullaryCons, cons) = partition isEmptyConstraint unionCons
-    nullaryMembers :: [UnionMember IN CONST]
-    nullaryMembers = mkNullaryMember . consName <$> nullaryCons
-    defineEnumEmpty
-      | null nullaryCons = pure ()
-      | otherwise = defineEnumUnit
-    typeMembers =
-      (<> nullaryMembers) . withRefs
-        <$> ( defineEnumEmpty *> buildUnions p cons
-            )
-      where
-        withRefs = fmap mkUnionMember . (unionRef <>)
-mkUnionType p@OutputType unionRef unionCons =
-  DataUnion <$> (buildUnions p unionCons >>= fromElems . map mkUnionMember . (unionRef <>))
-
-buildUnions ::
-  CatType kind a ->
-  [ConsRep (Maybe (FieldContent TRUE kind CONST))] ->
-  SchemaT c [TypeName]
-buildUnions proxy cons =
-  traverse_ (defineObjectType proxy) cons $> fmap consName cons
diff --git a/src/Data/Morpheus/Server/Deriving/Utils.hs b/src/Data/Morpheus/Server/Deriving/Utils.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Utils.hs
+++ /dev/null
@@ -1,40 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Utils
-  ( conNameProxy,
-    isRecordProxy,
-    selNameProxy,
-    ConsRep (..),
-    FieldRep (..),
-    isEmptyConstraint,
-    isUnionRef,
-    fieldTypeName,
-    unpackMonad,
-    symbolName,
-    DataType (..),
-    DeriveWith (..),
-    DeriveTypeOptions (..),
-    deriveTypeWith,
-  )
-where
-
-import Data.Morpheus.Server.Deriving.Utils.DeriveGType
-  ( DeriveTypeOptions (..),
-    DeriveWith (..),
-    deriveTypeWith,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Proxy
-  ( conNameProxy,
-    isRecordProxy,
-    selNameProxy,
-    symbolName,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Types
-  ( ConsRep (..),
-    DataType (..),
-    FieldRep (..),
-    fieldTypeName,
-    isEmptyConstraint,
-    isUnionRef,
-    unpackMonad,
-  )
diff --git a/src/Data/Morpheus/Server/Deriving/Utils/AST.hs b/src/Data/Morpheus/Server/Deriving/Utils/AST.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Utils/AST.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE RecordWildCards #-}
+
+module Data.Morpheus.Server.Deriving.Utils.AST
+  ( argumentsToObject,
+  )
+where
+
+import Data.Morpheus.Types.Internal.AST
+  ( Argument (..),
+    Arguments,
+    ObjectEntry (..),
+    VALID,
+    Value (..),
+  )
+
+argumentsToObject :: Arguments VALID -> Value VALID
+argumentsToObject = Object . fmap toEntry
+  where
+    toEntry Argument {..} = ObjectEntry argumentName argumentValue
diff --git a/src/Data/Morpheus/Server/Deriving/Utils/Decode.hs b/src/Data/Morpheus/Server/Deriving/Utils/Decode.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Utils/Decode.hs
+++ /dev/null
@@ -1,191 +0,0 @@
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE KindSignatures #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Utils.Decode
-  ( withInputObject,
-    withEnum,
-    withInputUnion,
-    decodeFieldWith,
-    withScalar,
-    handleEither,
-    getFieldName,
-    DecoderT,
-    setVariantRef,
-    Context (..),
-    getUnionInfos,
-    DescribeCons,
-    DescribeFields (countFields),
-  )
-where
-
-import Control.Monad.Except (MonadError (throwError))
-import Data.Morpheus.App.Internal.Resolving (ResolverState)
-import Data.Morpheus.Internal.Utils
-  ( selectOr,
-  )
-import Data.Morpheus.Server.Deriving.Utils (conNameProxy)
-import Data.Morpheus.Server.Deriving.Utils.Kinded (CatType (..))
-import Data.Morpheus.Server.Types.GQLType
-  ( GQLType,
-    deriveTypename,
-  )
-import Data.Morpheus.Types.GQLScalar
-  ( toScalar,
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( FieldName,
-    GQLError,
-    IN,
-    Msg (msg),
-    ObjectEntry (..),
-    ScalarValue,
-    Token,
-    TypeName,
-    VALID,
-    ValidObject,
-    ValidValue,
-    Value (..),
-    getInputUnionValue,
-    internal,
-  )
-import GHC.Generics
-import Relude
-
-withInputObject ::
-  MonadError GQLError m =>
-  (ValidObject -> m a) ->
-  ValidValue ->
-  m a
-withInputObject f (Object object) = f object
-withInputObject _ isType = throwError (typeMismatch "InputObject" isType)
-
--- | Useful for more restrictive instances of lists (non empty, size indexed etc)
-withEnum :: MonadError GQLError m => (TypeName -> m a) -> Value VALID -> m a
-withEnum decode (Enum value) = decode value
-withEnum _ isType = throwError (typeMismatch "Enum" isType)
-
-withInputUnion ::
-  (MonadError GQLError m, Monad m) =>
-  (TypeName -> ValidObject -> ValidObject -> m a) ->
-  ValidObject ->
-  m a
-withInputUnion decoder unions =
-  either onFail onSuccess (getInputUnionValue unions)
-  where
-    onSuccess (name, value) = withInputObject (decoder name unions) value
-    onFail = throwError . internal . msg
-
-withScalar ::
-  (Applicative m, MonadError GQLError m) =>
-  TypeName ->
-  (ScalarValue -> Either Token a) ->
-  Value VALID ->
-  m a
-withScalar typename decodeScalar value = case toScalar value >>= decodeScalar of
-  Right scalar -> pure scalar
-  Left message ->
-    throwError
-      ( typeMismatch
-          ("SCALAR(" <> msg typename <> ")" <> msg message)
-          value
-      )
-
-decodeFieldWith :: (Value VALID -> m a) -> FieldName -> ValidObject -> m a
-decodeFieldWith decoder = selectOr (decoder Null) (decoder . entryValue)
-
-handleEither :: MonadError GQLError m => Either GQLError a -> m a
-handleEither = either throwError pure
-
--- if value is already validated but value has different type
-typeMismatch :: GQLError -> Value s -> GQLError
-typeMismatch text jsType =
-  internal $
-    "Type mismatch! expected:"
-      <> text
-      <> ", got: "
-      <> msg jsType
-
-getFieldName :: FieldName -> Int -> FieldName
-getFieldName "" index = "_" <> show index
-getFieldName label _ = label
-
-data VariantKind = InlineVariant | VariantRef deriving (Eq, Ord)
-
-data Info = Info
-  { kind :: VariantKind,
-    tagName :: [TypeName]
-  }
-
-instance Semigroup Info where
-  Info VariantRef t1 <> Info _ t2 = Info VariantRef (t1 <> t2)
-  Info _ t1 <> Info VariantRef t2 = Info VariantRef (t1 <> t2)
-  Info InlineVariant t1 <> Info InlineVariant t2 = Info InlineVariant (t1 <> t2)
-
-data Context = Context
-  { isVariantRef :: Bool,
-    typeName :: TypeName,
-    enumVisitor :: TypeName -> TypeName,
-    fieldVisitor :: FieldName -> FieldName
-  }
-
-type DecoderT = ReaderT Context ResolverState
-
-setVariantRef :: Bool -> DecoderT a -> DecoderT a
-setVariantRef isVariantRef = local (\ctx -> ctx {isVariantRef})
-
-class DescribeCons (f :: Type -> Type) where
-  tags :: Proxy f -> Context -> Info
-
-instance (Datatype d, DescribeCons f) => DescribeCons (M1 D d f) where
-  tags _ = tags (Proxy @f)
-
-instance (DescribeCons a, DescribeCons b) => DescribeCons (a :+: b) where
-  tags _ = tags (Proxy @a) <> tags (Proxy @b)
-
-instance (Constructor c, DescribeFields a) => DescribeCons (M1 C c a) where
-  tags _ Context {typeName} = getTag (refType (Proxy @a))
-    where
-      getTag (Just memberRef)
-        | isUnionRef memberRef = Info {kind = VariantRef, tagName = [memberRef]}
-        | otherwise = Info {kind = InlineVariant, tagName = [consName]}
-      getTag Nothing = Info {kind = InlineVariant, tagName = [consName]}
-      --------
-      consName = conNameProxy (Proxy @c)
-      ----------
-      isUnionRef x = typeName <> x == consName
-
-getUnionInfos ::
-  forall f a b.
-  (DescribeCons a, DescribeCons b) =>
-  f (a :+: b) ->
-  DecoderT (Bool, ([TypeName], [TypeName]))
-getUnionInfos _ = do
-  context <- ask
-  let l = tags (Proxy @a) context
-  let r = tags (Proxy @b) context
-  let k = kind (l <> r)
-  pure (k == VariantRef, (tagName l, tagName r))
-
-class DescribeFields (f :: Type -> Type) where
-  refType :: Proxy f -> Maybe TypeName
-  countFields :: Proxy f -> Int
-
-instance (DescribeFields f, DescribeFields g) => DescribeFields (f :*: g) where
-  refType _ = Nothing
-  countFields _ = countFields (Proxy @f) + countFields (Proxy @g)
-
-instance (Selector s, GQLType a) => DescribeFields (M1 S s (K1 i a)) where
-  refType _ = Just $ deriveTypename (InputType :: CatType IN a)
-  countFields _ = 1
-
-instance DescribeFields U1 where
-  refType _ = Nothing
-  countFields _ = 0
diff --git a/src/Data/Morpheus/Server/Deriving/Utils/DeriveGType.hs b/src/Data/Morpheus/Server/Deriving/Utils/DeriveGType.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Utils/DeriveGType.hs
+++ /dev/null
@@ -1,148 +0,0 @@
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Utils.DeriveGType
-  ( DeriveWith (..),
-    DeriveValueOptions (..),
-    DeriveTypeOptions (..),
-    deriveValue,
-    deriveTypeWith,
-  )
-where
-
-import Data.Morpheus.Server.Deriving.Utils.Proxy
-  ( conNameProxy,
-    isRecordProxy,
-    selNameProxy,
-  )
-import Data.Morpheus.Server.Deriving.Utils.Types
-import Data.Morpheus.Server.Types.Internal
-  ( TypeData (..),
-  )
-import Data.Morpheus.Types.Internal.AST
-  ( TypeName,
-    TypeRef (..),
-  )
-import GHC.Generics
-  ( C,
-    Constructor,
-    D,
-    Datatype,
-    Generic (..),
-    K1 (..),
-    M1 (..),
-    Meta,
-    Rec0,
-    S,
-    Selector,
-    U1 (..),
-    (:*:) (..),
-    (:+:) (..),
-  )
-import Relude hiding (undefined)
-
-data DeriveValueOptions kind gql c v = DeriveValueOptions
-  { __valueTypeName :: TypeName,
-    __valueApply :: forall a. c a => a -> v,
-    __valueGetType :: forall f a. gql a => f a -> TypeData
-  }
-
-data DeriveTypeOptions kind gql derive v = DeriveTypeOptions
-  { __typeApply :: forall f a. derive a => f a -> v,
-    __typeGetType :: forall f a. gql a => f a -> TypeData
-  }
-
-deriveValue ::
-  (Generic a, DeriveWith gql constraint value (Rep a)) =>
-  DeriveValueOptions kind gql constraint value ->
-  a ->
-  DataType value
-deriveValue options = deriveTypeValue options . from
-
-deriveTypeWith ::
-  forall kind gql c v kinded a.
-  (DeriveWith gql c v (Rep a)) =>
-  DeriveTypeOptions kind gql c v ->
-  kinded kind a ->
-  [ConsRep v]
-deriveTypeWith options _ = deriveTypeDefinition options (Proxy @(Rep a))
-
---  GENERIC UNION
-class DeriveWith (gql :: Type -> Constraint) (c :: Type -> Constraint) (v :: Type) f where
-  deriveTypeValue :: DeriveValueOptions kind gql c v -> f a -> DataType v
-  deriveTypeDefinition :: DeriveTypeOptions kind gql c v -> proxy f -> [ConsRep v]
-
-instance (Datatype d, DeriveWith gql c v f) => DeriveWith gql c v (M1 D d f) where
-  deriveTypeValue options (M1 src) = (deriveTypeValue options src) {dataTypeName = __valueTypeName options}
-  deriveTypeDefinition options _ = deriveTypeDefinition options (Proxy @f)
-
--- | recursion for Object types, both of them : 'INPUT_OBJECT' and 'OBJECT'
-instance (DeriveWith gql c v a, DeriveWith gql c v b) => DeriveWith gql c v (a :+: b) where
-  deriveTypeValue f (L1 x) = (deriveTypeValue f x) {tyIsUnion = True}
-  deriveTypeValue f (R1 x) = (deriveTypeValue f x) {tyIsUnion = True}
-  deriveTypeDefinition options _ = deriveTypeDefinition options (Proxy @a) <> deriveTypeDefinition options (Proxy @b)
-
-instance (DeriveFieldRep gql con v f, Constructor c) => DeriveWith gql con v (M1 C c f) where
-  deriveTypeValue options (M1 src) =
-    DataType
-      { dataTypeName = "",
-        tyIsUnion = False,
-        tyCons = deriveConsRep (Proxy @c) (toFieldRep options src)
-      }
-  deriveTypeDefinition options _ = [deriveConsRep (Proxy @c) (conRep options (Proxy @f))]
-
-deriveConsRep ::
-  Constructor (c :: Meta) =>
-  f c ->
-  [FieldRep v] ->
-  ConsRep v
-deriveConsRep proxy fields = ConsRep {..}
-  where
-    consName = conNameProxy proxy
-    consFields
-      | isRecordProxy proxy = fields
-      | otherwise = enumerate fields
-
-class DeriveFieldRep (gql :: Type -> Constraint) (c :: Type -> Constraint) (v :: Type) f where
-  toFieldRep :: DeriveValueOptions kind gql c v -> f a -> [FieldRep v]
-  conRep :: DeriveTypeOptions kind gql c v -> proxy f -> [FieldRep v]
-
-instance (DeriveFieldRep gql c v a, DeriveFieldRep gql c v b) => DeriveFieldRep gql c v (a :*: b) where
-  toFieldRep options (a :*: b) = toFieldRep options a <> toFieldRep options b
-  conRep options _ = conRep options (Proxy @a) <> conRep options (Proxy @b)
-
-instance (Selector s, gql a, c a) => DeriveFieldRep gql c v (M1 S s (Rec0 a)) where
-  toFieldRep DeriveValueOptions {..} (M1 (K1 src)) =
-    [ FieldRep
-        { fieldSelector = selNameProxy (Proxy @s),
-          fieldTypeRef = TypeRef gqlTypeName gqlWrappers,
-          fieldValue = __valueApply src
-        }
-    ]
-    where
-      TypeData {gqlTypeName, gqlWrappers} = __valueGetType (Proxy @a)
-  conRep DeriveTypeOptions {..} _ =
-    [ FieldRep
-        { fieldSelector = selNameProxy (Proxy @s),
-          fieldTypeRef = TypeRef gqlTypeName gqlWrappers,
-          fieldValue = __typeApply (Proxy @a)
-        }
-    ]
-    where
-      TypeData {gqlTypeName, gqlWrappers} = __typeGetType (Proxy @a)
-
-instance DeriveFieldRep gql c v U1 where
-  toFieldRep _ _ = []
-  conRep _ _ = []
diff --git a/src/Data/Morpheus/Server/Deriving/Utils/GRep.hs b/src/Data/Morpheus/Server/Deriving/Utils/GRep.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Utils/GRep.hs
@@ -0,0 +1,198 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Utils.GRep
+  ( GRep (..),
+    RepContext (..),
+    ConsRep (..),
+    FieldRep (..),
+    TypeRep (..),
+    deriveValue,
+    deriveTypeWith,
+    isEmptyConstraint,
+    isUnionRef,
+    unpackMonad,
+  )
+where
+
+import Data.Morpheus.Server.Deriving.Utils.Proxy
+  ( conNameProxy,
+    isRecordProxy,
+    selNameProxy,
+  )
+import Data.Morpheus.Server.Types.Internal
+  ( TypeData (..),
+  )
+import Data.Morpheus.Types.Internal.AST
+  ( FieldName,
+    TypeName,
+    TypeRef (..),
+    packName,
+  )
+import qualified Data.Text as T
+import GHC.Generics
+  ( C,
+    Constructor,
+    D,
+    Datatype,
+    Generic (..),
+    K1 (..),
+    M1 (..),
+    Meta,
+    Rec0,
+    S,
+    Selector,
+    U1 (..),
+    (:*:) (..),
+    (:+:) (..),
+  )
+import Relude hiding (undefined)
+
+data RepContext gql fun f result = RepContext
+  { optApply :: forall a. fun a => f a -> result,
+    optTypeData :: forall proxy a. gql a => proxy a -> TypeData
+  }
+
+deriveValue ::
+  (Generic a, GRep gql constraint value (Rep a), gql a) =>
+  RepContext gql constraint Identity value ->
+  a ->
+  TypeRep value
+deriveValue options value = (deriveTypeValue options (from value)) {dataTypeName}
+  where
+    dataTypeName = gqlTypeName (optTypeData options (Identity value))
+
+deriveTypeWith ::
+  forall kind gql c v kinded a.
+  (GRep gql c v (Rep a)) =>
+  RepContext gql c Proxy v ->
+  kinded kind a ->
+  [ConsRep v]
+deriveTypeWith options _ = deriveTypeDefinition options (Proxy @(Rep a))
+
+--  GENERIC UNION
+class GRep (gql :: Type -> Constraint) (c :: Type -> Constraint) (v :: Type) f where
+  deriveTypeValue :: RepContext gql c Identity v -> f a -> TypeRep v
+  deriveTypeDefinition :: RepContext gql c Proxy v -> proxy f -> [ConsRep v]
+
+instance (Datatype d, GRep gql c v f) => GRep gql c v (M1 D d f) where
+  deriveTypeValue options (M1 src) = deriveTypeValue options src
+  deriveTypeDefinition options _ = deriveTypeDefinition options (Proxy @f)
+
+-- | recursion for Object types, both of them : 'INPUT_OBJECT' and 'OBJECT'
+instance (GRep gql c v a, GRep gql c v b) => GRep gql c v (a :+: b) where
+  deriveTypeValue f (L1 x) = (deriveTypeValue f x) {tyIsUnion = True}
+  deriveTypeValue f (R1 x) = (deriveTypeValue f x) {tyIsUnion = True}
+  deriveTypeDefinition options _ = deriveTypeDefinition options (Proxy @a) <> deriveTypeDefinition options (Proxy @b)
+
+instance (DeriveFieldRep gql con v f, Constructor c) => GRep gql con v (M1 C c f) where
+  deriveTypeValue options (M1 src) =
+    TypeRep
+      { dataTypeName = "",
+        tyIsUnion = False,
+        tyCons = deriveConsRep (Proxy @c) (toFieldRep options src)
+      }
+  deriveTypeDefinition options _ = [deriveConsRep (Proxy @c) (conRep options (Proxy @f))]
+
+deriveConsRep ::
+  Constructor (c :: Meta) =>
+  f c ->
+  [FieldRep v] ->
+  ConsRep v
+deriveConsRep proxy fields = ConsRep {..}
+  where
+    consName = conNameProxy proxy
+    consFields
+      | isRecordProxy proxy = fields
+      | otherwise = enumerate fields
+
+class DeriveFieldRep (gql :: Type -> Constraint) (c :: Type -> Constraint) (v :: Type) f where
+  toFieldRep :: RepContext gql c Identity v -> f a -> [FieldRep v]
+  conRep :: RepContext gql c Proxy v -> proxy f -> [FieldRep v]
+
+instance (DeriveFieldRep gql c v a, DeriveFieldRep gql c v b) => DeriveFieldRep gql c v (a :*: b) where
+  toFieldRep options (a :*: b) = toFieldRep options a <> toFieldRep options b
+  conRep options _ = conRep options (Proxy @a) <> conRep options (Proxy @b)
+
+instance (Selector s, gql a, c a) => DeriveFieldRep gql c v (M1 S s (Rec0 a)) where
+  toFieldRep RepContext {..} (M1 (K1 src)) =
+    [ FieldRep
+        { fieldSelector = selNameProxy (Proxy @s),
+          fieldTypeRef = TypeRef gqlTypeName gqlWrappers,
+          fieldValue = optApply (Identity src)
+        }
+    ]
+    where
+      TypeData {gqlTypeName, gqlWrappers} = optTypeData (Proxy @a)
+  conRep RepContext {..} _ =
+    [ FieldRep
+        { fieldSelector = selNameProxy (Proxy @s),
+          fieldTypeRef = TypeRef gqlTypeName gqlWrappers,
+          fieldValue = optApply (Proxy @a)
+        }
+    ]
+    where
+      TypeData {gqlTypeName, gqlWrappers} = optTypeData (Proxy @a)
+
+instance DeriveFieldRep gql c v U1 where
+  toFieldRep _ _ = []
+  conRep _ _ = []
+
+data TypeRep (v :: Type) = TypeRep
+  { dataTypeName :: TypeName,
+    tyIsUnion :: Bool,
+    tyCons :: ConsRep v
+  }
+  deriving (Functor)
+
+data ConsRep (v :: Type) = ConsRep
+  { consName :: TypeName,
+    consFields :: [FieldRep v]
+  }
+  deriving (Functor)
+
+data FieldRep (a :: Type) = FieldRep
+  { fieldSelector :: FieldName,
+    fieldTypeRef :: TypeRef,
+    fieldValue :: a
+  }
+  deriving (Functor)
+
+-- setFieldNames ::  Power Int Text -> Power { _1 :: Int, _2 :: Text }
+enumerate :: [FieldRep a] -> [FieldRep a]
+enumerate = zipWith setFieldName ([0 ..] :: [Int])
+  where
+    setFieldName i field = field {fieldSelector = packName $ "_" <> T.pack (show i)}
+
+isEmptyConstraint :: ConsRep a -> Bool
+isEmptyConstraint ConsRep {consFields = []} = True
+isEmptyConstraint _ = False
+
+isUnionRef :: TypeName -> ConsRep k -> Bool
+isUnionRef baseName ConsRep {consName, consFields = [fieldRep]} =
+  consName == baseName <> typeConName (fieldTypeRef fieldRep)
+isUnionRef _ _ = False
+
+unpackMonad :: Monad m => [ConsRep (m a)] -> m [ConsRep a]
+unpackMonad = traverse unpackMonadFromCons
+
+unpackMonadFromField :: Monad m => FieldRep (m a) -> m (FieldRep a)
+unpackMonadFromField FieldRep {..} = do
+  cont <- fieldValue
+  pure (FieldRep {fieldValue = cont, ..})
+
+unpackMonadFromCons :: Monad m => ConsRep (m a) -> m (ConsRep a)
+unpackMonadFromCons ConsRep {..} = ConsRep consName <$> traverse unpackMonadFromField consFields
diff --git a/src/Data/Morpheus/Server/Deriving/Utils/GScan.hs b/src/Data/Morpheus/Server/Deriving/Utils/GScan.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Utils/GScan.hs
@@ -0,0 +1,73 @@
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Utils.GScan
+  ( Scanner (..),
+    ScanRef (..),
+    scan,
+  )
+where
+
+import qualified Data.HashMap.Strict as HM
+import qualified Data.Map as M
+import Data.Morpheus.Server.Deriving.Utils.Gmap
+  ( Gmap,
+    GmapContext (..),
+    useGmap,
+  )
+import Data.Morpheus.Server.Types.TypeName (TypeFingerprint)
+import GHC.Generics (Generic (Rep))
+import Relude
+
+scan :: (Hashable k, Eq k) => (b -> k) -> Scanner c b -> [ScanRef c] -> HashMap k b
+scan toKey ctx = HM.fromList . map (\x -> (toKey x, x)) . toList . scanRefs ctx mempty
+
+fieldRefs :: Scanner c v -> ScanRef c -> [ScanRef c]
+fieldRefs ctx (ScanObject _ x) = useGmap (rep x) (mapContext ctx)
+fieldRefs _ ScanType {} = []
+
+rep :: f a -> Proxy (Rep a)
+rep _ = Proxy
+
+visited :: Map TypeFingerprint v -> ScanRef c -> Bool
+visited lib (ScanObject fp _) = M.member fp lib
+visited lib (ScanType fp _) = M.member fp lib
+
+getFingerprint :: ScanRef c -> TypeFingerprint
+getFingerprint (ScanObject fp _) = fp
+getFingerprint (ScanType fp _) = fp
+
+scanRefs :: Scanner c v -> Map TypeFingerprint v -> [ScanRef c] -> Map TypeFingerprint v
+scanRefs _ lib [] = lib
+scanRefs ctx lib (x : xs) = do
+  let values = runRef ctx x
+  let newLib = foldr (M.insert (getFingerprint x)) lib values
+  let refs = filter (not . visited newLib) (xs <> fieldRefs ctx x)
+  scanRefs ctx newLib refs
+
+runRef :: Scanner c v -> ScanRef c -> [v]
+runRef Scanner {..} (ScanObject _ t) = scannerFun t
+runRef Scanner {..} (ScanType _ t) = scannerFun t
+
+mapContext :: Scanner c v -> GmapContext c [ScanRef c]
+mapContext (Scanner _ f) = GmapContext f
+
+data ScanRef (c :: Type -> Constraint) where
+  ScanObject :: forall f a c. (Gmap c (Rep a), c a) => TypeFingerprint -> f a -> ScanRef c
+  ScanType :: forall f a c. (c a) => TypeFingerprint -> f a -> ScanRef c
+
+data Scanner (c :: Type -> Constraint) (v :: Type) = Scanner
+  { scannerFun :: forall f a. (c a) => f a -> [v],
+    scannerRefs :: forall f a. (c a) => f a -> [ScanRef c]
+  }
diff --git a/src/Data/Morpheus/Server/Deriving/Utils/GTraversable.hs b/src/Data/Morpheus/Server/Deriving/Utils/GTraversable.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Utils/GTraversable.hs
+++ /dev/null
@@ -1,115 +0,0 @@
-{-# LANGUAGE AllowAmbiguousTypes #-}
-{-# LANGUAGE ConstraintKinds #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE UndecidableSuperClasses #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Utils.GTraversable where
-
-import qualified Data.Map as M
-import Data.Morpheus.Server.Deriving.Utils.Kinded
-import Data.Morpheus.Server.NamedResolvers (NamedResolverT)
-import Data.Morpheus.Server.Types.GQLType (GQLType (KIND, __type))
-import Data.Morpheus.Server.Types.Internal
-  ( TypeData (gqlFingerprint),
-  )
-import Data.Morpheus.Server.Types.Kind
-import Data.Morpheus.Server.Types.SchemaT (TypeFingerprint)
-import Data.Morpheus.Types.Internal.AST
-import GHC.Generics
-import Relude hiding (Undefined)
-
-traverseTypes ::
-  (GFmap (ScanConstraint c) (KIND a) a, c (KIND a) a, GQLType a) =>
-  Mappable c v KindedProxy ->
-  Proxy a ->
-  Map TypeFingerprint v
-traverseTypes f = runMappable (scanner f mempty) . withDerivable
-
-class
-  (GFmap (ScanConstraint c) (KIND a) a, c (KIND a) a) =>
-  ScanConstraint
-    (c :: DerivingKind -> Type -> Constraint)
-    (k :: DerivingKind)
-    (a :: Type)
-
-instance (GFmap (ScanConstraint c) (KIND a) a, c (KIND a) a) => ScanConstraint c k a
-
-scanner ::
-  Mappable c v KindedProxy ->
-  Map TypeFingerprint v ->
-  Mappable (ScanConstraint c) (Map TypeFingerprint v) KindedProxy
-scanner c@(Mappable f) lib =
-  Mappable
-    ( \proxy -> do
-        let typeInfo = __type proxy OUT
-        let fingerprint = gqlFingerprint typeInfo
-        if M.member fingerprint lib
-          then lib
-          else do
-            let newLib = M.insert fingerprint (f proxy) lib
-            gfmap (scanner c newLib) proxy
-    )
-
-withDerivable :: proxy a -> KindedProxy (KIND a) a
-withDerivable _ = KindedProxy
-
-newtype Mappable (c :: DerivingKind -> Type -> Constraint) (v :: Type) (f :: DerivingKind -> Type -> Type) = Mappable
-  { runMappable :: forall a. (GQLType a, c (KIND a) a) => KindedProxy (KIND a) a -> v
-  }
-
--- Map
-class GFmap (c :: DerivingKind -> Type -> Constraint) (t :: DerivingKind) a where
-  gfmap :: (Monoid v, Semigroup v) => Mappable c v KindedProxy -> kinded t a -> v
-
-instance (GQLType a, c (KIND a) a) => GFmap c SCALAR a where
-  gfmap (Mappable f) _ = f (KindedProxy :: KindedProxy (KIND a) a)
-
-instance (GQLType a, c (KIND a) a, GFunctor c (Rep a)) => GFmap c TYPE a where
-  gfmap f@(Mappable fx) _ = fx (KindedProxy :: KindedProxy (KIND a) a) <> genericMap f (Proxy @(Rep a))
-
-instance GFmap c (KIND a) a => GFmap c WRAPPER (f a) where
-  gfmap f _ = gfmap f (KindedProxy :: KindedProxy (KIND a) a)
-
-instance GFmap c (KIND a) a => GFmap c CUSTOM (input -> a) where
-  gfmap f _ = gfmap f (KindedProxy :: KindedProxy (KIND a) a)
-
-instance GFmap c (KIND a) a => GFmap c CUSTOM (NamedResolverT m a) where
-  gfmap f _ = gfmap f (KindedProxy :: KindedProxy (KIND a) a)
-
---
---
--- GFunctor
---
---
-class GFunctor (c :: DerivingKind -> Type -> Constraint) a where
-  genericMap :: (Monoid v, Semigroup v) => Mappable c v p -> proxy a -> v
-
-instance (Datatype d, GFunctor c a) => GFunctor c (M1 D d a) where
-  genericMap fun _ = genericMap fun (Proxy @a)
-
-instance (GFunctor con a) => GFunctor con (M1 C c a) where
-  genericMap f _ = genericMap f (Proxy @a)
-
-instance (GFunctor c a, GFunctor c b) => GFunctor c (a :+: b) where
-  genericMap fun _ = genericMap fun (Proxy @a) <> genericMap fun (Proxy @b)
-
-instance (GFunctor c a, GFunctor c b) => GFunctor c (a :*: b) where
-  genericMap fun _ = genericMap fun (Proxy @a) <> genericMap fun (Proxy @b)
-
-instance (GQLType a, c (KIND a) a) => GFunctor c (M1 S s (K1 x a)) where
-  genericMap (Mappable f) _ = f (KindedProxy :: KindedProxy (KIND a) a)
-
-instance GFunctor c U1 where
-  genericMap _ _ = mempty
diff --git a/src/Data/Morpheus/Server/Deriving/Utils/Gmap.hs b/src/Data/Morpheus/Server/Deriving/Utils/Gmap.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Deriving/Utils/Gmap.hs
@@ -0,0 +1,65 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Deriving.Utils.Gmap
+  ( GmapContext (..),
+    useGmap,
+    Gmap (..),
+  )
+where
+
+import GHC.Generics
+  ( C,
+    D,
+    Datatype,
+    K1,
+    M1,
+    S,
+    U1,
+    type (:*:),
+    type (:+:),
+  )
+import Relude
+
+newtype GmapContext (fun :: Type -> Constraint) (v :: Type) = GmapContext
+  { gmapFun :: forall f a. (fun a) => f a -> v
+  }
+
+useGmap :: (Gmap c a, Monoid b) => f a -> GmapContext c b -> b
+useGmap x = runReader (gfmap x)
+
+class Gmap (c :: Type -> Constraint) a where
+  gfmap :: (Monoid v) => proxy a -> Reader (GmapContext c v) v
+
+instance (Datatype d, Gmap c a) => Gmap c (M1 D d a) where
+  gfmap _ = gfmap (Proxy @a)
+
+instance (Gmap con a) => Gmap con (M1 C c a) where
+  gfmap _ = gfmap (Proxy @a)
+
+instance (Gmap c a, Gmap c b) => Gmap c (a :+: b) where
+  gfmap _ = liftA2 (<>) (gfmap (Proxy @a)) (gfmap (Proxy @b))
+
+instance (Gmap c a, Gmap c b) => Gmap c (a :*: b) where
+  gfmap _ = liftA2 (<>) (gfmap (Proxy @a)) (gfmap (Proxy @b))
+
+instance (c a) => Gmap c (M1 S s (K1 x a)) where
+  gfmap _ = runFun <$> ask
+    where
+      runFun :: GmapContext c v -> v
+      runFun GmapContext {..} = gmapFun (Proxy @a)
+
+instance Gmap c U1 where
+  gfmap _ = pure mempty
diff --git a/src/Data/Morpheus/Server/Deriving/Utils/Kinded.hs b/src/Data/Morpheus/Server/Deriving/Utils/Kinded.hs
--- a/src/Data/Morpheus/Server/Deriving/Utils/Kinded.hs
+++ b/src/Data/Morpheus/Server/Deriving/Utils/Kinded.hs
@@ -10,19 +10,18 @@
 module Data.Morpheus.Server.Deriving.Utils.Kinded
   ( KindedProxy (..),
     setType,
-    setKind,
-    kinded,
     CatType (..),
     inputType,
     outputType,
     CatContext (..),
-    getCat,
-    typeCat,
     unliftKind,
     catMap,
     addContext,
     getCatContext,
     mkScalar,
+    isIN,
+    ForAll (..),
+    unForAll,
   )
 where
 
@@ -34,7 +33,8 @@
     TypeCategory (..),
     TypeContent (..),
   )
-import Prelude (Show)
+import Data.Proxy (Proxy (..))
+import Prelude (Bool (..), Show)
 
 -- | context , like Proxy with multiple parameters
 -- * 'kind': object, scalar, enum ...
@@ -45,12 +45,6 @@
 setType :: f a -> kinded (k :: t) a' -> KindedProxy k a
 setType _ _ = KindedProxy
 
-setKind :: f k -> kinded (k' :: t) a -> KindedProxy k a
-setKind _ _ = KindedProxy
-
-kinded :: f k -> f' a -> KindedProxy k a
-kinded _ _ = KindedProxy
-
 data CatContext (cat :: TypeCategory) where
   InputContext :: CatContext IN
   OutputContext :: CatContext OUT
@@ -59,16 +53,8 @@
   InputType :: CatType IN a
   OutputType :: CatType OUT a
 
--- liftKind :: CatType cat a -> CatType cat (f k a)
--- liftKind InputType = InputType
--- liftKind OutputType = OutputType
-
 deriving instance Show (CatType cat a)
 
--- converts:
---   f a -> KindedType IN a
--- or
---  f k a -> KindedType IN a
 inputType :: f a -> CatType IN a
 inputType _ = InputType
 
@@ -83,14 +69,6 @@
 catMap _ InputType = InputType
 catMap _ OutputType = OutputType
 
-getCat :: CatContext c -> TypeCategory
-getCat InputContext = IN
-getCat OutputContext = OUT
-
-typeCat :: CatType c a -> TypeCategory
-typeCat InputType = IN
-typeCat OutputType = OUT
-
 addContext :: CatContext c -> f a -> CatType c a
 addContext InputContext _ = InputType
 addContext OutputContext _ = OutputType
@@ -102,3 +80,12 @@
 mkScalar :: CatType c a -> ScalarDefinition -> TypeContent TRUE c s
 mkScalar InputType f = DataScalar f
 mkScalar OutputType f = DataScalar f
+
+isIN :: CatType c a -> Bool
+isIN InputType = True
+isIN _ = False
+
+newtype ForAll a = ForAll a
+
+unForAll :: f (ForAll a) -> Proxy a
+unForAll _ = Proxy
diff --git a/src/Data/Morpheus/Server/Deriving/Utils/Types.hs b/src/Data/Morpheus/Server/Deriving/Utils/Types.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/Deriving/Utils/Types.hs
+++ /dev/null
@@ -1,72 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE DeriveFunctor #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE PolyKinds #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.Deriving.Utils.Types
-  ( ConsRep (..),
-    FieldRep (..),
-    DataType (..),
-    enumerate,
-    isEmptyConstraint,
-    fieldTypeName,
-    isUnionRef,
-    unpackMonad,
-  )
-where
-
-import Data.Morpheus.Types.Internal.AST
-import qualified Data.Text as T
-import Relude
-
-data DataType (v :: Type) = DataType
-  { dataTypeName :: TypeName,
-    tyIsUnion :: Bool,
-    tyCons :: ConsRep v
-  }
-  deriving (Functor)
-
-data ConsRep (v :: Type) = ConsRep
-  { consName :: TypeName,
-    consFields :: [FieldRep v]
-  }
-  deriving (Functor)
-
-data FieldRep (a :: Type) = FieldRep
-  { fieldSelector :: FieldName,
-    fieldTypeRef :: TypeRef,
-    fieldValue :: a
-  }
-  deriving (Functor)
-
--- setFieldNames ::  Power Int Text -> Power { _1 :: Int, _2 :: Text }
-enumerate :: [FieldRep a] -> [FieldRep a]
-enumerate = zipWith setFieldName ([0 ..] :: [Int])
-  where
-    setFieldName i field = field {fieldSelector = packName $ "_" <> T.pack (show i)}
-
-isEmptyConstraint :: ConsRep a -> Bool
-isEmptyConstraint ConsRep {consFields = []} = True
-isEmptyConstraint _ = False
-
-fieldTypeName :: FieldRep k -> TypeName
-fieldTypeName = typeConName . fieldTypeRef
-
-isUnionRef :: TypeName -> ConsRep k -> Bool
-isUnionRef baseName ConsRep {consName, consFields = [fieldRep]} =
-  consName == baseName <> fieldTypeName fieldRep
-isUnionRef _ _ = False
-
-unpackMonad :: Monad m => [ConsRep (m a)] -> m [ConsRep a]
-unpackMonad = traverse unpackMonadFromCons
-
-unpackMonadFromField :: Monad m => FieldRep (m a) -> m (FieldRep a)
-unpackMonadFromField FieldRep {..} = do
-  cont <- fieldValue
-  pure (FieldRep {fieldValue = cont, ..})
-
-unpackMonadFromCons :: Monad m => ConsRep (m a) -> m (ConsRep a)
-unpackMonadFromCons ConsRep {..} = ConsRep consName <$> traverse unpackMonadFromField consFields
diff --git a/src/Data/Morpheus/Server/Deriving/Utils/Use.hs b/src/Data/Morpheus/Server/Deriving/Utils/Use.hs
--- a/src/Data/Morpheus/Server/Deriving/Utils/Use.hs
+++ b/src/Data/Morpheus/Server/Deriving/Utils/Use.hs
@@ -5,15 +5,18 @@
 {-# LANGUAGE RankNTypes #-}
 
 module Data.Morpheus.Server.Deriving.Utils.Use
-  ( UseDirective (..),
-    UseDeriveType (..),
-    UseArguments (..),
+  ( UseDeriving (..),
     UseGQLType (..),
-    useTypename,
+    UseValue (..),
+    UseResolver (..),
+    UseNamedResolver (..),
   )
 where
 
-import Data.Morpheus.Server.Deriving.Schema.Internal
+import Data.Morpheus.App.Internal.Resolving (NamedResolver (..), ResolverState, ResolverValue)
+import Data.Morpheus.Internal.Ext (GQLResult)
+import Data.Morpheus.Server.Deriving.Utils.GScan (ScanRef)
+import Data.Morpheus.Server.Deriving.Utils.Kinded (CatType)
 import Data.Morpheus.Server.Types.Directives
   ( GDirectiveUsages (..),
   )
@@ -25,36 +28,41 @@
   ( TypeFingerprint,
   )
 import Data.Morpheus.Types.Internal.AST
-  ( Arguments,
-    ArgumentsDefinition,
+  ( ArgumentsDefinition,
     CONST,
-    OUT,
-    TypeCategory (..),
+    TypeDefinition (..),
     TypeName,
+    ValidValue,
+    Value,
   )
 
-useTypename :: (gqlType a) => UseGQLType gqlType -> CatType c a -> TypeName
-useTypename gql proxy@InputType = __useTypename gql IN proxy
-useTypename gql proxy@OutputType = __useTypename gql OUT proxy
-
 data UseGQLType gql = UseGQLType
-  { __useFingerprint :: forall f a. gql a => TypeCategory -> f a -> TypeFingerprint,
-    __useTypename :: forall f a. gql a => TypeCategory -> f a -> TypeName,
-    __useTypeData :: forall f a. gql a => f a -> TypeCategory -> TypeData
+  { useFingerprint :: forall c a. gql a => CatType c a -> TypeFingerprint,
+    useTypename :: forall c a. gql a => CatType c a -> TypeName,
+    useTypeData :: forall c a. gql a => CatType c a -> TypeData,
+    useDeriveType :: forall c a. gql a => CatType c a -> SchemaT c (TypeDefinition c CONST),
+    useDeriveFieldArguments :: forall c a. gql a => CatType c a -> SchemaT c (Maybe (ArgumentsDefinition CONST))
   }
 
-data UseArguments args = UseArguments
-  { useDeriveArguments :: forall f a. args a => f a -> SchemaT OUT (ArgumentsDefinition CONST),
-    useEncodeArguments :: forall k a. args a => a -> SchemaT k (Arguments CONST)
+data UseValue val = UseValue
+  { useEncodeValue :: forall a. val a => a -> GQLResult (Value CONST),
+    useDecodeValue :: forall a. val a => ValidValue -> ResolverState a
   }
 
-data UseDirective gql args = UseDirective
-  { __directives :: forall f a. gql a => f a -> GDirectiveUsages gql args,
-    dirArgs :: UseArguments args,
+data UseResolver res gql val = UseResolver
+  { useEncodeResolver :: forall a m. res m a => a -> m (ResolverValue m),
+    resDrv :: UseDeriving gql val
+  }
+
+data UseDeriving gql val = UseDeriving
+  { __directives :: forall f a. gql a => f a -> GDirectiveUsages gql val,
+    dirArgs :: UseValue val,
     dirGQL :: UseGQLType gql
   }
 
-data UseDeriveType derive = UseDeriveType
-  { useDeriveType :: forall c a. derive c a => CatType c a -> SchemaT c (),
-    useDeriveContent :: forall c a. derive c a => CatType c a -> TyContentM c
+data UseNamedResolver named fun gql val = UseNamedResolver
+  { useNamedFieldResolver :: forall a m. fun m a => a -> m (ResolverValue m),
+    useDeriveNamedResolvers :: forall f a m. named m a => f a -> [NamedResolver m],
+    useDeriveNamedRefs :: forall f a m. named m a => f a -> [ScanRef (named m)],
+    namedDrv :: UseDeriving gql val
   }
diff --git a/src/Data/Morpheus/Server/NamedResolvers.hs b/src/Data/Morpheus/Server/NamedResolvers.hs
deleted file mode 100644
--- a/src/Data/Morpheus/Server/NamedResolvers.hs
+++ /dev/null
@@ -1,108 +0,0 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GADTs #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module Data.Morpheus.Server.NamedResolvers
-  ( ResolveNamed (..),
-    NamedResolverT (..),
-    resolve,
-    useBatched,
-    Dependency,
-    ignoreBatching,
-    NamedRef,
-  )
-where
-
-import Control.Monad.Except
-import Data.Aeson (ToJSON)
-import Data.Morpheus.Types.ID (ID)
-import Data.Morpheus.Types.Internal.AST (GQLError, internal)
-import Data.Vector (Vector)
-import Relude
-
-type family Target a :: Type where
-  Target (Maybe a) = a
-  Target [a] = a
-  Target (Set a) = a
-  Target (NonEmpty a) = a
-  Target (Seq a) = a
-  Target (Vector a) = a
-  Target a = a
-
-type family Dependency a :: Type where
-  -- wrappers
-  Dependency (Maybe a) = Dependency a
-  Dependency [a] = Dependency a
-  Dependency (Set a) = Dependency a
-  Dependency (NonEmpty a) = Dependency a
-  Dependency (Seq a) = Dependency a
-  Dependency (Vector a) = Dependency a
-  -- custom
-  Dependency a = Dep a
-
-ignoreBatching :: (Monad m) => (a -> m b) -> [a] -> m [Maybe b]
-ignoreBatching f = traverse (fmap Just . f)
-
-forward :: (Monad m, Dependency a ~ a) => [Dependency a] -> m [Maybe a]
-forward = pure . map Just
-
-{-# DEPRECATED useBatched " this function is obsolete" #-}
-useBatched :: (ResolveNamed m a, MonadError GQLError m) => Dependency a -> m a
-useBatched x = resolveBatched [x] >>= res
-  where
-    res [Just v] = pure v
-    res _ = throwError (internal "named resolver should return single value for single argument")
-
-{-# DEPRECATED resolveNamed "use: resolveBatched" #-}
-
-instance ResolveNamed m Int where
-  type Dep Int = Int
-  resolveBatched = forward
-
-instance ResolveNamed m Float where
-  type Dep Float = Float
-  resolveBatched = forward
-
-instance ResolveNamed m Double where
-  type Dep Double = Double
-  resolveBatched = forward
-
-instance ResolveNamed m Text where
-  type Dep Text = Text
-  resolveBatched = forward
-
-instance ResolveNamed m Bool where
-  type Dep Bool = Bool
-  resolveBatched = forward
-
-instance ResolveNamed m ID where
-  type Dep ID = ID
-  resolveBatched = forward
-
-class ToJSON (Dependency a) => ResolveNamed (m :: Type -> Type) (a :: Type) where
-  type Dep a :: Type
-  resolveBatched :: MonadError GQLError m => [Dependency a] -> m [Maybe a]
-
-  resolveNamed :: MonadError GQLError m => Dependency a -> m a
-  resolveNamed = useBatched
-
-data NamedResolverT (m :: Type -> Type) a where
-  NamedResolverT :: ResolveNamed m (Target a) => m (NamedRef a) -> NamedResolverT m a
-
-type family NamedRef a :: Type where
-  NamedRef [a] = [Dependency a]
-  NamedRef (Set a) = [Dependency a]
-  NamedRef (NonEmpty a) = [Dependency a]
-  NamedRef (Seq a) = [Dependency a]
-  NamedRef (Vector a) = [Dependency a]
-  NamedRef a = Dependency a
-
-resolve :: ResolveNamed m (Target a) => m (NamedRef a) -> NamedResolverT m a
-resolve = NamedResolverT
diff --git a/src/Data/Morpheus/Server/Resolvers.hs b/src/Data/Morpheus/Server/Resolvers.hs
--- a/src/Data/Morpheus/Server/Resolvers.hs
+++ b/src/Data/Morpheus/Server/Resolvers.hs
@@ -18,18 +18,22 @@
     defaultRootResolver,
     ResolverO,
     ComposedResolver,
-    publish,
     constRes,
     ResolverQ,
     ResolverM,
     ResolverS,
     useBatched,
     ignoreBatching,
+    Flexible,
+    Composed,
   )
 where
 
-import Data.Morpheus.App.Internal.Resolving (PushEvents (pushEvents), Resolver, WithOperation)
-import Data.Morpheus.Server.NamedResolvers
+import Data.Morpheus.App.Internal.Resolving
+  ( MonadResolver (..),
+    Resolver,
+  )
+import Data.Morpheus.Server.Types.NamedResolvers
   ( NamedResolverT (..),
     ResolveNamed (..),
     ignoreBatching,
@@ -94,14 +98,11 @@
 
 type ResolverO o e m a = Flexible (Resolver o e m) a
 
-type ResolverQ e m a = Flexible (Resolver QUERY e m) a
-
-type ResolverM e m a = Flexible (Resolver MUTATION e m) a
+type ResolverQ e m a = ResolverO QUERY e m a
 
-type ResolverS e m a = Flexible (Resolver SUBSCRIPTION e m) a
+type ResolverM e m a = ResolverO MUTATION e m a
 
-publish :: Monad m => [e] -> Resolver MUTATION e m ()
-publish = pushEvents
+type ResolverS e m a = ResolverO SUBSCRIPTION e m a
 
-constRes :: (WithOperation o, Monad m) => b -> a -> Resolver o e m b
+constRes :: (MonadResolver m) => b -> a -> m b
 constRes = const . pure
diff --git a/src/Data/Morpheus/Server/Types.hs b/src/Data/Morpheus/Server/Types.hs
--- a/src/Data/Morpheus/Server/Types.hs
+++ b/src/Data/Morpheus/Server/Types.hs
@@ -30,7 +30,6 @@
     SUBSCRIPTION,
     lift,
     WithOperation,
-    subscribe,
     ResolverContext (..),
     SubscriptionField,
     App,
@@ -68,6 +67,10 @@
     DefaultValue (..),
     Value (..),
     DirectiveLocation (..),
+    MonadResolver (..),
+    MonadIOResolver,
+    Flexible,
+    Composed,
   )
 where
 
@@ -75,19 +78,21 @@
   ( App,
   )
 import Data.Morpheus.App.Internal.Resolving
-  ( Resolver,
+  ( MonadIOResolver,
+    MonadResolver (..),
+    Resolver,
     ResolverContext (..),
     SubscriptionField,
     WithOperation,
-    subscribe,
   )
 import Data.Morpheus.Core
   ( RenderGQL,
     render,
   )
-import Data.Morpheus.Server.Deriving.Encode ()
 import Data.Morpheus.Server.Resolvers
-  ( RootResolver (..),
+  ( Composed,
+    Flexible,
+    RootResolver (..),
     defaultRootResolver,
   )
 import Data.Morpheus.Server.Types.DirectiveDefinitions
diff --git a/src/Data/Morpheus/Server/Types/DirectiveDefinitions.hs b/src/Data/Morpheus/Server/Types/DirectiveDefinitions.hs
--- a/src/Data/Morpheus/Server/Types/DirectiveDefinitions.hs
+++ b/src/Data/Morpheus/Server/Types/DirectiveDefinitions.hs
@@ -68,7 +68,7 @@
     )
 
 instance GQLType Deprecated where
-  __type _ = mkTypeData "deprecated"
+  __type = mkTypeData "deprecated"
 
 instance GQLDirective Deprecated where
   type
diff --git a/src/Data/Morpheus/Server/Types/Directives.hs b/src/Data/Morpheus/Server/Types/Directives.hs
--- a/src/Data/Morpheus/Server/Types/Directives.hs
+++ b/src/Data/Morpheus/Server/Types/Directives.hs
@@ -36,7 +36,6 @@
 where
 
 import qualified Data.HashMap.Strict as M
-import Data.Morpheus.Server.Types.TypeName (getTypename)
 import qualified Data.Morpheus.Server.Types.Visitors as Visitors
 import Data.Morpheus.Types.Internal.AST
   ( CONST,
@@ -126,9 +125,6 @@
 type FIELD_VISITOR_KIND = '[ 'LOCATION_INPUT_FIELD_DEFINITION, 'LOCATION_FIELD_DEFINITION]
 
 type ENUM_VISITOR_KIND = '[ 'LOCATION_ENUM_VALUE]
-
-__directiveName :: GQLDirective a => f a -> FieldName
-__directiveName = coerce . getTypename
 
 class
   ( ToLocations (DIRECTIVE_LOCATIONS a),
diff --git a/src/Data/Morpheus/Server/Types/GQLType.hs b/src/Data/Morpheus/Server/Types/GQLType.hs
--- a/src/Data/Morpheus/Server/Types/GQLType.hs
+++ b/src/Data/Morpheus/Server/Types/GQLType.hs
@@ -6,11 +6,9 @@
 {-# LANGUAGE DerivingStrategies #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE GADTs #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications #-}
@@ -19,18 +17,17 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 
 module Data.Morpheus.Server.Types.GQLType
-  ( DeriveDirective,
-    GQLType (KIND, directives, __type),
+  ( GQLType (KIND, directives, __type),
+    GQLValue (..),
     InputTypeNamespace (..),
-    deriveFingerprint,
-    deriveTypename,
-    encodeArguments,
-    __isEmptyType,
-    __typeData,
+    GQLResolver (..),
+    ignoreUndefined,
     withGQL,
     withDir,
-    withDeriveType,
-    DeriveType,
+    withValue,
+    withRes,
+    kindedProxy,
+    IgnoredResolver,
   )
 where
 
@@ -39,19 +36,32 @@
 import Control.Monad.Except (MonadError (throwError))
 import Data.Morpheus.App.Internal.Resolving
   ( Resolver,
+    ResolverState,
+    ResolverValue,
     SubscriptionField,
   )
-import Data.Morpheus.Internal.Ext
-import Data.Morpheus.Internal.Utils
-import Data.Morpheus.Server.Deriving.Schema.DeriveKinded
-import Data.Morpheus.Server.Deriving.Schema.Directive (UseDirective (..))
-import Data.Morpheus.Server.Deriving.Schema.Internal
-import Data.Morpheus.Server.Deriving.Utils (ConsRep (..), DataType (..), DeriveWith, FieldRep (..))
-import Data.Morpheus.Server.Deriving.Utils.DeriveGType (DeriveValueOptions (..), deriveValue)
-import Data.Morpheus.Server.Deriving.Utils.Kinded (KindedProxy (KindedProxy), inputType)
-import Data.Morpheus.Server.Deriving.Utils.Proxy (ContextValue (..))
-import Data.Morpheus.Server.Deriving.Utils.Use (UseArguments (..), UseDeriveType (..), UseGQLType (..))
-import Data.Morpheus.Server.NamedResolvers (NamedResolverT (..))
+import Data.Morpheus.Internal.Ext (GQLResult)
+import Data.Morpheus.Internal.Utils (singleton)
+import Data.Morpheus.Server.Deriving.Internal.Schema.Type
+  ( fillTypeContent,
+    injectType,
+  )
+import Data.Morpheus.Server.Deriving.Kinded.Arguments
+  ( DeriveFieldArguments (..),
+    HasArguments,
+  )
+import Data.Morpheus.Server.Deriving.Kinded.Resolver (KindedResolver (..))
+import Data.Morpheus.Server.Deriving.Kinded.Type
+  ( DERIVE_TYPE,
+    DeriveKindedType (..),
+    deriveInterfaceDefinition,
+    deriveScalarDefinition,
+    deriveTypeGuardUnions,
+  )
+import Data.Morpheus.Server.Deriving.Kinded.Value (KindedValue (..))
+import Data.Morpheus.Server.Deriving.Utils.Kinded (CatType (..), KindedProxy (KindedProxy), catMap, isIN)
+import Data.Morpheus.Server.Deriving.Utils.Proxy (ContextValue (..), symbolName)
+import Data.Morpheus.Server.Deriving.Utils.Use (UseDeriving (..), UseGQLType (..), UseResolver (..), UseValue (..))
 import Data.Morpheus.Server.Types.Directives
   ( GDirectiveUsages (..),
     GQLDirective (..),
@@ -69,8 +79,13 @@
     TYPE,
     WRAPPER,
   )
-import Data.Morpheus.Server.Types.SchemaT (SchemaT, withInput)
-import Data.Morpheus.Server.Types.TypeName (TypeFingerprint (..), getFingerprint, getTypename)
+import Data.Morpheus.Server.Types.NamedResolvers (NamedResolverT (..))
+import Data.Morpheus.Server.Types.SchemaT (SchemaT, extendImplements)
+import Data.Morpheus.Server.Types.TypeName
+  ( TypeFingerprint (..),
+    typeableFingerprint,
+    typeableTypename,
+  )
 import Data.Morpheus.Server.Types.Types
   ( Arg,
     Pair,
@@ -79,26 +94,28 @@
     __typenameUndefined,
   )
 import Data.Morpheus.Server.Types.Visitors (VisitType (..))
-import Data.Morpheus.Types.GQLScalar (EncodeScalar (..))
-import Data.Morpheus.Types.GQLWrapper (EncodeWrapperValue (..))
 import Data.Morpheus.Types.ID (ID)
 import Data.Morpheus.Types.Internal.AST
-  ( Argument (..),
-    Arguments,
-    ArgumentsDefinition,
+  ( ArgumentsDefinition,
     CONST,
     DirectiveLocation (..),
+    FieldDefinition,
     GQLError,
     IN,
+    Msg (msg),
     OUT,
-    ObjectEntry (..),
-    Position (..),
-    TypeCategory (..),
-    TypeName,
+    QUERY,
+    ScalarDefinition (..),
+    TRUE,
+    TypeContent (..),
+    TypeDefinition (..),
+    TypeRef (..),
     TypeWrapper (..),
+    VALID,
     Value (..),
     internal,
     mkBaseType,
+    mkField,
     toNullable,
     unitTypeName,
   )
@@ -108,30 +125,22 @@
 import GHC.TypeLits (KnownSymbol)
 import Relude hiding (Seq, Undefined, fromList, intercalate)
 
-__isEmptyType :: forall f a. GQLType a => f a -> Bool
-__isEmptyType _ = deriveFingerprint (OutputType :: CatType OUT a) == InternalFingerprint __typenameUndefined
-
-__typeData :: (GQLType a) => CatType cat a -> TypeData
-__typeData proxy@InputType = __type proxy IN
-__typeData proxy@OutputType = __type proxy OUT
-
-deriveTypename :: (GQLType a) => CatType cat a -> TypeName
-deriveTypename proxy = gqlTypeName $ __typeData proxy
-
-deriveFingerprint :: (GQLType a) => CatType cat a -> TypeFingerprint
-deriveFingerprint proxy = gqlFingerprint $ __typeData proxy
+ignoreUndefined :: forall f a. GQLType a => f a -> Maybe (f a)
+ignoreUndefined proxy
+  | gqlFingerprint (__type (OutputType :: CatType OUT a)) == InternalFingerprint __typenameUndefined = Nothing
+  | otherwise = Just proxy
 
 deriveTypeData ::
+  forall c (a :: Type).
   Typeable a =>
-  f a ->
+  CatType c a ->
   DirectiveUsages ->
-  TypeCategory ->
   TypeData
-deriveTypeData proxy GDirectiveUsages {typeDirectives} cat =
+deriveTypeData proxy GDirectiveUsages {typeDirectives} =
   TypeData
-    { gqlTypeName = foldr (`applyTypeName` (cat == IN)) (getTypename proxy) typeDirectives,
+    { gqlTypeName = foldr (`applyTypeName` isIN proxy) (typeableTypename (Proxy @a)) typeDirectives,
       gqlWrappers = mkBaseType,
-      gqlFingerprint = getFingerprint cat proxy
+      gqlFingerprint = typeableFingerprint proxy
     }
 
 list :: TypeWrapper -> TypeWrapper
@@ -140,6 +149,27 @@
 wrapper :: (TypeWrapper -> TypeWrapper) -> TypeData -> TypeData
 wrapper f TypeData {..} = TypeData {gqlWrappers = f gqlWrappers, ..}
 
+type Lifted a = (PARAM (KIND a) a)
+
+kindedProxy :: f a -> KindedProxy (KIND a) a
+kindedProxy _ = KindedProxy
+
+lifted :: CatType cat a -> CatType cat (f (KIND a) (Lifted a))
+lifted InputType = InputType
+lifted OutputType = OutputType
+
+type IgnoredResolver = (Resolver QUERY () Identity)
+
+-- lifts monadic object types with specific monad
+type family PARAM k a where
+  PARAM TYPE (t m) = t IgnoredResolver
+  PARAM k a = a
+
+type DERIVE_T c a = (DeriveKindedType GQLType GQLValue c (KIND a) (Lifted a))
+
+cantBeInputType :: (MonadError GQLError m, GQLType a) => CatType cat a -> m b
+cantBeInputType proxy = throwError $ internal $ "type " <> msg (gqlTypeName $ __type proxy) <> "can't be a input type"
+
 -- | GraphQL type, every graphQL type should have an instance of 'GHC.Generics.Generic' and 'GQLType'.
 --
 --  @
@@ -161,197 +191,146 @@
   directives :: f a -> DirectiveUsages
   directives _ = mempty
 
-  __type :: f a -> TypeCategory -> TypeData
-  default __type :: Typeable a => f a -> TypeCategory -> TypeData
+  __type :: CatType cat a -> TypeData
+  default __type :: Typeable a => CatType cat a -> TypeData
   __type proxy = deriveTypeData proxy (directives proxy)
 
+  __deriveType :: CatType c a -> SchemaT c (TypeDefinition c CONST)
+  default __deriveType :: DERIVE_T c a => CatType c a -> SchemaT c (TypeDefinition c CONST)
+  __deriveType = deriveKindedType withDir . lifted
+
+  __deriveFieldArguments :: CatType c a -> SchemaT c (Maybe (ArgumentsDefinition CONST))
+  default __deriveFieldArguments ::
+    DeriveFieldArguments GQLType (HasArguments a) =>
+    CatType c a ->
+    SchemaT c (Maybe (ArgumentsDefinition CONST))
+  __deriveFieldArguments OutputType = deriveFieldArguments withDir (Proxy @(HasArguments a))
+  __deriveFieldArguments InputType = pure Nothing
+
 instance GQLType Int where
   type KIND Int = SCALAR
-  __type _ = mkTypeData "Int"
+  __type = mkTypeData "Int"
 
 instance GQLType Double where
   type KIND Double = SCALAR
-  __type _ = mkTypeData "Float"
+  __type = mkTypeData "Float"
 
 instance GQLType Float where
   type KIND Float = SCALAR
-  __type _ = mkTypeData "Float32"
+  __type = mkTypeData "Float32"
 
 instance GQLType Text where
   type KIND Text = SCALAR
-  __type _ = mkTypeData "String"
+  __type = mkTypeData "String"
 
 instance GQLType Bool where
   type KIND Bool = SCALAR
-  __type _ = mkTypeData "Boolean"
+  __type = mkTypeData "Boolean"
 
 instance GQLType ID where
   type KIND ID = SCALAR
-  __type _ = mkTypeData "ID"
+  __type = mkTypeData "ID"
 
 instance GQLType (Value CONST) where
   type KIND (Value CONST) = CUSTOM
-  __type _ = mkTypeData "INTERNAL_VALUE"
+  __type = mkTypeData "INTERNAL_VALUE"
+  __deriveType = deriveScalarDefinition (const $ ScalarDefinition pure) withDir
 
 -- WRAPPERS
 instance GQLType () where
-  __type _ = mkTypeData unitTypeName
+  __type = mkTypeData unitTypeName
 
 instance Typeable m => GQLType (Undefined m) where
-  type KIND (Undefined m) = CUSTOM
-  __type _ = mkTypeData __typenameUndefined
+  __type = mkTypeData __typenameUndefined
 
 instance GQLType a => GQLType (Maybe a) where
   type KIND (Maybe a) = WRAPPER
-  __type _ = wrapper toNullable . __type (Proxy @a)
+  __type = wrapper toNullable . __type . catMap (Proxy @a)
 
 instance GQLType a => GQLType [a] where
   type KIND [a] = WRAPPER
-  __type _ = wrapper list . __type (Proxy @a)
+  __type = wrapper list . __type . catMap (Proxy @a)
 
 instance GQLType a => GQLType (Set a) where
   type KIND (Set a) = WRAPPER
-  __type _ = __type $ Proxy @[a]
+  __type = __type . catMap (Proxy @[a])
 
 instance GQLType a => GQLType (NonEmpty a) where
   type KIND (NonEmpty a) = WRAPPER
-  __type _ = __type $ Proxy @[a]
+  __type = __type . catMap (Proxy @[a])
 
-instance GQLType a => GQLType (Seq a) where
+instance (GQLType a) => GQLType (Seq a) where
   type KIND (Seq a) = WRAPPER
-  __type _ = __type $ Proxy @[a]
+  __type = __type . catMap (Proxy @[a])
 
 instance GQLType a => GQLType (Vector a) where
   type KIND (Vector a) = WRAPPER
-  __type _ = __type $ Proxy @[a]
+  __type = __type . catMap (Proxy @[a])
 
 instance GQLType a => GQLType (SubscriptionField a) where
   type KIND (SubscriptionField a) = WRAPPER
-  __type _ = __type $ Proxy @a
+  __type = __type . catMap (Proxy @a)
 
 instance (Typeable a, Typeable b, GQLType a, GQLType b) => GQLType (Pair a b) where
   directives _ = typeDirective InputTypeNamespace {inputTypeNamespace = "Input"}
 
 -- Manual
 
-instance GQLType b => GQLType (a -> b) where
+instance (GQLType b, GQLType a) => GQLType (a -> b) where
   type KIND (a -> b) = CUSTOM
-  __type _ = __type $ Proxy @b
+  __type = __type . catMap (Proxy @b)
+  __deriveType OutputType = __deriveType (OutputType :: CatType OUT b)
+  __deriveType proxy = cantBeInputType proxy
 
 instance (GQLType k, GQLType v, Typeable k, Typeable v) => GQLType (Map k v) where
   type KIND (Map k v) = CUSTOM
-  __type _ = __type $ Proxy @[Pair k v]
+  __type = __type . catMap (Proxy @[Pair k v])
+  __deriveType = __deriveType . catMap (Proxy @[(k, v)])
 
 instance GQLType a => GQLType (Resolver o e m a) where
   type KIND (Resolver o e m a) = CUSTOM
-  __type _ = __type $ Proxy @a
+  __type = __type . catMap (Proxy @a)
+  __deriveType = __deriveType . catMap (Proxy @a)
 
 instance (Typeable a, Typeable b, GQLType a, GQLType b) => GQLType (a, b) where
-  __type _ = __type $ Proxy @(Pair a b)
+  __type = __type . catMap (Proxy @(Pair a b))
   directives _ = typeDirective InputTypeNamespace {inputTypeNamespace = "Input"}
 
-instance (GQLType value) => GQLType (Arg name value) where
+instance (KnownSymbol name, GQLType value) => GQLType (Arg name value) where
   type KIND (Arg name value) = CUSTOM
-  __type _ = __type (Proxy @value)
-
-instance (GQLType interface) => GQLType (TypeGuard interface possibleTypes) where
-  type KIND (TypeGuard interface possibleTypes) = CUSTOM
-  __type _ = __type (Proxy @interface)
+  __type = __type . catMap (Proxy @value)
+  __deriveType OutputType = cantBeInputType (OutputType :: CatType OUT (Arg name value))
+  __deriveType p@InputType = do
+    injectType withDir proxy
+    fillTypeContent withDir p content
+    where
+      content :: TypeContent TRUE IN CONST
+      content = DataInputObject (singleton argName field)
+      proxy = InputType :: CatType IN value
+      argName = symbolName (Proxy @name)
+      field :: FieldDefinition IN CONST
+      field = mkField Nothing argName (TypeRef gqlTypeName gqlWrappers)
+      TypeData {gqlTypeName, gqlWrappers} = useTypeData withGQL proxy
 
-instance (GQLType a) => GQLType (Proxy a) where
-  type KIND (Proxy a) = KIND a
-  __type _ = __type (Proxy @a)
+instance (DERIVE_TYPE GQLType OUT i, DERIVE_TYPE GQLType OUT u) => GQLType (TypeGuard i u) where
+  type KIND (TypeGuard i u) = CUSTOM
+  __type = __type . catMap (Proxy @i)
+  __deriveType OutputType = do
+    unions <- deriveTypeGuardUnions withDir union
+    extendImplements (useTypename withGQL interface) unions
+    deriveInterfaceDefinition withDir interface
+    where
+      interface = OutputType :: CatType OUT i
+      union = OutputType :: CatType OUT u
+  __deriveType proxy = cantBeInputType proxy
 
 instance (GQLType a) => GQLType (NamedResolverT m a) where
   type KIND (NamedResolverT m a) = CUSTOM
-  __type _ = __type (Proxy :: Proxy a)
-
-type EncodeValue a = EncodeKind (KIND a) a
-
-encodeArguments :: forall m a. (MonadError GQLError m, EncodeValue a) => a -> m (Arguments CONST)
-encodeArguments x = resultOr (const $ throwError err) pure (encode x) >>= unpackValue
-  where
-    err = internal "could not encode arguments. Arguments should be an object like type!"
-    unpackValue (Object v) = pure $ fmap toArgument v
-    unpackValue _ = throwError err
-    toArgument ObjectEntry {..} = Argument (Position 0 0) entryName entryValue
-
-encode :: forall a. EncodeValue a => a -> GQLResult (Value CONST)
-encode x = encodeKind (ContextValue x :: ContextValue (KIND a) a)
-
-class EncodeKind (kind :: DerivingKind) (a :: Type) where
-  encodeKind :: ContextValue kind a -> GQLResult (Value CONST)
-
-instance (EncodeWrapperValue f, EncodeValue a) => EncodeKind WRAPPER (f a) where
-  encodeKind = encodeWrapperValue encode . unContextValue
-
-instance (EncodeScalar a) => EncodeKind SCALAR a where
-  encodeKind = pure . Scalar . encodeScalar . unContextValue
-
-instance (EncodeConstraint a) => EncodeKind TYPE a where
-  encodeKind = exploreResolvers . unContextValue
-
-instance EncodeKind CUSTOM (Value CONST) where
-  encodeKind = pure . unContextValue
-
--- TODO: remove me
-instance (KnownSymbol name) => EncodeKind CUSTOM (Arg name a) where
-  encodeKind _ = throwError "directives cant be tagged arguments"
-
-convertNode ::
-  DataType (GQLResult (Value CONST)) ->
-  GQLResult (Value CONST)
-convertNode
-  DataType
-    { tyIsUnion,
-      tyCons = ConsRep {consFields, consName}
-    } = encodeTypeFields consFields
-    where
-      encodeTypeFields ::
-        [FieldRep (GQLResult (Value CONST))] -> GQLResult (Value CONST)
-      encodeTypeFields [] = pure $ Enum consName
-      encodeTypeFields fields | not tyIsUnion = Object <$> (traverse fromField fields >>= fromElems)
-        where
-          fromField FieldRep {fieldSelector, fieldValue} = do
-            entryValue <- fieldValue
-            pure ObjectEntry {entryName = fieldSelector, entryValue}
-      -- Type References --------------------------------------------------------------
-      encodeTypeFields _ = throwError (internal "input unions are not supported")
-
--- Types & Constrains -------------------------------------------------------
-class (EncodeKind (KIND a) a) => ExplorerConstraint a
-
-instance (EncodeKind (KIND a) a) => ExplorerConstraint a
-
-exploreResolvers :: forall a. EncodeConstraint a => a -> GQLResult (Value CONST)
-exploreResolvers =
-  convertNode
-    . deriveValue
-      ( DeriveValueOptions
-          { __valueApply = encode,
-            __valueTypeName = deriveTypename (InputType :: CatType IN a),
-            __valueGetType = __typeData . inputType
-          } ::
-          DeriveValueOptions IN GQLType ExplorerConstraint (GQLResult (Value CONST))
-      )
-
-type EncodeConstraint a =
-  ( Generic a,
-    GQLType a,
-    DeriveWith GQLType ExplorerConstraint (GQLResult (Value CONST)) (Rep a)
-  )
-
--- DIRECTIVES
-type DeriveArguments a = DeriveArgs GQLType DeriveType (KIND a) a
-
-type DirectiveUsages = GDirectiveUsages GQLType DeriveDirective
-
-deriveArguments :: DeriveArgs GQLType DeriveType k a => f k a -> SchemaT OUT (ArgumentsDefinition CONST)
-deriveArguments = withInput . deriveArgs withDir withDeriveType
-
-class (EncodeValue a, DeriveArguments a) => DeriveDirective a
+  __type = __type . catMap (Proxy :: Proxy a)
+  __deriveType = __deriveType . catMap (Proxy @a)
+  __deriveFieldArguments = __deriveFieldArguments . catMap (Proxy @a)
 
-instance (EncodeValue a, DeriveArguments a) => DeriveDirective a
+type DirectiveUsages = GDirectiveUsages GQLType GQLValue
 
 newtype InputTypeNamespace = InputTypeNamespace {inputTypeNamespace :: Text}
   deriving (Generic)
@@ -375,50 +354,48 @@
     | isInput = inputTypeNamespace <> name
     | otherwise = name
 
-withArgs :: UseArguments DeriveDirective
-withArgs =
-  UseArguments
-    { useDeriveArguments = deriveArguments . withKind,
-      useEncodeArguments = encodeArguments
+withValue :: UseValue GQLValue
+withValue =
+  UseValue
+    { useDecodeValue = decodeValue,
+      useEncodeValue = encodeValue
     }
 
 withGQL :: UseGQLType GQLType
 withGQL =
   UseGQLType
-    { __useFingerprint = \c v -> gqlFingerprint (__type v c),
-      __useTypename = \c v -> gqlTypeName (__type v c),
-      __useTypeData = __type
+    { useFingerprint = gqlFingerprint . __type,
+      useTypename = gqlTypeName . __type,
+      useTypeData = __type,
+      useDeriveType = __deriveType,
+      useDeriveFieldArguments = __deriveFieldArguments
     }
 
-withDir :: UseDirective GQLType DeriveDirective
+withDir :: UseDeriving GQLType GQLValue
 withDir =
-  UseDirective
+  UseDeriving
     { __directives = directives,
       dirGQL = withGQL,
-      dirArgs = withArgs
+      dirArgs = withValue
     }
 
-withKind :: f a -> KindedProxy (KIND a) a
-withKind _ = KindedProxy
-
-withDeriveType :: UseDeriveType DeriveType
-withDeriveType =
-  UseDeriveType
-    { useDeriveType = deriveType,
-      useDeriveContent = deriveContent
-    }
+class GQLType a => GQLValue a where
+  decodeValue :: Value VALID -> ResolverState a
+  encodeValue :: a -> GQLResult (Value CONST)
 
--- DERIVE TYPE
+instance (GQLType a, KindedValue GQLType GQLValue (KIND a) a) => GQLValue a where
+  encodeValue value = encodeKindedValue withDir (ContextValue value :: ContextValue (KIND a) a)
+  decodeValue = decodeKindedValue withDir (Proxy @(KIND a))
 
--- |  Generates internal GraphQL Schema for query validation and introspection rendering
-class DeriveType (c :: TypeCategory) (a :: Type) where
-  deriveType :: CatType c a -> SchemaT c ()
-  deriveContent :: CatType c a -> TyContentM c
+class GQLResolver (m :: Type -> Type) resolver where
+  deriveResolver :: resolver -> m (ResolverValue m)
 
-instance (GQLType a, DeriveKindedType GQLType DeriveType DeriveDirective cat (KIND a) a) => DeriveType cat a where
-  deriveType = deriveKindedType withDir withDeriveType . liftKind
-  deriveContent = deriveKindedContent withDir withDeriveType . liftKind
+instance (KindedResolver GQLType GQLResolver GQLValue (KIND a) m a) => GQLResolver m a where
+  deriveResolver resolver = kindedResolver withRes (ContextValue resolver :: ContextValue (KIND a) a)
 
-liftKind :: CatType cat a -> CatType cat (f (KIND a) a)
-liftKind InputType = InputType
-liftKind OutputType = OutputType
+withRes :: UseResolver GQLResolver GQLType GQLValue
+withRes =
+  UseResolver
+    { useEncodeResolver = deriveResolver,
+      resDrv = withDir
+    }
diff --git a/src/Data/Morpheus/Server/Types/NamedResolvers.hs b/src/Data/Morpheus/Server/Types/NamedResolvers.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Morpheus/Server/Types/NamedResolvers.hs
@@ -0,0 +1,108 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Data.Morpheus.Server.Types.NamedResolvers
+  ( ResolveNamed (..),
+    NamedResolverT (..),
+    resolve,
+    useBatched,
+    Dependency,
+    ignoreBatching,
+    NamedRef,
+  )
+where
+
+import Control.Monad.Except
+import Data.Aeson (ToJSON)
+import Data.Morpheus.Types.ID (ID)
+import Data.Morpheus.Types.Internal.AST (GQLError, internal)
+import Data.Vector (Vector)
+import Relude
+
+type family Target a :: Type where
+  Target (Maybe a) = a
+  Target [a] = a
+  Target (Set a) = a
+  Target (NonEmpty a) = a
+  Target (Seq a) = a
+  Target (Vector a) = a
+  Target a = a
+
+type family Dependency a :: Type where
+  -- wrappers
+  Dependency (Maybe a) = Dependency a
+  Dependency [a] = Dependency a
+  Dependency (Set a) = Dependency a
+  Dependency (NonEmpty a) = Dependency a
+  Dependency (Seq a) = Dependency a
+  Dependency (Vector a) = Dependency a
+  -- custom
+  Dependency a = Dep a
+
+ignoreBatching :: (Monad m) => (a -> m b) -> [a] -> m [Maybe b]
+ignoreBatching f = traverse (fmap Just . f)
+
+forward :: (Monad m, Dependency a ~ a) => [Dependency a] -> m [Maybe a]
+forward = pure . map Just
+
+{-# DEPRECATED useBatched " this function is obsolete" #-}
+useBatched :: (ResolveNamed m a, MonadError GQLError m) => Dependency a -> m a
+useBatched x = resolveBatched [x] >>= res
+  where
+    res [Just v] = pure v
+    res _ = throwError (internal "named resolver should return single value for single argument")
+
+{-# DEPRECATED resolveNamed "use: resolveBatched" #-}
+
+instance ResolveNamed m Int where
+  type Dep Int = Int
+  resolveBatched = forward
+
+instance ResolveNamed m Float where
+  type Dep Float = Float
+  resolveBatched = forward
+
+instance ResolveNamed m Double where
+  type Dep Double = Double
+  resolveBatched = forward
+
+instance ResolveNamed m Text where
+  type Dep Text = Text
+  resolveBatched = forward
+
+instance ResolveNamed m Bool where
+  type Dep Bool = Bool
+  resolveBatched = forward
+
+instance ResolveNamed m ID where
+  type Dep ID = ID
+  resolveBatched = forward
+
+class ToJSON (Dependency a) => ResolveNamed (m :: Type -> Type) (a :: Type) where
+  type Dep a :: Type
+  resolveBatched :: MonadError GQLError m => [Dependency a] -> m [Maybe a]
+
+  resolveNamed :: MonadError GQLError m => Dependency a -> m a
+  resolveNamed = useBatched
+
+data NamedResolverT (m :: Type -> Type) a where
+  NamedResolverT :: ResolveNamed m (Target a) => m (NamedRef a) -> NamedResolverT m a
+
+type family NamedRef a :: Type where
+  NamedRef [a] = [Dependency a]
+  NamedRef (Set a) = [Dependency a]
+  NamedRef (NonEmpty a) = [Dependency a]
+  NamedRef (Seq a) = [Dependency a]
+  NamedRef (Vector a) = [Dependency a]
+  NamedRef a = Dependency a
+
+resolve :: ResolveNamed m (Target a) => m (NamedRef a) -> NamedResolverT m a
+resolve = NamedResolverT
diff --git a/src/Data/Morpheus/Server/Types/TypeName.hs b/src/Data/Morpheus/Server/Types/TypeName.hs
--- a/src/Data/Morpheus/Server/Types/TypeName.hs
+++ b/src/Data/Morpheus/Server/Types/TypeName.hs
@@ -3,6 +3,7 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PolyKinds #-}
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications #-}
@@ -10,9 +11,8 @@
 {-# LANGUAGE NoImplicitPrelude #-}
 
 module Data.Morpheus.Server.Types.TypeName
-  ( getTypename,
-    getTypeConstructorNames,
-    getFingerprint,
+  ( typeableTypename,
+    typeableFingerprint,
     TypeFingerprint (..),
   )
 where
@@ -23,12 +23,13 @@
 import Data.Morpheus.App.Internal.Resolving
   ( Resolver,
   )
-import Data.Morpheus.Server.NamedResolvers (NamedResolverT (..))
+import Data.Morpheus.Server.Deriving.Utils.Kinded (CatType (..))
+import Data.Morpheus.Server.Types.NamedResolvers (NamedResolverT (..))
 import Data.Morpheus.Server.Types.Types
   ( Pair,
   )
 import Data.Morpheus.Types.Internal.AST
-  ( TypeCategory,
+  ( TypeCategory (..),
     TypeName,
     packName,
   )
@@ -58,29 +59,31 @@
       Ord
     )
 
-getTypename :: Typeable a => f a -> TypeName
-getTypename = packName . intercalate "" . getTypeConstructorNames
+typeableTypename :: Typeable a => f a -> TypeName
+typeableTypename = packName . intercalate "" . fmap (pack . tyConName . replacePairCon) . getTypeConstructors
 
-getTypeConstructorNames :: Typeable a => f a -> [Text]
-getTypeConstructorNames = fmap (pack . tyConName . replacePairCon) . getTypeConstructors
+typeableFingerprint :: Typeable a => CatType c a -> TypeFingerprint
+typeableFingerprint p@InputType = TypeableFingerprint IN $ tyConFingerprint <$> getTypeConstructors p
+typeableFingerprint p@OutputType = TypeableFingerprint OUT $ tyConFingerprint <$> getTypeConstructors p
 
 getTypeConstructors :: Typeable a => f a -> [TyCon]
 getTypeConstructors = ignoreResolver . splitTyConApp . typeRep
 
+rep :: forall k (a :: k) f. Typeable a => f a -> TyCon
+rep = typeRepTyCon . typeRep
+
 -- | replaces typeName (A,B) with Pair_A_B
 replacePairCon :: TyCon -> TyCon
-replacePairCon x | hsPair == x = gqlPair
-  where
-    hsPair = typeRepTyCon $ typeRep $ Proxy @(Int, Int)
-    gqlPair = typeRepTyCon $ typeRep $ Proxy @(Pair Int Int)
+replacePairCon x | rep (Proxy @(Int, Int)) == x = rep (Proxy @(Pair Int Int))
 replacePairCon x = x
 
--- Ignores Resolver name  from typeName
-ignoreResolver :: (TyCon, [TypeRep]) -> [TyCon]
-ignoreResolver (con, _) | con == typeRepTyCon (typeRep $ Proxy @Resolver) = []
-ignoreResolver (con, _) | con == typeRepTyCon (typeRep $ Proxy @NamedResolverT) = []
-ignoreResolver (con, args) =
-  con : concatMap (ignoreResolver . splitTyConApp) args
+ignoredTypes :: [TyCon]
+ignoredTypes =
+  [ rep (Proxy @Resolver),
+    rep (Proxy @NamedResolverT)
+  ]
 
-getFingerprint :: Typeable a => TypeCategory -> f a -> TypeFingerprint
-getFingerprint category = TypeableFingerprint category . fmap tyConFingerprint . getTypeConstructors
+-- ignores resolver names from typename
+ignoreResolver :: (TyCon, [TypeRep]) -> [TyCon]
+ignoreResolver (con, _) | con `elem` ignoredTypes = []
+ignoreResolver (con, args) = con : concatMap (ignoreResolver . splitTyConApp) args
