|
| 1 | +Let's move to more complex example and learn how to make a blog using [APIQ CMS](https://www.apiq.io). Let's skip APIQ (and APIQ Models extension) installation steps and consider we already have blank CMS installation. By following steps below, you'll get fully functional blog. |
| 2 | + |
| 3 | +## Pick HTML template |
| 4 | + |
| 5 | +First, you need to have HTML either downloaded or prepared from scratch by HTML coder. I picked [this one](https://freehtml5.co/verb-free-html5-bootstrap-template-for-blog-websites/): |
| 6 | + |
| 7 | +## Create first temlate |
| 8 | + |
| 9 | +Ok, in downloaded template archive I have `index.html`. I'm going to use it as a template for blog index page. |
| 10 | +Just paste html content, give template a name, and click "Add template". |
| 11 | + |
| 12 | + |
| 13 | + |
| 14 | +## Upload assets |
| 15 | + |
| 16 | +Now we need to upload all assets (under "Assets" section) we have in downloaded template, i.e. images, stylesheets and javascripts. |
| 17 | +You could select multiple at once. For my template, I uploaded `js` folder content first, then `fonts`, `images` and `css`. |
| 18 | + |
| 19 | + |
| 20 | + |
| 21 | +Now we need to fix fonts URLs (like `url("../fonts/icomoon/icomoon.eot")`) or other URLs in our stylesheets by inserting correct URLs from "Assets" section. |
| 22 | + |
| 23 | +Next, let's find in template's content a place where page content should be injected and insert there special Liquor instruction `{% yield %}`. I'm going to insert it after `<div id="gtco-main"><div class="container">` and remove all content until closing tags. |
| 24 | + |
| 25 | +## Create index page |
| 26 | + |
| 27 | +Now let's create index page that uses just created template and paste there the content we've cut earlier from template. Once we have this in place, you should see something like this at website's root: |
| 28 | + |
| 29 | + |
| 30 | + |
| 31 | +## Create first model |
| 32 | + |
| 33 | +Next I'm going to make index page dynamic by introducing some models. First, I want main menu (`Develop`, `Business` and etc.) to represent blog categories. Let's create `Category` model under APIQ `Models` section. |
| 34 | + |
| 35 | + |
| 36 | + |
| 37 | +Now let's output categories as menu snippet. I extracted `<ul>...</ul>` from template into new snippet with "Menu" name and "menu" slug, and included this snippet in template with: |
| 38 | + |
| 39 | +```handlebars |
| 40 | +{% include 'menu' %} |
| 41 | +``` |
| 42 | + |
| 43 | +And finally, I modified snippet like this (`name` is the only property I added to `Category` model, `permalink` is built-in property): |
| 44 | +```handlebars |
| 45 | +<ul> |
| 46 | + {% for category in: models.categories do: %} |
| 47 | + <li><a href="/{{ category.permalink }}">{{ category.name }}</a></li> |
| 48 | + {% end for %} |
| 49 | +</ul> |
| 50 | +``` |
| 51 | + |
| 52 | +## Create Post model |
| 53 | + |
| 54 | +Ok, I can add categories and have dynamic menu based on them. Let's add second model - `Post` - and set up relationship between it and `Category` model. |
| 55 | + |
| 56 | + |
| 57 | + |
| 58 | +After this, I added one post belonging to "Development" category. Now I'm going to show the latest post as wide banner (as suggested by template design). I updated template's content like this (notice how I fetched the most recent post ): |
| 59 | + |
| 60 | +```handlebars |
| 61 | +{% assign recent_post = models.posts.order('created_at desc').first %} |
| 62 | +<header id="gtco-header" class="gtco-cover" role="banner" style="background-image:url({{ recent_post.image }});" data-stellar-background-ratio="0.5"> |
| 63 | + <div class="overlay"></div> |
| 64 | + <div class="container"> |
| 65 | + <div class="row"> |
| 66 | + <div class="col-md-7 text-left"> |
| 67 | + <div class="display-t"> |
| 68 | + <div class="display-tc animate-box" data-animate-effect="fadeInUp"> |
| 69 | + <span class="date-post">{{ recent_post.created_at | strftime format: '%d %B %Y' }}</span> |
| 70 | + <h1 class="mb30"> |
| 71 | + <a href="/{{ recent_post.permalink }}">{{ recent_post.title }}</a> |
| 72 | + </h1> |
| 73 | + <p><a href="/{{ recent_post.permalink }}" class="text-link">Read More</a></p> |
| 74 | + </div> |
| 75 | + </div> |
| 76 | + </div> |
| 77 | + </div> |
| 78 | + </div> |
| 79 | +</header> |
| 80 | +``` |
| 81 | + |
| 82 | +And now, below this header I'd like to list all posts. This is the only content of index page for this purpose: |
| 83 | +```handlebars |
| 84 | +<div class="row row-pb-md"> |
| 85 | + <div class="col-md-12"> |
| 86 | + <ul id="gtco-post-list"> |
| 87 | + {% for post in: models.posts.order("created_at desc") do: %} |
| 88 | + <li class="full entry animate-box" data-animate-effect="fadeIn"> |
| 89 | + <a href="/{{ post.permalink }}"> |
| 90 | + <div class="entry-img" style="background-image: url({{ post.image }})"></div> |
| 91 | + <div class="entry-desc"> |
| 92 | + <h3>{{ post.title }}</h3> |
| 93 | + {{ post.preview }} |
| 94 | + </div> |
| 95 | + </a> |
| 96 | + <a href="/{{ post.category.permalink }}" class="post-meta">{{ post.category.name }} <span class="date-posted">{{ post.created_at | strftime format: '%d %B %Y' }}</span></a> |
| 97 | + </li> |
| 98 | + {% end for %} |
| 99 | + </ul> |
| 100 | + </div> |
| 101 | +</div> |
| 102 | +``` |
| 103 | + |
| 104 | + |
| 105 | + |
| 106 | +Index page should look like this (isn't it cool?). |
| 107 | + |
| 108 | +## Create template pages for Category and Post models |
| 109 | + |
| 110 | +This is our final step: we want to have category page and post page so our `permalink` properties will start working and point to concrete category or post. Let's create these 2 pages as children of index page. The most tricky thing here is to enable `Use as object template` property and choose representable object. |
| 111 | + |
| 112 | + |
| 113 | + |
| 114 | +Don't forget to put some html displaying Category and Product in corresponding pages. In these pages you have access to current object via `item` object. I.e. you could output post's content like this (on Post page): |
| 115 | + |
| 116 | +```handlebars |
| 117 | +<h1>{{ item.title }}</h1> |
| 118 | +{{ item.content }} |
| 119 | +``` |
| 120 | + |
| 121 | +On Category page there's one more trick for fetching current category's posts (because I used `belongs to` field): |
| 122 | + |
| 123 | +```handlebars |
| 124 | +{% assign posts = models.posts.find_all_by(category: item.id).order("created_at desc") %} |
| 125 | +{% for post in: posts do: %} |
| 126 | +... |
| 127 | +``` |
| 128 | + |
| 129 | +And that's it - now I have completely dynamic and working Category page and Product page! And that's all for this tutorial: we have pretty basic blog functionality with a lot of possibilities to improve it further. For example, you might add `Published` field to `Post` model and list only published posts by default, or maybe introduce posts tagging. Your imagination is the only limit, so just try it ;-) |
| 130 | + |
| 131 | +You could find my final result at: <a target="_blank" rel="nofollow" href="http://patient-forest-605.app.apiq.io">http://patient-forest-605.app.apiq.io</a> |
0 commit comments