diff --git a/noli.cabal b/noli.cabal
--- a/noli.cabal
+++ b/noli.cabal
@@ -1,7 +1,7 @@
 name:                noli
-version:             0.1.0.3
+version:             0.1.1.0
 synopsis:            A static site generator
-description:         Yet Another static site generator for Haskell. This time easier to use.
+description:         A static site generator
 homepage:            https://github.com/Endi1/noli#readme
 license:             MIT
 license-file:        LICENSE
@@ -23,4 +23,8 @@
                        lucid >= 2.9,
                        cmark >= 0.6,
                        directory >= 1.3.6,
-                       regex-compat >= 0.95
+                       regex-compat >= 0.95,
+                       frontmatter,
+                       yaml,
+                       bytestring,
+                       aeson
diff --git a/src/Noli.hs b/src/Noli.hs
--- a/src/Noli.hs
+++ b/src/Noli.hs
@@ -9,6 +9,7 @@
   ( unless,
     when,
   )
+import Data.ByteString hiding (unpack)
 import Data.Text (unpack)
 import qualified Data.Text.IO as DT
 import Data.Text.Internal (Text)
@@ -61,7 +62,7 @@
   Prelude.mapM_
     ( \p ->
         DT.writeFile
-          (unpack (pagename p) ++ ".html")
+          (Data.Text.unpack (pagename p) ++ ".html")
           (toStrict $ renderText $ template p)
     )
     (pages project)
@@ -70,7 +71,7 @@
   Prelude.mapM_
     ( \p ->
         DT.writeFile
-          (unpack (filename p) ++ ".html")
+          (Data.Text.unpack (filename p) ++ ".html")
           (toStrict $ renderText $ compiled_html p)
     )
     (posts project)
diff --git a/src/Noli/Types.hs b/src/Noli/Types.hs
--- a/src/Noli/Types.hs
+++ b/src/Noli/Types.hs
@@ -1,35 +1,63 @@
-module Noli.Types (Settings (..), Post (..), Project (..), Page (..), PostTemplate) where
+{-# LANGUAGE DeriveAnyClass #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
 
+module Noli.Types
+  ( Settings (..),
+    Post (..),
+    Project (..),
+    Page (..),
+    PostTemplate,
+    FrontMatter (..),
+  )
+where
+
+import Data.Aeson
 import Data.Text
+import GHC.Generics
 import Lucid.Base
 
 -- | The "dynamic" representation of the static site
-data Project = Project
-  { posts :: [Post],
-    pages :: [Page]
-  }
+data Project
+  = Project
+      { posts :: [Post],
+        pages :: [Page]
+      }
 
-data Settings = Settings
-  { -- | The name of the site
-    name :: Text,
-    -- | The author's full name
-    author :: Text,
-    -- | The path to the folder that contains the markdown files
-    posts_location :: FilePath,
-    -- | The path to where the compiled static site will be saved
-    dist_location :: FilePath,
-    -- | The path to the static folder
-    static_location :: FilePath
-  }
+data Settings
+  = Settings
+      { -- | The name of the site
+        name :: Text,
+        -- | The author's full name
+        author :: Text,
+        -- | The path to the folder that contains the markdown files
+        posts_location :: FilePath,
+        -- | The path to where the compiled static site will be saved
+        dist_location :: FilePath,
+        -- | The path to the static folder
+        static_location :: FilePath
+      }
 
-data Post = Post
-  { title :: Text,
-    location :: FilePath,
-    filename :: Text,
-    raw :: Text,
-    raw_html :: Text,
-    compiled_html :: Html ()
-  }
+newtype FrontMatter
+  = FrontMatter
+      { frontmatter_title :: Text
+      }
+  deriving (Show, Generic, ToJSON)
+
+instance FromJSON FrontMatter where
+  parseJSON = withObject "FrontMatter" $ \obj -> do
+    frontmatter_title <- obj .: "title"
+    return (FrontMatter frontmatter_title)
+
+data Post
+  = Post
+      { title :: Text,
+        location :: FilePath,
+        filename :: Text,
+        raw :: Text,
+        raw_html :: Text,
+        compiled_html :: Html ()
+      }
   deriving (Show)
 
 data Page = Page {pagename :: Text, template :: Html ()}
diff --git a/src/PostUtils.hs b/src/PostUtils.hs
--- a/src/PostUtils.hs
+++ b/src/PostUtils.hs
@@ -1,10 +1,14 @@
-module PostUtils (compilePost, extname, copyFolder) where
+module PostUtils (compilePost, extname, copyFolder, parseFrontMatter) where
 
 import CMark (commonmarkToHtml)
 import Control.Monad (unless)
+import qualified Data.ByteString as BS
+import Data.Frontmatter (IResult (Done), parseYamlFrontmatter)
 import Data.Maybe (fromJust)
 import Data.Text (pack)
+import Data.Text.Encoding (decodeUtf8)
 import Data.Text.Internal (Text)
+import Data.Yaml (Object)
 import Lucid.Base (Html)
 import Noli.Types
 import System.Directory (copyFile, createDirectory, doesDirectoryExist, doesFileExist, listDirectory)
@@ -18,14 +22,14 @@
 
 compilePost :: PostTemplate -> FilePath -> IO Post
 compilePost postCompiler fp = do
-  fileContents <- pack <$> readFile fp
+  (frontMatter, fileContents) <- parseFrontMatter fp
   let compiledFileContents = commonmarkToHtml [] fileContents
       fn = fromJust $ getPostFileName fp
-      t = getPostName fn
-      compiledHtml = postCompiler (pack t) compiledFileContents
+      t = frontmatter_title frontMatter
+      compiledHtml = postCompiler t compiledFileContents
   return
     Post
-      { title = pack t,
+      { title = t,
         location = fp,
         filename = pack fn,
         raw = fileContents,
@@ -33,18 +37,19 @@
         compiled_html = compiledHtml
       }
 
+parseFrontMatter :: FilePath -> IO (FrontMatter, Text)
+parseFrontMatter fp = do
+  f <- BS.readFile fp
+  case parseYamlFrontmatter f of
+    Done ri fm -> return (fm, decodeUtf8 ri)
+    _ -> error "Parse failure"
+
 getPostFileName :: FilePath -> Maybe String
 getPostFileName fp = case match of
   Nothing -> Nothing
   Just (x : xs) -> Just x
   where
     match = matchRegex postNameRegex fp
-
-getPostName :: String -> String
-getPostName fn =
-  let repl '_' = ' '
-      repl x = x
-   in Prelude.map repl fn
 
 copyFolder :: FilePath -> FilePath -> IO ()
 copyFolder source destination = do
