Build a simple blog with Node.js, Express, MongoDB (Part 4)

At first, let's install MongoDB http://blog.alphaplus.vn/2017/08/how-to-install-mongodb-on-ubuntu.html, robomongo (optional) http://blog.alphaplus.vn/2017/08/robomongo-native-and-cross-platform-mongodb-manager.html and postman http://blog.alphaplus.vn/2017/08/postman-complete-api-development.html.

We will use RESTful (REpresentational State Transfer) web services to interact with the resources.
  • GET: receive the resource representation
  • POST: add some information to the resource
  • PATCH: modify the resources
  • DELETE: delete the resources

Why Web Services?

Interoperability - Other applications can also use the web services. For example, a VB, .NET, PHP, Ruby, Python or mobile application can talk to our web services.

We will create 5 different routes in our application:
HTTP Verb Path Used for
GET /posts display a list of all posts
POST /posts create a new post
GET /posts/:id display a specific post
PATCH /posts/:id update a specific post
DELETE /posts/:id delete a specific post

It's easy! Open server.js and add the following:
app.get('/posts', (req, res) => {
  res.send('Display a list of all posts.');
});
app.post('/posts', (req, res) => {
  res.send('Create a new post.');
});
app.get('/posts/:id', (req, res) => {
  res.send(`Display a specific post (ID: ${req.params.id}).`);
});
app.patch('/posts/:id', (req, res) => {
  res.send(`Update a specific post (ID: ${req.params.id}).`);
});
app.delete('/posts/:id', (req, res) => {
  res.send(`Delete a specific post (ID: ${req.params.id}).`);
});


Run the following command:
$ nodemon server.js

Then use postman to check all routes above.

We will use body-parser package https://www.npmjs.com/package/body-parser
This module provides the following parsers:
  • JSON body parser
  • Raw body parser
  • Text body parser
  • URL-encoded form body parser

Run the following command to install:
$ npm install body-parser --save

Add these lines to server.js:
const bodyParser = require('body-parser');
and
app.use(bodyParser.json());

It works as expected? Now we are going to interact with MongoDB, a NoSQL document database.

NoSQL vocabularies

Relational Database NoSQL Database
Database Database
Table Collection
Row/ Record Document
Column Field

Interact with MongoDB

To interact with MongoDB, we use mongodb package https://www.npmjs.com/package/mongodb
$ npm install mongodb --save

Let's create a new post first, then we will display a list of all posts, display a specific post, update a specific post and delete a specific post.

Follow the instruction at https://www.npmjs.com/package/mongodb, we add the following lines to server.js:
const MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/blogs';

(with blogs is the database name and 27017 is the port when set up MongoDB)

Create a new post

Replace
app.post('/posts', (req, res) => {
// ...
});
with the code to insert a document to "posts" collection:
app.post('/posts', (req, res) => {
  MongoClient.connect(url, (err, db) => {
    if (err) {
      res.send("Can't connect to MongoDB.");
    } else {
      db.collection('posts')
        .insertOne({
          title: req.body.title,
          content: req.body.content
        }, (err, result) => {
          if (err) {
            res.send('An error has been occurred while creating a new post.');
          } else {
            res.send(result.ops);
          }
        });
    }
  });
});


Open postman and test:

Use Robomongo to the check new post in the database



Display a list of all posts

Replace:
app.get('/posts', (req, res) => {
// ...
});

with:
app.get('/posts', (req, res) => {
  MongoClient.connect(url, (err, db) => {
    if (err) {
      res.send("Can't connect to MongoDB.");
    } else {
      db.collection('posts')
        .find()
        .toArray((err, docs) => {
          if (err) {
            res.send('An error has been occurred while displaying a list of all posts.');
          } else {
            res.send(docs);
          }
        });
    }
  });
});


Open postman and test:

Display a specific post

"_id" field isn't a string, it's an ObjectId type. So, we add to server.js:
const ObjectId = require('mongodb').ObjectId;

Or we change:
const MongoClient = require('mongodb').MongoClient;
to
const {MongoClient, ObjectId} = require('mongodb');

Then change:
app.get('/posts/:id', (req, res) => {
// ...
});

to
app.get('/posts/:id', (req, res) => {
  MongoClient.connect(url, (err, db) => {
    if (err) {
      res.send("Can't connect to MongoDB.");
    } else {
      db.collection('posts')
        .findOne({_id: new ObjectId(req.params.id)}, (err, doc) => {
          if (err) {
            res.send('An error has been occurred while displaying a specific post.');
          } else {
            res.send(doc);
          }
        });
    }
  });
});

Update a specific post

Change:
app.patch('/posts/:id', (req, res) => {
// ...
});


to:
app.patch('/posts/:id', (req, res) => {
  MongoClient.connect(url, (err, db) => {
    if (err) {
      res.send("Can't connect to MongoDB.");
    } else {
      db.collection('posts')
        .updateOne(
          {_id: new ObjectId(req.params.id)},
          {
            $set: {
              title: req.body.title,
              content: req.body.content
            }
          },
          (err, result) => {
          if (err) {
            res.send('An error has been occurred while updating a specific post.');
          } else {
            res.send(result);
          }
        });
    }
  });
});


Open postman and test:


Open Robomongo to check:


Delete a specific post

Change:
app.delete('/posts/:id', (req, res) => {
// ...
});


to:
app.delete('/posts/:id', (req, res) => {
  MongoClient.connect(url, (err, db) => {
    if (err) {
      res.send("Can't connect to MongoDB.");
    } else {
      db.collection('posts')
        .deleteOne({_id: new ObjectId(req.params.id)}, (err, result) => {
          if (err) {
            res.send('An error has been occurred while deleting a specific post.');
          } else {
            res.send(result);
          }
        });
    }
  });
});


Open postman and test:

Then open Robomongo to check:


OK, that's it.
In part 5, we are going to use https://www.npmjs.com/package/mongoose.

Part 5: http://blog.alphaplus.vn/2017/09/build-simple-blog-with-nodejs-express-mongodb-part-5.html
See you then.

HTTP Status Codes


httpstatuses.com is an easy to reference database of HTTP Status Codes with their definitions and helpful code references all in one place. Visit an individual status code via httpstatuses.com/code or browse the list below.

1×× Informational

100 Continue
101 Switching Protocols
102 Processing

2×× Success

200 OK
201 Created
202 Accepted
203 Non-authoritative Information
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status
208 Already Reported
226 IM Used

3×× Redirection

300 Multiple Choices
301 Moved Permanently
302 Found
303 See Other
304 Not Modified
305 Use Proxy
307 Temporary Redirect
308 Permanent Redirect

4×× Client Error

400 Bad Request
401 Unauthorized
402 Payment Required
403 Forbidden
404 Not Found
405 Method Not Allowed
406 Not Acceptable
407 Proxy Authentication Required
408 Request Timeout
409 Conflict
410 Gone
411 Length Required
412 Precondition Failed
413 Payload Too Large
414 Request-URI Too Long
415 Unsupported Media Type
416 Requested Range Not Satisfiable
417 Expectation Failed
418 I'm a teapot
421 Misdirected Request
422 Unprocessable Entity
423 Locked
424 Failed Dependency
426 Upgrade Required
428 Precondition Required
429 Too Many Requests
431 Request Header Fields Too Large
444 Connection Closed Without Response
451 Unavailable For Legal Reasons
499 Client Closed Request

5×× Server Error

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates
507 Insufficient Storage
508 Loop Detected
510 Not Extended
511 Network Authentication Required
599 Network Connect Timeout Error

Read more https://httpstatuses.com/

Postman - A complete API Development Environment

Postman makes API development faster, easier, and better. Postman is the most complete toolchain for API development. The most-used REST client worldwide. Designed from the ground up to support the API developer. Intuitive user interface to send requests, save responses, add tests, and create workflows.

Intro to API documentation

Postman’s API documentation feature allows you to share public or private API documentation, beautifully viewable via a web page.

Postman generates and hosts browser-based API documentation for your collections automatically in real-time. Each collection has a private and public documentation view, generated in real-time using the data synced to our servers. In order to access the private view, click “View in web” in the Postman app or in the “Team Library”. The public view is accessible via the public link, generated when you publish your documentation. This link will be displayed right after your documentation is published, and is also accessible via the “Published” dropdown in the private documentation view.

What gets automatically generated?

Documentation for your API includes the following:

  • Sample requests, and parameter tables, headers, and other metadata
  • Descriptions associated with requests, folders, and collections
  • Generated code snippets in some of the most popular programming languages

Documentation is organized into sections that reflect the structure of your collection, by ordered requests and folders. Descriptions can be customized using Markdown styling with embedded graphics to complement your documentation. GitHub flavored markdown is also supported, so you can even include tables. When including block elements, ensure that you leave an empty line before and after to avoid any rendering issues.

Download the version for MacOS, Windows or Linux at https://www.getpostman.com/postman
The Google Chrome browser extension is here https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop


Robomongo - Native and cross-platform MongoDB manager

Whatever platform you use today — Robo 3T (formerly Robomongo) is available for you. Distributed as a native application, fast and snappy Robo 3T uses very little of your machine resources.

Since it was launched, Robo 3T (formerly Robomongo) has provided an open source MongoDB tool that provides innovative functionality to meet the needs of enthusiasts and the wider community.

Embeds real MongoDB shell

Robo 3T (formerly Robomongo) doesn't emulate the MongoDB shell, it embeds the same engine and environment, that is a part of mongo shell. Currently it embeds the latest MongoDB 3.2 shell.

Provides real autocompletion

Robo 3T (formerly Robomongo) not only analyzes the semantic of the code, but also executes it in an internal JavaScript VM, allowing us to give you a runtime autocompletion that is impossible to obtain statically.

Fully asynchronous, non-blocking UI

All operations that you perform on MongoDB are done asynchronously and do not block main application thread. This makes Robo 3T (formerly Robomongo) feel light and snappy.

Download at https://robomongo.org/download

Note:
On Ubuntu, if you see this error message in terminal:
This application failed to start because it could not find or load the Qt platform plugin "xcb"
delete libstdc++* from lib folder solved the issue.



How to Install MongoDB on Ubuntu

MongoDB is a free and open-source NoSQL document database used commonly in modern web applications.


Step 1 — Adding the MongoDB Repository

At first, navigate to http://repo.mongodb.org/apt/ubuntu/dists/ and choose your Ubuntu version. The Ubuntu version name is at https://wiki.ubuntu.com/Releases

Then navigate to http://keyserver.ubuntu.com/pks/lookup?op=vindex&search=packaging%40mongodb.com&fingerprint=on, get the key from the version exist on both repo.mongodb.org and keyserver.ubuntu.com. MongoDB 3.4 is my choice.


Run the following command:
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv A15703C6

Create a list file for MongoDB:
$ echo "deb [ arch=amd64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list

Update the package list:
$ sudo apt update

Step 2 — Installing and Verifying MongoDB

Run the following command:
$ sudo apt install -y mongodb-org

Check MongoDB service status:
$ service mongod status

Run MongoDB Community Edition
  • Start:
    $ sudo service mongod start
  • Stop:
    $ sudo service mongod stop
  • Restart:
    $ sudo service mongod restart
Uninstall MongoDB Community Edition
This process will completely remove MongoDB, its configuration, and all databases. This process is not reversible, so ensure that all of your configuration and data is backed up before proceeding.
$ sudo service mongod stop
$ sudo apt purge mongodb-org*
$ sudo rm -r /var/log/mongodb
$ sudo rm -r /var/lib/mongodb


Read MongoDB manual - Installation here https://docs.mongodb.com/manual/installation/#tutorial-installation

Build a simple blog with Node.js, Express, MongoDB (Part 3)

Let's build the "About" page.

About page

At first, edit server.js, add the following:
app.get('/about', (req, res) => {
  res.render('about.hbs');
});


Then create "views/about.hbs" content:
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>About</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://getbootstrap.com/docs/3.3/examples/blog/blog.css">
  </head>
  <body>
    {{> header}}
    <div class="container">
      <div class="blog-header">
        <h1 class="blog-title">About</h1>
        <p class="lead blog-description">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc molestie, velit sed posuere accumsan, velit tellus finibus augue, eu blandit turpis mauris at nisi. Nulla vel quam vel turpis aliquet euismod.</p>
      </div>
      <div class="row">
        <div class="col-sm-8 blog-main">
          <div class="text-justify">
            <p>Nulla bibendum imperdiet finibus. Aenean sit amet sapien risus. Vivamus auctor, orci in fermentum rutrum, nulla sapien scelerisque ligula, in dignissim est odio id nisl. Donec ultrices mollis metus congue malesuada. Mauris pharetra nunc vel nunc malesuada sollicitudin. Nunc sed metus eget lorem faucibus dictum. Mauris sodales cursus ex non laoreet. Proin suscipit velit erat, ac varius nisl lacinia at. Vivamus ultricies molestie eros ac vestibulum. Nulla ornare luctus accumsan. Etiam mollis ornare dolor, ac sagittis quam sollicitudin ac. Nullam iaculis ligula a nibh lacinia tristique. Praesent vulputate dui magna, quis venenatis odio semper nec. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nunc ut elit turpis.</p>
            <p>Donec facilisis venenatis mauris, nec pulvinar odio consectetur quis. Duis ut ante facilisis, feugiat turpis vitae, tempor urna. Nulla ornare venenatis viverra. Donec malesuada, quam quis rutrum sodales, arcu tellus varius mi, sed dignissim est libero ac arcu. Pellentesque sollicitudin est nulla, nec hendrerit tortor congue ac. Nam tristique, nisi eu dignissim lobortis, augue urna blandit lacus, sit amet convallis nulla lorem id urna. Phasellus porta mauris vitae purus ullamcorper, at vulputate est rutrum. Ut non congue ipsum.</p>
          </div>
        </div>
        <div class="col-sm-3 col-sm-offset-1 blog-sidebar">
          {{> archives}}
        </div>
    </div>
    {{> footer}}
  </body>
</html>


Navigate to http://localhost:3000/about, refresh your browser. It works as expected!

Now, I want to dynamic year on the footer (with the current year) and archives on the sidebar (with the dummy array).

To do this, at first, we change the template files


Then also the server.js


You see? Yes, duplicate code!
Duplicate code is a computer programming term for a sequence of source code that occurs more than once, either within a program or across different programs owned or maintained by the same entity. Duplicate code is generally considered undesirable for a number of reasons

To prevent duplicate code, we can write functions:


Our code is clean now, but if we have 100 pages, we copy the highlighted above 100 times. It's terrible!!!
Helpers can resolve our issue.

Helpers

Helpers are used to extract complex logic out of the view so that you can organize our code better. They're included in views, but not in controllers or models.

We register 2 helpers: getArchives and getCurrentYear:
hbs.registerHelper('getArchives', () => {
  return [
    {url: '#', title: 'March 2017'},
    {url: '#', title: 'February 2017'},
    {url: '#', title: 'January 2017'},
    {url: '#', title: 'December 2016'},
    {url: '#', title: 'November 2016'},
    {url: '#', title: 'October 2016'},
    {url: '#', title: 'September 2016'}
  ];
});
hbs.registerHelper('getCurrentYear', () => {
  return new Date().getFullYear();
});


Remove some lines inside server.js

Modify footer.hbs and archives.hbs


Navigate to http://localhost:3000/about, refresh your browser. It works as expected!

Please remember to update the navigation links.

Part 4: http://blog.alphaplus.vn/2017/08/build-simple-blog-with-nodejs-express-mongodb-part-4.html
See you then!

Build a simple blog with Node.js, Express, MongoDB (Part 2)

On home page, I want to display the basic html page as the screenshot bellow

from the HTML:
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Index</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://getbootstrap.com/docs/3.3/examples/blog/blog.css">
  </head>
  <body>
    <div class="blog-masthead">
      <div class="container">
        <nav class="blog-nav">
          <a class="blog-nav-item" href="#">Home</a>
          <a class="blog-nav-item" href="#">About</a>
          <a class="blog-nav-item" href="#">Contact</a>
        </nav>
      </div>
    </div>
    <div class="container">
      <div class="blog-header">
        <h1 class="blog-title">Home</h1>
        <p class="lead blog-description">The official example template of creating a blog with Bootstrap.</p>
      </div>
      <div class="row">
        <div class="col-sm-8 blog-main">
          <div class="blog-post">
            <h2 class="blog-post-title"><a href="">Lorem ipsum dolor sit amet</a></h2>
            <p>Praesent scelerisque nibh mattis dui consectetur elementum. Sed porttitor mi sed fringilla commodo. Aliquam erat volutpat. Quisque nec mauris odio.</p>
          </div>
          <div class="blog-post">
            <h2 class="blog-post-title"><a href="">Aenean feugiat id dui nec sagittis</a></h2>
            <p>Praesent ut neque sed lorem suscipit bibendum. Curabitur at scelerisque augue. Integer sagittis, lacus sit amet semper euismod, turpis lectus mattis magna, sit amet scelerisque orci turpis in tellus</p>
          </div>
        </div>
        <div class="col-sm-3 col-sm-offset-1 blog-sidebar">
          <div class="sidebar-module">
            <h4>Archives</h4>
            <ol class="list-unstyled">
              <li><a href="#">March 2017</a></li>
              <li><a href="#">February 2017</a></li>
              <li><a href="#">January 2017</a></li>
              <li><a href="#">December 2016</a></li>
              <li><a href="#">November 2016</a></li>
              <li><a href="#">October 2016</a></li>
              <li><a href="#">September 2016</a></li>
              <li><a href="#">August 2016</a></li>
              <li><a href="#">July 2016</a></li>
              <li><a href="#">June 2016</a></li>
              <li><a href="#">May 2016</a></li>
              <li><a href="#">April 2016</a></li>
            </ol>
          </div>
        </div>
      </div>
    </div>
    <footer class="blog-footer">
      <p>Copyright &copy; 2017.</p>
    </footer>
  </body>
</html>


How we do?
Copy all and paste as string inside "res.send()"? It's terrible!
Let's use Handlebars.

Handlebars

Handlebars provides the power necessary to let you build semantic templates effectively with no frustration. Handlebars is largely compatible with Mustache templates. In most cases it is possible to swap out Mustache with Handlebars and continue using your current templates.
Read more http://handlebarsjs.com/

https://www.npmjs.com/package/hbs is the Express.js view engine for handlebars.js

To install hbs, open the terminal, then run the following command:
$ npm install hbs --save

Add two lines to your code:
const hbs = require('hbs');
and
app.set('view engine', 'hbs');

Then create "views/home.hbs" file, put all HTML code above to this.
Change res.send() to:
res.render('home.hbs');

Navigate to http://localhost:3000, it works as expected.

Partials

Partials allow you to easily organize and reuse your view code in an application (some blocks appear in more than one page).
Eg:
  1. Header
  2. Archives
  3. Footer


Create "views/partials/header.hbs", "views/partials/archives.hbs", and "views/partials/footer.hbs" then cut the corresponding lines of code to these.

Add
hbs.registerPartials(__dirname + '/views/partials');
to server.js

Update home.hbs, use {{> partialfilename}} to include.

Navigate to http://localhost:3000, it works as expected.

Rendering templates with data

Inside home.hbs, we will loop:
<div class="blog-post">
  <h2 class="blog-post-title"><a href="[URL]">[TITLE]</a></h2>
  <p>[SUMMARY]</p>
</div>

with the data from server.js

We will get items from the database later, now we get from dummy array.

Modify home.hbs, loop the items variable:

Navigate to http://localhost:3000, it works as expected.

Note: instead of
res.render('home.hbs', {
  items: items
});

you should write:
res.render('home.hbs', {
  items
});


Part 3: http://blog.alphaplus.vn/2017/08/build-simple-blog-with-nodejs-express-mongodb-part-3.html
See you then!

Emmet — the essential toolkit for web-developers


Emmet is a plugin for many popular text editors which greatly improves HTML & CSS workflow.

HTML from CSS

You’ve already known how to use Emmet abbreviations: its syntax is inspired by CSS selectors.

Dynamic snippets

Each abbreviation is transformed in runtime: just slightly change its name to get a different result.

Ultra-fast coding

With Emmet you can quickly write a bunch of code, wrap code with new tags, quickly traverse and select important code parts and more!

Customizable

Users can easily add new snippets and fine-tune Emmet experience with just a few JSON files.

Platform for new tools

Dig into Emmet source code and re-use its modules to create your very own and unique actions.

Highly portable

Emmet is written in pure JavaScript and works across different platforms: web browser, Node.js, Microsoft WSH and Mozilla Rhino.

Read more https://emmet.io/

Emmet plugin for Atom editor https://atom.io/packages/emmet

Build a simple blog with Node.js, Express, MongoDB (Part 1)

What are Node.js, Express and MongoDB?

  • Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
    Read more https://nodejs.org/en/
  • Express is a Fast, unopinionated, minimalist web framework for Node.js.
    Read more https://expressjs.com/
  • MongoDB is a document database with the scalability and flexibility that you want with the querying and indexing that you need.
    Read more https://www.mongodb.com/what-is-mongodb

Install Node.js

Node.js is available from the NodeSource Debian and Ubuntu binary distributions repository (formerly Chris Lea's Launchpad PPA). Support for this repository, along with its scripts, can be found on GitHub at nodesource/distributions.

$ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
$ sudo apt install -y nodejs


Optional: install build tools
To compile and install native addons from npm you may also need to install build tools:
$ sudo apt install -y build-essential

If you use one of the following OS:
  • Arch Linux
  • Enterprise Linux and Fedora
  • FreeBSD and OpenBSD
  • Gentoo
  • NetBSD
  • nvm
  • openSUSE and SLE
  • macOS
  • SmartOS and illumos
  • Void Linux
  • Windows

please use this link https://nodejs.org/en/download/package-manager/ to install.

Check the node version with:
$ node -v
My current version is v8.4.0.

npm is distributed with Node.js- which means that when you download Node.js, you automatically get npm installed on your computer.
Check the npm version with:
$ npm -v
My current version is 3.10.10.

Create a blog application

$ mkdir node-blog
$ cd node-blog/
$ npm init


This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults. Enter your information or press enter to use the default information for each key:

  • name: (node-blog) 
  • version: (1.0.0) 
  • description: 
  • entry point: (index.js) 
  • test command: 
  • git repository: 
  • keywords: 
  • author: 
  • license: (ISC) 

If ok, enter 'yes':

  • Is this ok? (yes) yes

The package.json file will be like:
{"name":"node-blog","version":"1.0.0","description":"","main":"index.js","scripts":{"test":"echo "Error:no test specified" && exit 1"},"author":"","license":"ISC"}

Install Express

Run the following command:
$ npm install express --save
Use `npm install <pkg> --save` afterwards to install a package and save it as a dependency in the package.json file.
When you push your project to GIT, you shouldn't push node_modules directory, so please add '--save' afterwards to update the package.json file. When others pull from GIT, they can use
$ npm install
to install all the dependencies.

Hello, Express!

Start up the web server

Create server.js with the basic form:
const express = require('express');

var app = express();

app.get('/', function(req, res) {
  res.send('Hello world!');
});

app.listen(3000);


The Text Editor the screenshot bellow is Atom, read more http://blog.alphaplus.vn/2017/08/atom-hackable-text-editor-for-21st.html

Then run the following command:
$ node server.js

Open your browser, navigate to localhost:3000

Now, please open the Text Editor again, change "world" to "Express", save and refresh your browser.
The browser also sends "Hello world!". It's not correct, because the "node server.js" command we used didn't monitor any changes in your node.js application.
To resolve this issue, we use nodemon https://www.npmjs.com/package/nodemon
nodemon will watch the files in the directory in which nodemon was started, and if any files change, nodemon will automatically restart your node application.

To install nodemon, please run the following command:
$ sudo npm install -g nodemon
And nodemon will be installed globally to your system path
Because we not only use nodemon for this project, but also others, so we install it as global (-g)

Now, open your terminal again, press Ctrl + C to cancel, then run the following command:
$ nodemon server.js

Open your browser again, refresh, then you can see "Hello Express!". Open your Text Editor, change "Express" to your first name, save the file, then refresh your browser, you will see the new change.

Follow ES6, we change "function(req, res)" to "(req, res) =>"
We can also send HTML or javascript object object with res.send method:
HTML:

Javascript object:

Javascript array is OK:
app.get('/', (req, res) => {
  res.send([{
    'id': 1,
    'title': 'Lorem ipsum dolor sit amet',
    'summary': 'Etiam sed ultricies erat. Aliquam a ligula erat. Fusce purus turpis, viverra non vestibulum a, vestibulum in orci.',
  }]);
});


We hard code:
app.listen(3000);

It's not good, the port should be changed in the terminal.
So, create the constant to get the environment port, if not, set it to 3000.
const port = process.env.PORT || 3000;
Then change the line:
app.listen(3000);
to
app.listen(port);

The complete source code:
const express = require('express');

const port = process.env.PORT || 3000;

var app = express();

app.get('/', (req, res) => {
  res.send([{
    'id': 1,
    'title': 'Lorem ipsum dolor sit amet',
    'summary': 'Etiam sed ultricies erat. Aliquam a ligula erat. Fusce purus turpis, viverra non vestibulum a, vestibulum in orci.',
  }]);
});

app.listen(port);


Open the terminal again, press Ctrl + C to cancel.
Then run the following command:
$ PORT=9000 nodemon server.js

Change 9000 to any available port you want, then open the browser with your port, in my case: http://localhost:9000

Part 2: http://blog.alphaplus.vn/2017/08/build-simple-blog-with-nodejs-express-mongodb-part-2.html
See you then!

Atom - A hackable text editor for the 21st Century


Atom is a text editor that's modern, approachable, yet hackable to the core—a tool you can customize to do anything but also use productively without ever touching a config file.

Cross-platform editing

Atom works across operating systems. You can use it on OS X, Windows, or Linux.

Built-in package manager

Search for and install new packages or start creating your own—all from within Atom.

Smart autocompletion

Atom helps you write code faster with a smart, flexible autocomplete.

File system browser

Easily browse and open a single file, a whole project, or multiple projects in one window.

Multiple panes

Split your Atom interface into multiple panes to compare and edit code across files.

Find and replace

Find, preview, and replace text as you type in a file or across all your projects.

Download at https://atom.io/

CSS Spinners and Loaders


CSS Spinners and Loaders - Modular, Customizable and Single HTML Element Code.
Link: https://webkul.github.io/csspin/

CSSPIN Library has a different set of interactive Pure CSS Loaders and Spinners which are built on the top of LESS Preprocessor. Individual Pure CSS Loader or Spinner can be easily customized and can be embedded with Single HTML Element in your next Dev Project.

To learn more and browse through all the documentation, check out the CSSPIN repo on GitHub https://github.com/webkul/csspin. The creator also made a small setup video that you can watch here https://www.youtube.com/watch?v=18uY-YueJeI.


OVH VPS root password lost/ forgotten

For obvious security reasons OVH has no access to your server’s root password.

In the OVH Manager, select your VPS from the Infrastructures list. From there, on the right-hand side of the page, you can click on the "Reset the password" button.


Once your VPS has rebooted, an email containing a temporary password will be sent to you.

Connect to your VPS via SSH using the temporary password that was sent to you.

On the command line interface, enter the following:
$ fdisk -l

This will list the partitions on your HDD, and the partition where the password is will be highlighted with an asterisk ( * ). It should look something like /dev/vdb1 * or /dev/sdb1 *

From this point on, I will use /dev/sdb1 as an example, but depending on your output in the previous step, you may have to use /dev/vdb1

Run the following command:
$ mount /dev/sdb1 /mnt
(You may get a message that it is already mounted)

Then enter:
$ chroot /mnt

Finally, generate your own root password with:
$ passwd

Once all of this is done, restart your VPS in normal mode from the control panel and you will then be able to connect using your new password.

AngularJS for newbie


HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web-applications. AngularJS lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop.


Make the web faster


Build a basic website is easy, but how to make the web more faster?
Here are some tips to make your website load faster.

  • Optimizing caching
  • Minimizing round-trip times
  • Optimizing browser rendering
  • Optimizing for mobile