diff --git a/plugins/blog/README.md b/plugins/blog/README.md
new file mode 100644
index 0000000..e9f5bbd
--- /dev/null
+++ b/plugins/blog/README.md
@@ -0,0 +1,2 @@
+Monstra CMS Blog
+================
diff --git a/plugins/blog/blog.plugin.php b/plugins/blog/blog.plugin.php
new file mode 100644
index 0000000..6f9c3e3
--- /dev/null
+++ b/plugins/blog/blog.plugin.php
@@ -0,0 +1,356 @@
+
+ * echo Blog::getTags();
+ *
+ *
+ * @return string
+ */
+ public static function getTags($slug = null) {
+
+ // Display view
+ return View::factory('blog/views/frontend/tags')
+ ->assign('tags', Blog::getTagsArray($slug))
+ ->render();
+
+ }
+
+
+ /**
+ * Get breadcrumbs
+ *
+ *
+ * echo Blog::breadcrumbs();
+ *
+ *
+ * @return string
+ */
+ public static function breadcrumbs() {
+ $current_page = Pages::$requested_page;
+ $parent_page = '';
+ if ($current_page !== 'error404') {
+ $page = Pages::$pages->select('[slug="'.$current_page.'"]', null);
+ if (trim($page['parent']) !== '') {
+ $parent = true;
+ $parent_page = Pages::$pages->select('[slug="'.$page['parent'].'"]', null);
+ } else {
+ $parent = false;
+ }
+
+ // Display view
+ View::factory('blog/views/frontend/breadcrumbs')
+ ->assign('current_page', $current_page)
+ ->assign('page', $page)
+ ->assign('parent', $parent)
+ ->assign('parent_page', $parent_page)
+ ->display();
+ }
+ }
+
+
+ /**
+ * Get tags array
+ *
+ *
+ * echo Blog::getTagsArray();
+ *
+ *
+ * @return array
+ */
+ public static function getTagsArray($slug = null) {
+
+ // Init vars
+ $tags = array();
+ $tags_string = '';
+
+ if ($slug == null) {
+ $posts = Pages::$pages->select('[parent="'.Blog::$parent_page_name.'" and status="published"]', 'all');
+ } else {
+ $posts = Pages::$pages->select('[parent="'.Blog::$parent_page_name.'" and status="published" and slug="'.$slug.'"]', 'all');
+ }
+
+ foreach($posts as $post) {
+ $tags_string .= $post['keywords'].',';
+ }
+
+ $tags_string = substr($tags_string, 0, strlen($tags_string)-1);
+
+ // Explode tags in tags array
+ $tags = explode(',', $tags_string);
+
+ // Remove empty array elementss
+ foreach ($tags as $key => $value) {
+ if ($tags[$key] == '') {
+ unset($tags[$key]);
+ }
+ }
+
+ // Trim tags
+ array_walk($tags, create_function('&$val', '$val = trim($val);'));
+
+ // Get unique tags
+ $tags = array_unique($tags);
+
+ // Return tags
+ return $tags;
+ }
+
+
+ /**
+ * Get posts
+ *
+ *
+ * // Get all posts
+ * echo Blog::getPosts();
+ *
+ * // Get last 5 posts
+ * echo Blog::getPosts(5);
+ *
+ *
+ * @param integer $num Number of posts to show
+ * @return string
+ */
+ public static function getPosts($nums = 10) {
+
+ // Get page param
+ $page = (Request::get('page')) ? (int)Request::get('page') : 1;
+
+ if (Request::get('tag')) {
+ $query = '[parent="'.Blog::$parent_page_name.'" and status="published" and contains(keywords, "'.Request::get('tag').'")]';
+ Notification::set('tag', Request::get('tag'));
+ } else {
+ $query = '[parent="'.Blog::$parent_page_name.'" and status="published"]';
+ Notification::clean();
+ }
+
+ // Get Elements Count
+ $elements = count(Pages::$pages->select($query, 'all'));
+
+ // Get Pages Count
+ $pages = ceil($elements/$nums);
+
+
+ if ($page < 1) {
+ $page = 1;
+ } elseif ($page > $pages) {
+ $page = $pages;
+ }
+
+ $start = ($page-1)*$nums;
+
+ // If there is no posts
+ if ($start < 0) $start = 0;
+
+ // Get posts and sort by DESC
+ $posts = Pages::$pages->select($query, $nums, $start, array('slug', 'title', 'author', 'date'), 'date', 'DESC');
+
+ // Loop
+ foreach($posts as $key => $post) {
+ $post_short = explode("{cut}", Text::toHtml(File::getContent(STORAGE . DS . 'pages' . DS . $post['id'] . '.page.txt')));
+ $posts[$key]['content'] = Filter::apply('content', $post_short[0]);
+ }
+
+ // Display view
+ return View::factory('blog/views/frontend/index')
+ ->assign('posts', $posts)
+ ->render().
+ View::factory('blog/views/frontend/pager')
+ ->assign('pages', $pages)
+ ->assign('page', $page)
+ ->render();
+ }
+
+
+ /**
+ * Get posts block
+ *
+ *
+ * // Get all posts
+ * echo Blog::getPostsBlock();
+ *
+ * // Get last 5 posts
+ * echo Blog::getPostsBlock(5);
+ *
+ *
+ * @param integer $num Number of posts to show
+ * @return string
+ */
+ public static function getPostsBlock($nums = 10) {
+
+ // XPath Query
+ $query = '[parent="'.Blog::$parent_page_name.'" and status="published"]';
+
+ // Get posts and sort by DESC
+ $posts = Pages::$pages->select($query, $nums, 0, array('slug', 'title', 'author', 'date'), 'date', 'DESC');
+
+ // Loop
+ foreach($posts as $key => $post) {
+ $post_short = explode("{cut}", Text::toHtml(File::getContent(STORAGE . DS . 'pages' . DS . $post['id'] . '.page.txt')));
+ $posts[$key]['content'] = Filter::apply('content', $post_short[0]);
+ }
+
+ // Display view
+ return View::factory('blog/views/frontend/block')
+ ->assign('posts', $posts)
+ ->render();
+
+ }
+
+
+ /**
+ * Get related posts
+ *
+ *
+ * echo Blog::getRelatedPosts();
+ *
+ *
+ * @return string
+ */
+ public static function getRelatedPosts($limit = null) {
+
+ $related_posts = array();
+ $tags = Blog::getTagsArray(Page::slug());
+
+ foreach($tags as $tag) {
+
+ $query = '[parent="'.Blog::$parent_page_name.'" and status="published" and contains(keywords, "'.$tag.'") and slug!="'.Page::slug().'"]';
+
+ if ($result = Arr::subvalSort(Pages::$pages->select($query, ($limit == null) ? 'all' : (int)$limit), 'date', 'DESC')) {
+ $related_posts = $result;
+ }
+ }
+
+ // Display view
+ return View::factory('blog/views/frontend/related_posts')
+ ->assign('related_posts', $related_posts)
+ ->render();
+
+ }
+
+
+ /**
+ * Get post content
+ *
+ *
+ * echo Blog::getPost();
+ *
+ *
+ * @return string
+ */
+ public static function getPost() {
+
+ // Get post
+ $post = Text::toHtml(File::getContent(STORAGE . DS . 'pages' . DS . Pages::$page['id'] . '.page.txt'));
+
+ // Apply content filter
+ $post = Filter::apply('content', $post);
+
+ // Remove {cut} shortcode
+ $post = strtr($post, array('{cut}' => ''));
+
+ // Return post
+ return $post;
+ }
+
+
+ /**
+ * Get post content before cut
+ *
+ *
+ * echo Blog::getPostBeforeCut('home');
+ *
+ *
+ * @return string
+ */
+ public static function getPostBeforeCut($slug) {
+
+ $page = Pages::$pages->select('[slug="'.$slug.'"]', null);
+
+ // Get post
+ $post = explode("{cut}", Text::toHtml(File::getContent(STORAGE . DS . 'pages' . DS . $page['id'] . '.page.txt')));
+
+ // Apply content filter
+ $post_content = Filter::apply('content', $post[0]);
+
+ // Return post
+ return $post_content;
+ }
+
+
+ /**
+ * Get post content after cut
+ *
+ *
+ * echo Blog::getPostAfterCut('home');
+ *
+ *
+ * @return string
+ */
+ public static function getPostAfterCut($slug) {
+
+ $page = Pages::$pages->select('[slug="'.$slug.'"]', null);
+
+ // Get post
+ $post = explode("{cut}", Text::toHtml(File::getContent(STORAGE . DS . 'pages' . DS . $page['id'] . '.page.txt')));
+
+ // Apply content filter
+ $post_content = Filter::apply('content', $post[1]);
+
+ // Return post
+ return $post_content;
+ }
+
+
+ /**
+ * Get Blog Post title
+ *
+ *
+ * echo Blog::getPostTitle();
+ *
+ *
+ * @return string
+ */
+ public static function getPostTitle() {
+ return Page::title();
+ }
+
+ }
+
diff --git a/plugins/blog/install/blog.manifest.xml b/plugins/blog/install/blog.manifest.xml
new file mode 100644
index 0000000..6724013
--- /dev/null
+++ b/plugins/blog/install/blog.manifest.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/plugins/blog/views/frontend/breadcrumbs.view.php b/plugins/blog/views/frontend/breadcrumbs.view.php
new file mode 100644
index 0000000..80cb029
--- /dev/null
+++ b/plugins/blog/views/frontend/breadcrumbs.view.php
@@ -0,0 +1,5 @@
+
+ →
+
+
+
\ No newline at end of file
diff --git a/plugins/blog/views/frontend/index.view.php b/plugins/blog/views/frontend/index.view.php
new file mode 100644
index 0000000..6bfe180
--- /dev/null
+++ b/plugins/blog/views/frontend/index.view.php
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/plugins/blog/views/frontend/pager.view.php b/plugins/blog/views/frontend/pager.view.php
new file mode 100644
index 0000000..dad22bb
--- /dev/null
+++ b/plugins/blog/views/frontend/pager.view.php
@@ -0,0 +1,28 @@
+ $pages) $right_neighbour = $pages;
+
+ if ($page > 1) {
+ echo ' '.__('begin', 'blog').' ... '.__('prev', 'blog').' ';
+ }
+
+ for ($i=$left_neighbour; $i<=$right_neighbour; $i++) {
+ if ($i != $page) {
+ echo ' ' . $i . ' ';
+ } else {
+ echo ' ' . $i . ' ';
+ }
+ }
+
+ if ($page < $pages) {
+ echo ' '.__('next', 'blog').' ... '.__('end', 'blog').' ';
+ }
+
+?>
\ No newline at end of file
diff --git a/plugins/blog/views/frontend/related_posts.view.php b/plugins/blog/views/frontend/related_posts.view.php
new file mode 100644
index 0000000..8f89431
--- /dev/null
+++ b/plugins/blog/views/frontend/related_posts.view.php
@@ -0,0 +1,7 @@
+
+:
+