Skip to content

Commit

Permalink
Merge pull request #3480 from xyzteam2016/docs/blog-on-keystone
Browse files Browse the repository at this point in the history
Guide about how to build a blog with Keystone
  • Loading branch information
JedWatson committed Dec 22, 2016
2 parents 19ba391 + ea6124d commit f951509
Showing 1 changed file with 181 additions and 0 deletions.
181 changes: 181 additions & 0 deletions docs/guides/how-to-create-a-blog-with-keystone.md
@@ -0,0 +1,181 @@
# How to create a blog with Keystone

In this guide we will walk you through building a simple blog with Keystone based on free [Bootstrap-clean-blog](https://blackrockdigital.github.io/startbootstrap-clean-blog/) theme.
Our blog will have 3 page templates: index page with blog feed, single post and About us page.
See the final blog's source code [here](https://github.com/xyzteam2016/xyzcodeblog).

## Install prerequisites

Before you begin, make sure you have [Node.js](http://nodejs.org/download) 0.10+ and [MongoDB](http://www.mongodb.org/downloads) v2.4+ installed.

## Use the generator

Build a skeleton of your blog using the [Yeoman](http://yeoman.io/) generator.

Install the generator by running the following command in your root directory:

```sh
npm install -g generator-keystone
```

Then create your blog folder and navigate to it:

```sh
mkdir my-blog
cd my-blog
```

Now run the generator like so:

```sh
yo keystone
```

The generator will ask a couple of questions about the configuration.
Go ahead and select the default options. Say `Y` when generator asks you if want you include a `Blog`.
In this guide, we will use `jade` templating engine, and `less` as a CSS pre-processor.

Once you've selected your requirements, the generator will prepare the skeleton of your app, configure the files and install npm dependencies as required.

## Run it for the first time!

Now you can navigate to your project folder and run your app:

```sh
cd my-blog
node keystone
```

You can now go to your browser and check out your new project on port 3000 (open http://localhost:3000).

## Changing blog styles and templates

After you run http://localhost:3000 for the first time, you can see the default blog template with default styles. Now it is time to make our blog look like [Bootstrap-clean-blog](https://blackrockdigital.github.io/startbootstrap-clean-blog/) theme. Download theme's [source files](https://github.com/BlackrockDigital/startbootstrap-clean-blog/archive/gh-pages.zip)

### Adding .less files

By default, Boostrap is already included with Keystone, so we would only have to add a few .less files. Copy contents of Boostrap theme's `less` folder, go to `public/styles/styles/site` and replace existing files with theme's files. Do not forget to `@import` correct .less files in `site.less`. Now re-run `node keystone` to recompile css.

### Editing templates

First, let's re-build header and footer. Open `templates/layouts/default.jade` file which contains template's wrapper. Now by following Bootstrap theme's `index.html`, add fonts, extra navigation elements and theme's classes using Jade. If you are not familiar with Jade (recently renamed to pug), refer to the [official documentation](https://pugjs.org/api/getting-started.html).

Blog and post templates are a bit more tricky to modify. When you open `templates/views/blog.jade`, you will see a mixin which renders a feed of the latest posts where each post has title, brief, image (if it exists) and meta information. Existing `blog.jade` template already contains most of this elements. Let's add missing classes and post's brief by following theme's `index.html` file.

In KeystoneJS, your data schema and models are controlled by [Lists](http://keystonejs.com/docs/database/). In our case, `Post` is a `List`, and we want to pull relevant data from its [fields](http://keystonejs.com/docs/database/#fields) or specify it's [options](http://keystonejs.com/docs/database/#fields-options) or [methods](http://keystonejs.com/docs/database/#fields-underscoremethods). This way, if we want to access post field data inside mixin, we will use the following syntax: `post.fieldname.subfieldname`. For example, to add post's brief, we will write `post.content.brief`. Similarly, if we want to check if image exists, we will access post image `exists` option, like this `if post.image.exists`, and if it results to true, we show a post's image scaled to fit within the specified width and height, like that `img(src=post._.image.fit(800,800))` using image's `fit` underscore method. For the full list of available fields and their options and methods, refer to (KeystoneJS documentation)[http://keystonejs.com/docs/database/]. Single post `post.jade` template can be modified in exactly same way as `blog.jade` file. The only difference is, in order to access field's data inside `post` template, you need to use `data.listname.fieldname.subfieldname` syntax.

### Creating Pages

By default, there is no Page `Model` shipped with default Keystone project. Since we want to have 'About us' page on our blog, let's go ahead and create it.

1) Create a new `Page.js` file in `models` folder. Since it is very similar to post data model, you can copy-paste contents of `Post.js` and use it as a template changing all occurrences of `Post` to `Page`. New `Page` model doesn't require so many fields as `Post` model, it would be enough to add the following fields:

```
Page.add({
title: { type: String, required: true },
state: { type: Types.Select, options: 'draft, published, archived', default: 'draft', index: true },
image: { type: Types.CloudinaryImage },
content: {
brief: { type: Types.Html, wysiwyg: true, height: 150 },
extended: { type: Types.Html, wysiwyg: true, height: 400 },
},
});
```

As the last step, specify which fields to display in `keystone/pages` in Admin UI where all your pages will be listed. In our case we only want to display page title and state, and we set column width to 20%. `Page.defaultColumns = 'title, state|20%';` Now run `node keystone` and go to `http://localhost:3000/keystone/pages` to see our brand new `Page` model in action. Now create a new page called 'About'.

2) Next step would be to add a `view` for pages. Let's use `post.js` as a template. Duplicate it and rename it to `page.js`. Go to `routes/views`, duplicate `post.js` to use as a template and rename it to `page.js`. Let's set `locals` to `pages` this way: `locals.section = 'pages';`, so our page URLs will look like following `http://localhost:3000/pages/pagename`. We can also remove post related code, like `populate('author categories')` since we don't have `author` field in our `Page` model.

3) Now let's define a new route for page. Open `routes/index.js` file, navigate to 'Setup Route Bindings' section and add `app.get('/pages/:page', routes.views.page);` line.

4) Now we are ready to add a template for our page. Go to `templates/views`, create `page.jade` file and copy-paste `post.jade` contents into it. You can access `page` fields and options similar way by using `data.list.fieldname.subfieldname` syntax. Remove post-only related code, and we are all set to move to the last step.

5) Add 'About' page link to navigation. Go to `routes/middleware.js` and add a new line to `res.locals.navLinks`

```
res.locals.navLinks = [
{ label: 'About', key: 'about', href: '/pages/page/about' }, // adding About to blog navigation
{ label: 'Blog', key: 'blog', href: '/blog' },
];
```

Last but not least, you may want to add `Pages` to Admin UI top navigation for easy access. To do so, open `keystone.js` file located in the root of your project and add a new route to `keystone.set(nav)`

```
keystone.set('nav', {
posts: ['posts', 'post-categories'],
users: 'users',
pages: 'pages', // adding pages to Admin UI nav
});
```

Re-run `node keystone` and celebrate your new blog ready to go live.

## Deploy to Heroku

Your blog is now running nicely on your local machine, which is good, but it would be better to show it to the world. Let's deploy it to Heroku!

First of all, head over to https://www.heroku.com/ and sign up for a free account.
Then, download the [Heroku Command Line Interface](https://devcenter.heroku.com/articles/heroku-command-line#download-and-install).

If you want, you can take a [crash course](https://devcenter.heroku.com/articles/getting-started-with-nodejs) on how to deploy a node.js app, to have a head start.

Now, if you are ready, navigate to your project folder, initialize the git repository and make the initial commit:

```sh
git init
git add .
git commit -m "Initial commit"
```

Login to Heroku and create your app:
```sh
heroku login
heroku create my-blog
```

If you run the `heroku create` command without the name parameter, heroku will assign a random name to your app and you will be able to change this later, if you wish.
The command will also automatically add a git remote `heroku`.

If you want to use an existing git repository, you can add it by running the command:
```sh
heroku git:remote -a my-blog
```

Or you can rename it by passing `-r my-best-blog`.

Now we are going to configure the environment variables.
Open the `.env` file in the root directory of your project. In case you accepted the default options in the Yeoman generator, then the file contains the test values. You may register for your own Cloudinary and Mandrill accounts and change these to your own keys, if you like.

Now that we are deploying the app, we need to set these variables using Heroku CLI.

Run `heroku config:set` with the variables from the `.env` file as parameters:

```sh
heroku config:set MANDRILL_API_KEY=<your-mandrill-api-key>
heroku config:set CLOUDINARY_URL=<your-cloudinary-url>
heroku config:set COOKIE_SECRET==<your-cookie-secret>
```

The last piece of set up is adding the MongoDB add-on, which will handle the database connection.

```sh
heroku addons:create mongolab
```

This automatically created another config variable called `MONGODB_URI`. However, Keystone needs it to be called `MONGOLAB_URI`. To fix this, go to your project in your Heroku [dashboard](https://dashboard.heroku.com/), open the Settings tab and rename the variable to `MONGOLAB_URI`

Alright, now we're all ready to deploy!
Push your files:

```sh
git push heroku master
```

And open your app in your browser:

```sh
heroku open
```

Tada! There we have it: your app is live on Heroku!

0 comments on commit f951509

Please sign in to comment.