diff --git a/example.json b/example.json
index f115628d692c0c24c00f6ec39d4ea21e76bdc400..1c11d168fe1adfb637ce1b99941ed46b12b90321 100644
--- a/example.json
+++ b/example.json
@@ -7,7 +7,8 @@
             "image": "https://pijar.com/static/images/pijar_pic.png",
             "css": [],
             "js": [],
-            "url_slug": ""
+            "url_slug": "",
+            "lang": "en"
         },
         "body": [
             {
diff --git a/src/website/item.rs b/src/website/html.rs
similarity index 59%
rename from src/website/item.rs
rename to src/website/html.rs
index 3a59435a056a5aef10791d2bfddd3841eaf83fac..0563966178743f6c60ebbd2ea8699a9e36d2bca7 100644
--- a/src/website/item.rs
+++ b/src/website/html.rs
@@ -1,6 +1,64 @@
+use super::page::Page;
+use regex::{Captures, Regex};
 use serde::{Deserialize, Serialize};
 use std::collections::HashMap;
 
+pub const CSS_LINK_FRAGMENT: &'static str = "<link rel='stylesheet' href='{url}'>";
+pub const SCRIPT_FRAGMENT: &'static str = "<script src='{url}'></script>";
+
+const HTML_DOC_TEMPLATE: &'static str = "
+<html lang='{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='{description}'>
+    <title>{title}</title>
+    {css}
+</head>
+
+<body>
+    {body}
+</body>
+
+{js}
+
+</html>
+";
+
+pub fn replace_placeholders(template: &str, map: HashMap<String, String>) -> String {
+    let re = Regex::new(r#"\{[a-z]+\}"#).unwrap();
+    let def = String::new();
+    re.replace_all(template, |captures: &Captures| {
+        let placeholder = captures.iter().next().unwrap().unwrap().as_str();
+        let placeholder = placeholder[1..placeholder.len() - 1].to_owned(); // strip the brackets
+        match map.get(&placeholder) {
+            Some(s) => s,
+            None => &def,
+        }
+    })
+    .to_string()
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+pub struct HtmlDoc(String);
+
+impl HtmlDoc {
+    pub fn from_page(page: &Page) -> Self {
+        HtmlDoc(replace_placeholders(HTML_DOC_TEMPLATE, page.to_map()))
+    }
+
+    pub fn new() -> Self {
+        HtmlDoc(String::new())
+    }
+}
+
+impl std::fmt::Display for HtmlDoc {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        write!(f, "{}", self.0)
+    }
+}
+
 #[derive(Debug, Serialize, Deserialize, Clone)]
 pub struct HtmlAttributes(pub HashMap<String, String>);
 
@@ -48,7 +106,7 @@ impl std::fmt::Display for HtmlElement {
         let body = match &self.contents {
             Some(contents) => contents
                 .iter()
-                .map(|item| item.to_string())
+                .map(|el| el.to_string())
                 .collect::<Vec<String>>()
                 .join(""),
             None => match &self.text {
@@ -62,39 +120,39 @@ impl std::fmt::Display for HtmlElement {
 }
 
 #[cfg(test)]
-mod test_items {
+mod test_html_elements {
     use super::*;
 
     #[test]
-    fn text_item_content_to_string() {
-        let item_content = HtmlElement {
+    fn text_html_element_to_string() {
+        let html_el = HtmlElement {
             tag: String::from("p"),
             text: Some(String::from("Hello")),
             contents: None,
             attrs: HtmlAttributes::new(),
         };
 
-        assert_eq!(item_content.to_string(), "<p>Hello</p>")
+        assert_eq!(html_el.to_string(), "<p>Hello</p>")
     }
 
     #[test]
-    fn item_content_with_attrs_to_string() {
+    fn html_el_with_attrs_to_string() {
         let mut attrs = HtmlAttributes::new();
         attrs.0.insert(String::from("id"), String::from("some-id"));
 
-        let item_content = HtmlElement {
+        let html_el = HtmlElement {
             tag: String::from("p"),
             text: Some(String::from("Hello")),
             contents: None,
             attrs: attrs.clone(),
         };
 
-        assert_eq!(item_content.to_string(), "<p id=\"some-id\">Hello</p>");
+        assert_eq!(html_el.to_string(), "<p id=\"some-id\">Hello</p>");
     }
 
     #[test]
-    fn complex_item_content_to_string() {
-        let item_content = HtmlElement {
+    fn complex_html_el_to_string() {
+        let html_el = HtmlElement {
             tag: String::from("p"),
             text: None,
             attrs: HtmlAttributes::new(),
@@ -115,7 +173,7 @@ mod test_items {
         };
 
         assert_eq!(
-            item_content.to_string(),
+            html_el.to_string(),
             "<p><span>Hello </span><b>World</b></p>"
         )
     }
diff --git a/src/website/html_doc.rs b/src/website/html_doc.rs
deleted file mode 100644
index 06a7d82d68b03fab95338c2068eddf9541a89a1e..0000000000000000000000000000000000000000
--- a/src/website/html_doc.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-use super::page::Page;
-use regex::{Captures, Regex};
-use serde::{Deserialize, Serialize};
-
-// const CSS_LINK_FRAGMENT: &'static str = "<link rel='stylesheet' href='{url}'>";
-// const SCRIPT_FRAGMENT: &'static str = "<script src='{url}'></script>";
-
-const HTML_DOC_TEMPLATE: &'static str = "
-<html lang='{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='{description}'>
-    <title>{title}</title>
-    {css}
-</head>
-
-<body>
-    {body}
-</body>
-
-{js}
-
-</html>
-";
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-pub struct HtmlDoc(String);
-
-impl HtmlDoc {
-    pub fn from_page(page: &Page) -> Self {
-        let re = Regex::new(r#"\{[a-z]+\}"#).unwrap();
-
-        let html = re
-            .replace_all(HTML_DOC_TEMPLATE, |captures: &Captures| {
-                let placeholder = captures.iter().next().unwrap().unwrap().as_str();
-                let placeholder = placeholder[1..placeholder.len() - 1].to_owned(); // strip the brackets
-                page.text_from_key(placeholder)
-            })
-            .to_string();
-
-        HtmlDoc(html)
-    }
-
-    pub fn new() -> Self {
-        HtmlDoc(String::new())
-    }
-}
-
-impl std::fmt::Display for HtmlDoc {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        write!(f, "{}", self.0)
-    }
-}
diff --git a/src/website/mod.rs b/src/website/mod.rs
index 0fd4f5bce2d0520bbebd6d061bab36ccbbd4c257..df329bf20e460e4767e629c900517b8b50597f50 100644
--- a/src/website/mod.rs
+++ b/src/website/mod.rs
@@ -1,6 +1,5 @@
 mod css;
-mod html_doc;
-mod item;
+mod html;
 mod page;
 mod website;
 
diff --git a/src/website/page.rs b/src/website/page.rs
index 68f47a9442659d7da201ea114041a766778a3ff5..c4b33a730a5365d8d349e3ba792cef75175b5d6d 100644
--- a/src/website/page.rs
+++ b/src/website/page.rs
@@ -1,7 +1,7 @@
 use super::css::StyleSheet;
-use super::html_doc::HtmlDoc;
-use super::item::*;
+use super::html::{replace_placeholders, HtmlDoc, HtmlElement, CSS_LINK_FRAGMENT, SCRIPT_FRAGMENT};
 use serde::{Deserialize, Serialize};
+use std::collections::HashMap;
 
 #[derive(Debug, Serialize, Deserialize, Clone)]
 pub struct Page {
@@ -46,8 +46,66 @@ pub struct PageMetadata {
     pub lang: String,
     pub description: String,
     pub url_slug: String,
-    pub css: Vec<String>,
-    pub js: Vec<String>,
+    #[serde(default = "CSSLinks::new")]
+    pub css: CSSLinks,
+    #[serde(default = "JSLinks::new")]
+    pub js: JSLinks,
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+pub struct CSSLinks(Vec<String>);
+
+impl CSSLinks {
+    pub fn new() -> Self {
+        CSSLinks(vec!["/static/default/style.css".to_owned()])
+    }
+}
+
+impl std::fmt::Display for CSSLinks {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        write!(
+            f,
+            "{}",
+            &self
+                .0
+                .iter()
+                .map(|url| replace_placeholders(CSS_LINK_FRAGMENT, {
+                    let mut map = HashMap::new();
+                    map.insert("url".to_string(), url.to_owned());
+                    map
+                }))
+                .collect::<Vec<String>>()
+                .join("")
+        )
+    }
+}
+
+#[derive(Debug, Serialize, Deserialize, Clone)]
+pub struct JSLinks(Vec<String>);
+
+impl JSLinks {
+    pub fn new() -> Self {
+        JSLinks(vec!["/static/default/script.js".to_owned()])
+    }
+}
+
+impl std::fmt::Display for JSLinks {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        write!(
+            f,
+            "{}",
+            &self
+                .0
+                .iter()
+                .map(|url| replace_placeholders(SCRIPT_FRAGMENT, {
+                    let mut map = HashMap::new();
+                    map.insert("url".to_string(), url.to_owned());
+                    map
+                }))
+                .collect::<Vec<String>>()
+                .join("")
+        )
+    }
 }
 
 impl Page {
@@ -56,28 +114,35 @@ impl Page {
     }
 
     pub fn build_body_template(&mut self, template: PageTemplate) {
-        let mut body = template.clone();
+        let mut complete_body = template.clone();
         self.template = Some(template);
         let err = "Couldn't find page-body placeholder";
-        body.contents
+
+        // Insert page body inside the template page-body container.
+        // Then replace the page body by the complete template
+        complete_body
+            .contents
             .iter_mut()
             .find(|el| el.attrs.get("id").unwrap_or(&String::new()).eq("page-body"))
             .expect(err)
             .set_contents(self.body.0.clone());
 
-        self.body.0 = body.contents;
+        self.body.0 = complete_body.contents;
     }
 
-    pub fn text_from_key(&self, key: String) -> String {
-        match &key[..] {
-            "title" => self.metadata.title.to_owned(),
-            "lang" => self.metadata.lang.to_owned(),
-            "description" => self.metadata.description.to_owned(),
-            "slug" => self.metadata.url_slug.to_owned(),
-            "body" => self.body.to_string(),
-            // "css" => self.css.as_ref().unwrap_or(&String::new()).to_owned(),
-            // "js" => self.js.as_ref().unwrap_or(&String::new()).to_owned(),
-            _ => String::new(),
-        }
+    pub fn to_map(&self) -> HashMap<String, String> {
+        let mut map = HashMap::new();
+        map.insert("title".to_string(), self.metadata.title.to_owned());
+        map.insert("lang".to_string(), self.metadata.lang.to_owned());
+        map.insert(
+            "description".to_string(),
+            self.metadata.description.to_owned(),
+        );
+        map.insert("slug".to_string(), self.metadata.url_slug.to_owned());
+        map.insert("body".to_string(), self.body.to_string());
+        map.insert("css".to_string(), self.metadata.css.to_string());
+        map.insert("js".to_string(), self.metadata.js.to_string());
+
+        map
     }
 }
diff --git a/src/website/website.rs b/src/website/website.rs
index 2645eaa1e5bc612b2c2d04d2b6bbcb51c48d9288..20274b3ba01d7a2175a57fe8fcecc29c64243abe 100644
--- a/src/website/website.rs
+++ b/src/website/website.rs
@@ -7,6 +7,7 @@ use std::path::PathBuf;
 #[derive(Debug, Serialize, Deserialize, Clone)]
 pub struct WebSite {
     root_page: Page,
+    #[serde(default = "AssetsIndex::new")]
     assets_index: AssetsIndex,
     templates: Vec<PageTemplate>,
     #[serde(default = "HashMap::new")]
@@ -22,12 +23,22 @@ pub struct AssetsIndex {
     pub source_code: Vec<String>,
 }
 
+impl AssetsIndex {
+    pub fn new() -> Self {
+        AssetsIndex {
+            images: Vec::new(),
+            sounds: Vec::new(),
+            videos: Vec::new(),
+            docs: Vec::new(),
+            source_code: Vec::new(),
+        }
+    }
+}
+
 impl WebSite {
     pub fn from_json(json: &str) -> Self {
-        let mut obj: Self = serde_json::from_str(json).unwrap();
-        obj.build_assets_index();
-        obj.build_pages_index(obj.root_page.clone(), PathBuf::from("/"));
-        obj.root_page.build_html();
+        let mut obj: WebSite = serde_json::from_str(json).unwrap();
+
         obj.root_page.build_body_template(
             obj.templates
                 .iter()
@@ -35,8 +46,10 @@ impl WebSite {
                 .expect("Page template not found")
                 .clone(),
         );
+
+        obj.root_page.build_html();
+
         for p in obj.root_page.sub_pages.iter_mut() {
-            p.build_html();
             p.build_body_template(
                 obj.templates
                     .iter()
@@ -44,7 +57,12 @@ impl WebSite {
                     .expect("Page template not found")
                     .clone(),
             );
+            p.build_html();
         }
+
+        obj.build_assets_index();
+        obj.build_pages_index(obj.root_page.clone(), PathBuf::from("/"));
+
         obj
     }
 
diff --git a/templates/new_website.json b/templates/new_website.json
index 29706c5138285bb9fb31780c74ed9d6fc571e41d..c13fb2d710b44dbfcbcfe476afc4abaefd471fda 100644
--- a/templates/new_website.json
+++ b/templates/new_website.json
@@ -5,9 +5,8 @@
             "title": "New Website",
             "description": "A new website",
             "image": "",
-            "css": [],
-            "js": [],
-            "url_slug": ""
+            "url_slug": "",
+            "lang": "en"
         },
         "body": [
             {