diff --git a/Cargo.toml b/Cargo.toml
index 8f4e7c4..ccc5131 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,19 +2,15 @@
 name = "codigocomentado"
 version = "0.1.0"
 authors = ["kirbylife <gabriel13m@gmail.com>"]
-edition = "2018"
+edition = "2021"
 
 [dependencies]
-rocket = "0.4.11"
+rocket = { version = "0.5.0", features = ["secrets"] }
+rocket_dyn_templates = { version = "0.1.0", features = ["tera"] }
 diesel = { version = "1.0.0", features = ["postgres", "chrono"] }
 dotenv = "0.9.0"
 rand = "0.6.0"
 chrono = { version = "0.4.9", features = ["serde"] }
 serde = { version = "1.0", features = ["derive"] }
-tera = "0.11"
 comrak = "0.6"
-
-[dependencies.rocket_contrib]
-version = "0.4.2"
-default-features = false
-features = ["json", "serve", "handlebars_templates", "tera_templates"]
\ No newline at end of file
+tera = "1.19.1"
diff --git a/Rocket.toml b/Rocket.toml
new file mode 100644
index 0000000..b6315da
--- /dev/null
+++ b/Rocket.toml
@@ -0,0 +1,7 @@
+[default]
+address = "0.0.0.0"
+limits = { form = "100 MiB", json = "100 MiB" }
+port = 8000
+
+[release]
+secret_key = "openssl rand -base64 32"
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..36c419b
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1 @@
+edition = "2021"
\ No newline at end of file
diff --git a/src/admin.rs b/src/admin.rs
index 5b93cec..111d77c 100644
--- a/src/admin.rs
+++ b/src/admin.rs
@@ -1,11 +1,11 @@
+use crate::contexts;
 use crate::controllers::posts;
-use crate::misc::get_context;
 use crate::models::NewPost;
-use rocket::http::{Cookie, Cookies};
-use rocket::request::Form;
+use rocket::form::Form;
+use rocket::http::{Cookie, CookieJar};
 use rocket::response::Redirect;
 use rocket::Route;
-use rocket_contrib::templates::Template;
+use rocket_dyn_templates::Template;
 use std::env;
 use std::vec::Vec;
 
@@ -16,20 +16,20 @@ struct Login {
 }
 
 #[get("/")]
-fn index(mut cookies: Cookies<'_>) -> Result<Redirect, Template> {
+fn index(cookies: &CookieJar<'_>) -> Result<Redirect, Template> {
     let password = env::var("admin_pass").expect("admin_pass not setted");
     match cookies.get_private("user") {
         Some(cookie) => {
             if cookie.value() == password {
                 Ok(Redirect::to("/admin/panel"))
             } else {
-                let context = get_context();
+                let context = contexts::Empty::new();
 
                 Err(Template::render("admin/index", context))
             }
         }
         None => {
-            let context = get_context();
+            let context = contexts::Empty::new();
 
             Err(Template::render("admin/index", context))
         }
@@ -37,7 +37,7 @@ fn index(mut cookies: Cookies<'_>) -> Result<Redirect, Template> {
 }
 
 #[post("/", data = "<login>")]
-fn login(mut cookies: Cookies<'_>, login: Form<Login>) -> Redirect {
+fn login(cookies: &CookieJar<'_>, login: Form<Login>) -> Redirect {
     let username = env::var("admin_user").expect("admin_user not setted");
     let password = env::var("admin_pass").expect("admin_pass not setted");
 
@@ -50,18 +50,16 @@ fn login(mut cookies: Cookies<'_>, login: Form<Login>) -> Redirect {
 }
 
 #[get("/panel")]
-fn panel(mut cookies: Cookies<'_>) -> Result<Template, Redirect> {
+fn panel(cookies: &CookieJar<'_>) -> Result<Template, Redirect> {
     let password = env::var("admin_pass").expect("admin_pass not setted");
 
     match cookies.get_private("user") {
         Some(cookie) => {
             if cookie.value() == password {
-                let mut context = get_context();
-
                 let (all_posts, n_posts) = posts::get_posts(None);
 
-                context.insert("posts", &all_posts);
-                context.insert("n_posts", &n_posts);
+                let context = contexts::AllPosts::new(all_posts, n_posts);
+
                 Ok(Template::render("admin/panel", context))
             } else {
                 Err(Redirect::to("/admin"))
@@ -72,17 +70,15 @@ fn panel(mut cookies: Cookies<'_>) -> Result<Template, Redirect> {
 }
 
 #[get("/add_post")]
-fn add_post(mut cookies: Cookies<'_>) -> Result<Template, Redirect> {
+fn add_post(cookies: &CookieJar<'_>) -> Result<Template, Redirect> {
     let password = env::var("admin_pass").expect("admin_pass not setted");
 
     match cookies.get_private("user") {
         Some(cookie) => {
             if cookie.value() == password {
-                let context = get_context();
+                let context = contexts::Empty::new();
 
                 Ok(Template::render("admin/add_post", context))
-            } else if cookie.value() == "123" {
-                Err(Redirect::to("/admin"))
             } else {
                 Err(Redirect::to("/admin"))
             }
@@ -92,7 +88,7 @@ fn add_post(mut cookies: Cookies<'_>) -> Result<Template, Redirect> {
 }
 
 #[post("/add_post", data = "<post>")]
-fn write_add_post(mut cookies: Cookies<'_>, post: Form<NewPost>) -> Redirect {
+fn write_add_post(cookies: &CookieJar<'_>, post: Form<NewPost>) -> Redirect {
     let password = env::var("admin_pass").expect("admin_pass not setted");
 
     match cookies.get_private("user") {
@@ -111,17 +107,16 @@ fn write_add_post(mut cookies: Cookies<'_>, post: Form<NewPost>) -> Redirect {
 }
 
 #[get("/edit_post/<id>")]
-fn edit_post(mut cookies: Cookies<'_>, id: i32) -> Result<Template, Redirect> {
+fn edit_post(cookies: &CookieJar<'_>, id: i32) -> Result<Template, Redirect> {
     let password = env::var("admin_pass").expect("admin_pass not setted");
 
     match cookies.get_private("user") {
         Some(cookie) => {
             if cookie.value() == password {
-                let mut context = get_context();
-
                 let post = posts::get_post(id).unwrap();
 
-                context.insert("post", &post);
+                let context = contexts::SinglePost::new(post);
+
                 Ok(Template::render("admin/edit_post", context))
             } else {
                 Err(Redirect::to("/admin"))
@@ -132,7 +127,7 @@ fn edit_post(mut cookies: Cookies<'_>, id: i32) -> Result<Template, Redirect> {
 }
 
 #[post("/edit_post/<id>", data = "<post>")]
-fn write_edit_post(mut cookies: Cookies<'_>, id: i32, post: Form<NewPost>) -> Redirect {
+fn write_edit_post(cookies: &CookieJar<'_>, id: i32, post: Form<NewPost>) -> Redirect {
     let password = env::var("admin_pass").expect("admin_pass not setted");
 
     match cookies.get_private("user") {
diff --git a/src/contexts.rs b/src/contexts.rs
new file mode 100644
index 0000000..16e0683
--- /dev/null
+++ b/src/contexts.rs
@@ -0,0 +1,94 @@
+use crate::controllers::posts;
+use crate::misc::gen_title;
+use crate::models::Post;
+use serde::Serialize;
+
+#[derive(Serialize)]
+pub struct PageOfPosts {
+    title: String,
+    posts: Vec<Post>,
+    total_pages: i64,
+    actual_page: u64,
+}
+
+impl PageOfPosts {
+    pub fn new(posts: Vec<Post>, actual_page: u64, n_posts: i64) -> Self {
+        let total_pages = (n_posts as f64 / posts::MAX_POSTS_PER_PAGE as f64).ceil() as i64;
+
+        PageOfPosts {
+            title: gen_title(),
+            posts,
+            total_pages,
+            actual_page,
+        }
+    }
+}
+
+#[derive(Serialize)]
+pub struct XmlFeed {
+    posts: Vec<Post>,
+}
+
+impl XmlFeed {
+    pub fn new(posts: Vec<Post>) -> Self {
+        XmlFeed { posts }
+    }
+}
+
+#[derive(Serialize)]
+pub struct SinglePost {
+    title: String,
+    post: Post,
+}
+
+impl SinglePost {
+    pub fn new(post: Post) -> Self {
+        SinglePost {
+            title: gen_title(),
+            post,
+        }
+    }
+}
+
+#[derive(Serialize)]
+pub struct NotFound {
+    title: String,
+    uri: String,
+}
+
+impl NotFound {
+    pub fn new(uri: String) -> Self {
+        NotFound {
+            title: gen_title(),
+            uri,
+        }
+    }
+}
+
+#[derive(Serialize)]
+pub struct AllPosts {
+    title: String,
+    posts: Vec<Post>,
+    n_posts: i64,
+}
+
+impl AllPosts {
+    pub fn new(posts: Vec<Post>, n_posts: i64) -> Self {
+        AllPosts {
+            title: gen_title(),
+            posts,
+            n_posts,
+        }
+    }
+}
+
+#[derive(Serialize)]
+pub struct Empty {
+    title: String,
+}
+
+impl Empty {
+    pub fn new() -> Self {
+        Empty { title: gen_title() }
+    }
+}
diff --git a/src/main.rs b/src/main.rs
index 41c84ef..eed923d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,5 @@
-#![feature(proc_macro_hygiene, decl_macro)]
-
 pub mod admin;
+pub mod contexts;
 pub mod controllers;
 pub mod misc;
 pub mod models;
@@ -10,20 +9,14 @@ mod schema;
 extern crate rocket;
 #[macro_use]
 extern crate diesel;
-extern crate comrak;
-extern crate dotenv;
-extern crate rocket_contrib;
-extern crate tera;
 
 use comrak::{markdown_to_html, ComrakOptions};
 use controllers::posts;
 use dotenv::dotenv;
-use misc::get_context;
-use rocket::response::content;
-use rocket::response::NamedFile;
+use rocket::fs::{FileServer, NamedFile};
+use rocket::response::content::RawXml;
 use rocket::Request;
-use rocket_contrib::serve::StaticFiles;
-use rocket_contrib::templates::Template;
+use rocket_dyn_templates::Template;
 use std::path::Path;
 use std::vec::Vec;
 
@@ -31,21 +24,15 @@ use std::vec::Vec;
 fn index(page: Option<u64>) -> Template {
     let page: u64 = page.unwrap_or(1);
 
-    let mut context = get_context();
-
     let (posts, n_posts) = posts::get_posts(Some(page));
 
-    let total_pages = (n_posts as f64 / posts::MAX_POSTS_PER_PAGE as f64).ceil() as i64;
+    let context = contexts::PageOfPosts::new(posts, page, n_posts);
 
-    context.insert("posts", &posts);
-    context.insert("total_pages", &total_pages);
-    context.insert("actual_page", &page);
     Template::render("index", context)
 }
 
 #[get("/feed.xml")]
-fn rss_feed() -> content::Xml<Template> {
-    let mut context = get_context();
+fn rss_feed() -> RawXml<Template> {
     let (mut posts, _) = posts::get_posts(None);
 
     let comrak_options = ComrakOptions {
@@ -61,14 +48,13 @@ fn rss_feed() -> content::Xml<Template> {
         post.content = content;
     });
 
-    context.insert("posts", &posts);
+    let context = contexts::XmlFeed::new(posts);
 
-    content::Xml(Template::render("rss", context))
+    RawXml(Template::render("rss", context))
 }
 
 #[get("/atom.xml")]
-fn atom_feed() -> content::Xml<Template> {
-    let mut context = get_context();
+fn atom_feed() -> RawXml<Template> {
     let (mut posts, _) = posts::get_posts(None);
 
     let comrak_options = ComrakOptions {
@@ -84,15 +70,13 @@ fn atom_feed() -> content::Xml<Template> {
         post.content = content;
     });
 
-    context.insert("posts", &posts);
+    let context = contexts::XmlFeed::new(posts);
 
-    content::Xml(Template::render("atom", context))
+    RawXml(Template::render("atom", context))
 }
 
 #[get("/post/<title>")]
 fn show_post(title: String) -> Template {
-    let mut context = get_context();
-
     let title_splited: Vec<&str> = title.split('-').collect();
     let id = title_splited.last().unwrap().parse().unwrap_or(-1);
 
@@ -109,12 +93,15 @@ fn show_post(title: String) -> Template {
             let content = markdown_to_html(&post.content, &comrak_options);
             post.content = content;
 
-            context.insert("post", &post);
+            let context = contexts::SinglePost::new(post);
+
             Template::render("post", context)
         }
         Err(_) => {
             let uri = format!("/post/{}", title_splited.join("-"));
-            context.insert("url", &uri);
+
+            let context = contexts::NotFound::new(uri);
+
             Template::render("404", context)
         }
     }
@@ -122,27 +109,26 @@ fn show_post(title: String) -> Template {
 
 #[catch(404)]
 fn not_found_404(req: &Request) -> Template {
-    let mut context = get_context();
-
     let uri = format!("{}", req.uri());
 
-    context.insert("url", &uri);
+    let context = contexts::NotFound::new(uri);
+
     Template::render("404", context)
 }
 
 #[get("/favicon.ico")]
-fn favicon() -> Option<NamedFile> {
-    NamedFile::open(Path::new("static/favicon.ico")).ok()
+async fn favicon() -> Option<NamedFile> {
+    NamedFile::open(Path::new("static/favicon.ico")).await.ok()
 }
 
-fn main() {
+#[launch]
+fn rocket() -> _ {
     dotenv().ok();
 
-    rocket::ignite()
+    rocket::build()
         .attach(Template::fairing())
         .mount("/", routes![index, show_post, favicon, rss_feed, atom_feed])
         .mount("/admin", admin::get_routes())
-        .mount("/static", StaticFiles::from("static"))
-        .register(catchers![not_found_404])
-        .launch();
+        .mount("/static", FileServer::from("static"))
+        .register("/", catchers![not_found_404])
 }
diff --git a/src/misc.rs b/src/misc.rs
index 2f75928..bc5daa3 100644
--- a/src/misc.rs
+++ b/src/misc.rs
@@ -1,7 +1,4 @@
-extern crate tera;
-
 use rand::Rng;
-use tera::Context;
 
 const TITLES: [&str; 11] = [
     "/* {} */",
@@ -17,13 +14,9 @@ const TITLES: [&str; 11] = [
     "(* {} *)",
 ];
 
-pub fn get_context() -> Context {
-    let mut context = Context::new();
-
+pub fn gen_title() -> String {
     let mut rng = rand::thread_rng();
     let title_fmt = TITLES[rng.gen_range(0, TITLES.len())];
     let title = str::replace(title_fmt, "{}", "CódigoComentado");
-
-    context.insert("title", &title);
-    context
+    title.to_string()
 }