From 2b34011c237deaaec9cd3c1373c01b3b29a7d687 Mon Sep 17 00:00:00 2001 From: Jake Lumetta Date: Mon, 26 Feb 2018 09:18:02 -0600 Subject: [PATCH 1/4] Adding serverless blog example --- src/v2/cookbook/serverless-blog.md | 268 +++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 src/v2/cookbook/serverless-blog.md diff --git a/src/v2/cookbook/serverless-blog.md b/src/v2/cookbook/serverless-blog.md new file mode 100644 index 0000000000..19650940a2 --- /dev/null +++ b/src/v2/cookbook/serverless-blog.md @@ -0,0 +1,268 @@ +# Create a serverless CMS-Powered Blog Using Vue.js + +So you've just launched your Vue.js website, congrats! Now you want to add a blog that quickly plugs into your website and you don't want to have to spin up a whole server just to host a Wordpress instance (or any DB-powered CMS for that matter). You want to just be able to add a few Vue.js blog components and some routes and have it all just work, right? + +This tutorial will teach you how to do just that. We're going to quickly build a serverless CMS-powered blog with Vue.js. It uses ButterCMS, an API-first CMS that lets you manage content using the ButterCMS dashboard and integrate our content API into your Vue.js app. You can use ButterCMS for new or existing Vue.js projects. + +![Butter Dashboard](https://user-images.githubusercontent.com/160873/36677285-648798e4-1ad3-11e8-9454-d22fca8280b7.png "Butter Dashboard") + +## Install + +Run this in your commandline: + +`npm install buttercms --save` + +Butter can also be loaded using a CDN: + +`` + +## Quickstart + +Set your API token: + +`var butter = require('buttercms')('your_api_token');` + +Using ES6: + +```javascript +import Butter from 'buttercms'; +const butter = Butter('your_api_token'); +``` + +Using CDN: + +```javascript + + +``` + + Import this file into any component you want to use ButterCMS. Then from the console run: + +```javascript +butter.post.list({page: 1, page_size: 10}).then(function(response) { + console.log(response) +}) +``` + +This API request fetches your blog posts. Your account comes with one example post which you'll see in the response. + +## Display posts +To display posts we create a simple `/blog` route (using vue-router) in our app and fetch blog posts from the Butter API, as well as a `/blog/:slug` route to handle individual posts. See our [API reference](https://buttercms.com/docs/api/?javascript#blog-posts) for additional options such as filtering by category or author. The response also includes some metadata we'll use for pagination. + +See our API reference for additional options such as filtering by category or author. The response also includes some metadata we'll use for pagination. + +`router/index.js:` + +```javascript +import Vue from 'vue' +import Router from 'vue-router' +import BlogHome from '@/components/BlogHome' +import BlogPost from '@/components/BlogPost' + +Vue.use(Router) + +export default new Router({ + mode: 'history', + routes: [ + { + path: '/blog/', + name: 'blog-home', + component: BlogHome + }, + { + path: '/blog/:slug', + name: 'blog-post', + component: BlogPost + } + ] +}) +``` + +Then create `components/BlogHome.vue` which will be your blog homepage that lists your most recent posts. + +```javascript + +Display the result + + +``` + +Now create `components/BlogPost.vue` which will be your Blog Post page to list a single post. + +```javascript + +Display the results + +``` + +Now our app is pulling all blog posts and we can navigate to individual posts. However, our next/previous post buttons are not working. + +One thing to note when using routes with params is that when the user navigates from /blog/foo to /blog/bar, the same component instance will be reused. Since both routes render the same component, this is more efficient than destroying the old instance and then creating a new one. However, this also means that the lifecycle hooks of the component will not be called. + +Visit the Vue.js docs to learn more about [Dynamic Route Matching](https://router.vuejs.org/en/essentials/dynamic-matching.html) + +To fix this we need to simply watch the `$route` object and call `getPost()` when the route changes. + +Updated `script` section in `components/BlogPost.vue`: + +```javascript + +``` + +Now our app has a working blog that can be updated easily in the ButterCMS dashboard. + +## Categories, Tags, and Authors + +Use Butter's APIs for categories, tags, and authors to feature and filter content on your blog. + +See our API reference for more information about these objects: + +* [Categories](https://buttercms.com/docs/api/?ruby#categories) +* [Tags](https://buttercms.com/docs/api/?ruby#tags) +* [Authors](https://buttercms.com/docs/api/?ruby#authors) + +Here's an example of listing all categories and getting posts by category. Call these methods on the `created()` lifecycle hook: + +``` +methods: { + ... + getCategories() { + butter.category.list() + .then((res) => { + console.log('List of Categories:') + console.log(res.data.data) + }) + }, + getPostsByCategory() { + butter.category.retrieve('example-category', { + include: 'recent_posts' + }) + .then((res) => { + console.log('Posts with specific category:') + console.log(res) + }) + } +}, +created() { + ... + this.getCategories() + this.getPostsByCategory() +} +``` +## Wrap up + +That's it! You now have a fully functional serverless blog running in your app. We hope this tutorial was helpful and made your development experience with Vue.js even more enjoyable :) + +If you have any questions or feedback, feel free to open a PR or leave a comment in Github. From 3eff7d878593f535ab28f20b309febd16ae3d758 Mon Sep 17 00:00:00 2001 From: Jake Lumetta Date: Thu, 1 Mar 2018 14:48:12 -0600 Subject: [PATCH 2/4] Pull request feedback --- src/v2/cookbook/serverless-blog.md | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/v2/cookbook/serverless-blog.md b/src/v2/cookbook/serverless-blog.md index 19650940a2..62b05867c5 100644 --- a/src/v2/cookbook/serverless-blog.md +++ b/src/v2/cookbook/serverless-blog.md @@ -1,8 +1,14 @@ +--- +title: Create a CMS-Powered Blog +type: cookbook +order: 5 +--- + # Create a serverless CMS-Powered Blog Using Vue.js -So you've just launched your Vue.js website, congrats! Now you want to add a blog that quickly plugs into your website and you don't want to have to spin up a whole server just to host a Wordpress instance (or any DB-powered CMS for that matter). You want to just be able to add a few Vue.js blog components and some routes and have it all just work, right? +So you've just launched your Vue.js website, congrats! Now you want to add a blog that quickly plugs into your website and you don't want to have to spin up a whole server just to host a Wordpress instance (or any DB-powered CMS for that matter). You want to just be able to add a few Vue.js blog components and some routes and have it all just work, right? What you're looking for a "serverless" blog that's powered entirely by API's you can consume directly from your Vue.js application. This tutorial will teach you how to do just that, let's dive in! -This tutorial will teach you how to do just that. We're going to quickly build a serverless CMS-powered blog with Vue.js. It uses ButterCMS, an API-first CMS that lets you manage content using the ButterCMS dashboard and integrate our content API into your Vue.js app. You can use ButterCMS for new or existing Vue.js projects. +We're going to quickly build a serverless CMS-powered blog with Vue.js. It uses [ButterCMS](https://buttercms.com/), an API-first CMS that lets you manage content using the ButterCMS dashboard and integrate our content API into your Vue.js app. You can use ButterCMS for new or existing Vue.js projects. ![Butter Dashboard](https://user-images.githubusercontent.com/160873/36677285-648798e4-1ad3-11e8-9454-d22fca8280b7.png "Butter Dashboard") @@ -49,7 +55,7 @@ butter.post.list({page: 1, page_size: 10}).then(function(response) { This API request fetches your blog posts. Your account comes with one example post which you'll see in the response. ## Display posts -To display posts we create a simple `/blog` route (using vue-router) in our app and fetch blog posts from the Butter API, as well as a `/blog/:slug` route to handle individual posts. See our [API reference](https://buttercms.com/docs/api/?javascript#blog-posts) for additional options such as filtering by category or author. The response also includes some metadata we'll use for pagination. +To display posts we create a `/blog` route (using vue-router) in our app and fetch blog posts from the Butter API, as well as a `/blog/:slug` route to handle individual posts. See our [API reference](https://buttercms.com/docs/api/?javascript#blog-posts) for additional options such as filtering by category or author. The response also includes some metadata we'll use for pagination. See our API reference for additional options such as filtering by category or author. The response also includes some metadata we'll use for pagination. @@ -133,6 +139,11 @@ Display the result ``` +Here's what it looks like (note we added CSS from https://bulma.io/ for quick styling): + +![buttercms-bloglist](https://user-images.githubusercontent.com/160873/36868500-1b22e374-1d5e-11e8-82a0-20c8dc312716.png) + + Now create `components/BlogPost.vue` which will be your Blog Post page to list a single post. ```javascript @@ -178,11 +189,16 @@ Display the results ``` +Here's a preview: + +![buttercms-blogdetail](https://user-images.githubusercontent.com/160873/36868506-218c86b6-1d5e-11e8-8691-0409d91366d6.png) + + Now our app is pulling all blog posts and we can navigate to individual posts. However, our next/previous post buttons are not working. -One thing to note when using routes with params is that when the user navigates from /blog/foo to /blog/bar, the same component instance will be reused. Since both routes render the same component, this is more efficient than destroying the old instance and then creating a new one. However, this also means that the lifecycle hooks of the component will not be called. +One thing to note when using routes with params is that when the user navigates from /blog/foo to /blog/bar, the same component instance will be reused. Since both routes render the same component, this is more efficient than destroying the old instance and then creating a new one. -Visit the Vue.js docs to learn more about [Dynamic Route Matching](https://router.vuejs.org/en/essentials/dynamic-matching.html) +

Be aware, that using the component this way will mean that the lifecycle hooks of the component will not be called. Visit the Vue.js docs to learn more about [Dynamic Route Matching](https://router.vuejs.org/en/essentials/dynamic-matching.html)

To fix this we need to simply watch the `$route` object and call `getPost()` when the route changes. @@ -221,13 +237,13 @@ Updated `script` section in `components/BlogPost.vue`: ``` -Now our app has a working blog that can be updated easily in the ButterCMS dashboard. +Now your app has a working blog that can be updated easily in the ButterCMS dashboard. ## Categories, Tags, and Authors Use Butter's APIs for categories, tags, and authors to feature and filter content on your blog. -See our API reference for more information about these objects: +See the ButterCMS API reference for more information about these objects: * [Categories](https://buttercms.com/docs/api/?ruby#categories) * [Tags](https://buttercms.com/docs/api/?ruby#tags) From 2f5392e8d2733611018f132e9433e5383f33bc4d Mon Sep 17 00:00:00 2001 From: Jake Lumetta Date: Tue, 6 Mar 2018 20:56:33 -0600 Subject: [PATCH 3/4] Adding Alternative Pattern section --- src/v2/cookbook/serverless-blog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/v2/cookbook/serverless-blog.md b/src/v2/cookbook/serverless-blog.md index 62b05867c5..34ba1b032a 100644 --- a/src/v2/cookbook/serverless-blog.md +++ b/src/v2/cookbook/serverless-blog.md @@ -281,4 +281,9 @@ created() { That's it! You now have a fully functional serverless blog running in your app. We hope this tutorial was helpful and made your development experience with Vue.js even more enjoyable :) +## Alternative Pattern + +An alternative pattern to consider, especially if you prefer writing only in Markdown, is using something like [Nuxtent](https://nuxtent.now.sh/guide/writing#async-components). Nuxtent allows you to use `Vue Component` inside of Markdown files. This approach would be akin to a static site approach (i.e. Jekyll) where you compose your blog posts in Markdown files. Nuxtent adds a nice integration between Vue.js and Markdown allowing you to live in a 100% Vue.js world. + + If you have any questions or feedback, feel free to open a PR or leave a comment in Github. From da3761e8cd59fc3eb2a2ed3c8cb48109ec0086b9 Mon Sep 17 00:00:00 2001 From: Jake Lumetta Date: Wed, 7 Mar 2018 07:46:14 -0600 Subject: [PATCH 4/4] A bit more cleanup from PR feedback --- src/v2/cookbook/serverless-blog.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/v2/cookbook/serverless-blog.md b/src/v2/cookbook/serverless-blog.md index 34ba1b032a..ff5a767717 100644 --- a/src/v2/cookbook/serverless-blog.md +++ b/src/v2/cookbook/serverless-blog.md @@ -4,11 +4,11 @@ type: cookbook order: 5 --- -# Create a serverless CMS-Powered Blog Using Vue.js +# Create a CMS-Powered Blog Using Vue.js -So you've just launched your Vue.js website, congrats! Now you want to add a blog that quickly plugs into your website and you don't want to have to spin up a whole server just to host a Wordpress instance (or any DB-powered CMS for that matter). You want to just be able to add a few Vue.js blog components and some routes and have it all just work, right? What you're looking for a "serverless" blog that's powered entirely by API's you can consume directly from your Vue.js application. This tutorial will teach you how to do just that, let's dive in! +So you've just launched your Vue.js website, congrats! Now you want to add a blog that quickly plugs into your website and you don't want to have to spin up a whole server just to host a Wordpress instance (or any DB-powered CMS for that matter). You want to just be able to add a few Vue.js blog components and some routes and have it all just work, right? What you're looking for a blog that's powered entirely by API's you can consume directly from your Vue.js application. This tutorial will teach you how to do just that, let's dive in! -We're going to quickly build a serverless CMS-powered blog with Vue.js. It uses [ButterCMS](https://buttercms.com/), an API-first CMS that lets you manage content using the ButterCMS dashboard and integrate our content API into your Vue.js app. You can use ButterCMS for new or existing Vue.js projects. +We're going to quickly build a CMS-powered blog with Vue.js. It uses [ButterCMS](https://buttercms.com/), an API-first CMS that lets you manage content using the ButterCMS dashboard and integrate our content API into your Vue.js app. You can use ButterCMS for new or existing Vue.js projects. ![Butter Dashboard](https://user-images.githubusercontent.com/160873/36677285-648798e4-1ad3-11e8-9454-d22fca8280b7.png "Butter Dashboard") @@ -55,9 +55,9 @@ butter.post.list({page: 1, page_size: 10}).then(function(response) { This API request fetches your blog posts. Your account comes with one example post which you'll see in the response. ## Display posts -To display posts we create a `/blog` route (using vue-router) in our app and fetch blog posts from the Butter API, as well as a `/blog/:slug` route to handle individual posts. See our [API reference](https://buttercms.com/docs/api/?javascript#blog-posts) for additional options such as filtering by category or author. The response also includes some metadata we'll use for pagination. +To display posts we create a `/blog` route (using vue-router) in our app and fetch blog posts from the Butter API, as well as a `/blog/:slug` route to handle individual posts. -See our API reference for additional options such as filtering by category or author. The response also includes some metadata we'll use for pagination. +See the ButterCMS [API reference](https://buttercms.com/docs/api/?javascript#blog-posts) for additional options such as filtering by category or author. The response also includes some metadata we'll use for pagination. `router/index.js:` @@ -200,7 +200,7 @@ One thing to note when using routes with params is that when the user navigates

Be aware, that using the component this way will mean that the lifecycle hooks of the component will not be called. Visit the Vue.js docs to learn more about [Dynamic Route Matching](https://router.vuejs.org/en/essentials/dynamic-matching.html)

-To fix this we need to simply watch the `$route` object and call `getPost()` when the route changes. +To fix this we need to watch the `$route` object and call `getPost()` when the route changes. Updated `script` section in `components/BlogPost.vue`: @@ -277,13 +277,13 @@ created() { this.getPostsByCategory() } ``` -## Wrap up - -That's it! You now have a fully functional serverless blog running in your app. We hope this tutorial was helpful and made your development experience with Vue.js even more enjoyable :) -## Alternative Pattern +## Alternative Patterns An alternative pattern to consider, especially if you prefer writing only in Markdown, is using something like [Nuxtent](https://nuxtent.now.sh/guide/writing#async-components). Nuxtent allows you to use `Vue Component` inside of Markdown files. This approach would be akin to a static site approach (i.e. Jekyll) where you compose your blog posts in Markdown files. Nuxtent adds a nice integration between Vue.js and Markdown allowing you to live in a 100% Vue.js world. -If you have any questions or feedback, feel free to open a PR or leave a comment in Github. +## Wrap up + +That's it! You now have a fully functional CMS-powered blog running in your app. We hope this tutorial was helpful and made your development experience with Vue.js even more enjoyable :) +