From 62d0aa159fc046a27bed47e337d787a08f4687d0 Mon Sep 17 00:00:00 2001
From: Sunaina Pai
Date: Sat, 17 Mar 2018 14:45:21 +0530
Subject: Add makesite: A simple static site generator
---
.coveragerc | 3 +
.gitignore | 8 +
.travis.yml | 19 ++
LICENSE.md | 22 ++
Makefile | 73 ++++++
README.md | 376 +++++++++++++++++++++++++++++
content/_index.html | 28 +++
content/about.html | 23 ++
content/blog/2018-01-01-proin-quam.md | 29 +++
content/blog/2018-01-03-sed-finibus.md | 29 +++
content/contact.html | 21 ++
content/news/2018-01-02-vivamus-purus.html | 30 +++
content/news/2018-01-04-mauris-tempor.html | 37 +++
layout/feed.xml | 12 +
layout/item.html | 10 +
layout/item.xml | 13 +
layout/list.html | 5 +
layout/page.html | 42 ++++
layout/post.html | 5 +
makesite.py | 213 ++++++++++++++++
static/css/style.css | 136 +++++++++++
test/__init__.py | 0
test/path.py | 16 ++
test/test_content.py | 114 +++++++++
test/test_file_io.py | 39 +++
test/test_headers.py | 43 ++++
test/test_list.py | 46 ++++
test/test_main.py | 73 ++++++
test/test_pages.py | 63 +++++
test/test_path.py | 78 ++++++
test/test_render.py | 25 ++
31 files changed, 1631 insertions(+)
create mode 100644 .coveragerc
create mode 100644 .gitignore
create mode 100644 .travis.yml
create mode 100644 LICENSE.md
create mode 100644 Makefile
create mode 100755 README.md
create mode 100644 content/_index.html
create mode 100644 content/about.html
create mode 100644 content/blog/2018-01-01-proin-quam.md
create mode 100644 content/blog/2018-01-03-sed-finibus.md
create mode 100644 content/contact.html
create mode 100644 content/news/2018-01-02-vivamus-purus.html
create mode 100644 content/news/2018-01-04-mauris-tempor.html
create mode 100644 layout/feed.xml
create mode 100644 layout/item.html
create mode 100644 layout/item.xml
create mode 100644 layout/list.html
create mode 100644 layout/page.html
create mode 100644 layout/post.html
create mode 100755 makesite.py
create mode 100644 static/css/style.css
create mode 100644 test/__init__.py
create mode 100644 test/path.py
create mode 100644 test/test_content.py
create mode 100644 test/test_file_io.py
create mode 100644 test/test_headers.py
create mode 100644 test/test_list.py
create mode 100644 test/test_main.py
create mode 100644 test/test_pages.py
create mode 100644 test/test_path.py
create mode 100644 test/test_render.py
diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000..4ed6f59
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,3 @@
+[report]
+exclude_lines =
+ if __name__ == '__main__':
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..77cf371
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+_site
+*.pyc
+__pycache__
+.coverage
+htmlcov
+*.sw?
+.DS_Store
+venv
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..ef70b91
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,19 @@
+language: python
+
+python:
+ - "2.7"
+ - "3.3"
+ - "3.4"
+ - "3.5"
+ - "3.6"
+
+install:
+ - pip install commonmark coverage coveralls
+
+script:
+ - python -m unittest discover -bv
+ - coverage run --branch --source=. -m unittest discover -bv
+ - coverage report -m
+
+after_success:
+ - coveralls
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..3129e86
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+=====================
+Copyright (c) 2018 Sunaina Pai
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..c00a218
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,73 @@
+site:
+ ./makesite.py
+
+serve: site
+ cd _site && python -m SimpleHTTPServer 2> /dev/null || python3 -m http.server
+
+venv2:
+ virtualenv ~/.venv/makesite
+ echo . ~/.venv/makesite/bin/activate > venv
+ . ./venv && pip install commonmark coverage
+
+venv: FORCE
+ python3 -m venv ~/.venv/makesite
+ echo . ~/.venv/makesite/bin/activate > venv
+ . ./venv && pip install commonmark coverage
+
+test: FORCE
+ . ./venv && python -m unittest -bv
+
+coverage:
+ . ./venv && coverage run --branch --source=. -m unittest discover -bv; :
+ . ./venv && coverage report -m
+ . ./venv && coverage html
+
+clean:
+ find . -name "__pycache__" -exec rm -r {} +
+ find . -name "*.pyc" -exec rm {} +
+ rm -rf .coverage htmlcov
+
+REV = cat /tmp/rev.txt
+example:
+ #
+ # Remove existing output directories.
+ rm -rf _site /tmp/_site
+ #
+ # Create params.json for makesite-demo.
+ echo '{ "base_path": "/makesite-demo", "site_url":' \
+ '"https://tmug.github.io/makesite-demo" }' > params.json
+ #
+ # Generate the website.
+ . ./venv && ./makesite.py
+ rm params.json
+ #
+ # Get current commit ID.
+ git rev-parse --short HEAD > /tmp/rev.txt
+ #
+ # Write a README for makesite-demo repository.
+ echo makesite.py demo > _site/README.md
+ echo ================ >> _site/README.md
+ echo This is the HTML/CSS source of an example static >> _site/README.md
+ echo website auto-generated with [sunainapai/makesite][makesite] >> _site/README.md
+ echo "([$$($(REV))][commit])". >> _site/README.md
+ echo >> _site/README.md
+ echo Visit "" to >> _site/README.md
+ echo view the example website. >> _site/README.md
+ echo >> _site/README.md
+ echo [makesite]: https://github.com/sunainapai/makesite >> _site/README.md
+ echo [commit]: https://github.com/sunainapai/makesite/commit/$$($(COMMIT)) >> _site/README.md
+ echo [demo]: https://tmug.github.io/makesite-demo >> _site/README.md
+ #
+ # Publish makesite-demo.
+ mv _site /tmp
+ cd /tmp/_site && git init
+ cd /tmp/_site && git add .
+ cd /tmp/_site && git commit -m "Auto-generated with sunainapai/makesite - $$($(REV))"
+ cd /tmp/_site && git remote add origin https://github.com/tmug/makesite-demo.git
+ cd /tmp/_site && git log
+ cd /tmp/_site && git push -f origin master
+
+loc:
+ grep -vE '^[[:space:]]*#|^[[:space:]]*$$' makesite.py | wc -l
+
+FORCE:
diff --git a/README.md b/README.md
new file mode 100755
index 0000000..0f625a9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,376 @@
+makesite.py
+===========
+Take full control of your static website/blog generation by writing your
+own simple, lightweight, and magic-free static site generator in
+Python. That's right! Reinvent the wheel, fellas!
+
+[![View Source][SOURCE-BADGE]](makesite.py)
+[![View Demo][DEMO-BADGE]](https://tmug.github.io/makesite-demo)
+[![MIT License][LICENSE-BADGE]](LICENSE.md)
+
+[SOURCE-BADGE]: https://img.shields.io/badge/view-source-brightgreen.svg
+[DEMO-BADGE]: https://img.shields.io/badge/view-demo-brightgreen.svg
+[LICENSE-BADGE]: https://img.shields.io/badge/license-MIT-blue.svg
+
+
+Contents
+--------
+* [Introduction](#introduction)
+* [But Why?](#but-why)
+* [Get Started](#get-started)
+* [The Code](#the-code)
+* [Layout](#layout)
+* [Content](#content)
+* [Credits](#credits)
+* [License](#license)
+* [Support](#support)
+
+
+Introduction
+------------
+This repository contains the source code of an example website
+containing two static blogs and a few static pages. The website can be
+generated by running [makesite.py](makesite.py). The output looks like
+[this](https://tmug.github.io/makesite-demo). That's it!
+
+So go ahead, fork this repository, replace the [content](content) with
+your own, and generate your static website. It's that simple!
+
+You are [free](LICENSE.md) to copy, use, and modify this project for
+your blog or website, so go ahead and fork this repository and make it
+your own project. Change the [layout](layout) if you wish to, improve
+the [stylesheet](static/css/style.css) to suit your taste, enhance
+[makesite.py](makesite.py) if you need to, and develop your website/blog
+just the way you want it.
+
+
+But Why?
+--------
+For fun and profit! Okay, maybe not for profit, but hopefully for fun.
+
+Have you used a popular static site generator like Jekyll to generate
+your blog? I have too. It is simple and great. But then did you yearn
+to use something even simpler to generate your blog? Do you like Python?
+Perhaps the thought of writing your own static site generator crossed
+your mind but you thought it would be too much work? If you answered
+"yes" to these questions, then this project is for you.
+
+With this project, you are in full control. There is no hidden magic!
+Everything is laid out in [makesite.py](makesite.py) as plain and simple
+Python code. It is just 125 lines of code (excluding blank lines
+and comments). It gets you off the ground pretty quickly. You can have a
+decent website/blog generated within a few minutes and then you can
+begin tinkering with the [source code](makesite.py), the
+[layout](layout), and the [css](static/css/style.css) to customize the
+look and feel of your website to your satisfaction.
+
+
+Get Started
+-----------
+This section provides some quick steps to get you off the ground as
+quickly as possible.
+
+ 1. For a quick demo on your local system, just enter this command:
+
+ make serve
+
+ If you don't have `make` but have Python 3.x, enter this command:
+
+ python3 makesite.py
+ cd _site
+ python3 -m http.server
+
+ Note: In some environments, you may need to use `python` instead of
+ `python3` to invoke Python 3.x.
+
+ If you only have Python 2.7, enter this command:
+
+ python makesite.py
+ cd _site
+ python -m SimpleHTTPServer
+
+ Then visit http://localhost:8000/. It should look like
+ [this](https://tmug.github.io/makesite-demo).
+
+ Note: You can run [makesite.py](makesite.py) with Python 2.7 or
+ Python 3.x.
+
+ 2. You may see a few `Cannot render Markdown` warning messages in the
+ output of the previous command. This is due to the fact that an
+ example [blog](content/blog) in this project has a few posts written
+ in Markdown. To render them correctly, install the `commonmark`
+ package with this command:
+
+ pip install commonmark
+
+ Then try the previous step again.
+
+ 3. For an Internet-facing website, you would be hosting the static
+ website/blog on a hosting service and/or with a web server such as
+ Apache HTTP Server, Nginx, etc. You probably only need to generate
+ the static files and know where the static files are and move them
+ to your hosting location.
+
+ If you have the `make` command, enter this command to generate your
+ website:
+
+ make site
+
+ If you don't have `make` but have `python3`, enter this command:
+
+ python3 makesite.py
+
+ Note: In some environments, you may need to use `python` instead of
+ `python3` to invoke Python 3.x.
+
+ If you only have `python`, enter this command:
+
+ python makesite.py
+
+ The `_site` directory contains the entire generated website. The
+ content of this directory may be copied to your website hosting
+ location.
+
+
+The Code
+--------
+Now that you know how to generate the static website that comes with
+this project, it is time to see what [makesite.py](makesite.py) does.
+You probably don't really need to read the entire section. The source
+code is pretty self-explanatory but just in case, you need a detailed
+overview of what it does, here are the details:
+
+ 1. The `main()` function is the starting point of website generation.
+ It calls the other functions necessary to get the website generation
+ done.
+
+ 2. First it creates a fresh new `_site` directory from scratch. All
+ files in the [static directory](static) are copied to this
+ directory. Later the static website is generated and written to this
+ directory.
+
+ 3. Then it creates a `params` dictionary with some default parameters.
+ This dictionary is passed around to other functions. These other
+ functions would pick values from this dictionary to populate
+ placeholders in the layout template files.
+
+ Let us take the `subtitle` parameter for example. It is set
+ to our example website's fictitious brand name: "Lorem Ipsum". We
+ want each page to include this brand name as a suffix in the title.
+ For example, the [about page](https://tmug.github.io/makesite-demo/about/)
+ has "About - Lorem Ipsum" in its title. Now take a look at the
+ [page layout template](layout/page.html) that is used as the layout
+ for all pages in the static website. This layout file uses the
+ `{{ subtitle }}` syntax to denote that it is a placeholder that
+ should be populated while rendering the template.
+
+ Another interesting thing to note is that a content file can
+ override these parameters by defining its own parameters in the
+ content header. For example, take a look at the content file for
+ the [home page](content/_index.html). In its content header, i.e.,
+ the HTML comments at the top with key-value pairs, it defines a new
+ parameter named `title` and overrides the `subtitle` parameter.
+
+ We will discuss the syntax for placeholders and content headers
+ later. It is quite simple.
+
+ 4. It then loads all the layout templates. There are 6 of them in this
+ project.
+
+ - [layout/page.html](layout/page.html): It contains the base
+ template that applies to all pages. It begins with
+ `` and ``, and ends with ``. The
+ `{{ content }}` placeholder in this template is replaced with
+ the actual content of the page. For example, for the about page,
+ the `{{ content }}` placeholder is replaced with the the entire
+ content from [content/about.html](content/about.html). This is
+ done with the `make_pages()` calls further down in the code.
+
+ - [layout/post.html](layout/post.html): It contains the template
+ for the blog posts. Note that it does not begin with `` and does not contain the `` and `` tags.
+ This is not a complete standalone template. This template
+ defines only a small portion of the blog post pages that are
+ specific to blog posts. It contains the HTML code and the
+ placeholders to display the title, publication date, and author
+ of blog posts.
+
+ This template must be combined with the
+ [page layout template](layout/page.html) to create the final
+ standalone template. To do so, we replace the `{{ content }}`
+ placeholder in the [page layout template](layout/page.html) with
+ the HTML code in the [post layout template](layout/post.html) to
+ get a final standalone template. This is done with the
+ `render()` calls further down in the code.
+
+ The resulting standalone template still has a `{{ content }}`
+ placeholder from the [post layout template](layout/post.html)
+ template. This `{{ content }}` placeholder is then replaced
+ with the actual content from the [blog posts](content/blog).
+
+ - [layout/list.html](layout/list.html): It contains the template
+ for the blog listing page, the page that lists all the posts in
+ a blog in reverse chronological order. This template does not do
+ much except provide a title at the top and an RSS link at the
+ bottom. The `{{ content }}` placeholder is populated with the
+ list of blog posts in reverse chronological order.
+
+ Just like the [post layout template](layout/post.html) , this
+ template must be combined with the
+ [page layout template](layout/page.html) to arrive at the final
+ standalone template.
+
+ - [layout/item.html](layout/item.html): It contains the template
+ for each blog post item in the blog listing page. The
+ `make_list()` function renders each blog post item with this
+ template and inserts them into the
+ [list layout template](layout/list.html) to create the blog
+ listing page.
+
+ - [layout/feed.xml](layout/feed.xml): It contains the XML template
+ for RSS feeds. The `{{ content }}` placeholder is populated with
+ the list of feed items.
+
+ - [layout/item.xml](layout/item.xml): It contains the XML template for
+ each blog post item to be included in the RSS feed. The
+ `make_list()` function renders each blog post item with this
+ template and inserts them into the
+ [layout/feed.xml](layout/feed.xml) template to create the
+ complete RSS feed.
+
+ 5. After loading all the layout templates, it makes a `render()` call
+ to combine the [post layout template](layout/post.html) with the
+ [page layout template](layout/page.html) to form the final
+ standalone post template.
+
+ Similarly, it combines the [list layout template](layout/list.html)
+ template with the [page layout template](layout/page.html) to form
+ the final list template.
+
+ 6. Then it makes two `make_pages()` calls to render the home page and a
+ couple of other site pages: the [contact page](content/contact.html)
+ and the [about page](content/about.html).
+
+ 7. Then it makes two more `make_pages()` calls to render two blogs: one
+ that is named simply [blog](content/blog) and another that is named
+ [news](content/news).
+
+ Note that the `make_pages()` call accepts three positional
+ arguments:
+
+ - Path to content source files provided as a glob pattern.
+ - Output path template as a string.
+ - Layout template code as a string.
+
+ These three positional arguments are then followed by keyword
+ arguments. These keyword arguments are used as template parameters
+ in the output path template and the layout template to replace the
+ placeholders with their corresponding values.
+
+ As described in point 2 above, a content file can override these
+ parameters in its content header.
+
+ 8. Then it makes two `make_list()` calls to render the blog listing
+ pages for the two blogs. These calls are very similar to the
+ `make_pages()` calls. There are only two things that are different
+ about the `make_list()` calls:
+
+ - There is no point in reading the same blog posts again that were
+ read by `make_pages()`, so instead of passing the path to
+ content source files, we feed a chronologically reverse-sorted
+ index of blog posts returned by `make_pages()` to `make_list()`.
+ - There is an additional argument to pass the
+ [item layout template](layout/item.html) as a string.
+
+ 9. Finally it makes two more `make_list()` calls to generate the RSS
+ feeds for the two blogs. There is nothing different about these
+ calls than the previous ones except that we use the feed XML
+ templates here to generate RSS feeds.
+
+To recap quickly, we create a `_site` directory to write the static site
+generated, define some default parameters, load all the layout
+templates, and then call `make_pages()` to render pages and blog posts
+with these templates, call `make_list()` to render blog listing pages
+and RSS feeds. That's all!
+
+Take a look at how the `make_pages()` and `make_list()` functions are
+implemented. They are very simple with less than 20 lines of code each.
+Once you are comfortable with this code, you can begin modifying it to
+add more blogs or reduce them. For example, you probably don't need a
+news blog, so you may delete the `make_pages()` and `make_list()` calls
+for `'news'` along with its content at [content/news](content/news).
+
+
+Layout
+------
+In this project, the layout template files are located in the [layout
+directory](layout). But they don't necessarily have to be there. You can
+place the layout files wherever you want and update
+[makesite.py](makesite.py) accordingly.
+
+The source code of [makesite.py](makesite.py) that comes with this
+project understands the notion of placeholders in the layout templates.
+The template placeholders have the following syntax:
+
+ {{ }}
+
+Any whitespace before `{{`, around ``, and after `}}` is ignored.
+The `` should be a valid Python identifier. Here is an example of
+template placeholder:
+
+ {{ title }}
+
+This is a very simple template mechanism that is implemented already in
+the [makesite.py](makesite.py). For a simple website or blog, this
+should be sufficient. If you need a more sophisticated template engine
+such as [Jinja2](http://jinja.pocoo.org/) or
+[Cheetah](https://pythonhosted.org/Cheetah/), you need to modify
+[makesite.py](makesite.py) to add support for it.
+
+
+Content
+-------
+In this project, the content files are located in the [content
+directory](content). Most of the content files are written in HTML.
+However, the content files for the blog named [blog](content/blog) are
+written in Markdown.
+
+The notion of headers in the content files is supported by
+[makesite.py](makesite.py). Each content file may begin with one or more
+consecutive HTML comments that contain headers. Each header has the
+following syntax:
+
+
+
+Any whitespace before, after, and around the `` tokens are ignored. Here are some example headers:
+
+
+
+
+
+It looks for the headers at the top of every content file. As soon as
+some non-header text is encountered, the rest of the content from that
+point is not checked for headers.
+
+
+Credits
+-------
+Thanks to [Susam](https://github.com/susam) for writing the
+documentation and the unit tests.
+
+
+License
+-------
+This is free and open source software. You can use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell copies of it,
+under the terms of the [MIT License](LICENSE.md).
+
+This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
+express or implied. See the [MIT License](LICENSE.md) for details.
+
+
+Support
+-------
+To report bugs, suggest improvements, or ask questions, please visit
+.
diff --git a/content/_index.html b/content/_index.html
new file mode 100644
index 0000000..8cc489a
--- /dev/null
+++ b/content/_index.html
@@ -0,0 +1,28 @@
+
+
+
Lorem Ipsum
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc nibh
+tellus, vehicula ut maximus sed, fringilla a justo. Nunc vitae efficitur
+nisl. Ut sapien erat, pretium et commodo nec, rutrum bibendum magna. Sed
+ut massa massa. Etiam euismod neque lacus, id tincidunt risus iaculis a.
+Aliquam porta venenatis bibendum. Nam id varius nulla. Sed vitae purus
+ac odio ornare vestibulum vitae tempor arcu. Nunc non venenatis purus.
+Duis a augue at nulla congue egestas. Morbi mattis felis sit amet tortor
+euismod, fringilla viverra est elementum.
+
+
+Suspendisse vestibulum sed massa eu tincidunt. Pellentesque cursus, nisl
+at gravida suscipit, odio quam placerat mi, in iaculis nunc risus eu
+sapien. Suspendisse potenti. Nullam fermentum, tellus vel faucibus
+dictum, arcu ante rutrum nisi, ut iaculis eros felis a lectus. Etiam vel
+maximus nulla, sed mattis lectus. Aliquam commodo est massa, at
+vestibulum diam commodo vehicula. Nullam et tristique tortor. Praesent
+luctus, leo id mattis mattis, ex dui dapibus dolor, nec ultrices turpis
+nibh in sem. In efficitur, velit ut bibendum interdum, libero turpis
+mattis odio, non pharetra metus leo nec arcu. Maecenas auctor laoreet
+maximus. Donec metus massa, scelerisque a lacinia et, viverra eget
+metus. Aenean vitae tellus vehicula, mattis metus in, facilisis purus.
+In purus erat, fringilla ut diam et, convallis convallis nunc. Morbi
+sagittis interdum ipsum sit amet fringilla.
+
diff --git a/content/about.html b/content/about.html
new file mode 100644
index 0000000..f51d17d
--- /dev/null
+++ b/content/about.html
@@ -0,0 +1,23 @@
+
+
About
+
+Quisque quam nisl, egestas nec convallis vitae, fringilla nec mauris.
+Sed et cursus lacus, a pharetra ex. Pellentesque rhoncus malesuada elit
+at sodales. In ut elit lectus. Phasellus et hendrerit odio, ac hendrerit
+ante. Pellentesque habitant morbi tristique senectus et netus et
+malesuada fames ac turpis egestas. Quisque sem nibh, auctor vel dictum
+eu, pharetra sit amet nunc. Integer suscipit suscipit dapibus.
+Suspendisse vulputate sed mauris eget tempus. Etiam rhoncus, leo nec
+cursus elementum, massa lorem fermentum nisi, non convallis nisl dolor
+vel ipsum.
+
+
+Aliquam imperdiet vel purus sed facilisis. Mauris condimentum vel nulla
+ac tempor. In non venenatis arcu. Nam in sapien purus. Suspendisse
+faucibus, erat et fringilla vestibulum, ligula nisi porta odio, ut
+tristique dui ante eu nisi. Mauris vitae vulputate lorem. Proin tortor
+nisl, vehicula sed justo sed, volutpat bibendum purus. Phasellus luctus
+fringilla augue ac sodales. Aenean ac nisi sit amet neque pulvinar
+tincidunt ut nec ipsum. Aliquam purus tellus, dignissim a augue
+placerat, aliquet semper turpis. Fusce id lacinia quam, vel porta quam.
+
diff --git a/content/blog/2018-01-01-proin-quam.md b/content/blog/2018-01-01-proin-quam.md
new file mode 100644
index 0000000..540a467
--- /dev/null
+++ b/content/blog/2018-01-01-proin-quam.md
@@ -0,0 +1,29 @@
+
+Proin quam urna, pulvinar id ipsum ac, mattis consectetur ante. Praesent
+non justo lectus. Duis egestas arcu libero, quis laoreet dolor volutpat
+ut. Donec facilisis orci sit amet sem blandit elementum. Vestibulum
+suscipit consectetur diam, ac posuere metus condimentum in. Integer
+vehicula vitae enim id gravida. Vestibulum ut eros vitae risus porttitor
+porta in eget felis. Nulla lorem erat, mattis eget lacus eget, interdum
+aliquet lectus. Fusce non felis diam. Mauris sagittis porttitor est et
+vestibulum. Duis faucibus commodo est. Maecenas elit purus, auctor a
+consectetur eu, suscipit nec metus. Nam gravida id massa quis faucibus.
+Sed non consectetur eros. Nullam iaculis sit amet ex eget ultrices. Sed
+ligula arcu, vehicula vel ipsum nec, ultrices pulvinar ante.
+
+Vivamus egestas justo sed nulla condimentum iaculis. Pellentesque
+eleifend elementum turpis sed tempus. Aliquam erat volutpat. In hac
+habitasse platea dictumst. Integer elementum sed diam at vulputate.
+Donec maximus, lacus a vulputate sagittis, felis turpis vestibulum
+massa, nec tincidunt libero felis eget arcu. Morbi eget velit vulputate,
+pellentesque odio laoreet, consequat orci. Aliquam erat volutpat. Nulla
+a vulputate mi, sed laoreet ipsum. Nulla nunc ipsum, ultricies at
+suscipit id, consectetur id erat. Suspendisse scelerisque vehicula felis
+quis luctus.
+
+Donec posuere ante a nibh dictum suscipit. Mauris interdum dolor nulla,
+sit amet fermentum quam porta a. Ut metus ipsum, venenatis a lorem
+pellentesque, finibus commodo turpis. Cras mollis dui quis varius
+placerat. Phasellus nec nisi nec quam tincidunt luctus. Sed nec
+vulputate enim, vel dapibus enim. Praesent mollis maximus enim in
+tempus. Phasellus a arcu lorem. Sed dictum rhoncus tempus.
diff --git a/content/blog/2018-01-03-sed-finibus.md b/content/blog/2018-01-03-sed-finibus.md
new file mode 100644
index 0000000..783129c
--- /dev/null
+++ b/content/blog/2018-01-03-sed-finibus.md
@@ -0,0 +1,29 @@
+
+Sed finibus fermentum convallis. Sed consequat, lacus a pellentesque
+suscipit, lorem libero egestas dui, sit amet volutpat mi dolor sit amet
+nisl. Maecenas faucibus iaculis nibh id gravida. Aenean ac nulla
+efficitur, pulvinar massa eget, viverra enim. Ut vulputate velit nisl,
+id volutpat nibh rhoncus a. Phasellus pretium finibus tempus.
+Suspendisse placerat nibh sem, sit amet vehicula urna porta quis.
+Suspendisse ac nisi maximus, porttitor sem id, dignissim ipsum. Sed
+suscipit dolor sed velit viverra, quis viverra dui placerat. Vestibulum
+dapibus molestie dapibus.
+
+Praesent fringilla dapibus enim quis consectetur. Donec eget nibh nisl.
+Proin venenatis interdum nunc, sed venenatis orci suscipit in. Morbi sed
+lacinia tellus, iaculis condimentum tellus. Pellentesque habitant morbi
+tristique senectus et netus et malesuada fames ac turpis egestas.
+Maecenas sem mi, commodo ut facilisis pharetra, aliquam id nisi. Morbi
+nec nisi sed tortor faucibus pretium nec non eros. Nullam rhoncus
+pharetra elementum. Ut tincidunt fermentum metus, at fermentum mi
+scelerisque id. Aenean sed odio auctor, placerat velit sed, consectetur
+felis. Donec volutpat id lorem non ornare. Phasellus convallis mi magna,
+vel laoreet ex efficitur fermentum.
+
+Phasellus a interdum odio, vitae finibus leo. Pellentesque porta quis
+massa non suscipit. Mauris finibus vel nibh quis scelerisque.
+Suspendisse eget molestie lacus, eu mattis felis. Proin ex tellus,
+ultrices eu facilisis vel, faucibus eget enim. Integer sit amet magna
+ligula. Ut massa nisl, sodales vel eros ac, dignissim maximus metus.
+Donec odio nulla, sollicitudin quis dolor in, varius sodales lectus. Sed
+non lacinia ligula, eu pulvinar eros.
diff --git a/content/contact.html b/content/contact.html
new file mode 100644
index 0000000..f868ad9
--- /dev/null
+++ b/content/contact.html
@@ -0,0 +1,21 @@
+
+
Contact
+
+In hac habitasse platea dictumst. Suspendisse purus leo, laoreet ac
+scelerisque vitae, gravida vitae turpis. Etiam lacinia justo in pharetra
+tincidunt. Donec id mi in elit euismod feugiat. Fusce eget velit nec
+nunc fermentum ultrices ut auctor tellus. Suspendisse convallis lacus a
+mollis volutpat. Donec maximus eros lorem, non faucibus sapien tristique
+a. Proin ut magna eget nunc sagittis sodales ac suscipit dolor.
+Vestibulum sit amet velit nunc. Nam euismod fermentum neque ac
+facilisis. Phasellus imperdiet arcu a lorem pulvinar accumsan. Sed
+maximus neque tristique, sollicitudin risus sed, interdum enim.
+
+
+Curabitur vel augue mattis, blandit libero rhoncus, fringilla augue.
+Aenean condimentum ex justo. In hac habitasse platea dictumst. Etiam
+ullamcorper finibus enim, nec cursus dui tristique nec. Phasellus et
+tortor libero. Vivamus viverra euismod pulvinar. Fusce maximus, ante
+quis lobortis facilisis, lectus mi consequat purus, sed vestibulum ipsum
+mi sit amet dui.
+
diff --git a/content/news/2018-01-02-vivamus-purus.html b/content/news/2018-01-02-vivamus-purus.html
new file mode 100644
index 0000000..42845b1
--- /dev/null
+++ b/content/news/2018-01-02-vivamus-purus.html
@@ -0,0 +1,30 @@
+
+
+Vivamus purus tellus, facilisis in sapien quis, ullamcorper lacinia
+neque. Morbi tincidunt ac leo sit amet auctor. Donec dolor mauris,
+lobortis eget faucibus sit amet, egestas non ante. Sed quam erat,
+consectetur eget magna in, pretium aliquet ligula. Proin id nunc ex.
+Curabitur posuere lectus neque, ut blandit diam scelerisque sed. In
+semper lacinia ipsum a malesuada. Nam accumsan consequat sem, eu mollis
+diam iaculis commodo.
+
+
+Fusce arcu turpis, blandit lacinia augue et, dignissim imperdiet lorem.
+Donec fermentum dui eu fermentum accumsan. Nunc porta tellus sit amet
+nulla tempor varius. Ut id dolor velit. Aenean et dolor ac nisl mattis
+iaculis. Phasellus at convallis lectus. Curabitur volutpat purus sed
+purus feugiat, in elementum orci ullamcorper. Nam sollicitudin pretium
+lacus, quis convallis massa suscipit et. Fusce ac elit tristique,
+efficitur est at, pellentesque tellus.
+
+
+Suspendisse vel eleifend nunc. Vivamus ac sem luctus, luctus velit ac,
+pretium urna. Sed eu diam quis odio euismod sollicitudin. Ut faucibus
+pharetra sem, ut malesuada sapien maximus at. Quisque et eleifend augue.
+Sed dignissim urna ac justo venenatis vestibulum. Vivamus sodales, dui
+sed luctus porttitor, ante purus pretium velit, at dapibus enim felis a
+tortor. Fusce sit amet ipsum odio. Etiam eget felis sed risus efficitur
+rutrum at a libero. Praesent finibus pellentesque tellus sed maximus.
+Morbi sit amet turpis eros. Vivamus rhoncus libero ut lacinia luctus. Ut
+nec ex dui.
+
diff --git a/content/news/2018-01-04-mauris-tempor.html b/content/news/2018-01-04-mauris-tempor.html
new file mode 100644
index 0000000..b7dd769
--- /dev/null
+++ b/content/news/2018-01-04-mauris-tempor.html
@@ -0,0 +1,37 @@
+
+
+Mauris tempor nulla odio, vel tempus metus bibendum sit amet. Vivamus
+consequat fringilla tristique. Nullam a congue ligula, eget rutrum
+lectus. In pulvinar at nunc ac finibus. Sed cursus consequat sem et
+egestas. Cras eu eros vel mi eleifend efficitur eu dapibus orci.
+Phasellus non bibendum purus. Nam facilisis laoreet massa tempus
+vehicula. Donec a hendrerit nisi.
+
+
+Vestibulum blandit dui a lorem pulvinar, et auctor eros elementum.
+Vestibulum tortor ex, pharetra id metus vel, tincidunt faucibus nisl.
+Suspendisse potenti. Nam maximus est mi, sit amet tristique nisi pretium
+sed. Maecenas in nulla at nibh volutpat lacinia. Aliquam erat volutpat.
+Donec odio magna, imperdiet quis risus at, ultricies faucibus lorem.
+Quisque tempus enim purus. Integer interdum mauris lorem, in accumsan
+lorem tempor quis. Praesent facilisis, velit vitae aliquam mattis,
+turpis justo malesuada odio, nec hendrerit tortor sapien sit amet diam.
+Praesent aliquam malesuada feugiat. Proin vitae efficitur massa.
+Vestibulum quam enim, finibus et magna ac, pellentesque aliquet leo.
+Nullam condimentum neque nec ex viverra, sit amet ullamcorper lectus
+sodales. Suspendisse non est et velit malesuada ullamcorper maximus
+porta quam.
+
+
+Cras ornare maximus augue nec varius. Aliquam tincidunt sodales ipsum.
+Sed viverra ut nibh sit amet porta. Cras sit amet condimentum est.
+Suspendisse quis tristique ipsum. Etiam vel lorem bibendum, laoreet dui
+vitae, rutrum leo. Nullam cursus dui a augue lobortis euismod.
+Suspendisse finibus id neque ut imperdiet. Pellentesque vel suscipit
+est, vel vulputate neque. Curabitur eu eros auctor, laoreet nunc quis,
+laoreet erat. Fusce rhoncus mattis lorem, et imperdiet nisi lacinia sit
+amet. Integer et cursus lacus. Nullam id arcu et libero condimentum
+tristique. Pellentesque arcu magna, aliquam sed lectus in, tempor mattis
+erat. Curabitur vel massa sit amet nunc suscipit pulvinar. In tincidunt
+diam metus, eu sollicitudin velit commodo a.
+
diff --git a/layout/feed.xml b/layout/feed.xml
new file mode 100644
index 0000000..388c39e
--- /dev/null
+++ b/layout/feed.xml
@@ -0,0 +1,12 @@
+
+
+
+
+{{ title }}
+{{ site_url }}/
+Grow with Technology
+
+{{ content }}
+
+
+
diff --git a/layout/item.html b/layout/item.html
new file mode 100644
index 0000000..b16a097
--- /dev/null
+++ b/layout/item.html
@@ -0,0 +1,10 @@
+
+