diff --git a/.gitignore b/.gitignore
index 8d7b400ad2178f45bdba1ead91052fb284e216f3..f500892940542a8edf87c12a7c2502885f175003 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,5 @@ bundle.js
 node_modules
 target
 .env
-public/**/*.js
\ No newline at end of file
+public/**/*.js
+public/**/view/*
\ No newline at end of file
diff --git a/admin-frontend/src/article.js b/admin-frontend/src/article.js
index 6ba6b37e8409d9ff8667e83f2e72264a9a9401c7..c583c3d94684bc947ebcf11577d71afd9d32cb75 100644
--- a/admin-frontend/src/article.js
+++ b/admin-frontend/src/article.js
@@ -12,6 +12,7 @@ class Article {
             this.images = [];
             this.body = "";
             this.locale = "";
+            this.display_priority_index = 1;
         }
     }
 
diff --git a/admin-frontend/src/xhr.js b/admin-frontend/src/xhr.js
index 32845c93ec1121fef9b79b74fc8c61c31191467c..5fc0148ff0d28e8c48bc08947afaaa348731a9db 100644
--- a/admin-frontend/src/xhr.js
+++ b/admin-frontend/src/xhr.js
@@ -11,25 +11,6 @@ async function fetch_article(article_id) {
     })
 }
 
-async function fetch_article_by_title(article_title) {
-    const form_data = new FormData();
-    form_data.append("title", article_title);
-
-    return new Promise((resolve, reject) => {
-        fetch(`/article-by-title/`, {
-            method: "POST",
-            body: new URLSearchParams(form_data),
-        }).then(async res => {
-            if (res.status >= 400 && res.status < 600) {
-                const text = await res.text();
-                reject(text);
-            } else {
-                resolve(await res.json());
-            }
-        }).catch(e => reject(e))
-    })
-}
-
 async function fetch_articles_by_category(category) {
     return new Promise((resolve, reject) => {
         fetch(`/articles/${category}`).then(async res => {
@@ -126,7 +107,6 @@ async function fetch_all_articles() {
 
 module.exports = {
     fetch_article,
-    fetch_article_by_title,
     fetch_articles_by_category,
     fetch_post_article,
     fetch_update_article,
diff --git a/dev.docker-compose.yml b/dev.docker-compose.yml
index 0adb1e276001171a192bd4f17e6e0c97f250e09d..6847c9548ce1e5ea42ea4cee9a45e8a897519a6e 100644
--- a/dev.docker-compose.yml
+++ b/dev.docker-compose.yml
@@ -14,7 +14,7 @@ services:
         volumes:
             - ./src:/usr/src/kuadrado_server/src:ro
             - ./Cargo.toml:/usr/src/kuadrado_server/Cargo.toml:ro
-            - ./public:${RESOURCES_DIR}/public:ro
+            - ./public:${RESOURCES_DIR}/public
             - /etc/letsencrypt/:${RESOURCES_DIR}/certs:ro
         command: cargo run
         env_file:
@@ -34,3 +34,7 @@ services:
             - ./mongo/scripts:/mongo-scripts
         ports:
             - "27017-27019:27017-27019"
+        deploy:
+            resources:
+                limits:
+                    memory: 250M
diff --git a/docker-compose.yml b/docker-compose.yml
index 9bb27056ac8d5f468e91fe9bfdcb4d2d30ab6d39..0a9ac506a6a76e86d7518e219c487547e297cd87 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -31,3 +31,7 @@ services:
             - ./mongo/scripts:/mongo-scripts
         ports:
             - "27017-27019:27017-27019"
+        deploy:
+            resources:
+                limits:
+                    memory: 250M
diff --git a/src/env.rs b/src/env.rs
index cf5860ba3b3edac6a6ce52757cd4b1000b0c336a..c0b0b9900271ef347e75ee8c412f0cd25517627e 100644
--- a/src/env.rs
+++ b/src/env.rs
@@ -12,6 +12,7 @@ pub struct Env {
     pub crypt_key: String,
     pub default_admin_username: String,
     pub default_admin_password: String,
+    pub public_dir: std::path::PathBuf,
 }
 
 static RELEASE_MODES: [&str; 3] = ["debug", "test", "prod"];
@@ -54,6 +55,10 @@ impl Env {
                 .expect("DEFAULT_ADMIN_USERNAME is not defined"),
             default_admin_password: env::var("DEFAULT_ADMIN_PASSWORD")
                 .expect("DEFAULT_ADMIN_PASSWORD is not defined"),
+            public_dir: std::path::PathBuf::from(
+                env::var("RESOURCES_DIR").expect("RESOURCES_DIR is not defined"),
+            )
+            .join("public"),
         }
     }
 
@@ -72,6 +77,10 @@ impl Env {
                 .expect("DEFAULT_ADMIN_USERNAME is not defined"),
             default_admin_password: env::var("DEFAULT_ADMIN_PASSWORD")
                 .expect("DEFAULT_ADMIN_PASSWORD is not defined"),
+            public_dir: std::path::PathBuf::from(
+                env::var("RESOURCES_DIR").expect("RESOURCES_DIR is not defined"),
+            )
+            .join("public"),
         }
     }
 }
diff --git a/src/main.rs b/src/main.rs
index d094fb032166982f6e59f38eacd0a8bc7f7ad11b..b8a1f8644140c25b34452c16e67d23ea8e6d1ce1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,6 +7,7 @@ mod middleware;
 mod model;
 mod service;
 mod standard_static_files;
+mod static_view;
 mod tls;
 mod view;
 mod view_resource;
@@ -34,10 +35,6 @@ async fn main() -> std::io::Result<()> {
 
     let server_port = env_var("SERVER_PORT").expect("SERVER_PORT is not defined.");
     let server_port_tls = env_var("SERVER_PORT_TLS").expect("SERVER_PORT_TLS is not defined.");
-    let public_dir =
-        std::path::PathBuf::from(env_var("RESOURCES_DIR").expect("RESOURCES_DIR is not defined"))
-            .join("public");
-
     let app_state = AppState::with_default_admin_user().await;
 
     HttpServer::new(move || {
@@ -89,7 +86,6 @@ async fn main() -> std::io::Result<()> {
             .service(delete_article)
             .service(get_articles_by_category)
             .service(get_article)
-            .service(get_article_by_title)
             .service(get_all_articles)
             /////////////////////////////////////////////////////////////////////////////////////////////////////////////
             // STANDARD FILES ///////////////////////////////////////////////////////////////////////////////////////////
@@ -102,18 +98,18 @@ async fn main() -> std::io::Result<()> {
                 scope("/v")
                     .service(Files::new(
                         "/admin-panel/assets",
-                        public_dir.join("views/admin-panel/assets"),
+                        app_state.env.public_dir.join("views/admin-panel/assets"),
                     ))
                     .service(Files::new(
                         "/admin-login/assets",
-                        public_dir.join("views/admin-login/assets"),
+                        app_state.env.public_dir.join("views/admin-login/assets"),
                     ))
                     // get_view will match any url to we put it at last
                     .service(get_view),
             )
             /////////////////////////////////////////////////////////////////////////////////////////////////////////////
             // PUBLIC WEBSITE //////////////////////////////////////////////////////////////////////////////////////////////
-            .service(Files::new("/", &public_dir).index_file("index.html"))
+            .service(Files::new("/", &app_state.env.public_dir).index_file("index.html"))
             /////////////////////////////////////////////////////////////////////////////////////////////////////////////
             // empty 404 ////////////////////////////////////////////////////////////////////////////////////////////////
             .default_service(to(|| {
diff --git a/src/service/articles.rs b/src/service/articles.rs
index a1287cc0157e2d39f02899781c9297d112082314..c38caf10a5bffdc0701bf97478a3940792b70931 100644
--- a/src/service/articles.rs
+++ b/src/service/articles.rs
@@ -1,14 +1,17 @@
-use crate::{middleware::AuthenticatedAdminMiddleware, model::Article, AppState};
+use crate::{
+    middleware::AuthenticatedAdminMiddleware, model::Article, static_view::create_static_view,
+    AppState,
+};
 use actix_web::{
     delete, get, post, put,
-    web::{Data, Form, Json, Path},
+    web::{Data, Json, Path},
     HttpRequest, HttpResponse, Responder,
 };
 use chrono::Utc;
 use futures::stream::StreamExt;
 use serde::{Deserialize, Serialize};
 use wither::{
-    bson::{doc, oid::ObjectId, DateTime},
+    bson::{doc, oid::ObjectId, Bson, DateTime},
     mongodb::Collection,
     prelude::Model,
 };
@@ -22,6 +25,38 @@ fn get_collection(app_state: &AppState) -> Collection<Article> {
     app_state.db.collection_with_type::<Article>("articles")
 }
 
+async fn generate_article_view(app_state: &AppState, id: &ObjectId) -> Result<(), String> {
+    match Article::find_one(&app_state.db, doc! {"_id":&id}, None).await {
+        Ok(art) => {
+            if art.is_none() {
+                return Err(format!("Article with id {} was not found", id));
+            }
+
+            let art = art.unwrap();
+            let html = format!(
+                "
+<html lang='{}'>
+<head>
+    <meta charset='UTF-8'>
+    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
+    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
+    <meta name='description' content='{}'>
+    <title>{}</title>
+</head>
+<body>
+    <div>{}<div>
+</body>
+</html>
+            ",
+                art.locale, art.subtitle, art.title, art.body,
+            );
+
+            create_static_view(&app_state, art.category, art.title, html)
+        }
+        Err(e) => return Err(format!("ERR {}", e)),
+    }
+}
+
 #[post("/post-article")]
 pub async fn post_article(
     app_state: Data<AppState>,
@@ -40,7 +75,20 @@ pub async fn post_article(
         .insert_one(article_data, None)
         .await
     {
-        Ok(res) => HttpResponse::Created().json(res),
+        Ok(res) => {
+            match &res.inserted_id {
+                Bson::ObjectId(id) => {
+                    if let Err(e) = generate_article_view(&app_state, id).await {
+                        return HttpResponse::InternalServerError()
+                            .body(format!("Error creating article page {:?}", e));
+                    }
+                }
+                _ => {
+                    return HttpResponse::InternalServerError().body("Error creating article page")
+                }
+            }
+            HttpResponse::Created().json(res)
+        }
         Err(e) => {
             HttpResponse::InternalServerError().body(format!("Error inserting new article {:?}", e))
         }
@@ -159,24 +207,6 @@ pub async fn get_article(app_state: Data<AppState>, article_id: Path<String>) ->
     }
 }
 
-#[post("/article-by-title")]
-pub async fn get_article_by_title(
-    app_state: Data<AppState>,
-    form_data: Form<ArticleTitleFormData>,
-) -> impl Responder {
-    let title = form_data.into_inner().title;
-    match Article::find_one(&app_state.db, doc! {"title":title}, None).await {
-        Ok(art) => {
-            if art.is_none() {
-                return HttpResponse::NotFound().body("Article was not found");
-            }
-
-            HttpResponse::Ok().json(art)
-        }
-        Err(e) => HttpResponse::InternalServerError().body(format!("Database error: {:#?}", e)),
-    }
-}
-
 #[get("/articles")]
 pub async fn get_all_articles(app_state: Data<AppState>) -> impl Responder {
     match get_collection(&app_state).find(None, None).await {
@@ -221,7 +251,6 @@ mod test_articles {
         web::Bytes,
         App,
     };
-    use wither::bson::Bson;
 
     async fn insert_test_article(
         app_state: &AppState,
@@ -558,42 +587,6 @@ mod test_articles {
         assert_eq!(del_count, 1);
     }
 
-    #[tokio::test]
-    async fn test_get_article_by_title() {
-        dotenv::dotenv().ok();
-
-        let app_state = AppState::for_test().await;
-
-        let mut app = test::init_service(
-            App::new()
-                .app_data(Data::new(app_state.clone()))
-                .service(get_article_by_title),
-        )
-        .await;
-
-        let article = Article::test_article();
-        let (article_id, article_title) = insert_test_article(&app_state, article.clone())
-            .await
-            .unwrap();
-
-        let req = test::TestRequest::with_uri("/article-by-title")
-            .header("Accept", "application/json")
-            .method(Method::POST)
-            .set_form(&ArticleTitleFormData {
-                title: article_title.to_owned(),
-            })
-            .to_request();
-
-        let resp = test::call_service(&mut app, req).await;
-
-        assert_eq!(resp.status(), StatusCode::OK);
-        let result: Article = test::read_body_json(resp).await;
-        assert_eq!(result.title, article_title);
-
-        let del_count = delete_test_article(&app_state, &article_id).await.unwrap();
-        assert_eq!(del_count, 1);
-    }
-
     #[tokio::test]
     async fn test_get_articles_by_category() {
         dotenv::dotenv().ok();
diff --git a/src/static_view.rs b/src/static_view.rs
new file mode 100644
index 0000000000000000000000000000000000000000..75cc486764fb43c626cf301e81fd58c498ce3dc9
--- /dev/null
+++ b/src/static_view.rs
@@ -0,0 +1,40 @@
+use crate::app_state::AppState;
+use std::fs::{create_dir, create_dir_all, File};
+use std::io::Write;
+
+pub fn create_static_view(
+    app_state: &AppState,
+    category: String,
+    filename: String,
+    html: String,
+) -> Result<(), String> {
+    let view_path = app_state.env.public_dir.join(&category).join("view");
+
+    if !view_path.exists() {
+        if let Err(e) = create_dir(&view_path) {
+            return Err(format!("Couldn't create directory {:?}: {}", view_path, e));
+        }
+    }
+
+    let d_path = app_state
+        .env
+        .public_dir
+        .join(&category)
+        .join("view")
+        .join(&filename);
+
+    if let Err(e) = create_dir_all(&d_path) {
+        return Err(format!("Error creating directory {:?} : {}", d_path, e));
+    }
+
+    let f_path = d_path.join("index.html");
+    match File::create(&f_path) {
+        Ok(mut f) => {
+            if let Err(e) = f.write_all(html.as_bytes()) {
+                return Err(format!("Error writing to {:?} : {}", f_path, e));
+            }
+            Ok(())
+        }
+        Err(e) => Err(format!("Error creating {:?} : {}", f_path, e)),
+    }
+}
diff --git a/src/view_resource.rs b/src/view_resource.rs
index 0678220a212fa65d82cfdcc0d9116dfe4ae2df95..a1ab07b6731806b9de116c81431aec315ded3ade 100644
--- a/src/view_resource.rs
+++ b/src/view_resource.rs
@@ -61,7 +61,7 @@ impl ViewResourceManager {
         let path: PathBuf = format!("{}/{}", dir_path.to_str().unwrap(), desc.index_file_name)
             .parse()
             .expect(&format!(
-                "Failed to pare resource index file path {:?}",
+                "Failed to parse resource index file path {:?}",
                 desc.index_file_name
             ));