diff --git a/include/chimney.hpp b/include/chimney.hpp
index 0f5e2f6..204d039 100644
--- a/include/chimney.hpp
+++ b/include/chimney.hpp
@@ -1,4 +1,6 @@
 #ifndef _CHIMNEY_HPP__
 #define _CHIMNEY_HPP__
 
+#include <chimney/markdown.hpp>
+
 #endif
diff --git a/include/chimney/markdown.hpp b/include/chimney/markdown.hpp
new file mode 100644
index 0000000..2885ad1
--- /dev/null
+++ b/include/chimney/markdown.hpp
@@ -0,0 +1,13 @@
+#ifndef _CHIMNEY_MARKDOWN_HPP__
+#define _CHIMNEY_MARKDOWN_HPP__
+
+#include <string>
+
+namespace chimney {
+  class MarkdownFile {
+  public:
+    MarkdownFile(std::string contents);
+  };
+}
+
+#endif
diff --git a/src/chimney.cpp b/src/chimney.cpp
index 376dac7..a363d16 100644
--- a/src/chimney.cpp
+++ b/src/chimney.cpp
@@ -1,21 +1,22 @@
 #include <algorithm>
+#include <chimney.hpp>
 #include <filesystem>
+#include <fstream>
 #include <iostream>
-#include <string>
 #include <vector>
 
 namespace fs = std::filesystem;
 
 int main(int argc, char **argv) {
   /*
-   * config stub
+   * Configuration stub
    */
 
   std::vector<std::string> ignored_dirs { ".git" };
   std::vector<std::string> ignored_files { "README.md", "LICENSE" };
 
   /*
-   * argument parser stub
+   * Argument parser stub
    */
 
   std::string dir = ".";
@@ -25,19 +26,19 @@ int main(int argc, char **argv) {
   }
 
   /*
-   * directory tree builder
+   * Directory tree builder & compiler
    */
 
   auto entry = fs::recursive_directory_iterator(dir);
 
   for(; entry != fs::recursive_directory_iterator(); entry++) {
-    std::string filename = entry->path().filename();
-    auto haystack = ignored_files;
+    std::vector<std::string> haystack = ignored_files;
 
     if(entry->is_directory()) {
       haystack = ignored_dirs;
     }
 
+    std::string filename = entry->path().filename();
     auto iter = std::find(haystack.begin(), haystack.end(), filename);
     bool ignored = iter != haystack.end();
 
@@ -45,7 +46,11 @@ int main(int argc, char **argv) {
       entry.disable_recursion_pending();
     } else if(!entry->is_directory()) {
       if(entry->path().extension() == ".md") {
-        // process markdown file
+        std::ifstream reader { entry->path().c_str() };
+        std::string contents(entry->file_size(), ' ');
+        reader.read(&contents[0], entry->file_size());
+        // Loading the file into memory might need a bit of refactoring.
+        chimney::MarkdownFile md_file { contents };
       } else {
         // copy file to output directory
       }
diff --git a/src/markdown.cpp b/src/markdown.cpp
new file mode 100644
index 0000000..ae1f600
--- /dev/null
+++ b/src/markdown.cpp
@@ -0,0 +1,35 @@
+#include <cctype>
+#include <chimney/markdown.hpp>
+#include <ostream>
+#include <vector>
+
+namespace {
+  class MarkdownWord {
+  public:
+    bool start;
+    bool end;
+    std::string word;
+
+    MarkdownWord(bool start, bool end, std::string word)
+      : start(start), end(end), word(word) { }
+  };
+}
+
+chimney::MarkdownFile::MarkdownFile(std::string contents) {
+  std::vector<MarkdownWord> words;
+  std::string word;
+  bool start = true;
+
+  for(auto rune: contents) {
+    if(!std::isspace(rune)) {
+      word += rune;
+    } else if(!word.empty()) {
+      words.push_back(MarkdownWord {
+        start, rune == '\n', word
+      });
+
+      start = rune == '\n';
+      word.clear();
+    }
+  }
+}