diff --git a/hyakko.cabal b/hyakko.cabal
--- a/hyakko.cabal
+++ b/hyakko.cabal
@@ -1,5 +1,5 @@
 name:             hyakko
-version:          0.6.1
+version:          0.6.2
 cabal-version:    >= 1.6
 build-type:       Simple
 license:          MIT
@@ -17,6 +17,8 @@
                   quick-and-dirty, hundred-line-long,
                   literate-programming-style documentation generator.
 data-files:
+                  -- language definition file
+                  resources/languages.json
                   -- linear layout files
                   resources/linear/hyakko.html
                   resources/linear/hyakko.css
@@ -62,14 +64,15 @@
                   ghc >= 7,
                   filepath >= 1.2,
                   regex-pcre >= 0.9,
-                  containers >= 0.4,
+                  unordered-containers >= 0.2,
                   directory >= 1,
                   pandoc >= 1.10,
                   bytestring >= 0.9,
                   text >= 0.11,
                   highlighting-kate >= 0.5,
                   blaze-html >= 0.5,
-                  cmdargs >= 0.10
+                  cmdargs >= 0.10,
+                  aeson >= 0.6
   hs-source-dirs: src
   ghc-options:    -O2 -Wall
   main-is:        Hyakko.lhs
diff --git a/resources/languages.json b/resources/languages.json
new file mode 100644
--- /dev/null
+++ b/resources/languages.json
@@ -0,0 +1,7 @@
+{ ".hs":     {"name": "haskell", "symbol": "--"}
+, ".lhs":    {"name": "haskell", "symbol": "--", "literate": true, "litSymbol": ">"}
+, ".coffee": {"name": "coffee", "symbol": "#"}
+, ".js":     {"name": "javascript", "symbol": "//"}
+, ".py":     {"name": "python", "symbol": "#"}
+, ".rb":     {"name": "ruby", "symbol": "#"}
+}
diff --git a/src/Hyakko.lhs b/src/Hyakko.lhs
--- a/src/Hyakko.lhs
+++ b/src/Hyakko.lhs
@@ -27,7 +27,8 @@
 There is a ["literate"
 style](http://www.haskell.org/haskellwiki/Literate_programming) of Haskell,
 only one supported at this time, but other literate styles can be added
-fairly easily.
+fairly easily via a [separate languages
+file](https://github.com/sourrust/hyakko/blob/master/resources/languages.json).
 
 > {-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}
 
@@ -35,8 +36,9 @@
 
 > import Text.Markdown
 
-> import Data.Map (Map)
-> import qualified Data.Map as M
+> import Data.Aeson
+> import Data.HashMap.Strict (HashMap)
+> import qualified Data.HashMap.Strict as M
 > import Data.ByteString.Lazy.Char8 (ByteString)
 > import qualified Data.ByteString.Lazy.Char8 as L
 > import Data.Text (Text)
@@ -45,6 +47,7 @@
 > import Data.List (sort)
 > import Data.Maybe (fromJust, isNothing)
 > import Data.Version (showVersion)
+> import Control.Applicative ((<$>), (<*>), empty)
 > import Control.Monad (filterM, (>=>), forM, forM_, unless)
 > import qualified Text.Blaze.Html as B
 > import Text.Blaze.Html.Renderer.Utf8 (renderHtml)
@@ -58,6 +61,7 @@
 >                         , createDirectoryIfMissing
 >                         , copyFile
 >                         )
+> import System.IO.Unsafe (unsafePerformIO)
 > import System.FilePath ( takeBaseName
 >                        , takeExtension
 >                        , takeFileName
@@ -102,7 +106,7 @@
 individual **section** for it. Each section is Map with `docText` and
 `codeText` properties, and eventuall `docsHtml` and `codeHtml` as well.
 
-> inSections :: [Text] -> ByteString -> [Map String Text]
+> inSections :: [Text] -> ByteString -> Sections
 > inSections xs r =
 >   let sections = sectionOff "" "" xs
 >   in map M.fromList sections
@@ -139,11 +143,11 @@
 sanitates the file — turing literate into regular source and take out
 shebangs — then feed it to `inSections`, and finally return the results.
 
-> parse :: Maybe (Map String ByteString) -> Text -> [Map String Text]
+> parse :: Maybe Language -> Text -> Sections
 > parse Nothing _       = []
 > parse (Just src) code =
->   inSections (newlines line (M.lookup "literate" src) True)
->              (src M.! "comment")
+>   inSections (newlines line (literate src) True)
+>              ("^\\s*" ++* symbol src ++* "\\s?")
 >   where line :: [Text]
 >         line = filter ((/=) "#!" . T.take 2) $ T.lines code
 
@@ -151,12 +155,12 @@
 style language. If it is normal, `newlines` for returns the same list of
 `Text` that was passed in.
 
->         newlines :: [Text] -> Maybe ByteString -> Bool -> [Text]
+>         newlines :: [Text] -> Maybe Bool -> Bool -> [Text]
 >         newlines [] _ _            = []
 >         newlines xs Nothing _      = xs
 >         newlines (x:xs) lit isText =
->           let s       = src M.! "symbol"
->               r       = "^" ++* (src M.! "symbol2") ++* "\\s?"
+>           let s       = symbol src
+>               r       = "^" ++* (fromJust $ litSymbol src) ++* "\\s?"
 >               r1      = L.pack "^\\s*$"
 >               (x', y) = if T.unpack x =~ r then
 >                      (replace r x "", False)
@@ -172,17 +176,17 @@
 
 >           where insert :: Bool -> Bool -> Text -> (Text, Bool)
 >                 insert True True _  = (T.pack . L.unpack
->                                         $ src M.! "symbol", True)
+>                                       $ symbol src, True)
 >                 insert True False _ = ("", False)
 >                 insert False _ y    = (y, True)
 
 Highlights the current file of code, using **Kate**, and outputs the the
 highlighted html to its caller.
 
-> highlight :: FilePath -> [Map String Text] -> [Text]
+> highlight :: FilePath -> Sections -> [Text]
 > highlight src section =
 >   let language = fromJust $ getLanguage src
->       langName = L.unpack $ language M.! "name"
+>       langName = L.unpack $ name_ language
 >       input    = map (\x -> T.unpack $ x M.! "codeText") section
 >       html     = B.toHtml . K.formatHtmlBlock K.defaultFormatOpts
 >                           . K.highlightAs langName
@@ -192,7 +196,7 @@
 `mapSections` is used to insert the html parts of the mapped sections of
 text into the corresponding keys of `docsHtml` and `codeHtml`.
 
-> mapSections :: [Map String Text] -> [Text] -> [Map String Text]
+> mapSections :: Sections -> [Text] -> Sections
 > mapSections section highlighted =
 >   let docText s  = toHTML . T.unpack $ s M.! "docsText"
 >       codeText i = highlighted !! i
@@ -225,7 +229,7 @@
 Depending on the layout type, `sectionTemplate` will produce the HTML that
 will be hooked into the templates layout theme.
 
-> sectionTemplate :: [Map String Text]
+> sectionTemplate :: Sections
 >                 -> Maybe String
 >                 -> [Int]
 >                 -> [(String, String)]
@@ -281,7 +285,7 @@
 template found in `resources/linear/hyakko.html` or
 `resources/parallel/hyakko.html`.
 
-> generateHTML :: Hyakko -> FilePath -> [Map String Text] -> IO ()
+> generateHTML :: Hyakko -> FilePath -> Sections -> IO ()
 > generateHTML opts src section = do
 >   let title       = takeFileName src
 >       dest        = destination (output opts) src
@@ -311,6 +315,33 @@
 Helpers & Setup
 ---------------
 
+The `Sections` type is just an alias to keep type signatures short.
+
+> type Sections = [HashMap String Text]
+
+Alias `Languages`, for the multiple different languages inside the
+`languages.json` file.
+
+> type Languages = HashMap String Language
+
+Better data type for language info — compared to the `Object` data type in
+`Aeson`.
+
+> data Language =
+>   Language { name_     :: ByteString
+>            , symbol    :: ByteString
+>            , literate  :: Maybe Bool
+>            , litSymbol :: Maybe ByteString
+>            }
+
+> instance FromJSON Language where
+>   parseJSON (Object o) = Language
+>                      <$> o .:  "name"
+>                      <*> o .:  "symbol"
+>                      <*> o .:? "literate"
+>                      <*> o .:? "litSymbol"
+>   parseJSON _          = empty
+
 Infix functions for easier concatenation with Text and ByteString.
 
 > (++.) :: Text -> Text -> Text
@@ -329,44 +360,23 @@
 >       (_, _, rp) = str =~ reg :: (String, String, String)
 >   in y ++. (T.pack rp)
 
+> readLanguageFile :: IO ByteString
+> readLanguageFile = getDataFileName "resources/languages.json"
+>                >>= L.readFile
 
 A list of the languages that Hyakko supports, mapping the file extension to
 the name of the Pygments lexer and the symbol that indicates a comment. To
 add another language to Hyakko's repertoire, add it here.
 
-> languages :: Map String (Map String ByteString)
+> languages :: Languages
 > languages =
->   let hashSymbol = ("symbol", "#")
->       language   = M.fromList [
->           (".hs", M.fromList [
->             ("name", "haskell"), ("symbol", "--")]),
->           (".lhs", M.fromList [
->             ("name", "haskell"), ("symbol", "--"),
->             ("literate", "True"), ("symbol2", ">")]),
->           (".coffee", M.fromList [
->             ("name", "coffee-script"), hashSymbol]),
->           (".js", M.fromList [
->             ("name", "javascript"), ("symbol", "//")]),
->           (".py", M.fromList [
->             ("name", "python"), hashSymbol]),
->           (".rb", M.fromList [
->             ("name", "ruby"), hashSymbol])
->           ]
-
-Does the line begin with a comment?
-
->       hasComments symbol = "^\\s*" ++* symbol ++*  "\\s?"
->       intoMap lang = M.insert "comment"
->                               (hasComments $ lang M.! "symbol")
->                               lang
-
-Build out the appropriate matchers and delimiters for each language.
-
->  in M.map intoMap language
+>   let content  = unsafePerformIO $ readLanguageFile
+>       jsonData = decode' content
+>   in fromJust jsonData
 
 Get the current language we're documenting, based on the extension.
 
-> getLanguage :: FilePath -> Maybe (Map String ByteString)
+> getLanguage :: FilePath -> Maybe Language
 > getLanguage src = M.lookup (takeExtension src) languages
 
 Compute the destination HTML path for an input source file path. If the
