diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4164df0196096498ffde75427703fff90177ee16
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 3.10)
+
+project(cpphttpd)
+
+file(GLOB SRC_FILES "src/*.cpp")
+file(GLOB HEADER_FILES "inc/*.hpp")
+
+include_directories(inc)
+
+add_library(cpphttpd STATIC ${SRC_FILES} ${HEADER_FILES})
+set_target_properties(cpphttpd PROPERTIES PREFIX "")
+
+
+add_executable(example.run EXCLUDE_FROM_ALL example/main.cpp)
+target_link_libraries(example.run cpphttpd)
+target_link_libraries(example.run pthread)
+add_custom_target(example example.run)
diff --git a/Makefile b/Makefile
index 4264a41969b7834f555af406042b88c4a2638568..f76195613065399950c55a8c22de00b375cb9156 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,8 @@
 # Name of the executable
-NAME = prog.run
+NAME = cpphttpd.a
 
+# Include directory
+INC_DIR = inc
 # Main source code directory
 SRC_DIR = src
 # Build output directory
@@ -13,24 +15,27 @@ SRC = $(wildcard $(SRC_DIR)/*.cpp)
 
 OBJ = $(addprefix $(BUILD_DIR)/, $(notdir $(SRC:.cpp=.o)))
 
-LD_FLAGS = -g -pthread
-COMPILE_FLAGS = -g -c -O3
+LD_FLAGS = -g -pthread -I$(INC_DIR)
+COMPILE_FLAGS = -g -c -O3 -I$(INC_DIR)
 
 
 # Build rule for the main target executable
 $(TARGET): $(OBJ)
-	g++ $(LD_FLAGS) -o $@ $(OBJ)
+	ar rcs $@ $(OBJ)
+
 
 # Build rule for normal source files
 $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
 	g++ $(COMPILE_FLAGS) -o $@ $<
 
 
+example: $(TARGET)
+	g++ $(LD_FLAGS) -o build/example.run example/main.cpp $(TARGET)
 
 .PHONY: clean
 clean:
 	rm $(OBJ) $(TARGET)
 
 .PHONY: run
-run: $(TARGET)
-	./$(TARGET)
+run: $(TARGET) example
+	./build/example.run
diff --git a/src/main.cpp b/example/main.cpp
similarity index 96%
rename from src/main.cpp
rename to example/main.cpp
index 31913c41d755125e2101ec5a355f6733aaef6973..e567d8be1d3586c9fc073ba3a41cff5914213402 100644
--- a/src/main.cpp
+++ b/example/main.cpp
@@ -1,147 +1,147 @@
-#include <iostream>
-#include <string>
-#include <vector>
-#include <unordered_map>
-#include <cstring>
-#include <sstream>
-#include <chrono>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <unistd.h>
-
-#include "httpd.hpp"
-#include "http_service.hpp"
-
-
-HttpRouteHandling handle_echo_path(const HttpRequest &req, HttpResponse &res)
-{
-    std::string echo_text = req.regexMatches().at(1);
-
-    std::string resp = "Echo:  " + echo_text;
-
-    res.send((uint8_t*) resp.c_str(), resp.size());
-
-    return HttpRouteHandling::End;
-}
-
-// Calculate the first N prime numbers where N is extracted from the request uri
-HttpRouteHandling handle_prime(const HttpRequest &req, HttpResponse &res)
-{
-    std::string result;
-    int number_of_primes_found = 0;
-
-    int max = std::stoi(req.regexMatches().at(1));
-
-    int num = 2;
-    while(number_of_primes_found < max)
-    {
-        bool is_prime = true;
-        for (int i = 2; i <= num/2; i++)
-        {
-            if (num % i == 0)
-            {
-                is_prime = false;
-                break;
-            }
-        }
-        if (is_prime)
-        {
-            result += std::to_string(num) + " ";
-            number_of_primes_found++;
-        }
-        num++;
-    }
-
-    res.send((uint8_t*) result.c_str(), result.size());
-
-    return HttpRouteHandling::End;
-}
-
-int main(int argc, char **argv)
-{
-    // Create the webserver on port 8081. By default listening on 0.0.0.0
-    HttpServer srv(8081);
-
-    // Log Middleware example
-    srv.addRoute(HttpRoute(
-        "",
-        [](const HttpRequest &req, HttpResponse &res) {
-
-            std::string log = "Request: " + req.ip() + " => " + req.uri() + "\n";
-            log +=            "  Agent: " + req.headers().getHeader(HttpHeader::UserAgent).getValue() + "\n";
-
-            std::cout << log;
-            
-            return HttpRouteHandling::Continue;
-        },
-        HttpRoute::MatchType::MatchAny
-    ));
-
-    // Example index route with hardcoded html response
-    srv.addRoute(HttpRoute(
-        "/(index.html)?", // match "/" or "/index.html"
-        [](const HttpRequest &req, HttpResponse &res) {
-
-            char body[] = R"EOT(
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <title>Example HTML Document</title>
-</head>
-<body>
-    <h1><a href="/example.html">example.html</a></h1>
-    <h1><a href="/cached/example.html">cached example.html</a></h1>
-    <h1><a href="/prime/100">first 100 primes</a></h1>
-    <h1><a href="/echo/Hello">echo hello</a></h1>
-</body>
-</html>
-            )EOT";
-            res.sendAll((uint8_t*)body, sizeof(body));
-
-            return HttpRouteHandling::End;
-        }
-    ));
-
-    // Static file example
-    srv.addRoute(serveFile(
-        "/example.html",
-        "./static/example.html",
-        "text/html; charset=utf-8"
-    ));
-
-    // Cached static file example. The file is loaded into memory at launch
-    srv.addRoute(serveFileCached(
-        "/cached/example.html",
-        "./static/example.html",
-        "text/html; charset=utf-8"
-    ));
-
-    // Example for a handler function that uses regex to extract a path segment
-    srv.addRoute(HttpRoute(
-        "/prime/(\\d+)",
-        &handle_prime
-    ));
-
-    // Example for a handler function that uses regex to extract a path segment
-    srv.addRoute(HttpRoute(
-        "/echo/([a-zA-Z0-9_\\-.]+)/?", 
-        &handle_echo_path
-    ));
-
-    try
-    {
-
-        // Start serving the content
-        srv.serveForever();
-
-    }
-    catch(const HttpException& e)
-    {
-        std::cerr << e.what() << '\n';
-    }
-
-    return 0;
-    
-}
+#include <iostream>
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <cstring>
+#include <sstream>
+#include <chrono>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+#include "httpd.hpp"
+#include "http_service.hpp"
+
+
+HttpRouteHandling handle_echo_path(const HttpRequest &req, HttpResponse &res)
+{
+    std::string echo_text = req.regexMatches().at(1);
+
+    std::string resp = "Echo:  " + echo_text;
+
+    res.send((uint8_t*) resp.c_str(), resp.size());
+
+    return HttpRouteHandling::End;
+}
+
+// Calculate the first N prime numbers where N is extracted from the request uri
+HttpRouteHandling handle_prime(const HttpRequest &req, HttpResponse &res)
+{
+    std::string result;
+    int number_of_primes_found = 0;
+
+    int max = std::stoi(req.regexMatches().at(1));
+
+    int num = 2;
+    while(number_of_primes_found < max)
+    {
+        bool is_prime = true;
+        for (int i = 2; i <= num/2; i++)
+        {
+            if (num % i == 0)
+            {
+                is_prime = false;
+                break;
+            }
+        }
+        if (is_prime)
+        {
+            result += std::to_string(num) + " ";
+            number_of_primes_found++;
+        }
+        num++;
+    }
+
+    res.send((uint8_t*) result.c_str(), result.size());
+
+    return HttpRouteHandling::End;
+}
+
+int main(int argc, char **argv)
+{
+    // Create the webserver on port 8081. By default listening on 0.0.0.0
+    HttpServer srv(8081);
+
+    // Log Middleware example
+    srv.addRoute(HttpRoute(
+        "",
+        [](const HttpRequest &req, HttpResponse &res) {
+
+            std::string log = "Request: " + req.ip() + " => " + req.uri() + "\n";
+            log +=            "  Agent: " + req.headers().getHeader(HttpHeader::UserAgent).getValue() + "\n";
+
+            std::cout << log;
+            
+            return HttpRouteHandling::Continue;
+        },
+        HttpRoute::MatchType::MatchAny
+    ));
+
+    // Example index route with hardcoded html response
+    srv.addRoute(HttpRoute(
+        "/(index.html)?", // match "/" or "/index.html"
+        [](const HttpRequest &req, HttpResponse &res) {
+
+            char body[] = R"EOT(
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <title>Example HTML Document</title>
+</head>
+<body>
+    <h1><a href="/example.html">example.html</a></h1>
+    <h1><a href="/cached/example.html">cached example.html</a></h1>
+    <h1><a href="/prime/100">first 100 primes</a></h1>
+    <h1><a href="/echo/Hello">echo hello</a></h1>
+</body>
+</html>
+            )EOT";
+            res.sendAll((uint8_t*)body, sizeof(body));
+
+            return HttpRouteHandling::End;
+        }
+    ));
+
+    // Static file example
+    srv.addRoute(serveFile(
+        "/example.html",
+        "./static/example.html",
+        "text/html; charset=utf-8"
+    ));
+
+    // Cached static file example. The file is loaded into memory at launch
+    srv.addRoute(serveFileCached(
+        "/cached/example.html",
+        "./static/example.html",
+        "text/html; charset=utf-8"
+    ));
+
+    // Example for a handler function that uses regex to extract a path segment
+    srv.addRoute(HttpRoute(
+        "/prime/(\\d+)",
+        &handle_prime
+    ));
+
+    // Example for a handler function that uses regex to extract a path segment
+    srv.addRoute(HttpRoute(
+        "/echo/([a-zA-Z0-9_\\-.]+)/?", 
+        &handle_echo_path
+    ));
+
+    try
+    {
+
+        // Start serving the content
+        srv.serveForever();
+
+    }
+    catch(const HttpException& e)
+    {
+        std::cerr << e.what() << '\n';
+    }
+
+    return 0;
+    
+}
diff --git a/src/http_err.hpp b/inc/http_err.hpp
similarity index 100%
rename from src/http_err.hpp
rename to inc/http_err.hpp
diff --git a/src/http_header.hpp b/inc/http_header.hpp
similarity index 100%
rename from src/http_header.hpp
rename to inc/http_header.hpp
diff --git a/src/http_request.hpp b/inc/http_request.hpp
similarity index 100%
rename from src/http_request.hpp
rename to inc/http_request.hpp
diff --git a/src/http_response.hpp b/inc/http_response.hpp
similarity index 100%
rename from src/http_response.hpp
rename to inc/http_response.hpp
diff --git a/src/http_route.hpp b/inc/http_route.hpp
similarity index 100%
rename from src/http_route.hpp
rename to inc/http_route.hpp
diff --git a/src/http_service.hpp b/inc/http_service.hpp
similarity index 100%
rename from src/http_service.hpp
rename to inc/http_service.hpp
diff --git a/src/httpd.hpp b/inc/httpd.hpp
similarity index 100%
rename from src/httpd.hpp
rename to inc/httpd.hpp
diff --git a/src/semaphore.hpp b/inc/semaphore.hpp
similarity index 100%
rename from src/semaphore.hpp
rename to inc/semaphore.hpp
diff --git a/src/threadpool.hpp b/inc/threadpool.hpp
similarity index 100%
rename from src/threadpool.hpp
rename to inc/threadpool.hpp