diff --git a/lib/Proteome/Config.hs b/lib/Proteome/Config.hs
--- a/lib/Proteome/Config.hs
+++ b/lib/Proteome/Config.hs
@@ -15,21 +15,26 @@
 import qualified Data.Map as Map
 import Data.Foldable (traverse_)
 import Data.Map.Strict (Map)
-import Neovim (NvimObject, toObject, Dictionary, Object, vim_command')
+import Data.Text.Prettyprint.Doc ((<+>), viaShow)
+import Neovim (NvimObject(..), Dictionary, Object(ObjectMap), vim_command')
 import Ribosome.Data.Ribo (Ribo)
+import Ribosome.Internal.NvimObject (extractObject)
 import qualified Ribosome.Data.Ribo as Ribo (inspect)
 import qualified Proteome.Data.Env as Env (mainProject)
 import Proteome.Data.Project (
   Project(Project, types),
   ProjectType(ProjectType, projectType),
+  ProjectLang,
   ProjectName(ProjectName),
   ProjectMetadata(DirProject),
   )
 import Proteome.Data.Proteome
 
-newtype ProjectConfig =
+data ProjectConfig =
   ProjectConfig {
-    projectTypes :: Map ProjectType [FilePath]
+    projectTypes :: Map ProjectType [FilePath],
+    typeMap :: Map ProjectType [ProjectType],
+    langMap :: Map ProjectType [ProjectLang]
   }
   deriving (Generic, NFData)
 
@@ -37,8 +42,15 @@
   toObject ProjectConfig {..} =
     (toObject :: Dictionary -> Object) . Map.fromList $
     [
-      ("projectTypes", toObject projectTypes)
+      ("projectTypes", toObject projectTypes),
+      ("typeMap", toObject typeMap)
     ]
+  fromObject (ObjectMap o) = do
+    projectTypes' <- extractObject "projectTypes" o
+    typeMap' <- extractObject "typeMap" o
+    langMap' <- extractObject "langMap" o
+    return $ ProjectConfig projectTypes' typeMap' langMap'
+  fromObject o = Left ("invalid type for ProjectConfig: " <+> viaShow o)
 
 runtime :: FilePath -> Ribo a ()
 runtime path = vim_command' $ "runtime " ++ path ++ ".vim"
diff --git a/lib/Proteome/Data/ProjectSpec.hs b/lib/Proteome/Data/ProjectSpec.hs
--- a/lib/Proteome/Data/ProjectSpec.hs
+++ b/lib/Proteome/Data/ProjectSpec.hs
@@ -9,7 +9,7 @@
 
 import GHC.Generics (Generic)
 import Control.DeepSeq (NFData)
-import qualified Data.Map as Map
+import qualified Data.Map as Map (fromList)
 import Data.Maybe (catMaybes)
 import Data.MessagePack
 import Neovim.Classes (NvimObject(..), Dictionary)
diff --git a/lib/Proteome/Init.hs b/lib/Proteome/Init.hs
--- a/lib/Proteome/Init.hs
+++ b/lib/Proteome/Init.hs
@@ -10,7 +10,7 @@
 import System.FilePath (takeFileName, takeDirectory)
 import System.Log.Logger (updateGlobalLogger, setLevel, Priority(ERROR))
 import Control.Monad.IO.Class (MonadIO)
-import Neovim.Context.Internal (Neovim)
+import Neovim (Neovim)
 import UnliftIO.STM (TVar, newTVarIO)
 import Ribosome.Config.Settings (setting, settingE, updateSetting)
 import Ribosome.Data.Ribo (Ribo)
diff --git a/lib/Proteome/Project/Resolve.hs b/lib/Proteome/Project/Resolve.hs
--- a/lib/Proteome/Project/Resolve.hs
+++ b/lib/Proteome/Project/Resolve.hs
@@ -5,10 +5,12 @@
 ) where
 
 import Data.List (find)
+import Data.List.Utils (uniq)
 import Data.Maybe (fromMaybe)
+import Data.Map.Strict ((!?), Map)
 import System.FilePath (takeDirectory)
 import Ribosome.Data.Maybe (orElse)
-import Proteome.Config (ProjectConfig)
+import Proteome.Config (ProjectConfig(ProjectConfig))
 import Proteome.Data.Project (
   Project(Project),
   ProjectName(..),
@@ -58,6 +60,25 @@
   where
     byRoot = find (hasProjectRoot root) explicit
 
+augment :: Eq a => Map ProjectType [a] -> ProjectType -> [a] -> [a]
+augment m tpe as =
+  case m !? tpe of
+    Just extra -> uniq $ as ++ extra
+    Nothing -> as
+
+augmentTypes :: ProjectConfig -> ProjectType -> [ProjectType] -> [ProjectType]
+augmentTypes (ProjectConfig _ typeMap _) =
+  augment typeMap
+
+augmentLangs :: ProjectConfig -> ProjectType -> [ProjectLang] -> [ProjectLang]
+augmentLangs (ProjectConfig _ _ langMap) =
+  augment langMap
+
+augmentFromConfig :: ProjectConfig -> Project -> Project
+augmentFromConfig config (Project meta@(DirProject _ _ (Just tpe)) types lang langs) =
+  Project meta (augmentTypes config tpe types) lang (augmentLangs config tpe langs)
+augmentFromConfig _ project = project
+
 resolveProject ::
   [FilePath] ->
   [ProjectSpec] ->
@@ -66,9 +87,10 @@
   ProjectName ->
   Maybe ProjectType ->
   Project
-resolveProject baseDirs explicit _ root name tpe =
-  fromMaybe byTypeOrVirtual byRoot
+resolveProject baseDirs explicit config root name tpe =
+  augmentFromConfig config project
   where
+    project = fromMaybe byTypeOrVirtual byRoot
     byTypeOrVirtual = fromMaybe (virtualProject name) byType
     byType = tpe >>= resolveByType baseDirs explicit root name
     byRoot = resolveByRoot explicit root
diff --git a/lib/Proteome/Settings.hs b/lib/Proteome/Settings.hs
--- a/lib/Proteome/Settings.hs
+++ b/lib/Proteome/Settings.hs
@@ -12,7 +12,7 @@
   tagsFileName,
 ) where
 
-import qualified Data.Map as Map
+import Data.Default.Class (Default(def))
 import Ribosome.Config.Settings
 import Proteome.Data.Project (ProjectName, ProjectType)
 import Proteome.Data.ProjectSpec (ProjectSpec)
@@ -31,7 +31,7 @@
 projectTypeDirs = Setting "project_type_dirs" True (Just [])
 
 projectConfig :: Setting ProjectConfig
-projectConfig = Setting "project_config" True (Just (ProjectConfig Map.empty))
+projectConfig = Setting "project_config" True (Just (ProjectConfig def def def))
 
 mainName :: Setting ProjectName
 mainName = Setting "main_name" True Nothing
diff --git a/lib/Ribosome/Config/Settings.hs b/lib/Ribosome/Config/Settings.hs
--- a/lib/Ribosome/Config/Settings.hs
+++ b/lib/Ribosome/Config/Settings.hs
@@ -20,11 +20,11 @@
 settingVariableName :: Setting a -> Ribo e String
 settingVariableName (Setting n False _) = return n
 settingVariableName (Setting n True _) = do
-  pluginName <- fmap R.name $ ask
+  pluginName <- R.name <$> ask
   return $ pluginName ++ "_" ++ n
 
 settingE :: NvimObject a => Setting a -> Ribo e (Either String a)
-settingE s @ (Setting _ _ fallback') = do
+settingE s@(Setting _ _ fallback') = do
   varName <- settingVariableName s
   raw <- vim_get_var varName
   case raw of
diff --git a/lib/Ribosome/Internal/NvimObject.hs b/lib/Ribosome/Internal/NvimObject.hs
--- a/lib/Ribosome/Internal/NvimObject.hs
+++ b/lib/Ribosome/Internal/NvimObject.hs
@@ -1,8 +1,21 @@
 module Ribosome.Internal.NvimObject(
   deriveString,
+  extractObject,
 ) where
 
-import Neovim (Object, Doc, AnsiStyle, fromObject)
+import qualified Data.ByteString.UTF8 as UTF8 (fromString)
+import Data.Map.Strict (Map, (!?))
+import Data.Text.Prettyprint.Doc ((<+>), pretty)
+import Neovim (Object(ObjectBinary), Doc, AnsiStyle, fromObject, NvimObject)
 
 deriveString :: (String -> a) -> Object -> Either (Doc AnsiStyle) a
-deriveString cons o = fmap cons ((fromObject o) :: Either (Doc AnsiStyle) String)
+deriveString cons o = fmap cons (fromObject o :: Either (Doc AnsiStyle) String)
+
+objectKeyMissing :: String -> Maybe Object -> Either (Doc AnsiStyle) Object
+objectKeyMissing _ (Just o) = Right o
+objectKeyMissing key Nothing = Left (pretty "missing key in nvim data: " <+> pretty key)
+
+extractObject :: NvimObject o => String -> Map Object Object -> Either (Doc AnsiStyle) o
+extractObject key data' = do
+  value <- objectKeyMissing key $ data' !? (ObjectBinary . UTF8.fromString) key
+  fromObject value
diff --git a/proteome.cabal b/proteome.cabal
--- a/proteome.cabal
+++ b/proteome.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: f32ec9d6b642269ce47df16a64625c3790d331489866939c1d0b07b3a38bc26d
+-- hash: d8c758912e68ecefbaea1bcb1ecd5360f7c66a328ccdaa216bfc91c304743273
 
 name:           proteome
-version:        0.2.1.0
+version:        0.3.0.0
 synopsis:       neovim project manager
 description:    Please see the README on GitHub at <https://github.com/tek/proteome-hs>
 category:       Neovim
@@ -173,6 +173,7 @@
       Config
       ResolveSpec
       TagsSpec
+      TypeMapSpec
       Paths_proteome
   hs-source-dirs:
       test/u
diff --git a/test/f/ConfigSpec.hs b/test/f/ConfigSpec.hs
--- a/test/f/ConfigSpec.hs
+++ b/test/f/ConfigSpec.hs
@@ -7,7 +7,7 @@
 import Control.Monad.IO.Class (liftIO)
 import Test.Framework
 import Data.MessagePack (Object(ObjectInt))
-import Neovim (vim_call_function, vim_get_var')
+import Neovim (vim_call_function, vim_get_var', vim_command')
 import Ribosome.Data.Ribo (Ribo)
 import Proteome.Test.Functional (specWith)
 import Config (vars)
@@ -15,6 +15,7 @@
 configSpec :: Ribo env ()
 configSpec = do
   _ <- vim_call_function "ProReadConfig" []
+  vim_command' "doautocmd User Test"
   value <- vim_get_var' "flag"
   liftIO $ assertEqual value (ObjectInt 1)
 
diff --git a/test/u/ResolveSpec.hs b/test/u/ResolveSpec.hs
--- a/test/u/ResolveSpec.hs
+++ b/test/u/ResolveSpec.hs
@@ -4,8 +4,20 @@
   htf_thisModulesTests
 ) where
 
+import qualified Data.Map as Map (fromList)
+import Data.Default.Class (Default(def))
 import Test.Framework
 import Ribosome.File (canonicalPaths)
+import Proteome.Config (ProjectConfig(ProjectConfig))
+import Proteome.Data.Project (
+  Project(Project),
+  ProjectRoot(ProjectRoot),
+  ProjectType(ProjectType),
+  ProjectName(ProjectName),
+  ProjectLang(ProjectLang),
+  ProjectMetadata(DirProject),
+  )
+import Proteome.Project.Resolve (resolveProject)
 
 paths :: [FilePath]
 paths = [
@@ -18,3 +30,38 @@
   canon <- canonicalPaths paths
   print canon
   assertNotEqual canon paths
+
+root :: ProjectRoot
+root = ProjectRoot "/projects/haskell/flagellum"
+
+name :: ProjectName
+name = ProjectName "flagellum"
+
+tpe :: ProjectType
+tpe = ProjectType "haskell"
+
+tpe1 :: ProjectType
+tpe1 = ProjectType "idris"
+
+tpe2 :: ProjectType
+tpe2 = ProjectType "agda"
+
+lang :: ProjectLang
+lang = ProjectLang "haskell"
+
+lang1 :: ProjectLang
+lang1 = ProjectLang "idris"
+
+lang2 :: ProjectLang
+lang2 = ProjectLang "agda"
+
+config :: ProjectConfig
+config = ProjectConfig def (Map.fromList [(tpe, [tpe1, tpe2])]) (Map.fromList [(tpe, [lang1, lang2])])
+
+targetProject :: Project
+targetProject = Project (DirProject name root (Just tpe)) [tpe1, tpe2] (Just lang) [lang1, lang2]
+
+test_typeMap :: IO ()
+test_typeMap = do
+  let project = resolveProject ["/projects"] [] config root name (Just tpe)
+  assertEqual targetProject project
diff --git a/test/u/SpecMain.hs b/test/u/SpecMain.hs
--- a/test/u/SpecMain.hs
+++ b/test/u/SpecMain.hs
@@ -4,6 +4,7 @@
 
 import {-@ HTF_TESTS @-} TagsSpec
 import {-@ HTF_TESTS @-} ResolveSpec
+import {-@ HTF_TESTS @-} TypeMapSpec
 import Test.Framework
 import Test.Framework.BlackBoxTest ()
 
diff --git a/test/u/TypeMapSpec.hs b/test/u/TypeMapSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/u/TypeMapSpec.hs
@@ -0,0 +1,35 @@
+{-# OPTIONS_GHC -F -pgmF htfpp #-}
+
+module TypeMapSpec(
+  htf_thisModulesTests
+) where
+
+import Control.Lens (set)
+import Test.Framework
+import qualified Ribosome.Data.Ribo as Ribo (modify)
+import Ribosome.Test.Unit (tempDir)
+import Proteome.Data.Proteome (Proteome)
+import Proteome.Data.Env (_mainProject)
+import Proteome.Data.Project (
+  ProjectName(..),
+  ProjectRoot(..),
+  ProjectType(..),
+  ProjectLang(..),
+  ProjectMetadata(DirProject),
+  _meta,
+  _lang,
+  )
+import Proteome.Test.Unit (specWithDef)
+import Config (vars)
+
+main :: FilePath -> ProjectMetadata
+main root = DirProject (ProjectName "flagellum") (ProjectRoot root) (Just (ProjectType "haskell"))
+
+typeMapSpec :: Proteome ()
+typeMapSpec = do
+  root <- tempDir "projects/haskell/flagellum"
+  Ribo.modify $ set (_mainProject._meta) (main root)
+  Ribo.modify $ set (_mainProject._lang) (Just (ProjectLang "idris"))
+
+test_typeMap :: IO ()
+test_typeMap = vars >>= specWithDef typeMapSpec
