diff --git a/README.md b/README.md
index 3628df9..2318093 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,14 @@
   <img alt="Obsidian serve" src="./screenshot/serve.png" >
 </div>
 
+## Get Started
+```toml
+[dependencies]
+# add these 2 dependencies in Cargo.toml file
+obsidian = "0.2.2"
+tokio = "0.2.21"
+```
+
 ## Hello World
 
 ```rust
@@ -30,44 +38,32 @@ use obsidian::{context::Context, App};
 #[tokio::main]
 async fn main() {
     let mut app: App = App::new();
-    let addr = ([127, 0, 0, 1], 3000).into();
-
     app.get("/", |ctx: Context| async { ctx.build("Hello World").ok() });
-
-    app.listen(&addr, || {
-        println!("server is listening to {}", &addr);
-    }).await;
+    app.listen(3000).await;
 }
 ```
 
 ## Hello World (with handler function)
 
 ```rust
-use obsidian::{context::Context, App, ContextResult};
+use obsidian::{context::Context, handler::ContextResult, App};
 
 async fn hello_world(ctx: Context) -> ContextResult {
     ctx.build("Hello World").ok()
 }
 
-
 #[tokio::main]
 async fn main() {
     let mut app: App = App::new();
-    let addr = ([127, 0, 0, 1], 3000).into();
-
     app.get("/", hello_world);
-
-    app.listen(&addr, || {
-        println!("server is listening to {}", &addr);
-    })
-    .await;
+    app.listen(3000).await;
 }
 ```
 
 ## JSON Response
 
 ```rust
-use obsidian::{context::Context, App, ContextResult};
+use obsidian::{context::Context, handler::ContextResult, App};
 use serde::*;
 
 async fn get_user(ctx: Context) -> ContextResult {
@@ -85,28 +81,33 @@ async fn get_user(ctx: Context) -> ContextResult {
 #[tokio::main]
 async fn main() {
     let mut app: App = App::new();
-    let addr = ([127, 0, 0, 1], 3000).into();
-
     app.get("/user", get_user);
-
-    app.listen(&addr, || {
-        println!("server is listening to {}", &addr);
-    })
-    .await;
+    app.listen(3000).await;
 }
 
 ```
 
-## Example Files
+## More Examples
 
-Example are located in `example/main.rs`.
+Examples are located in `example` folder. You can run these examples by using:
+```bash
+cargo run --example [name]
 
-## Run Example
+// show a list of available examples
+cargo run --example 
 
-```
+// run the example
 cargo run --example example
 ```
 
+## App Lifecycle
+![app lifecycle](./screenshot/lifecycle.png)
+
+## Contributors
+<a href="https://github.com/obsidian-rs/obsidian/graphs/contributors">
+  <img src="https://contributors-img.web.app/image?repo=obsidian-rs/obsidian" />
+</a>
+
 ## Current State
 
-NOT READY FOR PRODUCTION YET!
+Under active development and **NOT READY FOR PRODUCTION YET!**
diff --git a/examples/app_state.rs b/examples/app_state.rs
index 9862511..500881a 100644
--- a/examples/app_state.rs
+++ b/examples/app_state.rs
@@ -1,4 +1,4 @@
-use obsidian::{context::Context, App, ObsidianError};
+use obsidian::{context::Context, App};
 
 #[derive(Clone)]
 pub struct AppState {
@@ -8,21 +8,20 @@ pub struct AppState {
 #[tokio::main]
 async fn main() {
     let mut app: App<AppState> = App::new();
-    let addr = ([127, 0, 0, 1], 3000).into();
 
     app.set_app_state(AppState {
-        db_connection_string: "localhost:1433".to_string()
+        db_connection_string: "localhost:1433".to_string(),
     });
 
-    app.get("/", |ctx: Context| async { 
-        let app_state = ctx.get::<AppState>().ok_or(ObsidianError::NoneError)?;
-        let res = Some(format!("connection string: {}", &app_state.db_connection_string));
+    app.get("/", |ctx: Context| async move {
+        let app_state = ctx.get::<AppState>().unwrap();
+        let res = Some(format!(
+            "connection string: {}",
+            &app_state.db_connection_string
+        ));
 
-        ctx.build(res).ok() 
+        res
     });
 
-    app.listen(&addr, || {
-        println!("server is listening to {}", &addr);
-    })
-    .await;
+    app.listen(3000).await;
 }
diff --git a/examples/hello.rs b/examples/hello.rs
index 56d4d46..3c9f4f2 100644
--- a/examples/hello.rs
+++ b/examples/hello.rs
@@ -3,12 +3,8 @@ use obsidian::{context::Context, App};
 #[tokio::main]
 async fn main() {
     let mut app: App = App::new();
-    let addr = ([127, 0, 0, 1], 3000).into();
 
-    app.get("/", |ctx: Context| async { ctx.build("Hello World").ok() });
+    app.get("/", |_ctx: Context| async { "Hello, Obsidian!" });
 
-    app.listen(&addr, || {
-        println!("server is listening to {}", &addr);
-    })
-    .await;
+    app.listen(3000).await;
 }
diff --git a/examples/hello_handler.rs b/examples/hello_handler.rs
index d83de9a..18ac958 100644
--- a/examples/hello_handler.rs
+++ b/examples/hello_handler.rs
@@ -1,5 +1,6 @@
-use obsidian::{context::Context, App, ContextResult};
+use obsidian::{context::Context, handler::ContextResult, App};
 
+// this is handler function
 async fn hello_world(ctx: Context) -> ContextResult {
     ctx.build("Hello World").ok()
 }
@@ -7,12 +8,8 @@ async fn hello_world(ctx: Context) -> ContextResult {
 #[tokio::main]
 async fn main() {
     let mut app: App = App::new();
-    let addr = ([127, 0, 0, 1], 3000).into();
 
     app.get("/", hello_world);
 
-    app.listen(&addr, || {
-        println!("server is listening to {}", &addr);
-    })
-    .await;
+    app.listen(3000).await;
 }
diff --git a/examples/json.rs b/examples/json.rs
index 83dca39..ef1f66a 100644
--- a/examples/json.rs
+++ b/examples/json.rs
@@ -1,27 +1,28 @@
-use obsidian::{context::Context, App, ContextResult};
+use obsidian::{context::Context, handler::ContextResult, router::Response, App};
 use serde::*;
 
-async fn get_user(ctx: Context) -> ContextResult {
-    #[derive(Serialize, Deserialize)]
+async fn get_user(mut ctx: Context) -> ContextResult {
+    #[derive(Serialize, Deserialize, Debug)]
     struct User {
         name: String,
     };
 
-    let user = User {
-        name: String::from("Obsidian"),
+    #[derive(Serialize, Deserialize, Debug)]
+    struct UserParam {
+        name: String,
+        age: i8,
     };
-    ctx.build_json(user).ok()
+
+    let user: UserParam = ctx.json().await?;
+
+    Ok(Response::ok().json(user))
 }
 
 #[tokio::main]
 async fn main() {
-    let mut app: App = App::new();
-    let addr = ([127, 0, 0, 1], 3000).into();
+    let mut app: App = App::default();
 
     app.get("/user", get_user);
 
-    app.listen(&addr, || {
-        println!("server is listening to {}", &addr);
-    })
-    .await;
+    app.listen(3000).await;
 }
diff --git a/examples/main.rs b/examples/main.rs
index f69d09f..5d4982a 100644
--- a/examples/main.rs
+++ b/examples/main.rs
@@ -7,7 +7,7 @@ use std::{fmt, fmt::Display};
 use obsidian::{
     context::Context,
     router::{header, Responder, Response, Router},
-    App, ObsidianError, StatusCode,
+    App, StatusCode,
 };
 
 // Testing example
@@ -66,20 +66,18 @@ impl Display for JsonTest {
 //         .header("X-Custom-Header", "custom-value")
 //         .header("X-Custom-Header-2", "custom-value-2")
 //         .header("X-Custom-Header-3", "custom-value-3")
-//         .set_headers(headers)
-//         .status(StatusCode::CREATED)
+//         .set_headers(headers) .status(StatusCode::CREATED)
 // }
 
 #[tokio::main]
 async fn main() {
     let mut app: App = App::default();
-    let addr = ([127, 0, 0, 1], 3000).into();
 
-    app.get("/", |ctx: Context| async {
+    app.get("/", |ctx: Context| async move {
 ctx.build(Response::ok().html("<!DOCTYPE html><html><head><link rel=\"shotcut icon\" href=\"favicon.ico\" type=\"image/x-icon\" sizes=\"32x32\" /></head> <h1>Hello Obsidian</h1></html>")).ok()
     });
 
-    app.get("/json", |ctx: Context| async {
+    app.get("/json", |ctx: Context| async move {
         let point = Point { x: 1, y: 2 };
 
         ctx.build_json(point)
@@ -89,7 +87,7 @@ ctx.build(Response::ok().html("<!DOCTYPE html><html><head><link rel=\"shotcut ic
             .ok()
     });
 
-    app.get("/user", |mut ctx: Context| async {
+    app.get("/user", |mut ctx: Context| async move {
         #[derive(Serialize, Deserialize, Debug)]
         struct QueryString {
             id: String,
@@ -112,11 +110,11 @@ ctx.build(Response::ok().html("<!DOCTYPE html><html><head><link rel=\"shotcut ic
         ctx.build("").ok()
     });
 
-    app.patch("/patch-here", |ctx: Context| async {
+    app.patch("/patch-here", |ctx: Context| async move {
         ctx.build("Here is patch request").ok()
     });
 
-    app.get("/json-with-headers", |ctx: Context| async {
+    app.get("/json-with-headers", |ctx: Context| async move {
         let point = Point { x: 1, y: 2 };
 
         let custom_headers = vec![
@@ -139,7 +137,7 @@ ctx.build(Response::ok().html("<!DOCTYPE html><html><head><link rel=\"shotcut ic
         .ok()
     });
 
-    app.get("/string-with-headers", |ctx: Context| async {
+    app.get("/string-with-headers", |ctx: Context| async move {
         let custom_headers = vec![
             ("X-Custom-Header-1", "Custom header 1"),
             ("X-Custom-Header-2", "Custom header 2"),
@@ -157,37 +155,37 @@ ctx.build(Response::ok().html("<!DOCTYPE html><html><head><link rel=\"shotcut ic
             .ok()
     });
 
-    app.get("/empty-body", |ctx: Context| async {
+    app.get("/empty-body", |ctx: Context| async move {
         ctx.build(StatusCode::OK).ok()
     });
 
-    app.get("/vec", |ctx: Context| async {
+    app.get("/vec", |ctx: Context| async move {
         ctx.build(vec![1, 2, 3])
             .with_status(StatusCode::CREATED)
             .ok()
     });
 
-    app.get("/String", |ctx: Context| async {
+    app.get("/String", |ctx: Context| async move {
         ctx.build("<h1>This is a String</h1>".to_string()).ok()
     });
 
-    app.get("/test/radix", |ctx: Context| async {
+    app.get("/test/radix", |ctx: Context| async move {
         ctx.build("<h1>Test radix</h1>".to_string()).ok()
     });
 
-    app.get("/team/radix", |ctx: Context| async {
+    app.get("/team/radix", |ctx: Context| async move {
         ctx.build("Team radix".to_string()).ok()
     });
 
-    app.get("/test/radix2", |ctx: Context| async {
+    app.get("/test/radix2", |ctx: Context| async move {
         ctx.build("<h1>Test radix2</h1>".to_string()).ok()
     });
 
-    app.get("/jsontest", |ctx: Context| async {
+    app.get("/jsontest", |ctx: Context| async move {
         ctx.build_file("./testjson.html").await.ok()
     });
 
-    app.get("/jsan", |ctx: Context| async {
+    app.get("/jsan", |ctx: Context| async move {
         ctx.build("<h1>jsan</h1>".to_string()).ok()
     });
 
@@ -202,10 +200,7 @@ ctx.build(Response::ok().html("<!DOCTYPE html><html><head><link rel=\"shotcut ic
     });
 
     app.get("router/test", |ctx: Context| async move {
-        let result = ctx
-            .extensions()
-            .get::<LoggerExampleData>()
-            .ok_or(ObsidianError::NoneError)?;
+        let result = ctx.extensions().get::<LoggerExampleData>().unwrap();
 
         dbg!(&result.0);
 
@@ -300,11 +295,11 @@ ctx.build(Response::ok().html("<!DOCTYPE html><html><head><link rel=\"shotcut ic
     app.use_service(logger_example);
 
     app.scope("params", |router: &mut Router| {
-        router.get("/test-next-wild/*", |ctx: Context| async {
+        router.get("/test-next-wild/*", |ctx: Context| async move {
             ctx.build("<h1>test next wild</h1>".to_string()).ok()
         });
 
-        router.get("/*", |ctx: Context| async {
+        router.get("/*", |ctx: Context| async move {
             ctx.build(
                 "<h1>404 Not Found</h1>"
                     .to_string()
@@ -316,5 +311,5 @@ ctx.build(Response::ok().html("<!DOCTYPE html><html><head><link rel=\"shotcut ic
 
     app.use_static_to("/files/", "/assets/");
 
-    app.listen(&addr, || {}).await;
+    app.listen(3000).await
 }
diff --git a/examples/middleware/logger_example.rs b/examples/middleware/logger_example.rs
index 30baefb..37c8a45 100644
--- a/examples/middleware/logger_example.rs
+++ b/examples/middleware/logger_example.rs
@@ -3,7 +3,9 @@ use async_trait::async_trait;
 #[cfg(debug_assertions)]
 use colored::*;
 
-use obsidian::{context::Context, middleware::Middleware, ContextResult, EndpointExecutor};
+use obsidian::{
+    context::Context, handler::ContextResult, middleware::Middleware, EndpointExecutor,
+};
 
 #[derive(Default)]
 pub struct LoggerExample {}
diff --git a/screenshot/lifecycle.png b/screenshot/lifecycle.png
new file mode 100644
index 0000000..8664f16
Binary files /dev/null and b/screenshot/lifecycle.png differ
diff --git a/src/app.rs b/src/app.rs
index 1ad9a64..4ab0363 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -1,4 +1,3 @@
-use std::net::SocketAddr;
 use std::sync::Arc;
 
 use colored::*;
@@ -9,9 +8,9 @@ use hyper::{
 };
 
 use crate::context::Context;
-use crate::error::ObsidianError;
+use crate::handler::{ContextResult, Handler};
 use crate::middleware::Middleware;
-use crate::router::{ContextResult, Handler, RouteValueResult, Router};
+use crate::router::{RouteValueResult, Router};
 
 use crate::middleware::logger::Logger;
 
@@ -141,7 +140,7 @@ where
         self.app_state = Some(app_state);
     }
 
-    pub async fn listen(self, addr: &SocketAddr, callback: impl Fn()) {
+    pub async fn listen(self, port: u16) {
         let app_server: AppServer = AppServer {
             router: self.router,
         };
@@ -160,6 +159,7 @@ where
             }
         });
 
+        let addr = ([127, 0, 0, 1], port).into();
         let server = Server::bind(&addr).serve(service);
 
         let logo = r#"
@@ -199,8 +199,6 @@ where
 
         println!(" 🎉  {}: http://{}\n", "Served at".green().bold(), addr);
 
-        callback();
-
         server.await.map_err(|_| println!("Server error")).unwrap();
     }
 }
@@ -237,38 +235,41 @@ impl AppServer {
                 let route_result = executor.next(context).await;
 
                 let route_response = match route_result {
-                    Ok(ctx) => {
+                    Ok(response) => {
                         let mut res = Response::builder();
-                        if let Some(response) = ctx.take_response() {
-                            if let Some(headers) = response.headers() {
-                                if let Some(response_headers) = res.headers_mut() {
-                                    headers.iter().for_each(move |(key, value)| {
-                                        response_headers
-                                            .insert(key, header::HeaderValue::from_static(value));
-                                    });
-                                }
+                        if let Some(headers) = response.headers() {
+                            if let Some(response_headers) = res.headers_mut() {
+                                headers.iter().for_each(move |(key, value)| {
+                                    response_headers
+                                        .insert(key, header::HeaderValue::from_static(value));
+                                });
                             }
-                            res.status(response.status()).body(response.body())
-                        } else {
-                            // No response found
-                            res.status(StatusCode::OK).body(Body::from(""))
                         }
+                        res.status(response.status()).body(response.body())
                     }
                     Err(err) => {
-                        let body = Body::from(err.to_string());
-                        Response::builder()
-                            .status(StatusCode::INTERNAL_SERVER_ERROR)
-                            .body(body)
+                        let response = err.into_error_response();
+                        let mut res = Response::builder();
+                        if let Some(headers) = response.headers() {
+                            if let Some(response_headers) = res.headers_mut() {
+                                headers.iter().for_each(move |(key, value)| {
+                                    response_headers
+                                        .insert(key, header::HeaderValue::from_static(value));
+                                });
+                            }
+                        }
+                        res.status(response.status()).body(response.body())
                     }
                 };
 
-                Ok::<_, hyper::Error>(route_response.unwrap_or_else(|_| {
-                    internal_server_error(ObsidianError::GeneralError(
-                        "Error while constructing response body".to_string(),
-                    ))
-                }))
+                // Ok::<_, hyper::Error>(route_response.unwrap_or_else(|_| {
+                //     internal_server_error(ObsidianError::GeneralError(
+                //         "Error while constructing response body".to_string(),
+                //     ))
+                // }))
+                Ok::<_, hyper::Error>(route_response.unwrap())
             }
-            _ => Ok::<_, hyper::Error>(page_not_found()),
+            None => Ok::<_, hyper::Error>(page_not_found()),
         }
     }
 }
@@ -280,33 +281,33 @@ fn page_not_found() -> Response<Body> {
     server_response
 }
 
-fn internal_server_error(err: impl std::error::Error) -> Response<Body> {
-    let body = Body::from(err.to_string());
-    Response::builder()
-        .status(StatusCode::INTERNAL_SERVER_ERROR)
-        .body(body)
-        .unwrap()
-}
+// fn internal_server_error(err: impl std::error::Error) -> Response<Body> {
+//     let body = Body::from(err.to_string());
+//     Response::builder()
+//         .status(StatusCode::INTERNAL_SERVER_ERROR)
+//         .body(body)
+//         .unwrap()
+// }
 
 pub struct EndpointExecutor<'a> {
     pub route_endpoint: &'a Arc<dyn Handler>,
-    pub middleware: &'a [Arc<dyn Middleware>],
+    pub middlewares: &'a [Arc<dyn Middleware>],
 }
 
 impl<'a> EndpointExecutor<'a> {
     pub fn new(
         route_endpoint: &'a Arc<dyn Handler>,
-        middleware: &'a [Arc<dyn Middleware>],
+        middlewares: &'a [Arc<dyn Middleware>],
     ) -> Self {
         EndpointExecutor {
             route_endpoint,
-            middleware,
+            middlewares,
         }
     }
 
     pub async fn next(mut self, context: Context) -> ContextResult {
-        if let Some((current, all_next)) = self.middleware.split_first() {
-            self.middleware = all_next;
+        if let Some((current, all_next)) = self.middlewares.split_first() {
+            self.middlewares = all_next;
             current.handle(context, self).await
         } else {
             self.route_endpoint.call(context).await
diff --git a/src/context.rs b/src/context.rs
index 05e72e9..ac6f540 100644
--- a/src/context.rs
+++ b/src/context.rs
@@ -9,8 +9,9 @@ use std::collections::HashMap;
 use std::convert::From;
 use std::str::FromStr;
 
-use crate::router::{from_cow_map, ContextResult, Responder, Response};
-use crate::ObsidianError;
+use crate::error::{InternalError, ObsidianError};
+use crate::handler::ContextResult;
+use crate::router::{from_cow_map, Responder, Response};
 use crate::{
     header::{HeaderName, HeaderValue},
     Body, HeaderMap, Method, Request, StatusCode, Uri,
@@ -86,9 +87,8 @@ impl Context {
     ///
     /// ```
     /// # use obsidian::StatusCode;
-    /// # use obsidian::ContextResult;
+    /// # use obsidian::handler::ContextResult;
     /// # use obsidian::context::Context;
-    ///
     /// // Assumming ctx contains params for id and mode
     /// async fn get_handler(ctx: Context) -> ContextResult {
     ///     let id: i32 = ctx.param("id")?;
@@ -102,12 +102,16 @@ impl Context {
     ///
     /// ```
     ///
-    pub fn param<T: FromStr>(&self, key: &str) -> Result<T, ObsidianError> {
+    pub fn param<T: FromStr>(&self, key: &str) -> Result<T, InternalError> {
         self.params_data
             .get(key)
-            .ok_or(ObsidianError::NoneError)?
+            .ok_or(InternalError::NoneError(format!(
+                "The key [{}] not found",
+                key
+            )))?
             .parse()
-            .map_err(|_err| ObsidianError::ParamError(format!("Failed to parse param {}", key)))
+            .map_err(|_err| InternalError::ParamError(format!("Failed to parse param {}", key)))
+        // The error will never happen
     }
 
     /// Method to get the string query data from the request url.
@@ -116,10 +120,8 @@ impl Context {
     /// # Example
     /// ```
     /// # use serde::*;
-    ///
     /// # use obsidian::context::Context;
-    /// # use obsidian::{ContextResult, StatusCode};
-    ///
+    /// # use obsidian::{handler::ContextResult, StatusCode};
     /// #[derive(Deserialize, Serialize, Debug)]
     /// struct QueryString {
     ///     id: i32,
@@ -153,10 +155,8 @@ impl Context {
     /// # Example
     /// ```
     /// # use serde::*;
-    ///
     /// # use obsidian::context::Context;
-    /// # use obsidian::{ContextResult, StatusCode};
-    ///
+    /// # use obsidian::{handler::ContextResult, StatusCode};
     /// #[derive(Deserialize, Serialize, Debug)]
     /// struct FormResult {
     ///     id: i32,
@@ -176,12 +176,7 @@ impl Context {
     pub async fn form<T: DeserializeOwned>(&mut self) -> Result<T, ObsidianError> {
         let body = self.take_body();
 
-        let buf = match body::aggregate(body).await {
-            Ok(buf) => buf,
-            _ => {
-                return Err(ObsidianError::NoneError);
-            }
-        };
+        let buf = body::aggregate(body).await?;
 
         Self::parse_queries(buf.bytes())
     }
@@ -200,10 +195,8 @@ impl Context {
     /// ### Handle by static type
     /// ```
     /// # use serde::*;
-    ///
     /// # use obsidian::context::Context;
-    /// # use obsidian::{ContextResult, StatusCode};
-    ///
+    /// # use obsidian::{handler::ContextResult, StatusCode};
     /// #[derive(Deserialize, Serialize, Debug)]
     /// struct JsonResult {
     ///     id: i32,
@@ -224,10 +217,7 @@ impl Context {
     /// ### Handle by dynamic map
     /// ```
     /// # use serde_json::Value;
-    ///
-    /// # use obsidian::context::Context;
-    /// # use obsidian::{ContextResult, StatusCode};
-    ///
+    /// # use obsidian::{context::Context, handler::ContextResult, StatusCode};
     /// // Assume ctx contains json with data {id:1, mode:'edit'}
     /// async fn get_handler(mut ctx: Context) -> ContextResult {
     ///     let result: serde_json::Value = ctx.json().await?;
@@ -241,12 +231,7 @@ impl Context {
     pub async fn json<T: DeserializeOwned>(&mut self) -> Result<T, ObsidianError> {
         let body = self.take_body();
 
-        let buf = match body::aggregate(body).await {
-            Ok(buf) => buf,
-            _ => {
-                return Err(ObsidianError::NoneError);
-            }
-        };
+        let buf = body::aggregate(body).await?;
 
         Ok(serde_json::from_slice(buf.bytes())?)
     }
@@ -275,18 +260,18 @@ impl Context {
     }
 
     /// Build any kind of response which implemented Responder trait
-    pub fn build(self, res: impl Responder) -> ResponseBuilder {
-        ResponseBuilder::new(self, res.respond_to())
+    pub fn build(&self, res: impl Responder) -> ResponseBuilder {
+        ResponseBuilder::new(res.respond_to())
     }
 
     /// Build data into json format. The data must implement Serialize trait
-    pub fn build_json(self, body: impl Serialize) -> ResponseBuilder {
-        ResponseBuilder::new(self, Response::ok().json(body))
+    pub fn build_json(&self, body: impl Serialize) -> ResponseBuilder {
+        ResponseBuilder::new(Response::ok().json(body))
     }
 
     /// Build response from static file.
-    pub async fn build_file(self, file_path: &str) -> ResponseBuilder {
-        ResponseBuilder::new(self, Response::ok().file(file_path).await)
+    pub async fn build_file(&self, file_path: &str) -> ResponseBuilder {
+        ResponseBuilder::new(Response::ok().file(file_path).await)
     }
 
     fn parse_queries<T: DeserializeOwned>(query: &[u8]) -> Result<T, ObsidianError> {
@@ -317,13 +302,12 @@ impl Context {
 }
 
 pub struct ResponseBuilder {
-    ctx: Context,
     response: Response,
 }
 
 impl ResponseBuilder {
-    pub fn new(ctx: Context, response: Response) -> Self {
-        ResponseBuilder { ctx, response }
+    pub fn new(response: Response) -> Self {
+        ResponseBuilder { response }
     }
 
     /// set http status code for response
@@ -354,9 +338,9 @@ impl ResponseBuilder {
         self
     }
 
-    pub fn ok(mut self) -> ContextResult {
-        *self.ctx.response_mut() = Some(self.response);
-        Ok(self.ctx)
+    pub fn ok(self) -> ContextResult {
+        // *self.ctx.response_mut() = Some(self.response);
+        Ok(self.response)
     }
 }
 
diff --git a/src/error.rs b/src/error.rs
index 38937cb..74a1c99 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,3 +1,3 @@
-mod obsidian_error;
+mod error_response;
 
-pub use obsidian_error::ObsidianError;
+pub use error_response::{InternalError, IntoErrorResponse, ObsidianError};
diff --git a/src/error/error_response.rs b/src/error/error_response.rs
new file mode 100644
index 0000000..0e8bdba
--- /dev/null
+++ b/src/error/error_response.rs
@@ -0,0 +1,95 @@
+use crate::router::FormError;
+use crate::router::Response;
+use hyper::{Body, StatusCode};
+use serde_json::error::Error as JsonError;
+use std::fmt;
+
+#[derive(Debug)]
+pub struct ObsidianError {
+    inner: Box<dyn IntoErrorResponse>,
+}
+
+#[derive(Debug)]
+pub enum InternalError {
+    GeneralError(String),
+    NoneError(String),
+    ParamError(String),
+}
+
+impl fmt::Display for InternalError {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        let error_msg = match *self {
+            InternalError::GeneralError(ref msg) => msg.to_string(),
+            InternalError::NoneError(ref msg) => msg.to_string(),
+            InternalError::ParamError(ref msg) => msg.to_string(),
+        };
+
+        formatter.write_str(&error_msg)
+    }
+}
+
+impl ObsidianError {
+    pub fn into_error_response(self) -> Response {
+        self.inner.into_error_response()
+    }
+}
+
+impl fmt::Display for ObsidianError {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&self.inner, formatter)
+    }
+}
+
+pub trait IntoErrorResponse: fmt::Debug + fmt::Display {
+    /// convert Error into error response
+    fn into_error_response(&self) -> Response {
+        let body = Body::from(self.to_string());
+        Response::new_with_body(body).set_status(self.status_code())
+    }
+
+    /// status code for this error response
+    /// this will return Internal Server Error (500) by default
+    fn status_code(&self) -> StatusCode {
+        StatusCode::INTERNAL_SERVER_ERROR
+    }
+}
+
+impl<T: IntoErrorResponse + 'static> From<T> for ObsidianError {
+    fn from(err: T) -> Self {
+        ObsidianError {
+            inner: Box::new(err),
+        }
+    }
+}
+
+impl IntoErrorResponse for JsonError {}
+impl IntoErrorResponse for FormError {}
+impl IntoErrorResponse for hyper::error::Error {}
+impl IntoErrorResponse for String {}
+impl IntoErrorResponse for InternalError {
+    /// convert Error into error response
+    fn into_error_response(&self) -> Response {
+        let body = Body::from(self.to_string());
+        Response::new_with_body(body).set_status(self.status_code())
+    }
+
+    /// status code for this error response
+    /// this will return Internal Server Error (500) by default
+    fn status_code(&self) -> StatusCode {
+        match self {
+            InternalError::GeneralError(_) => StatusCode::INTERNAL_SERVER_ERROR,
+            InternalError::NoneError(_) => StatusCode::NOT_FOUND,
+            InternalError::ParamError(_) => StatusCode::BAD_REQUEST,
+        }
+    }
+}
+
+impl std::error::Error for InternalError {}
+
+impl From<std::convert::Infallible> for ObsidianError {
+    fn from(_: std::convert::Infallible) -> Self {
+        // `std::convert::Infallible` indicates an error
+        // that will never happen
+        unreachable!()
+    }
+}
diff --git a/src/error/obsidian_error.rs b/src/error/obsidian_error.rs
deleted file mode 100644
index 9caccbd..0000000
--- a/src/error/obsidian_error.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-use std::error::Error;
-use std::fmt;
-use std::fmt::Display;
-
-use serde_json::error::Error as JsonError;
-
-use crate::router::FormError;
-
-/// Errors occurs in Obsidian framework
-#[derive(Debug)]
-pub enum ObsidianError {
-    ParamError(String),
-    JsonError(JsonError),
-    FormError(FormError),
-    GeneralError(String),
-    NoneError,
-}
-
-impl Display for ObsidianError {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        let error_msg = match *self {
-            ObsidianError::ParamError(ref msg) => msg.to_string(),
-            ObsidianError::JsonError(ref err) => err.to_string(),
-            ObsidianError::FormError(ref err) => err.to_string(),
-            ObsidianError::GeneralError(ref msg) => msg.to_string(),
-            ObsidianError::NoneError => "Input should not be None".to_string(),
-        };
-
-        formatter.write_str(&error_msg)
-    }
-}
-
-impl From<FormError> for ObsidianError {
-    fn from(error: FormError) -> Self {
-        ObsidianError::FormError(error)
-    }
-}
-
-impl From<JsonError> for ObsidianError {
-    fn from(error: JsonError) -> Self {
-        ObsidianError::JsonError(error)
-    }
-}
-
-impl Error for ObsidianError {
-    fn description(&self) -> &str {
-        "Obsidian Error"
-    }
-}
diff --git a/src/handler/mod.rs b/src/handler/mod.rs
new file mode 100644
index 0000000..478a194
--- /dev/null
+++ b/src/handler/mod.rs
@@ -0,0 +1,29 @@
+use crate::context::Context;
+use crate::error::ObsidianError;
+use crate::router::{Responder, Response};
+
+use async_trait::async_trait;
+use std::future::Future;
+
+/// A HTTP request handler.
+///
+/// This trait is expected by router to perform function for every request.
+#[async_trait]
+pub trait Handler: Send + Sync + 'static {
+    async fn call(&self, ctx: Context) -> ContextResult;
+}
+
+#[async_trait]
+impl<T, F, R> Handler for T
+where
+    T: Fn(Context) -> F + Send + Sync + 'static,
+    F: Future<Output = R> + Send + 'static,
+    R: Responder + 'static,
+{
+    async fn call(&self, ctx: Context) -> ContextResult {
+        Ok((self)(ctx).await.respond_to())
+    }
+}
+
+/// `Result` with the error type `ObsidianError`.
+pub type ContextResult<E = ObsidianError> = Result<Response, E>;
diff --git a/src/lib.rs b/src/lib.rs
index cd702ac..6964e7f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,10 +4,10 @@ mod app;
 pub mod error;
 
 pub mod context;
+pub mod handler;
 pub mod middleware;
 pub mod router;
 
 pub use app::{App, EndpointExecutor};
 pub use error::ObsidianError;
 pub use hyper::{header, Body, HeaderMap, Method, Request, Response, StatusCode, Uri, Version};
-pub use router::ContextResult;
diff --git a/src/middleware.rs b/src/middleware.rs
index 88b8d17..723bc34 100644
--- a/src/middleware.rs
+++ b/src/middleware.rs
@@ -4,8 +4,40 @@ use async_trait::async_trait;
 
 use crate::app::EndpointExecutor;
 use crate::context::Context;
-use crate::router::ContextResult;
+use crate::handler::ContextResult;
 
+/// Middleware trait provides a way to allow user to:
+/// 1. alter the request data before proceeding to the next middleware or the handler
+/// 2. transform the response on the way out
+/// 3. perform side-effects before or after handler processing
+///
+/// ```
+/// use async_trait::async_trait;
+/// use obsidian::{
+///     context::Context, handler::ContextResult, middleware::Middleware, EndpointExecutor,
+/// };
+///
+/// // Middleware struct
+/// pub struct ExampleMiddleware {}
+///
+/// #[async_trait]
+/// impl Middleware for ExampleMiddleware {
+///     async fn handle<'a>(
+///         &'a self,
+///         context: Context,
+///         ep_executor: EndpointExecutor<'a>,
+///     ) -> ContextResult {
+///
+///         // actions BEFORE handler processing write here...
+///
+///         let result = ep_executor.next(context).await?;
+///
+///         // actions AFTER handler processing write here...
+///
+///         Ok(result)
+///     }
+/// }
+/// ```
 #[async_trait]
 pub trait Middleware: Send + Sync + 'static {
     async fn handle<'a>(
diff --git a/src/middleware/logger.rs b/src/middleware/logger.rs
index 5a7537d..2d364a2 100644
--- a/src/middleware/logger.rs
+++ b/src/middleware/logger.rs
@@ -3,8 +3,8 @@ use std::time::Instant;
 
 use crate::app::EndpointExecutor;
 use crate::context::Context;
+use crate::handler::ContextResult;
 use crate::middleware::Middleware;
-use crate::router::ContextResult;
 
 use colored::*;
 
@@ -31,14 +31,11 @@ impl Middleware for Logger {
         println!("{} {:#?}", "[debug]".cyan(), context);
 
         match ep_executor.next(context).await {
-            Ok(context_after) => {
+            Ok(response) => {
                 let duration = start.elapsed();
-                println!(
-                    "[info] Sent {} in {:?}",
-                    context_after.response().as_ref().unwrap().status(),
-                    duration
-                );
-                Ok(context_after)
+                let status = response.status();
+                println!("[info] Sent {} in {:?}", status, duration);
+                Ok(response)
             }
             Err(error) => {
                 println!("{} {}", "[error]".red(), error);
diff --git a/src/router.rs b/src/router.rs
index 8eff03d..5508cbe 100644
--- a/src/router.rs
+++ b/src/router.rs
@@ -1,4 +1,3 @@
-mod handler;
 mod req_deserializer;
 mod resource;
 mod responder;
@@ -9,11 +8,11 @@ mod route_trie;
 
 use self::route_trie::RouteTrie;
 use crate::context::Context;
+use crate::handler::{ContextResult, Handler};
 use crate::middleware::Middleware;
 use crate::Method;
 pub use hyper::header;
 
-pub use self::handler::{ContextResult, Handler};
 pub use self::req_deserializer::{from_cow_map, Error as FormError};
 pub use self::resource::Resource;
 pub use self::responder::Responder;
@@ -137,10 +136,7 @@ impl Router {
 
             dir_path.append(&mut relative_path);
 
-            Box::pin(async move {
-                ctx.build(Response::ok().file(&dir_path.join("/")).await)
-                    .ok()
-            })
+            Box::pin(async move { Response::ok().file(&dir_path.join("/")).await })
         }
     }
 
@@ -153,8 +149,7 @@ impl Router {
             .map(|x| x.to_string())
             .collect::<Vec<String>>();
 
-        ctx.build(Response::ok().file(&relative_path.join("/")).await)
-            .ok()
+        Ok(Response::ok().file(&relative_path.join("/")).await)
     }
 }
 
diff --git a/src/router/handler.rs b/src/router/handler.rs
deleted file mode 100644
index 3250e4c..0000000
--- a/src/router/handler.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use crate::context::Context;
-use crate::error::ObsidianError;
-
-use async_trait::async_trait;
-use std::future::Future;
-
-pub type ContextResult<T = ObsidianError> = Result<Context, T>;
-
-#[async_trait]
-pub trait Handler: Send + Sync + 'static {
-    async fn call(&self, ctx: Context) -> ContextResult;
-}
-
-#[async_trait]
-impl<T, F> Handler for T
-where
-    T: Fn(Context) -> F + Send + Sync + 'static,
-    F: Future<Output = ContextResult> + Send + 'static,
-{
-    async fn call(&self, ctx: Context) -> ContextResult {
-        (self)(ctx).await
-    }
-}
diff --git a/src/router/responder.rs b/src/router/responder.rs
index c7ba32d..6f0cd04 100644
--- a/src/router/responder.rs
+++ b/src/router/responder.rs
@@ -1,5 +1,7 @@
 use super::Response;
 use super::ResponseBody;
+use crate::error::IntoErrorResponse;
+use crate::handler::ContextResult;
 use hyper::{header, StatusCode};
 
 pub trait Responder {
@@ -112,6 +114,42 @@ impl Responder for Option<&'static str> {
     }
 }
 
+// For Result<Response, E> where E: IntoErrorResponse
+impl<E> Responder for ContextResult<E>
+where
+    E: IntoErrorResponse,
+{
+    fn respond_to(self) -> Response {
+        match self {
+            Ok(resp) => resp.respond_to(),
+            Err(err) => err.into_error_response(),
+        }
+    }
+}
+
+// For Result<Response, ObsidianError>
+impl Responder for ContextResult {
+    fn respond_to(self) -> Response {
+        match self {
+            Ok(resp) => resp,
+            Err(err) => err.to_string().respond_to(),
+        }
+    }
+}
+
+impl<T, E> Responder for Result<T, E>
+where
+    T: Responder + ResponseBody,
+    E: IntoErrorResponse,
+{
+    fn respond_to(self) -> Response {
+        match self {
+            Ok(resp) => resp.respond_to(),
+            Err(err) => err.into_error_response(),
+        }
+    }
+}
+
 #[cfg(test)]
 mod test {
     use super::*;
diff --git a/src/router/response.rs b/src/router/response.rs
index 974df78..2e910ed 100644
--- a/src/router/response.rs
+++ b/src/router/response.rs
@@ -4,6 +4,7 @@ use async_std::fs;
 use http::StatusCode;
 use hyper::{header, Body};
 use serde::ser::Serialize;
+use std::fmt::Debug;
 
 #[derive(Debug)]
 pub struct Response {
@@ -21,6 +22,14 @@ impl Response {
         }
     }
 
+    pub fn new_with_body(body: Body) -> Self {
+        Response {
+            body,
+            status: StatusCode::OK,
+            headers: None,
+        }
+    }
+
     pub fn status(&self) -> StatusCode {
         self.status
     }
diff --git a/src/router/route_trie.rs b/src/router/route_trie.rs
index 2eb7880..7cf94a5 100644
--- a/src/router/route_trie.rs
+++ b/src/router/route_trie.rs
@@ -4,10 +4,10 @@ use std::sync::Arc;
 
 use hyper::Method;
 
+use crate::error::InternalError;
 use crate::middleware::Middleware;
 use crate::router::Resource;
 use crate::router::Route;
-use crate::ObsidianError;
 
 #[derive(Clone, Default)]
 pub struct RouteValue {
@@ -324,7 +324,7 @@ impl Node {
     }
 
     /// Process the side effects of node insertion
-    fn process_insertion(&mut self, key: &str) -> Result<&mut Self, ObsidianError> {
+    fn process_insertion(&mut self, key: &str) -> Result<&mut Self, InternalError> {
         let action = self.get_insertion_action(key);
 
         match action.name {
@@ -388,7 +388,7 @@ impl Node {
             }
             ActionName::Error => {
                 if let Some(node) = self.child_nodes.get(action.payload.node_index) {
-                    return Err(ObsidianError::GeneralError(format!(
+                    return Err(InternalError::GeneralError(format!(
                         "ERROR: Ambigous definition between {} and {}",
                         key, node.key
                     )));