Introduction
Nuxt.JS is a framework for creating Vue.JS applications, you can choose between Universal, Static Generated or Single Page application.
Why Nuxt.JS?
- Nuxt.JS create a framework flexible enough that can be used as a main project base or in addition to your current project based on it. Nuxt.JS focuses on UI rendering while abstracting away the client / server distribution.
- Nuxt.JS create single page applications (SPA mode) quickly, useful to keep Nuxt features while working on back office applications.
- Nuxt.JS comes with a lot of features to help you in your development between the client side and the server side such as Asynchronous Data, Middleware, Layouts, Pages, Plugins etc.
- Nuxt.JS presets all the configuration needed to make your development of a server rendered Vue.JS application more enjoyable.
Resources
The following resources were used in this tutorial:
- Node.JS
- Vue 2
- Vue Router
- Vuex (included only when using the store option)
- Vue Server Renderer (excluded when using mode: ‘spa’)
- vue-meta
Under the hood Nuxt.JS uses Webpack with vue-loader and babel-loader to bundle, code-split and minify your code.
Setup
Create a Nuxt.JS project by running the following command on your terminal:
$ npx create-nuxt-app <project-name>
Or with yarn:
$ yarn create nuxt-app <project-name>
It will ask you some questions:
- Choose between integrated server-side frameworks:
Select None for this tutorial
2. Choose your favorite UI framework:
- None (feel free to add one later)
- Bootstrap
- Vuetify
- Bulma
- Tailwind
- Element UI
- Ant Design Vue
- Buefy
Select Vuetify for this tutorial
3. Choose your favorite testing framework:
Select None as we won’t be testing.
4. The Nuxt mode you want (Universal
or SPA
)
5. Add axios module to make HTTP request easily into your application.
6. Add EsLint to Lint your code on save.
7. Add Prettier to prettify your code on save.
When answered, it will install all the dependencies so the next step is to navigate to the project folder and launch it with:
$ cd <project-name> $ npm run dev
The application is now running on http://localhost:3000.
NOTE: Nuxt.js listens to changes in the pages directory so there is no need to restart the application when adding new pages.
Here is what the applications looks like on port http://localhost:3000.
Here is what the directory structure looks like on Visual Studio Code editor.
For the majority of the tutorial we would most work with within the layout > default.vue file and the pages > index.vue and pages > inspire.vue files respectively.
First, remove one of the drawers, icons and rename the app to NewsApp.
Lastly, adding a route and making modification on the inspire route to news, below is a code sample to effect the changes:
Building a News App
<template> <v-app dark> <v-navigation-drawer v-model="drawer" :mini-variant="miniVariant" :clipped="clipped" fixed app > <v-list> <v-list-tile v-for="(item, i) in items" :key="i" :to="item.to" router exact > <v-list-tile-action> <v-icon>{{ item.icon }}</v-icon> </v-list-tile-action> <v-list-tile-content> <v-list-tile-title v-text="item.title" /> </v-list-tile-content> </v-list-tile> </v-list> </v-navigation-drawer> <!-- title bar --> <v-toolbar :clipped-left="clipped" fixed app > <v-toolbar-side-icon @click="drawer = !drawer" /> <v-toolbar-title v-text="title" /> <v-spacer /> </v-toolbar> <!-- end title bar --> <!-- main content --> <v-content> <v-container> <nuxt /> </v-container> </v-content> <!-- ends main content --> <!-- footer page --> <v-footer :fixed="fixed" app > <span>© 2019</span> </v-footer> <!-- ends footer --> </v-app> </template> <script> export default { data() { return { clipped: false, drawer: false, fixed: false, items: [ { icon: 'apps', title: 'Welcome', to: '/' }, { icon: 'bubble_chart', title: 'News', to: '/news' }, { icon: 'group_work', title: 'About', to: '/about' } ], miniVariant: false, right: true, rightDrawer: false, title: 'NewsApp' } } } </script>
Now lets make modification to the pages > index.vue. We include a carousel / slider to display images from a cdn to our News Web App. See the sample code below:
<template> <v-layout row wrap> <v-flex xs12> <v-carousel> <v-carousel-item v-for="(article, index) in articles" :src="article.src" :key="index" > </v-carousel-item> </v-carousel> <v-divider></v-divider> </v-flex> </v-layout> </template> <script> export default { data () { return { articles: [ { src: 'https://i0.wp.com/cdn.vanguardngr.com/wp-content/uploads/2018/10/pdp-members.gif?fit=412%2C230&ssl=1' }, { src: 'https://cdn.punchng.com/wp-content/uploads/2019/06/02173535/Trump-and-Meghan.jpg' }, { src: 'https://cdn.punchng.com/wp-content/uploads/2019/01/28153616/Pope-Francis1.jpg' }, { src: 'https://cdn.punchng.com/wp-content/uploads/2018/10/01183201/Pastor-William-Kumuyi-and-President-Muhammadu-Buhari.jpg' } ], } } } </script>
Now we need to sign up for an account on the official News API website for real time new top headlines.
A key would be generated once sign up has been successful hence users can make real time GET REQUEST to fetch data.
Moving on we need to modify the pages > news.vue to enable us make a GET request to our News API.
<template> <v-flex> <v-flex xs12 sm6 pb-3 offset-sm3 v-for="(article, index) in articles" :key="index"> <v-card> <img :src="article.urlToImage" width="100%" height="200px" > <v-card-title primary-title> <div> <div class="headline">{{article.title}}</div> </div> </v-card-title> <v-card-text> {{article.content}} </v-card-text> <v-card-actions> <v-spacer></v-spacer> <v-btn flat :href="article.url" target="_blank">Open</v-btn> <v-spacer></v-spacer> </v-card-actions> </v-card> </v-flex> </v-flex> </template> <script> export default { data: () => ({ show: false }), async asyncData({$axios}){ const {articles} = await $axios.$get('https://newsapi.org/v2/top-headlines?country=ng&apiKey=af4129710bf14609b57b33cc43239681'); return{articles}; } } </script>
Installing Axios and Font Awesome Icons
From the snippet above, I made use of my generated API key so you should feel free to replace it with once you have already signed up.
Up next, we need to tidy up our codes on the layouts > default.vue file such that relevant social media links to our profile be added including loading in of various brand icons.
To work with fonts in Nuxt we need to install Nuxt Font Awesome. Feel free to read the documentation.
We also need to setup Axios to enable us make successful request. Feel free to read documentation and setup.
Now we need to modify the nuxt.config.js and add our new installed configuration.
import VuetifyLoaderPlugin from 'vuetify-loader/lib/plugin' import pkg from './package' export default { mode: 'universal', /* ** Headers of the page */ head: { title: pkg.name, meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: pkg.description } ], link: [ { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }, { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' } ] }, /* ** Customize the progress-bar color */ loading: { color: '#fff' }, /* ** Global CSS */ css: [ '~/assets/style/app.styl' ], /* ** Plugins to load before mounting the App */ plugins: [ '@/plugins/vuetify', ], /* ** Nuxt.js modules */ modules: [ '@nuxtjs/axios', 'nuxt-fontawesome', ['nuxt-fontawesome', { component: 'fa', imports: [ //import whole set { set: '@fortawesome/free-solid-svg-icons', icons: ['fas'] }, { set:'@fortawesome/free-brands-svg-icons', icons: ['fab'] } ] }], ], axios: { // proxyHeaders: false }, /* ** Build configuration */ build: { transpile: ['vuetify/lib'], plugins: [new VuetifyLoaderPlugin()], loaders: { stylus: { import: ['~assets/style/variables.styl'] } }, /* ** You can extend webpack config here */ extend(config, ctx) { } } }
Adding Social Media Icons to Default Page
Lastly, add the existing features to the layouts > default.vue to include Social Media icons and our fetched news headlines.
<template> <v-app dark> <v-navigation-drawer v-model="drawer" :mini-variant="miniVariant" :clipped="clipped" fixed app > <v-list> <v-list-tile v-for="(item, i) in items" :key="i" :to="item.to" router exact > <v-list-tile-action> <v-icon>{{ item.icon }}</v-icon> </v-list-tile-action> <v-list-tile-content> <v-list-tile-title v-text="item.title" /> </v-list-tile-content> </v-list-tile> </v-list> </v-navigation-drawer> <!-- title bar --> <v-toolbar :clipped-left="clipped" fixed app > <v-toolbar-side-icon @click="drawer = !drawer" /> <v-toolbar-title v-text="title" /> <v-spacer /> </v-toolbar> <!-- end title bar --> <!-- main content --> <v-content> <v-container> <nuxt /> </v-container> </v-content> <!-- ends main content --> <!-- footer page --> <v-footer :fixed="fixed" app height="auto" > <v-card class="flex dark lighten-1 white--text" flat tile > <v-card-title> <v-layout row wrap> <v-flex xs4> <strong class="subheading">Get connected</strong> </v-flex> <v-flex xs2> <a href="https://www.linkedin.com/in/suleolanrewaju/"><fa :icon="fab.faLinkedin" class="mx-4 fa-2x"/></a> </v-flex> <v-flex xs2> <a href="https://medium.com/@suleabimbola/"><fa :icon="fab.faMedium" class="mx-4 fa-2x"/></a> </v-flex> <v-flex xs2> <a href="https://twitter.com/lanromanero"><fa :icon="fab.faTwitter" class="mx-4 fa-2x"/></a> </v-flex> <v-flex xs2> <a href="https://github.com/larrysul"><fa :icon="fab.faGithub" class="mx-4 fa-2x"/></a> </v-flex> </v-layout> </v-card-title> </v-card> </v-footer> <!-- ends footer --> </v-app> </template> <style> a{ color:#fff } </style> <script> import {fab} from '@fortawesome/free-brands-svg-icons' export default { data() { return { clipped: false, drawer: false, fixed: false, items: [ { icon: 'apps', title: 'Welcome', to: '/' }, { icon: 'arrow_forward_io', title: 'Latest News', to: '/news' }, { icon: 'arrow_forward_io', title: 'About App', to: '/about' } ], miniVariant: false, right: true, rightDrawer: false, title: 'Top Headlines' } }, computed: { fab () { return fab } } } </script>
About Us Page
A brief information can also be added to the pages > about.vue.
<template> <div> <v-container> <v-layout> <h3> Simple app based on Nuxt.js, which is a framework for creating Vue.js applications. It uses a news api <a href="https://newsapi.org/">https://newsapi.org/</a> to get various content before rendering </h3> </v-layout> </v-container> </div> </template>
Each time you make changes the Nuxt.JS recompiles and serves the app on localhost:3000. If it does not you can always do npm run dev to start development server.
Now here is what our application looks pretty much like.
Welcome Page
News Page
Build and Deploy Using Surge
We need to run npm run generate in the command line interface. this will help build and generate the static files required to be deployed on Surge.
Installing Surge
To install Surge run npm install –global surge. This allows Surge to be installed globally and readily available any other time there is a need to deploy. For more information see the Surge online documentation.
Once installation is complete run surge. This will start the deployment and you will be required to set a path which is always in the \dist and generate a domain url through which the application will be accessed.
Useful Links:
News API with Nuxt.JS on GitHub