One place for hosting & domains

      How To Build a Blog with Nest.js, MongoDB, and Vue.js


      The author selected Software in the Public Interest Inc to receive a donation as part of the Write for DOnations program.

      Introduction

      Nest.js is a scalable, server-side JavaScript framework built with TypeScript that still preserves compatibility with JavaScript, which makes it an effective tool for building efficient and reliable back-end applications. It has a modular architecture that provides a mature, structural design pattern to the Node.js development world.

      Vue.js is a front-end JavaScript framework for building user interfaces. It has a simple, yet very powerful API along with great performance. Vue.js is capable of powering the front-end layer and logic of any web application irrespective of the size. The ease of integrating it with other libraries or existing projects makes it a perfect choice for most modern web applications.

      In this tutorial, you’ll build a Nest.js application to get yourself familiar with its building blocks as well as the fundamental principles of building modern web applications. You’ll approach this project by separating the application into two different sections: the frontend and the backend. Firstly, you’ll concentrate on the RESTful back-end API built with Nest.js. You’ll then focus on the frontend, which you will build with Vue.js. Both applications will run on different ports and will function as separate domains.

      You’ll build a blog application with which users can create and save a new post, view the saved posts on the homepage, and carry out other processes such as editing and deleting posts. Furthermore, you’ll connect your application and persist its data with MongoDB, which is a schema-less NoSQL database that can receive and store JSON documents. This tutorial focuses on building your application in a development environment. For a production environment, you should also consider user authentication for your application.

      Prerequisites

      To complete this tutorial, you will need:

      Note: This tutorial uses a macOS machine for development. If you’re using another operating system, you may need to use sudo for npm commands throughout the tutorial.

      Step 1 — Installing Nest.js and Other Dependencies

      In this section, you will get started with Nest.js by installing the application and its required dependencies on your local machine. You can easily install Nest.js by either using the CLI that Nest.js provides, or, by installing the starter project from GitHub. For the purpose of this tutorial, you’ll use the CLI to set up the application. To begin, run the following command from the terminal to have it installed globally on your machine:

      You will see output similar to the following:

      Output

      @nestjs/cli@5.8.0 added 220 packages from 163 contributors in 49.104s

      To confirm your installation of the Nest CLI, run this command from your terminal:

      You'll see output showing the current version installed on your machine:

      Output

      5.8.0

      You'll make use of the nest command to manage your project and use it to generate relevant files — like the controller, modules, and providers.

      To begin the project for this tutorial, use the nest command to craft a new Nest.js project named blog-backend by running the following command from your terminal:

      Immediately after running the command, nest will prompt you to provide some basic information like the description, version, and author. Go ahead and provide the appropriate details. Hit ENTER on your computer to proceed after responding to each prompt.

      Next, you'll choose a package manager. For the purpose of this tutorial, select npm and hit ENTER to start installing Nest.js.

      Alt Creating a Nest project

      This will generate a new Nest.js project in a blog-backend folder within your local development folder.

      Next, navigate to the new project’s folder from your terminal:

      Run the following command to install other server dependencies:

      • npm install --save @nestjs/mongoose mongoose

      You've installed @nestjs/mongoose, which is a Nest.js dedicated package for an object modelling tool for MongoDB, and mongoose, which is a package for Mongoose.

      Now you'll start the application using the following command:

      Now, if you navigate to http://localhost:3000 from your favorite browser, you will see your application running.

      Alt Welcome page of the fresh installation of Nest.js application

      You've successfully generated the project by leveraging the availability of the Nest CLI command. Afterward, you proceeded to run the application and accessed it on the default port 3000 on your local machine. In the next section, you'll take the application further by setting up the configuration for the database connection.

      Step 2 — Configuring and Connecting with the Database

      In this step, you'll configure and integrate MongoDB into your Nest.js application. You'll use MongoDB to store data for your application. MongoDB stores its data in documents as field : value pairs. To access this data structure, you'll use Mongoose, which is an object document modeling (ODM) that allows you to define schemas representing the types of data that a MongoDB database stores.

      To start MongoDB, open a separate terminal window so that the application can keep running, and then execute the following command:

      This will start the MongoDB service and run the database in the background of your machine.

      Open the project blog-backend in your text editor and navigate to ./src/app.module.ts. You can set up a connection to the database by including the installed MongooseModule within the root ApplicationModule. To achieve this, update the content in app.module.ts with the following highlighted lines:

      ~/blog-backend/src/app.module.ts

      import { Module } from '@nestjs/common';
      import { AppController } from './app.controller';
      import { AppService } from './app.service';
      import { MongooseModule } from '@nestjs/mongoose';
      
      @Module({
        imports: [
          MongooseModule.forRoot('mongodb://localhost/nest-blog', { useNewUrlParser: true }),
        ],
        controllers: [AppController],
        providers: [AppService],
      })
      export class AppModule { }
      

      In this file, you use the forRoot() method to supply the connection to the database. Save and close the file when you are finished editing.

      With this in place, you have set up the database connection by using the Mongoose module for MongoDB. In the next section, you will create a database schema using the Mongoose library, a TypeScript interface, and a data transfer object (DTO) schema.

      Step 3 — Creating a Database Schema, Interfaces, and DTO

      In this step, you will create a schema, interface, and a data transfer object for your database using Mongoose. Mongoose helps to manage relationships between data and provides schema validation for data types. To help define the structure and datatype of the data in your application's database, you'll create files that determine the following:

      • database schema: This is an organization of data as a blueprint for defining the structure and the types of data that the database needs to store.

      • interfaces: TypeScript interfaces are used for type-checking. It can be used to define the types of data that should be passed for an application.

      • data transfer object: This is an object that defines how data will be sent over the network and carries the data between processes.

      To begin, go back to your terminal where the application is currently running and stop the process with CTRL + C, then navigate to the ./src/ folder:

      Then, create a directory named blog, and a schemas folder within that:

      In the schemas folder, create a new file called blog.schema.ts and open it using your text editor. Then, add the following content:

      ~/blog-backend/src/blog/schemas/blog.schema.ts

      import * as mongoose from 'mongoose';
      
      export const BlogSchema = new mongoose.Schema({
          title: String,
          description: String,
          body: String,
          author: String,
          date_posted: String
      })
      

      Here, you have used Mongoose to define the type of data that you will store in the database. You've specified that all the fields will store and only accept string values. Save and close the file when you are finished editing.

      Now, with the database schema determined, you can move on to creating the interfaces.

      To begin, navigate back into the blog folder:

      • cd ~/blog-backend/src/blog/

      Create a new folder named interfaces and move into it:

      In the interfaces folder, create a new file called post.interface.ts and open it using your text editor. Add the following content to define the types of data for a Post:

      ~/blog-backend/src/blog/interfaces/post.interface.ts

      import { Document } from 'mongoose';
      
      export interface Post extends Document {
          readonly title: string;
          readonly description: string;
          readonly body: string;
          readonly author: string;
          readonly date_posted: string
      }
      

      In this file, you have successfully defined the types of data for a Post type as string values. Save and exit the file.

      Since your application will carry out the functionality of posting data to the database, you will create a data transfer object that will define how data will be sent over the network.

      To achieve this, create a folder dto inside the ./src/blog folder. Within the newly created folder, create another file named create-post.dto.ts

      Navigate back into the blog folder:

      • cd ~/blog-backend/src/blog/

      Then create a folder named dto and move into it:

      In the dto folder, create a new file called create-post.dto.ts and open it using your text editor to add the following content:

      ~/blog-backend/src/blog/dto/create-post.dto.ts

      export class CreatePostDTO {
          readonly title: string;
          readonly description: string;
          readonly body: string;
          readonly author: string;
          readonly date_posted: string
      }
      

      You've marked each of the individual properties in the CreatePostDTO class to have a data type of string and as readonly to avoid unnecessary mutation. Save and exit the file when you are finished editing.

      In this step, you have created a database schema for the database, an interface, and a data transfer object for the data your database will store. Next, you'll generate a module, controller, and service for your blog.

      Step 4 — Creating the Module, Controller, and Service for the Blog

      In this step, you're going to improve on the existing structure of the application by creating a module for your blog. This module will organize the file structure of your application. Next, you'll create a controller to handle routes and process HTTP requests from the client. To wrap things up, you'll set up a service to handle all the business logic that is too complex for the controller of the application to process.

      Generating a Module

      Similarly to the Angular front-end web framework, Nest.js uses a modular syntax. Nest.js applications have a modular design; it comes installed with a single root module, which is often sufficient for a small application. But when an application starts to grow, Nest.js recommends a multiple-module organization, splitting the code into related features.

      A module in Nest.js is identified by the @Module() decorator and takes in an object with properties such as controllers and providers. Each of these properties takes an array of controllers and providers respectively.

      You will generate a new module for this blog application in order to keep the structure more organized. To begin, still in the ~/blog-backend folder, execute the following command:

      • nest generate module blog

      You will see output similar to the following:

      Output

      CREATE /src/blog/blog.module.ts UPDATE /src/app.module.ts

      The command generated a new module named blog.module.ts for the application and imported the newly created module into the root module for the application. This will allow Nest.js to be aware of another module besides the root module.

      In this file, you will see the following code:

      ~/blog-backend/src/blog/blog.module.ts

      import { Module } from '@nestjs/common';
      
      @Module({})
      export class BlogModule {}
      

      You will update this BlogModule with the required properties later in the tutorial. Save and exit the file.

      Generating a Service

      A service, which can also be called a provider in Nest.js, was designed to remove logic from controllers, which are meant to only handle HTTP requests and redirect more complex tasks to services. Services are plain JavaScript classes with an @Injectable() decorator on top of them. To generate a new service, run the following command from the terminal while you are still within the project directory:

      • nest generate service blog

      You will see output similar to the following:

      Output

      CREATE /src/blog/blog.service.spec.ts (445 bytes) CREATE /src/blog/blog.service.ts (88 bytes) UPDATE /src/blog/blog.module.ts (529 bytes)

      The nest command used here has created a blog.service.spec.ts file, which you can use for testing. It has also created a new blog.service.ts file, which will hold all the logic for this application and handle adding and retrieving documents to the MongoDB database. Also, it automatically imported the newly created service and added to blog.module.ts.

      The service handles all the logic within the application, is responsible for interacting with the database, and returns the appropriate responses back to the controller. To accomplish this, open the blog.service.ts file in your text editor and replace the contents with the following:

      ~/blog-backend/src/blog/blog.service.ts

      import { Injectable } from '@nestjs/common';
      import { Model } from 'mongoose';
      import { InjectModel } from '@nestjs/mongoose';
      import { Post } from './interfaces/post.interface';
      import { CreatePostDTO } from './dto/create-post.dto';
      
      @Injectable()
      export class BlogService {
      
          constructor(@InjectModel('Post') private readonly postModel: Model<Post>) { }
      
          async getPosts(): Promise<Post[]> {
              const posts = await this.postModel.find().exec();
              return posts;
          }
      
          async getPost(postID): Promise<Post> {
              const post = await this.postModel
                  .findById(postID)
                  .exec();
              return post;
          }
      
          async addPost(createPostDTO: CreatePostDTO): Promise<Post> {
              const newPost = await this.postModel(createPostDTO);
              return newPost.save();
          }
      
          async editPost(postID, createPostDTO: CreatePostDTO): Promise<Post> {
              const editedPost = await this.postModel
                  .findByIdAndUpdate(postID, createPostDTO, { new: true });
              return editedPost;
          }
      
          async deletePost(postID): Promise<any> {
              const deletedPost = await this.postModel
                  .findByIdAndRemove(postID);
              return deletedPost;
          }
      
      }
      
      

      In this file, you first imported the required module from @nestjs/common, mongoose, and @nestjs/mongoose. You also imported an interface named Post and a data transfer object CreatePostDTO.

      In the constructor, you added @InjectModel('Post'), which will inject the Post model into this BlogService class. You will now be able to use this injected model to retrieve all posts, fetch a single post, and carry out other database-related activities.

      Next, you created the following methods:

      • getPosts(): to fetch all posts from the database.
      • getPost(): to retrieve a single post from the database.
      • addPost(): to add a new post.
      • editPost(): to update a single post.
      • deletePost(): to delete a particular post.

      Save and exit the file when you are finished.

      You have finished setting up and creating several methods that will handle proper interaction with the MongoDB database from the back-end API. Now, you will create the required routes that will handle HTTP calls from a front-end client.

      Generating a Controller

      In Nest. js, controllers are responsible for handling any incoming requests from the client side of an application and returning the appropriate response. Similarly to most other web frameworks, it is important for the application to listen for a request and respond to it.

      To cater to all the HTTP requests for your blog application, you will leverage the nest command to generate a new controller file. Ensure that you are still in the project directory, blog-backend, and run the following command:

      • nest generate controller blog

      You will see output similar to:

      Output

      CREATE /src/blog/blog.controller.spec.ts (474 bytes) CREATE /src/blog/blog.controller.ts (97 bytes) UPDATE /src/blog/blog.module.ts (483 bytes)

      The output indicates that this command created two new files within the src/blog directory. They are blog.controller.spec.ts and blog.controller.ts. The former is a file that you can use to write automated testing for the newly created controller. The latter is the controller file itself. Controllers in Nest.js are TypeScript files decorated with @Controller metadata. The command also imported the newly created controller and added to the blog module.

      Next, open the blog.controller.ts file with your text editor and update it with the following content:

      ~/blog-backend/src/blog/blog.controller.ts

      import { Controller, Get, Res, HttpStatus, Param, NotFoundException, Post, Body, Query, Put, Delete } from '@nestjs/common';
      import { BlogService } from './blog.service';
      import { CreatePostDTO } from './dto/create-post.dto';
      import { ValidateObjectId } from '../shared/pipes/validate-object-id.pipes';
      
      
      @Controller('blog')
      export class BlogController {
      
          constructor(private blogService: BlogService) { }
      
          @Get('posts')
          async getPosts(@Res() res) {
              const posts = await this.blogService.getPosts();
              return res.status(HttpStatus.OK).json(posts);
          }
      
          @Get('post/:postID')
          async getPost(@Res() res, @Param('postID', new ValidateObjectId()) postID) {
              const post = await this.blogService.getPost(postID);
              if (!post) throw new NotFoundException('Post does not exist!');
              return res.status(HttpStatus.OK).json(post);
      
          }
      
          @Post('/post')
          async addPost(@Res() res, @Body() createPostDTO: CreatePostDTO) {
              const newPost = await this.blogService.addPost(createPostDTO);
              return res.status(HttpStatus.OK).json({
                  message: "Post has been submitted successfully!",
                  post: newPost
              })
          }
      }
      

      In this file, you first imported the necessary modules to handle HTTP requests from @nestjs/common module. Then, you imported three new modules which are: BlogService, CreatePostDTO, and ValidateObjectId. After that, you injected the BlogService into the controller via a constructor in order to gain access and make use of the functions that are already defined within the BlogService file. This is a pattern regarded as dependency injection used in Nest.js to increase efficiency and enhance the modularity of the application.

      Finally, you created the following asynchronous methods:

      • getPosts(): This method will carry out the functionality of receiving an HTTP GET request from the client to fetch all posts from the database and then return the appropriate response. It is decorated with a @Get('posts').

      • getPost(): This takes a postID as a parameter and fetches a single post from the database. In addition to the postID parameter passed to this method, you realized the addition of an extra method named ValidateObjectId(). This method implements the PipeTransform interface from Nest.js. Its purpose is to validate and ensure that the postID parameter can be found in the database. You will define this method in the next section.

      • addPost(): This method will handle a POST HTTP request to add a new post to the database.

      To be able to edit and delete a particular post, you will need to add two more methods to the blog.controller.ts file. To do that, include the following editPost() and deletePost() methods directly after the addPost() method you previously added to blog.controller.ts:

      ~/blog-backend/src/blog/blog.controller.ts

      
      ...
      @Controller('blog')
      export class BlogController {
          ...
          @Put('/edit')
          async editPost(
              @Res() res,
              @Query('postID', new ValidateObjectId()) postID,
              @Body() createPostDTO: CreatePostDTO
          ) {
              const editedPost = await this.blogService.editPost(postID, createPostDTO);
              if (!editedPost) throw new NotFoundException('Post does not exist!');
              return res.status(HttpStatus.OK).json({
                  message: 'Post has been successfully updated',
                  post: editedPost
              })
          }
      
      
          @Delete('/delete')
          async deletePost(@Res() res, @Query('postID', new ValidateObjectId()) postID) {
              const deletedPost = await this.blogService.deletePost(postID);
              if (!deletedPost) throw new NotFoundException('Post does not exist!');
              return res.status(HttpStatus.OK).json({
                  message: 'Post has been deleted!',
                  post: deletedPost
              })
          }
      }
      

      Here you have added:

      • editPost(): This method accepts a query parameter of postID and will carry out the functionality of updating a single post. It also made use of the ValidateObjectId method to provide proper validation for the post that you need to edit.

      • deletePost(): This method will accept a query parameter of postID and will delete a particular post from the database.

      Similarly to the BlogController, each of the asynchronous methods you have defined here has a metadata decorator and takes in a prefix that Nest.js uses as a routing mechanism. It controls which controller receives which requests and points to the methods that should process the request and return a response respectively.

      For example, the BlogController that you have created in this section has a prefix of blog and a method named getPosts() that takes in a prefix of posts. This means that any GET request sent to an endpoint of blog/posts (http:localhost:3000/blog/posts) will be handled by the getPosts()method. This example is similar to how other methods will handle HTTP requests.

      Save and exit the file.

      For the complete blog.controller.ts file, visit the DO Community repository for this application.

      In this section, you have created a module to keep the application more organized. You also created a service to handle the business logic for the application by interacting with the database and returning the appropriate response. Finally, you generated a controller and created the required methods to handle HTTP requests such as GET, POST, PUT, and DELETE from the client side. In the next step, you'll complete your back-end setup.

      You can identify each post in your blog application by a unique ID, also known as PostID. This means that fetching a post will require you to pass this ID as a query parameter. To validate this postID parameter and ensure that the post is available in the database, you need to create a reusable function that can be initialized from any method within the BlogController.

      To configure this, navigate to the ./src/blog folder:

      Then, create a new folder named shared:

      In the pipes folder, using your text editor, create a new file called validate-object-id.pipes.ts and open it. Add the following content to define the accepted postID data:

      ~/blog-backend/src/blog/shared/pipes/validate-object-id.pipes.ts

      import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
      import * as mongoose from 'mongoose';
      
      @Injectable()
      export class ValidateObjectId implements PipeTransform<string> {
          async transform(value: string, metadata: ArgumentMetadata) {
              const isValid = mongoose.Types.ObjectId.isValid(value);
              if (!isValid) throw new BadRequestException('Invalid ID!');
              return value;
          }
      }
      

      The ValidateObjectId() class implements the PipeTransform method from the @nestjs/common module. It has a single method named transform() that takes in value as a parameter — postID in this case. With the method above, any HTTP request from the frontend of this application with a postID that can’t be found in the database will be regarded as invalid. Save and close the file.

      After creating both the service and controller, you need to set up the Post model that is based on the BlogSchema. This configuration could be set up within the root ApplicationModule, but in this instance building the model in BlogModule will maintain your application's organization. Open the ./src/blog/blog.module.ts and update it with the following highlighted lines:

      ~/blog-backend/src/blog/blog.module.ts

      import { Module } from '@nestjs/common';
      import { BlogController } from './blog.controller';
      import { BlogService } from './blog.service';
      import { MongooseModule } from '@nestjs/mongoose';
      import { BlogSchema } from './schemas/blog.schema';
      
      @Module({
        imports: [
          MongooseModule.forFeature([{ name: 'Post', schema: BlogSchema }])
       ],
        controllers: [BlogController],
        providers: [BlogService]
      })
      export class BlogModule { }
      

      This module uses the MongooseModule.forFeature() method to define which models should be registered in the module. Without this, injecting the PostModel within the BlogService using @injectModel() decorator wouldn't work. Save and close the file when you have finished adding the content.

      In this step, you've created the complete backend RESTful API with Nest.js and integrated it with MongoDB. In the next section, you'll configure the server to allow HTTP requests from another server, because your frontend application will be running on a different port.

      Step 6 — Enabling CORS

      An HTTP request from one domain to another is often blocked by default, except when specified by the server to allow it. For your front-end application to make a request to the back-end server, you must enable Cross-origin resource sharing (CORS), which is a technique that allows requests for restricted resources on a web page.

      In Nest.js to enable CORS, you need to add a single method to your main.ts file. Open this file in your text editor, which is located at ./src/main.ts, and update it with the following highlighted content:

      ~/blog-backend/src/main.ts

      import { NestFactory } from '@nestjs/core';
      import { AppModule } from './app.module';
      
      async function bootstrap() {
        const app = await NestFactory.create(AppModule);
        app.enableCors();
        await app.listen(3000);
      }
      bootstrap();
      
      

      Save and exit the file.

      Now that you have completed the back-end setup, you'll shift your focus to the frontend and use Vue.js to consume the APIs built so far.

      Step 7 — Creating the Vue.js Frontend

      In this section, you are going to create your front-end application with Vue.js. Vue CLI is a standard tool that allows you to quickly generate and install a new Vue.js project without much hassle.

      To begin, you first need to install the Vue CLI globally on your machine. Open another terminal, and instead of working from the blog-backend folder, navigate to your local project's development folder and run:

      Once the installation process is complete, you'll make use of the vue command to create a new Vue.js project:

      You'll see a short prompt after you've entered this command. Choose the manually select features option, and then select the features you'll need for this project by pressing SPACE on your computer to highlight multiple features. You'll select Babel, Router, and Linter / Formatter.

      Alt Vue project CLI set up

      For the next instructions, type y to use history mode for a router; this will ensure that history mode is enabled within the router file, which will automatically generate for this project. In addition, select ESLint with error prevention only to pick a linter/formatter configuration. Next, select Lint on save for additional Lint features. Then select to save your configuration in a dedicated config file for future projects. Type a name for your preset, like vueconfig.

      Alt Vue.js final CLI set up

      Vue.js will then start creating the application and all its required dependencies in a directory named blog-frontend.

      Once the installation process is complete, navigate inside the Vue.js application:

      Then, start the development server with:

      Your application will be running on http://localhost:8080.

      Alt Vue.js home view

      Since you'll be performing HTTP requests within this application, you'll need to install Axios, which is a promise-based HTTP client for the browser. You'll use Axios here to perform HTTP requests from the different components within the application. Stop the front-end application by hitting CTRL + C from the terminal on your computer and then run the following command:

      Your front-end application will be making an API call to the back-end API on a particular domain from different components within the application. In order to ensure proper structure for this application, you can create a helper file and define the server baseURL.

      To begin, from you terminal still within blog-frontend, navigate to the ./src/ folder:

      Create another folder named utils:

      In the utils folder, using your text editor, create a new file called helper.js and open it. Add the following content to define the baseURL for the back-end Nest.js project:

      ~blog-frontend/src/utils/helper.js

      export const server = {
      
      baseURL: 'http://localhost:3000'
      
      }
      

      By defining a baseURL, you'll be able to call it from anywhere within you Vue.js component files. In the event that you need to change the URL, it will be an easier process to update the baseURL in this file rather than across your application.

      In this section, you installed the Vue CLI, a tool for creating a new Vue.js application. You used this tool to craft the blog-frontend application. In addition, you ran the application and installed a library named Axios, which you will use whenever there is an HTTP call within the app. Next, you will create components for the application.

      Step 8 — Creating Reusable Components

      Now you're going to create reusable components for your application, which is the standard structure for Vue.js applications. The component system in Vue.js makes it possible for developers to build a single, independent unit of an interface that can have its own state, markup, and style. This makes it appropriate for components in Vue.js to be reusable.

      Every Vue.js component contains three different sections:

      • <template>: contains the HTML contents

      • <script>: holds all the basic frontend logic and defines the functions

      • <style>: the stylesheet for each separate component

      First, you'll start by creating a component to create a new post. To do that, create a new folder named post within the ./src/components folder, which will house the necessary reusable components for posts. Then using your text editor, inside the newly created post folder, create another file and name it Create.vue. Open the new file and add the following code, which contains the necessary input fields for submitting a post:

      ~blog-frontend/src/components/post/Create.vue

      <template>
         <div>
              <div class="col-md-12 form-wrapper">
                <h2> Create Post </h2>
                <form id="create-post-form" @submit.prevent="createPost">
                     <div class="form-group col-md-12">
                      <label for="title"> Title </label>
                      <input type="text" id="title" v-model="title" name="title" class="form-control" placeholder="Enter title">
                     </div>
                    <div class="form-group col-md-12">
                        <label for="description"> Description </label>
                        <input type="text" id="description" v-model="description" name="description" class="form-control" placeholder="Enter Description">
                    </div>
                    <div class="form-group col-md-12">
                        <label for="body"> Write Content </label>
                        <textarea id="body" cols="30" rows="5" v-model="body" class="form-control"></textarea>
                    </div>
                    <div class="form-group col-md-12">
                        <label for="author"> Author </label>
                        <input type="text" id="author" v-model="author" name="author" class="form-control">
                    </div>
      
                    <div class="form-group col-md-4 pull-right">
                        <button class="btn btn-success" type="submit"> Create Post </button>
                    </div>          
                </form>
              </div>
          </div>
      </template>
      

      This is the <template> section of the CreatePost component. It contains the HTML input elements required to create a new post. Each of the input fields has a v-model directive as an input attribute. This is to ensure two-way data bindings on each of the form input to make it easy for Vue.js to obtain the user's input.

      Next, add the <script> section to the same file directly following the preceding content:

      ~blog-frontend/src/components/post/Create.vue

      ...
      <script>
      import axios from "axios";
      import { server } from "../../utils/helper";
      import router from "../../router";
      export default {
        data() {
          return {
            title: "",
            description: "",
            body: "",
            author: "",
            date_posted: ""
          };
        },
        created() {
          this.date_posted = new Date().toLocaleDateString();
        },
        methods: {
          createPost() {
            let postData = {
              title: this.title,
              description: this.description,
              body: this.body,
              author: this.author,
              date_posted: this.date_posted
            };
            this.__submitToServer(postData);
          },
          __submitToServer(data) {
            axios.post(`${server.baseURL}/blog/post`, data).then(data => {
              router.push({ name: "home" });
            });
          }
        }
      };
      </script>
      
      

      Here you've added a method named createPost() to create a new post and submit it to the server using Axios. Once a user creates a new post, the application will redirect back to the homepage where users can view the list of created posts.

      You will configure vue-router to implement the redirection later in this tutorial.

      Save and close the file when you are finished editing. For the complete Create.vue file, visit the DO Community repository for this application.

      Now, you need to create another component for editing a particular post. Navigate to ./src/components/post folder and create another file and name it Edit.vue. Add the following code that contains the <template> section to it:

      ~blog-frontend/src/components/post/Edit.vue

      <template>
      <div>
            <h4 class="text-center mt-20">
             <small>
               <button class="btn btn-success" v-on:click="navigate()"> View All Posts </button>
             </small>
          </h4>
              <div class="col-md-12 form-wrapper">
                <h2> Edit Post </h2>
                <form id="edit-post-form" @submit.prevent="editPost">
                  <div class="form-group col-md-12">
                      <label for="title"> Title </label>
                      <input type="text" id="title" v-model="post.title" name="title" class="form-control" placeholder="Enter title">
                  </div>
                  <div class="form-group col-md-12">
                      <label for="description"> Description </label>
                      <input type="text" id="description" v-model="post.description" name="description" class="form-control" placeholder="Enter Description">
                  </div>
                  <div class="form-group col-md-12">
                      <label for="body"> Write Content </label>
                      <textarea id="body" cols="30" rows="5" v-model="post.body" class="form-control"></textarea>
                  </div>
                  <div class="form-group col-md-12">
                      <label for="author"> Author </label>
                      <input type="text" id="author" v-model="post.author" name="author" class="form-control">
                  </div>
      
                  <div class="form-group col-md-4 pull-right">
                      <button class="btn btn-success" type="submit"> Edit Post </button>
                  </div>
                </form>
              </div>
          </div>
      </template>
      
      

      This template section holds similar content as the CreatePost() component; the only difference is that it contains the details of the particular post that needs to be edited.

      Next, add the<script> section directly following the </template> section in Edit.vue:

      ~blog-frontend/src/components/post/Edit.vue

      ...
      <script>
      import { server } from "../../utils/helper";
      import axios from "axios";
      import router from "../../router";
      export default {
        data() {
          return {
            id: 0,
            post: {}
          };
        },
        created() {
          this.id = this.$route.params.id;
          this.getPost();
        },
        methods: {
          editPost() {
            let postData = {
              title: this.post.title,
              description: this.post.description,
              body: this.post.body,
              author: this.post.author,
              date_posted: this.post.date_posted
            };
      
            axios
              .put(`${server.baseURL}/blog/edit?postID=${this.id}`, postData)
              .then(data => {
                router.push({ name: "home" });
              });
          },
          getPost() {
            axios
              .get(`${server.baseURL}/blog/post/${this.id}`)
              .then(data => (this.post = data.data));
          },
          navigate() {
            router.go(-1);
          }
        }
      };
      </script>
      
      

      Here, you obtained the route parameter id to identify a particular post. You then created a method named getPost() to retrieve the details of this post from the database and updated the page with it. Finally, you created an editPost() method to submit the edited post back to the back-end server with a PUT HTTP request.

      Save and exit the file. For the complete Edit.vue file, visit the DO Community repository for this application.

      Now, you'll create a new component within the ./src/components/post folder and name it Post.vue. This will allow you to view the details of a particular post from the homepage. Add the following content to Post.vue:

      ~blog-frontend/src/components/post/Post.vue

      <template>
          <div class="text-center">
              <div class="col-sm-12">
            <h4 style="margin-top: 30px;"><small><button class="btn btn-success" v-on:click="navigate()"> View All Posts </button></small></h4>
            <hr>
            <h2>{{ post.title }}</h2>
            <h5><span class="glyphicon glyphicon-time"></span> Post by {{post.author}}, {{post.date_posted}}.</h5>
            <p> {{ post.body }} </p>
      
          </div>
          </div>
      </template>
      

      This code renders the details of a post that includes, title, author, and the post body.

      Now, directly following </template>, add the following code to the file:

      ~blog-frontend/src/components/post/Post.vue

      ...
      <script>
      import { server } from "../../utils/helper";
      import axios from "axios";
      import router from "../../router";
      export default {
        data() {
          return {
            id: 0,
            post: {}
          };
        },
        created() {
          this.id = this.$route.params.id;
          this.getPost();
        },
        methods: {
          getPost() {
            axios
              .get(`${server.baseURL}/blog/post/${this.id}`)
              .then(data => (this.post = data.data));
          },
          navigate() {
            router.go(-1);
          }
        }
      };
      </script>
      

      Similar to the <script> section of the edit post component, you obtained the route parameter id and used it to retrieve the details of a particular post.

      Save and close the file when you are finished adding the content. For the complete Post.vue file, visit the DO Community repository for this application.

      Next, to display all the created posts to users, you will create a new component. If you navigate to the views folder in src/views, you will see a Home.vue component — if this file is not present, use your text editor to create it, add the following code:

      ~blog-frontend/src/views/Home.vue

      <template>
          <div>
      
            <div class="text-center">
              <h1>Nest Blog Tutorial</h1>
             <p> This is the description of the blog built with Nest.js, Vue.js and MongoDB</p>
      
             <div v-if="posts.length === 0">
                  <h2> No post found at the moment </h2>
              </div>
            </div>
      
              <div class="row">
                 <div class="col-md-4" v-for="post in posts" :key="post._id">
                    <div class="card mb-4 shadow-sm">
                      <div class="card-body">
                         <h2 class="card-img-top">{{ post.title }}</h2>
                        <p class="card-text">{{ post.body }}</p>
                        <div class="d-flex justify-content-between align-items-center">
                          <div class="btn-group" style="margin-bottom: 20px;">
                            <router-link :to="{name: 'Post', params: {id: post._id}}" class="btn btn-sm btn-outline-secondary">View Post </router-link>
                             <router-link :to="{name: 'Edit', params: {id: post._id}}" class="btn btn-sm btn-outline-secondary">Edit Post </router-link>
                             <button class="btn btn-sm btn-outline-secondary" v-on:click="deletePost(post._id)">Delete Post</button>
                          </div>
                        </div>
      
                        <div class="card-footer">
                          <small class="text-muted">Posted on: {{ post.date_posted}}</small><br/>
                          <small class="text-muted">by: {{ post.author}}</small>
                        </div>
      
                      </div>
                    </div>
                  </div>
            </div>
          </div>
      </template>
      
      

      Here, within the <template> section, you used the <router-link> to create a link for editing as well as for viewing a post by passing the post._id as a query parameter. You also used the v-if directive to conditionally render the post for users. If there is no post from the database, a user will only see this text: No post found at the moment.

      Save and exit the file. For the complete Home.vue file, visit the DO Community repository for this application.

      Now, directly following the </template> section in Home.vue, add the following </script> section:

      ~blog-frontend/src/views/Home.vue

      ...
      <script>
      // @ is an alias to /src
      import { server } from "@/utils/helper";
      import axios from "axios";
      
      export default {
        data() {
          return {
            posts: []
          };
        },
        created() {
          this.fetchPosts();
        },
        methods: {
          fetchPosts() {
            axios
              .get(`${server.baseURL}/blog/posts`)
              .then(data => (this.posts = data.data));
          },
          deletePost(id) {
            axios.delete(`${server.baseURL}/blog/delete?postID=${id}`).then(data => {
              console.log(data);
              window.location.reload();
            });
          }
        }
      };
      </script>
      
      

      Within the <script> section of this file, you created a method named fetchPosts() to fetch all posts from the database, and you updated the page with the data returned from the server.

      Now, you'll update the App component of the front-end application in order to create links to the Home and Create components. Open src/App.vue and update it with the following:

      ~blog-frontend/src/App.vue

      <template>
        <div id="app">
          <div id="nav">
            <router-link to="/">Home</router-link> |
            <router-link to="/create">Create</router-link>
          </div>
          <router-view/>
        </div>
      </template>
      
      <style>
      #app {
        font-family: "Avenir", Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        color: #2c3e50;
      }
      #nav {
        padding: 30px;
        text-align: center;
      }
      
      #nav a {
        font-weight: bold;
        color: #2c3e50;
      }
      
      #nav a.router-link-exact-active {
        color: #42b983;
      }
      </style>
      

      Apart from including the links to both Home and Create components, you also included the <Style> section, which is the stylesheet for this component and holds the definition of styles for some of the elements on the page. Save and exit the file.

      You have created all the required components for your application in this step. Next, you will configure the router file.

      Step 9 — Setting Up Routing

      After creating all the necessary reusable components, you can now properly configure the router file by updating its content with links to all the components you've created. This will ensure that all endpoints within the front-end application are mapped to a particular component for appropriate action. Navigate to ./src/router.js and replace its content with the following:

      ~blog-frontend/src/router.js

      import Vue from 'vue'
      import Router from 'vue-router'
      import HomeComponent from '@/views/Home';
      import EditComponent from '@/components/post/Edit';
      import CreateComponent from '@/components/post/Create';
      import PostComponent from '@/components/post/Post';
      
      Vue.use(Router)
      
      export default new Router({
        mode: 'history',
        routes: [
          { path: '/', redirect: { name: 'home' } },
          { path: '/home', name: 'home', component: HomeComponent },
          { path: '/create', name: 'Create', component: CreateComponent },
          { path: '/edit/:id', name: 'Edit', component: EditComponent },
          { path: '/post/:id', name: 'Post', component: PostComponent }
        ]
      });
      

      You imported Router from the vue-router module and instantiated it by passing the mode and routes parameters. The default mode for vue-router is a hash mode, which uses the URL hash to simulate a full URL so that the page won't be reloaded when the URL changes. In order to make the hash unnecessary, you have used history mode here to achieve URL navigation without a page reload. Finally, within the routes option, you specified the path for the endpoint — a name for the route and the component that should be rendered when the route is called within the application. Save and exit the file.

      Now that you have set up routing to the application, you need to include the Bootstrap file to help with pre-built styling for the user interface of the application. To achieve that, open ./public/index.html file in your text editor and include the CDN file for Bootstrap by adding the following content to the file:

      ~blog-frontend/public/index.html

      <!DOCTYPE html>
      <html lang="en">
      <head>
        ...
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
        <title>blog-frontend</title>
      </head>
      <body>
         ...
      </body>
      </html>
      

      Save and exit the file, and then restart the application with npm run serve for your blog-frontend, if it is not currently running.

      Note: Ensure that both the back-end server and the MongoDB instance are running as well. If otherwise, navigate to the blog-backend from another terminal and run npm run start. Also, start the MongoDB service by running sudo mongod from a new terminal as well.

      Navigate to your application at: http://localhost:8080. Now you can test your blog by creating and editing posts.

      Alt Create a new post

      Click on Create on your application to see the Create Post screen, which relates to and renders the CreateComponent file. Enter values into the input fields and click on the Create Post button to submit a post. Once you are done, the application will redirect you back to the homepage.

      The homepage of the application renders the HomeComponent. This component has a method that sends an HTTP call to fetch all posts from the database and displays them to users.

      Alt View all posts from the database

      Clicking on the Edit Post button for a particular post will take you to an edit page where you can incorporate any changes and save your post.

      Alt Edit a new post

      In this section, you configured and set up routing for the application. With this in place, your blog application is ready.

      Conclusion

      In this tutorial, you have explored a new way of structuring a Node.js application by using Nest.js. You created a simple blog application using Nest.js to build the back-end RESTful API and used Vue.js to handle all the front-end logic. Furthermore, you also integrated MongoDB as a database for your Nest.js application.

      To learn more about how to add authentication to your application, you can make use of Passport.js, a popular Node.js authentication library. You can learn about Passport.js integration in the Nest.js documentation.

      You can find the complete source code for this project here on GitHub. For more information about Nest.js, you can visit the official documentation.



      Source link

      Keep Your Blog Fresh: How to Repurpose Old Posts


      I’m just going to throw this out there: dealing with old content on your website has a lot more in common with cleaning out your sock drawer than you’d think.

      Yes, socks. Hear me out.

      No one ever wants to clean out the sock drawer, and while you’re procrastinating, those old, hole-ridden, stinky socks are piling up, taking up precious real estate. As the stinkers take up more space, it gets harder to find the fresh, new socks you actually want to wear.

      When you have dated material clunking up your website, it’s not as easy for people to find the new posts you want to show off. Just like a little spring cleaning goes a long way, you’ll want to do the same for your website. It isn’t quite as bad a chore as you’d expect,  and the benefits are tenfold.

      Here’s why you should keep your blog fresh — and a guide on what to do with those old posts.

      Do I Really Need to Go Through Old Content?  

      The answer is a big ‘yes.’

      “Your blog is a reflection of your company,” says Kathryn Marr, co-founder of digital marketing and web development company, Blue Ivory Creative. “It shows that you’re knowledgeable in your industry, provides valuable information that keeps potential clients interested, and is one of the keys to a successful SEO strategy. So if you haven’t posted in a while and if your content is outdated or incorrect, then you’re not making the most of an extremely valuable tool. Plus, depending on your site, it can result in decreased search engine rankings and potential liabilities.”

      Just imagine if someone finds your site and clicks on an old post that is riddled with outdated information. Do you think that visitor will take your site — and potentially your business — seriously after that?

      If someone spots numbers or statistics that are no longer correct, he might assume you’re either not knowledgeable about your industry, or you don’t care about the information you present to potential clients.

      “Internet users move quickly,” says Phil Weaver, CMO of Learning Success. “Often they may land on a post from a search query and not realize that the post is very old. If the post is no longer accurate, this may reflect badly on the company. This problem can be magnified if the post gets a lot of search engine traffic, slowly eating away at the company’s reputation. Inaccurate posts that get traffic can taint the company image in the minds of visitors to that page. This could be a problem that adversely affects a company for a long period, damaging company image without the cause being discovered.”

      Another reason to update your site regularly is old posts can be bad for SEO. “Google does like to see a history of great, consistent content so, in a lot of ways, old blog posts are beneficial to SEO, if they’re high-quality, relevant, and well-optimized,” Marr says. “But, there are three scenarios in which old posts can hurt you.”

      1. If your blog itself is old and hasn’t been updated in a long time, Google will see those way-back-there publishing dates and push you to the bottom of search results. That’s why updating those old posts and writing new ones consistently is key.
      2. Your old posts could have been optimized for outdated SEO standards that now have penalties associated with them. For example, before 2011, keyword stuffing — that’s adding as many keywords as possible into your content — was encouraged, but now it’s bad practice and can lead to Google penalties.
      3. With older posts, you may have been trying to rank for different keywords. However, Google can only display so many of your site pages and posts on the top few pages of their search engine, which can make it more difficult for your relevant, targeted posts to rank well.

      Plus, updating content is a lot more cost-effective than to create new content constantly.

      “Content creation is a very resourceintensive process,” Weaver says. “Each old post should be considered a business asset. Just like any business asset, old posts should be maintained to get the maximum benefit from that asset.”

      A common mistake is people thinking the more content they have up on their site, the better, so that’s why they don’t pay attention to older posts. But the truth is, it should always be about quality over quantity.

      “There’s this content marketing myth that goes something like this: Post as often as you can to get more traffic,” says Camilla Hallstrom, content marketing consultant at Influence With Content. “Sure, that might have worked five years ago, and yes, it might still work today, to some extent. But quality rules. People engage more with quality content, and it’s the best way to build a brand they love. After all, there’s a lot of noise online. The only way to stand out is to create something worth caring about. And that’s why updating content is so important. Quality takes time, and the only way to ensure all your content is top-notch is to focus on a smaller pool of content.”

      How Often Do You Need to Update Your Content?

      The answer can vary according to the type of work you do and the nature of your site, but a good rule of thumb is to do a thorough review annually.

      “I recommend content managers try to complete a full content audit once a year, provided your catalog isn’t thousands of articles deep,” says Sam Warren, marketing director at RankPay. “The larger your catalog, the more likely it is that you’ll want to develop a process for rolling updates in lieu of taking a project-based approach.”

      If your industry is competitive, fast-moving, or frequently has innovations, then you’ll probably need to update your content more often to give yourself an edge — particularly in industries such as law, finance, and marketing.

      “Why? Think about how you use Google or any other search engine,” Hallstrom says. “When you search for something, you have lots of options, so you need to decide which headline to click on. It’s much likelier that you’ll click on something that was published or updated recently than something that was last updated four years ago. And if you have a headline like ‘The 7 Best Computers (2018 Edition),’ that’s a lot more compelling than a generic headline like ‘The 7 Best Computers’ because it’s so much more specific to you as the user.”

      Also, if there’s a significant breakthrough, an innovation or something similar, Hallstrom suggests updating your content within the next month or so.

      How Do You Choose Which Posts to Update?

      While updating a post might sound like a lot of work to you, think of the time and effort that you’ve already put into your content. Sometimes just a few text tweaks or new images is all you need to make old posts fresh and relevant again. Here’s how to decide which are worth revamping.

      Measure Analytics

      “You might have more than a few blog posts on your site, and in that case, it doesn’t make sense to update all your content on a regular basis,” Hallstrom says. “Instead, check your analytics once in a while (at least every 12 months) to identify your top content.” That means content that gets traffic, content that could get traffic in the future, and content that converts.

      You can check this with tools like Google Analytics; Be sure to add conversions to the analytics you’re tracking. You’ll want to update posts that are already ranking high on Google to ensure you maintain your spot, posts that are close to ranking high (since just a few updated tweaks can increase their standing) and posts that once got a lot of attention on social media — since they’re no longer fresh and relevant, they aren’t being shared anymore.

      Research Your Industry

      Take the time to see what’s new in your field. Any news might be worth updating your content to include. “Then, research your competition,” Hallstrom says. “Has new content been published that outranks you on Google?”

      Check Your User Metrics

      See how people interact with your content, including how much time is spent on pages and bounce rates. This can be found via Google Analytics. If that engagement is low, there are updates you can make to improve it. Also, check user comments to see if people have questions about your content — you’ll want to add answers to your refresh. “You can also use user metrics to improve your conversions,” Hallstrom says. “If your content isn’t converting as it should, these metrics will help you understand why and what you can do to improve it.”

      Conduct an SEO Analysis

      Make sure your SEO is up to date by checking keyword analytics to ensure you use the right keywords since search habits can change over time. “The insights you get from your user metrics will help you decide if your content needs to be optimized for engagement,” Hallstrom says. “Remember, this is an important metric for Google! Use Google Search Console to see what keywords people use to find your content and to check your click-through rates. These metrics can pinpoint if your SEO titles need updates.”

      What’s the Best Way to Update Older Posts?

      Not every refresh is equal. Some will require more heavy lifting than others, and use the information you found during your research to help you determine exactly what that makeover should look like.

      “Use the insights you’ve gained to improve your titles, texts, and images,” Marr says. “For example, maybe there’s new data you can use to include in a graph? Update your SEO and improve the user experience, if possible. You want your posts to have accurate information, be optimized strategically for specific keywords, and contain relevant photos. Each post should play a role in your overall marketing strategy, and refreshing them to fit into your strategy can make them even more valuable.”

      Keep these approaches to recycling old content in mind:

      • Turn old posts into infographics. “Use the content and statistics from your blog post to create an easy-to-understand visual infographic,Marr says. “These are great for generating social shares — especially on platforms like Pinterest — and for presenting your information quickly.”
      • Get new facts. Update old posts with new information, such as current statistics and news. Add relevant details that might not have been around when the original post was created.
      • Refresh for social. “If it did really well in social media then what we generally do is look over the post and see how we can improve it,” Weaver says. “Are the resources still fresh? Are there others we can add? Has more information come to light over this time frame? Are our call to actions good? Do we have a strong lead and kicker? We do everything we can to improve the article, and then we repost.” And don’t forget to promote it again.
      • Create “best of” posts. Consider this your version of a greatest hits album. This is a way to categorize collections of old posts and make them feel fresh again, and could be anything from ‘Our Top 20 Marketing Tips’ or ‘Best How-To Arrange Flowers Posts of 2017.’
      • Film a video for an old post. “This works really well for tutorials, recipes, and similar types of posts,” Marr says. “Film a video walking your readers through something you described in a blog post. Then, share it on your social media accounts and add it to the old post for more engagement.”
      • Do a mini makeover. “If it is good information, but it did not do exceptionally well, then we closely look at the title and image,” Weaver says. “We will likely rewrite the title and replace the image.” You’ll be amazed at what a difference this can make. Catchy, clickable images don’t just make a post more visual — it also makes it much more likely to be shared on social media.
      • Enable rich snippets on your blog. “These provide additional information that will show up on search engines like reviews, author information, etc.,” Marr says.

      How Can You Use Old Posts to Improve SEO?

      A refreshed old post can be just as valuable as a brand new post. “Consistent, high-quality posts are critical for a good SEO strategy,” Marr says. “Optimizing them for specific, strategic keywords, adding alt tags to images, and increasing the length and quality of content can go a long way to making that content rank. You can also use old evergreen posts to drive traffic through social media and email marketing.”

      Using a keyword tool, such as Ahrefs or Buzzsumo, Warren recommends taking a look at how the keyword landscape has shifted for each piece of content.

      “Maybe your original keyword has lost significant volume, or maybe a competitor came in and created something even better than your original piece,” he says. “Whatever the cause, it’s often going to be worth the effort to identify the most promising keywords that the old content can rank for and then go after them.”

      Other ways to boost SEO is increasing the post length, adding optimized meta descriptions and titles, avoiding outdated SEO practices like keyword stuffing, linking to related posts that your audience might find interesting and useful, and adding compelling images and set up alt tags both for search engines and accessibility.

      Of course, while SEO is essential for driving traffic, you also want to focus on engagement.

      “To make sure your content is as engaging as it gets, it needs to be valuable, and most often, that means you need to write long-form content so that you have room to include everything you want to talk about,” Hallstrom says.

      “Your content needs to be easy to read and skim through — simple words, short sentences, and short paragraphs,” she adds. “Make sure you offer an amazing user experience. That’s what makes Google happy no matter how many times it changes algorithms.”

      Don’t Forget to Toot Your Own Horn (Again)

      Once your old-is-new-again content is refreshed, it’s time to promote it. “Old posts can drive new traffic by putting them on a similar promotion schedule as new posts,” Weaver says. “Plus, the social sharing links already showing shares from the last go-around looks good to new visitors and may incite more shares.

      How you promote refreshed content is largely dependent on the channel you use. For social media, it is usually appropriate to promote it in the same way you promote new content. Since your social media audience is constantly changing, it’s likely that many of your followers did not see the post the first time around.

      For others that did see it, it is very likely that they have forgotten or vaguely remember and are happy to engage with that content again.”

      For email lists, it’s better to only send to subscribers who have not previously opened an email promoting that content. And depending on the design of your site, you can push the revamped content to the front page again.

      Other ways to spread the word? Here are Marr’s suggestions:

      • Link to your old blog posts in new blog posts.
      • Reach out to bloggers and influencers who might be willing to share your posts with their audience.
      • Link to the posts in guest posts that you write for other sites.
      • Promote the stories as “with new content!” or “now updated!” on social.
      • Create “best of” posts that highlight categorized old posts.

      Whether new or old, you always want to attract the right traffic, so target your audience. “To ensure your content is attracting your target audience, you should check your analytics and ask yourself: ‘How do people find my content?’” says Hallstrom. “If you notice that a lot of site visitors find your content on Google, you’ll want to check what keywords they use. If those keywords are irrelevant to your products and services, you probably want to improve your SEO. Or, maybe you get traffic from a social media site like Twitter, but your audience hangs out on Pinterest. Then, you can update it to attract Pinterest users, so optimize your images and copy for Pinterest.”

      How Can You Give Your Blog Posts a Longer Shelf Life?

       There are a few tricks of the trade to avoid having to update your content as frequently. “If you create evergreen content from the get-go, you don’t have to worry as much about updating it,” Hallstrom says. “Make sure your content is the best content on your topic. Take a look at content that’s already out there. How can you make something that’s even better?”

      To help content last longer, avoid seasonal posts or content with a short time-frame of relevance. “Think about what people will want to read in five years,” Marr says. “Put the time into creating high-quality content that you’re going to be proud of years from now.”

      But ultimately, Warren advises against trying to make your posts last forever.

      “Often, being timely and current with your content will help it take off. You could try to remove popular culture references, dates, and other things to prolong shelf-life. But don’t diminish the potential impact of your content today in the hopes of avoiding refreshing it later.”

      Another way to consider it is approaching it from the vantage point of a visitor to your site. “Although many site owners feel that updating blog content is a nuisance, it can actually have a very high ROI,” Weaver says. “Site owners think content is old news, but for a site visitor, the content is new.”

      And while it might seem like deleting an old post is a quick fix, think again. “It’s important that you’re very careful when deleting old blog posts as it can affect your search engine rankings,” cautions Marr.

      “You should consider deleting an old blog post if it is no longer relevant nor can it be made relevant, the post is generating very low traffic or had negative responses, your services or products changed and the blog post is about old offerings,” she says. “Most of the time, though, it’s really best to repurpose and update the content. Don’t just delete blog posts to delete them. Have a good reason, backed by research, for removing that post.”

      That philosophy should apply to how you approach all the content on your site.

      “One of the biggest things that I can stress is to coordinate all of your blog post changes with an overarching website strategy,” Marr says. “And when you repurpose a post, do it in a way that really fits your business plan. For example, a video might not appeal to your audience, but an infographic might resonate really well!”

      Hopefully, the many perks of refreshing old posts will convince you that cleaning out your sock drawer isn’t so bad after all.

      Just like you won’t have to buy as many new socks, you don’t have to produce new content all the time either. “Instead, you ensure your existing content is the best of the best,” Hallstrom. “It takes some work up front, but you’ll be reaping the rewards for years to come.”

      Refreshed Content? Check!

      Now get everything you need to take your website to the next level. DreamHost plans start at $2.59/mo.



      Source link

      A Beginner’s Guide to Crafting the Perfect Blog — From Site Creation to Broadcasting Your Brand


      Back in the day, blogging essentially amounted to taking the stage in an empty theater. The spotlight shone on you as you stood behind the microphone and embarked on a soliloquy about your day. Maybe your dog did something funny and adorable, or perhaps you had a handful of vacation stories and photos to share. Maybe your aging water heater finally keeled over and died, setting off a tragically comedic series of home improvement projects.

      The availability and accessibility of personal web space in the mid-2000s gave rise to countless bloggers — but not many readers or business opportunities. Blogs typically added up to online diaries shared among close friends and family members, words thrown into the ether.

      via GIPHY

      Over the last several years, however, blogging has shifted from a self-serving ritual to an often fruitful endeavor. Several top blogs have turned into leading voices of industry and now amass hundreds of thousands of dollars each month.

      But blogging success isn’t just reserved for the Arianna Huffingtons of the world. From personal finance and fitness to food and fashion, individual writers can use their voice (well, their fingers and keyboard) to build a brand and expand it into a livelihood.

      However, don’t let the technical aspects of creating an online presence weigh you down or prevent you from starting. Coming up with your blogging idea and goals is plenty intimidating; once you’ve overcome that big hurdle, take a look at the steps we’ve outlined below to see how to make your dream a reality.

      Step 1: Pick Your Platform

      You know what you want to say, but how will anyone hear you? Your new blogging venture will face a critical early test when you choose which venue to share your point of view. While the writing, editing, and publishing features found in most blogging platforms are mostly the same, your experience and effectiveness will be significantly impacted.

      Website builders offer a beginner-friendly way to get online, but many of the big-name services tend to emphasize drag-and-drop design over providing a substantive and dynamic writing environment. Blogging is a bit of an afterthought, more of an extra feature thrown into the mix.

      Third-party publishing platforms like Blogger, Tumblr, or Medium emphasizes content and community, but it’s easy for authors to get lost in the crowd. Your brand becomes absorbed by the platform displaying your work.

      Even though all these options come with free or low-cost options, expenses can get a bit out of hand once you add the features you need to be successful (a custom domain name, for instance). You tend not to have as much flexibility as you’d think.

      Worst of all, those platforms own your content. The proprietary programs often make it difficult for you to download your content, and you won’t be able to transfer your site anywhere else without completely rebuilding. Granted, the companies mentioned likely aren’t disappearing anytime soon, but even promising startups can vanish in the blink of an eye — and take your blog with them.

      Turning to an open-source content management system like WordPress immediately solves all these woes. This free software powers nearly a third of the web, making it the most popular and trusted publishing tool.

      With a history rooted in blogging, WordPress balances writing tools with beautiful customizable designs (that will soon get even easier to use with the debut of Gutenberg and blocks). Both hobbyists and Fortune 500 companies use WordPress to build their brand and foster interactions with readers. You maintain complete control over your site and content. Trust us: go with WordPress.

      Want to learn more about WordPress? Check out our WordPress tutorials.

      Step 2: Set the Stage With a Domain Name and Hosting

      Although you can dip a toe into WordPress by using the all-in-one WordPress.com, we think self-hosted WordPress (found at WordPress.org) is the way to go. Hosting your website files with a trusted provider like DreamHost gives you extra security and stability, along with unlimited growth opportunities and friendly support.

      What’s the difference between WordPress.com and WordPress.org? Turns out, it’s big, especially when you want full control over your website.

      Most new bloggers will be well served with a shared web hosting plan. The configuration is the thankfully the cheapest option, but smaller price tags can open the door for performance issues or crummy customer service, depending on your provider.

      Instead of signing up with a generic web hosting plan, explore the specialized features WordPress hosting introduces. If you’re worried about the tech stuff becoming too involved or complicated, purchase managed WordPress hosting and let the experts take care of it. For more information on the similarities and differences between traditional web hosting and the managed WordPress variety, check out this resource from HostingAdvice.com.

      Once hosting is acquired, it’s time to take the first big, demonstrable step in establishing your blog! Many new hosting accounts, including ones through DreamHost, come with a free domain name registration. This is the URL your readers will associate with you and your content, so you’ll want to make this count! Hopefully, you already have a brand name in mind, but don’t be crushed if it’s not available as a domain. Some tips to consider when domain shopping:

      • Use descriptive keywords to describe your blog
      • Look for something short, pronounceable, and easy to spell
      • Avoid hyphens and other punctuation
      • Don’t be afraid to try different domain extensions
      • See if your name is also available on social media
      • Make sure there are no trademark or copyright infringements

      Step 3: Find a Theme and Customize Your Look

      Many hosts have simplified the WordPress installation process to just a click or two, but DreamHost has even eliminated that step. We’ll install WordPress for you, along with a handful of rock-solid themes and plugins to get you started. Finding the right theme or design is critical for your blog’s success, as it connects your readers with your content and quickly informs their first impression of your brand.

      Instead of getting bogged down in color schemes and typography, focus on functionality. Good blog themes should make your content easy to find. As such, pay attention to the information you display above the fold:

      • Is your navigation menu there?
      • What about a search box?
      • Recent or popular posts?

      Don’t feel like you need to make some big splash with your theme — clean, simple, useful designs always win.

      Obviously, your blog’s landing page and individual posts will garner the lion’s share of looks, but don’t forget about creating a visually engaging and useful design for an about page and a contact page. An about page helps build trust with your readers and enables you to share your personality and credentials, along with the blog’s mission and aspirations.

      Your theme and your content should work together and add value, not compete for attention. Fonts should be large and readable. Make sure the responsive or mobile-friendly versions of your site don’t hide important information on smaller screens. Instead of playing with the fun parts of web design, such as colors, imagery, and animations, concentrate on user experience. After all, your blog’s design is for your readers, not you!

      Step 4: Construct a Keyword-Driven Content Strategy

      Sure, you know you want to blog. But are you sure you’re treating this as a possible business venture and source of income (and not as a self-satisfying bout of verbal preening)? Briefly put your writing talents aside and come up with a business plan for your blog that avoids these common mistakes.

      For instance, how often do you plan on publishing a new post? Temper the initial excitement and avoid committing to an unsustainable writing schedule. Seek consistency, both in terms of frequency and tone. Your personality and chosen topic area will likely shape the voice you naturally bring to your content, but don’t lose sight of your target audience. Your readers’ demographics, locations, interests, and habits all offer hints as to what information will be the most useful and entertaining.

      Take the guesswork out of your writing prompts by engaging in a healthy bit of keyword research. In addition to the obvious benefits to search engine optimization and higher rankings, keyword research reveals what your target audience is actually looking for. Your blog might be the best content on the web, but it’s all largely for naught if Google can’t find it. If a tree falls in the forest and no one is around to hear it, does it make a sound?

      Instead of jumping straight into the deep end with high-value — and highly competitive — broad search terms, identify a handful of more specific searches that you can build a base around. Don’t write content around the area’s best restaurants; craft your posts around, say, the coziest Italian restaurant that’s the best spot to bring a date. The experts at Moz do a great job of explaining a straightforward, easy-to-follow method of keyword research.

      Step 5: Work Ahead With Writing

      Once you have a healthy list of topics to explore, it’s time to finally get to work! Are you surprised that writing is such a small part of establishing a successful blog? Because writing is theoretically the part that comes most natural to you, we’re just helping establish the guidelines through which to funnel your creativity and steer your success.

      For starters, you’ll want to publish a few posts before you officially launch your blog. Give readers a glimpse of what they can expect from your brand by covering a handful of topics in the voice and tone you envision using for the long haul. This enables your visitors to connect with you more personally and gain insights and information beyond the generic, “Hey, I started a blog” post.

      via GIPHY

      You might be chomping at the bit to get started blogging, but channel that excitement in ways that will keep that momentum going long after the initial rush wears off. In addition to the three to five posts you’ll publish, try to have another five to 10 posts written and saved in drafts. Beyond that, maintain a list of ideas or keywords you’ll want to write about in the future. By stocking up on content and topics, you’ll be poised to handle any bout of writer’s block that emerges.

      As for the content itself, find a schedule that works best for you. Publishing only two or three new posts a week is perfectly acceptable (that’s what we aim to do on the DreamHost blog). Daily articles sound great in theory, but first you need to find out if that is the right amount of content for your audience. Then take your time working up to that cadence. Spend the extra time formatting, proofreading, and otherwise perfecting each post.

      Step 6: Build Interactions and Boost Your Following

      Once your new blog is open for business, now it’s time to start attacking the second part of this post’s headline: broadcasting your brand. Just as the quality of your content won’t matter if Google can’t find you, the same can be said for your audience. Ideally, you set up your blog’s social media accounts as you worked on the site and starter content (remember when we listed social media availability as part of a strong domain name?).

      Naturally, you’ll frequently rely on your brand’s social media profiles to share new blog posts, but don’t resort to mindlessly copy/pasting links into your feed. Many of your same content creation and brainstorming exercises for your blog should also be used toward your social media: How can you be engaging, entertaining, and relevant to your followers? Find compelling images and other visual elements to accompany your posts; graphics alone can lead to more than 30 percent more clicks and visits on social media. Pose questions to your readers and lend timely insights into trending issues.

      Be sure to keep in mind that interactions with readers don’t (and shouldn’t) need to happen away from your blog. Social media networks connect broad swaths of people, but the most important audiences to focus on are the ones who have already found you. Turn your readers into brand advocates by creating engaging opportunities to interact and return to your blog. You can bridge the gap by making it easy for visitors to share their favorite post on Facebook and Twitter, of course, but consider allowing them to comment directly on the post — and be sure to respond to their questions and opinions. Doing so humanizes your brand and deepens the relationship with your readers.

      Consider capturing readers’ attention by flipping the relationship. Instead of sitting back and hoping for readers to come to your blog, set up an email newsletter or subscription and collect people’s addresses. That way, you can more actively get your content to the front and center, rather than waiting for someone to browse your blog’s way. This can easily be accomplished with an email marketing platform that provides embeddable code that can be placed in a widget on your blog’s sidebar or footer. Alternatively, consider a WordPress plugin that pops open a window directly asking for engagement. While these can be extraordinarily effective, beware of the fine line between user engagement and dark UX practices.

      Step 7: Analyze Analytics and Tweak Your Tactics

      So now your blog is a buzzing hive of activity. Readers are zipping around from one post to the next. Or maybe they’re checking out your About Page. Or instead of reading a post until the end, they’re just glancing at the headings. Maybe they’re not even opening a post.

      You’ll never know for sure until you look at analytics or the data that shows where visitors come from, how they move around their site, and why they leave. Google Analytics is the go-to (and free!) service that can provide a wealth of information about your audience and your site’s performance. Pageviews can identify your most popular blog post over a certain period, for instance, while a high bounce rate (the percentage of users who leave a site quickly after viewing only one page) may indicate some design or content changes could be in order.

      As you learn how long your readers stay on your blog and where they go, you might discover they don’t interact with your website quite how you anticipated. Find where the common hangups are and make the related tweaks to your navigation menu, read more links, and other interaction points. By solving your first few users’ problems, you’re paving the way for more and more readers.

      Do you have any questions about crafting the perfect blog? Join the DreamHost Community and let’s talk shop!



      Source link