├── .eslintrc.js ├── .gitignore ├── README.md ├── assets └── README.md ├── components ├── README.md └── author.vue ├── content └── posts │ ├── 1.md │ └── 2.md ├── layouts ├── README.md ├── default.vue └── slug.vue ├── middleware └── README.md ├── nuxt.config.js ├── package-lock.json ├── package.json ├── pages ├── README.md ├── _slug │ └── index.vue └── index.vue ├── plugins └── README.md ├── static ├── README.md └── favicon.ico ├── store ├── README.md └── index.js └── styles └── base.less /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: 'babel-eslint', 4 | env: { 5 | browser: true, 6 | node: true 7 | }, 8 | extends: 'standard', 9 | // required to lint *.vue files 10 | plugins: [ 11 | 'html' 12 | ], 13 | // add your custom rules here 14 | rules: {}, 15 | globals: {} 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | dist 4 | .nuxt 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue Static CMS 2 | created by [andreliem](https://twitter.com/andreliem) 3 | 4 | Static Markdown blogging using VueJS + Nuxt. 5 | 6 | Use this setup to create a simple blogging system for your personal website. 7 | 8 | The goal of this repository is to provide developers with a static blogging platform that is compatible with 9 | the latest releases of Nuxt. 10 | 11 | ## Examples 12 | - [vuejsradar.com](http://vuejsradar.com) 13 | - [andreliem.ca](http://andreliem.ca) 14 | 15 | 16 | ## Supported Features 17 | - Markdown blogging 18 | - Locally stored posts `/content/posts` 19 | - Example configuration in `nuxt.config.js` for loading common modules and route generation 20 | - Two layouts (default home page and blog posts using slug urls) 21 | - Integration of disqus 22 | - Less css (easy to swap to SASS if you prefer) 23 | 24 | ## Roadmap 25 | - Site Map (SEO) 26 | - Syntax highlighting of code 27 | - Time to read posts 28 | - Social Media Sharing 29 | - Swap in Axios API provider for markdown 30 | - Runnable Code snippets 31 | 32 | ## Installation 33 | 34 | ``` bash 35 | # install dependencies 36 | npm install 37 | 38 | # serve locally with hot reload 39 | npm run dev 40 | 41 | # build /dist for production 42 | npm run generate 43 | 44 | ``` 45 | (refer to the offical [Nuxt documentation](https://nuxtjs.org) for help) 46 | 47 | 48 | 49 | ## License 50 | 51 | [MIT](http://opensource.org/licenses/MIT) 52 | 53 | -------------------------------------------------------------------------------- /assets/README.md: -------------------------------------------------------------------------------- 1 | # ASSETS 2 | 3 | This directory contains your un-compiled assets such as LESS, SASS, or JavaScript. 4 | 5 | More information about the usage of this directory in the documentation: 6 | https://nuxtjs.org/guide/assets#webpacked 7 | 8 | **This directory is not required, you can delete it if you don't want to use it.** 9 | -------------------------------------------------------------------------------- /components/README.md: -------------------------------------------------------------------------------- 1 | # COMPONENTS 2 | 3 | The components directory contains your Vue.js Components. 4 | Nuxt.js doesn't supercharge these components. 5 | 6 | **This directory is not required, you can delete it if you don't want to use it.** 7 | -------------------------------------------------------------------------------- /components/author.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 29 | 30 | 47 | -------------------------------------------------------------------------------- /content/posts/1.md: -------------------------------------------------------------------------------- 1 | Welcome to the first post for my static blog using VueJS + Nuxt! 2 | 3 | This file is all `markdown`. Checkout some lorem ipsum mark down below! 4 | 5 | --- 6 | 7 | # Mihi respiciens morari situsque fluminis Hodites simul 8 | 9 | ## Ut silices proles 10 | 11 | Lorem markdownum adsumptumque secutum si quod amori reddidit Phaestia ipse, 12 | Veneri, torosa, mihi illis dicere oderat? Tam captavit gloria [domos 13 | vidimus](http://ulla.org/quae-in) abominor aquae gravis tollens! Haud **Helles 14 | non** acta forem capitis vellent; pia et persequar natura. 15 | 16 | > Virgineum [pastor positoris 17 | > iamdudum](http://possum-iuvencae.io/corpora-lacrimas.html) erat. Vocari navis 18 | > laticemque sinit subdita insula quae ripis, gelidumque quae! Iam amantem 19 | > [si](http://www.scitepigeat.org/sortehomines.html) caeloque querenda attonitus 20 | > adventuque phaethon alii visceribus ignaroque. 21 | 22 | Nec iam, se sede mirator. *Detur bene* nympham? Mei tum cornua tellus. Fertilis 23 | Penthea se urbes, in, suos et profanos, fulvo. Quis suo nudans actis, maior 24 | quidem bipennifer auxilium cristis mitia alite arceat. 25 | 26 | ## Deorum bos hostibus 27 | 28 | Oblitus lucos, vindicat nec tum illas prohibete nomen, ille haec habitare. Esse 29 | est ora auferor que, tamen haec deceptus Thereaque Boeotia? 30 | 31 | Saevis vestibus erit quam qui linguam Niobe mea et racemis felix simulac parte 32 | vagina *penates negata odore*! Aegro nam cristis, solis hoc este; nec iam nec 33 | parva o Ilioneus cornua multi *mater*, et? 34 | 35 | Et actae, soror aethere quaeque *tam caput* insidias invitum intellectumque 36 | serosque, **quamvis** decent reparabile quicquam? Leves cumulusque ingemuit, 37 | pete mutat futuro carior visus! Nec oculis oculos! 38 | 39 | Ipsa eas crinem, spoliataque aliud stimulos exit Eurotas mutua chrysolithi in 40 | tenemur ferrumque teneat. Erat terras cornua, cum cum *dixit ut* not 41 | 42 | 43 | ``` 44 | 47 | 48 | ``` 49 | -------------------------------------------------------------------------------- /content/posts/2.md: -------------------------------------------------------------------------------- 1 | # Hello Foo Bar 2 | 3 | Just another example of a 2nd blog post! -------------------------------------------------------------------------------- /layouts/README.md: -------------------------------------------------------------------------------- 1 | # LAYOUTS 2 | 3 | This directory contains your Application Layouts. 4 | 5 | More information about the usage of this directory in the documentation: 6 | https://nuxtjs.org/guide/views#layouts 7 | 8 | **This directory is not required, you can delete it if you don't want to use it.** 9 | -------------------------------------------------------------------------------- /layouts/default.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /layouts/slug.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 50 | 51 | 72 | 73 | 79 | -------------------------------------------------------------------------------- /middleware/README.md: -------------------------------------------------------------------------------- 1 | # MIDDLEWARE 2 | 3 | This directory contains your Application Middleware. 4 | The middleware lets you define custom function to be ran before rendering a page or a group of pages (layouts). 5 | 6 | More information about the usage of this directory in the documentation: 7 | https://nuxtjs.org/guide/routing#middleware 8 | 9 | **This directory is not required, you can delete it if you don't want to use it.** 10 | -------------------------------------------------------------------------------- /nuxt.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /* 3 | ** Headers of the page 4 | */ 5 | head: { 6 | title: 'Vue Static CMS', 7 | meta: [ 8 | { charset: 'utf-8' }, 9 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 10 | { hid: 'description', name: 'description', content: 'Nuxt.js project' } 11 | ], 12 | link: [ 13 | { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } 14 | ] 15 | }, 16 | generate: { 17 | routes: [ 18 | '/', 19 | '/hello-static-blogging', 20 | '/foo-bar' 21 | ] 22 | }, 23 | /* 24 | ** Customize the progress-bar color 25 | */ 26 | loading: { color: '#3B8070' }, 27 | /* 28 | ** Build configuration 29 | */ 30 | build: { 31 | loaders: [ 32 | { 33 | test: /\.(png|jpe?g|gif|svg)$/, 34 | loader: 'url-loader', 35 | query: { 36 | limit: 1000, // 1KO 37 | name: 'img/[name].[hash:7].[ext]' 38 | } 39 | }, 40 | { 41 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 42 | loader: 'url-loader', 43 | query: { 44 | limit: 1000, // 1 KO 45 | name: 'fonts/[name].[hash:7].[ext]' 46 | } 47 | } 48 | ], 49 | /* 50 | ** Run ESLINT on save 51 | */ 52 | extend (config, ctx) { 53 | if (ctx.isClient) { 54 | config.module.rules.push({ 55 | enforce: 'pre', 56 | test: /\.(js|vue)$/, 57 | loader: 'eslint-loader', 58 | exclude: /(node_modules)/ 59 | }) 60 | } 61 | } 62 | }, 63 | css: [ 64 | ], 65 | plugins: [ 66 | ], 67 | modules: [ 68 | '@nuxtjs/bootstrap-vue', 69 | '@nuxtjs/font-awesome', 70 | /* ['@nuxtjs/google-analytics', { ua: 'YOUR_ANALYTICS_ID' }], */ 71 | ['@nuxtjs/markdownit', { html: true, linkify: true, breaks: true }] 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vuecms", 3 | "version": "0.1.0", 4 | "description": "VueJS News", 5 | "author": "Andre Liem ", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/andreliem/vuecms.git" 10 | }, 11 | "private": false, 12 | "dependencies": { 13 | "nuxt": "latest", 14 | "vue-disqus": "^2.0.3" 15 | }, 16 | "scripts": { 17 | "dev": "nuxt", 18 | "build": "nuxt build", 19 | "start": "nuxt start", 20 | "generate": "nuxt generate", 21 | "lint": "eslint --ext .js,.vue --ignore-path .gitignore .", 22 | "precommit": "npm run lint" 23 | }, 24 | "devDependencies": { 25 | "@nuxtjs/bootstrap-vue": "^1.0.4", 26 | "@nuxtjs/font-awesome": "^1.0.1", 27 | "@nuxtjs/google-analytics": "^0.2.0", 28 | "@nuxtjs/markdownit": "^1.1.2", 29 | "babel-eslint": "^7.1.1", 30 | "eslint": "^3.15.0", 31 | "eslint-config-standard": "^6.2.1", 32 | "eslint-loader": "^1.6.1", 33 | "eslint-plugin-html": "^2.0.0", 34 | "eslint-plugin-promise": "^3.4.1", 35 | "eslint-plugin-standard": "^2.0.1", 36 | "less": "^2.7.2", 37 | "less-loader": "^4.0.4", 38 | "marked": "^0.3.6", 39 | "vue-style-loader": "^3.0.1" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /pages/README.md: -------------------------------------------------------------------------------- 1 | # PAGES 2 | 3 | This directory contains your Application Views and Routes. 4 | The framework reads all the .vue files inside this directory and create the router of your application. 5 | 6 | More information about the usage of this directory in the documentation: 7 | https://nuxtjs.org/guide/routing 8 | -------------------------------------------------------------------------------- /pages/_slug/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 57 | 74 | 75 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 53 | 54 | 85 | -------------------------------------------------------------------------------- /plugins/README.md: -------------------------------------------------------------------------------- 1 | # PLUGINS 2 | 3 | This directory contains your Javascript plugins that you want to run before instantiating the root vue.js application. 4 | 5 | More information about the usage of this directory in the documentation: 6 | https://nuxtjs.org/guide/plugins 7 | 8 | **This directory is not required, you can delete it if you don't want to use it.** 9 | -------------------------------------------------------------------------------- /static/README.md: -------------------------------------------------------------------------------- 1 | # STATIC 2 | 3 | This directory contains your static files. 4 | Each file inside this directory is mapped to /. 5 | 6 | Example: /static/robots.txt is mapped as /robots.txt. 7 | 8 | More information about the usage of this directory in the documentation: 9 | https://nuxtjs.org/guide/assets#static 10 | 11 | **This directory is not required, you can delete it if you don't want to use it.** 12 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andreliem/vuecms/31a0715d742a0cc3585f16ff3c3613d24cfef697/static/favicon.ico -------------------------------------------------------------------------------- /store/README.md: -------------------------------------------------------------------------------- 1 | # STORE 2 | 3 | This directory contains your Vuex Store files. 4 | Vuex Store option is implemented in the Nuxt.js framework. 5 | Creating a index.js file in this directory activate the option in the framework automatically. 6 | 7 | More information about the usage of this directory in the documentation: 8 | https://nuxtjs.org/guide/vuex-store 9 | 10 | **This directory is not required, you can delete it if you don't want to use it.** 11 | -------------------------------------------------------------------------------- /store/index.js: -------------------------------------------------------------------------------- 1 | import Vuex from 'vuex' 2 | 3 | const makeStore = () => { 4 | return new Vuex.Store({ 5 | state: { 6 | posts: [], 7 | post: {} 8 | }, 9 | mutations: { 10 | updatePosts (state, { posts }) { 11 | state.posts = posts 12 | }, 13 | updatePost (state, { post }) { 14 | state.post = post 15 | } 16 | }, 17 | actions: { 18 | getPostWithSlug ({commit, state}, slug) { 19 | let post = state.posts.find((post) => { 20 | return (post.slug === slug) 21 | }) 22 | commit('updatePost', { post: post }) 23 | }, 24 | getPosts ({commit}) { 25 | commit('updatePosts', { posts: [ 26 | { 27 | id: 1, 28 | slug: 'hello-static-blogging', 29 | title: 'Hello Static Blogging', 30 | created_at: '06/27/2017', 31 | meta: { 32 | id: 1, 33 | name: 'Hello Static Blogging', 34 | content: 'Hello Static Blogging' 35 | } 36 | }, 37 | { 38 | id: 2, 39 | slug: 'foo-bar', 40 | title: 'Foo Bar', 41 | created_at: '10/18/2016', 42 | meta: { 43 | id: 2, 44 | name: 'Foo Bar', 45 | content: 'Foo Bar' 46 | } 47 | } 48 | ]}) 49 | } 50 | } 51 | }) 52 | } 53 | 54 | export default makeStore 55 | -------------------------------------------------------------------------------- /styles/base.less: -------------------------------------------------------------------------------- 1 | // Colour palette 2 | @default-color: #333; 3 | @red: #ee2b31; 4 | @grey: #707070; 5 | @grey-light: #8b8b8b; 6 | @blue: #1abccf; 7 | @green: #46cfa9; 8 | 9 | html 10 | { 11 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Lato", "Helvetica Neue", sans-serif; 12 | font-size: 16px; 13 | word-spacing: 1px; 14 | -ms-text-size-adjust: 100%; 15 | -webkit-text-size-adjust: 100%; 16 | -moz-osx-font-smoothing: grayscale; 17 | -webkit-font-smoothing: antialiased; 18 | box-sizing: border-box; 19 | } 20 | 21 | body { 22 | background-color: #fcfcfc; 23 | } 24 | 25 | *, *:before, *:after 26 | { 27 | box-sizing: border-box; 28 | margin: 0; 29 | } 30 | 31 | a { 32 | color: @green; 33 | &:hover { 34 | color: @blue; 35 | text-decoration: none; 36 | } 37 | } 38 | 39 | .site-title { 40 | font-weight: 600; 41 | font-size: 4em; 42 | a { 43 | color: @default-color; 44 | } 45 | } 46 | 47 | .site-subtitle { 48 | color: @grey-light; 49 | font-weight: 300; 50 | font-size: 2em; 51 | } 52 | 53 | .me { 54 | width: 25%; 55 | border-radius: 500px; 56 | border: 5px solid #ddd; 57 | @media (min-width: 992px) { 58 | width: 10%; 59 | } 60 | } 61 | 62 | .social { 63 | list-style: none; 64 | color: @blue; 65 | font-size: 2em; 66 | 67 | .item { 68 | margin: 0 0.5em 0 0.5em; 69 | } 70 | } 71 | 72 | .page-enter-active, .page-leave-active { 73 | transition: opacity .2s 74 | } 75 | .page-enter, .page-leave-active { 76 | opacity: 0 77 | } 78 | 79 | .bounce-enter-active { 80 | animation: bounce-in .8s; 81 | } 82 | .bounce-leave-active { 83 | animation: bounce-out .5s; 84 | } 85 | @keyframes bounce-in { 86 | 0% { transform: scale(0) } 87 | 50% { transform: scale(1.5) } 88 | 100% { transform: scale(1) } 89 | } 90 | @keyframes bounce-out { 91 | 0% { transform: scale(1) } 92 | 50% { transform: scale(1.5) } 93 | 100% { transform: scale(0) } 94 | } 95 | --------------------------------------------------------------------------------