Building a REST API with Node, KOA and PostgreSQL

This post describes how to create a REST API using Node, KOA and PostgreSQL. It’s intended for beginners but is based on best practice. Most articles for beginners will tell you to focus on understanding the basics and don’t worry about design practices. They are probably right but that’s just not how my mind works. You should have your development environment ready with Node, NPM and Git installed before starting. If you need help; look at my previous articles on setting up your web development environment and getting started with Git. All of the code is documented below but the complete application code is here https://github.com/infornite/n4nite-rest-api if you want to refer to it as you follow along.

Setup the project directory

Create an empty directory for your project and cd into it. Execute the command npm init which will guide you through creating a new package.json file. This is where Node will store information about our project. You can select the default answer for most prompts except for the ‘entry point’ where you should type ‘app.js’. This tells Node that we want to run a Javascript file called app.js as the first step when we start our server. Of course we will need to create this app.js file later on.

Install your dependencies

The next step is to install dependencies. Dependencies are simply packages or modular pieces of code that we can plug into our application to give us extra functionality. There are literally thousands of packages that have been created by companies and people and made available under open source licensing. Think of these packages as the tools that we can use to program our application. They are broadly split into dev dependencies which are packages that you use only during development to make your life easier and non-dev dependencies which are the packages that get deployed with your application and make it work.

Dev Dependencies

For now, we are going to install 2 really useful dev dependencies.

  • nodemon: This watches for changes when we save our code and automatically restarts the node server so those changes are reflected. It saves us from having to manually stop and restart the server every time we make a change.
  • typescript: Typescript makes our lives a lot easier by highlighting syntax errors in our code and providing auto-complete functionality. Because we are using Typescript we save our code in files with a .ts extension and write in a Typescript syntax. Typescript converts these files to normal Javascript in the background for us.
npm install nodemon --save-dev
npm install typescript --save-dev

The --save places a note in our package.json file about these dependencies. If you ever need to rebuild your application these entries can be used to do that without having to remember which packages and versions you were using.

We also need to create 2 files in our root directory that contain configuration details for Typescript and Nodemon. Go ahead and create a tsconfig.json and nodemon.json file based on the following.

//tsconfij.json
{
    "compileOnSave": false,
    "compilerOptions": {
      "noImplicitAny": false,
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "moduleResolution" : "node",
      "lib": [
        "es2017"
      ],
      "types": [
        "node"
      ],
      "sourceMap": true,
      "baseUrl": "./src"
    },
    "exclude": [
      "node_modules",
      "**/*.spec.ts"
    ]
  }

This is all fairly standard. The main things of note is that we set emitDecoratorMetadata and experimentalDecorators because they are needed for Typeorm to work. We also specify "baseUrl": "./src" which allows us to more easily reference paths in our code based on the main folder we will call src (e.g. instead of writing import '../../../entities/card' we can just write import 'models/card').

//nodemon.json
{
    "watch": ["./src"],
    "ext": "ts",
    "exec": "ts-node --inspect -r tsconfig-paths/register ./src/server.ts"
   }

In nodemon.json we are just telling nodemon to watch for changes in the src folder to any file types ending with .ts and to restart the server when these changes are detected. While you are editing the JSON files go ahead and add an entry under the scripts section of your package.json as well as follows.

//package.json
.....
.....
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon"
  },
.....
.....

Non-Dev Dependencies

  • koa: This is the framework that we are going to be using. Check my note below for more information on KOA and why we are using it.
  • koa-router: Needed for creating and managing routes. Basically, we use this to tell the server how to handle client requests to different URL’s (my-website.com/users vs my-website.com/products)
  • koa-bodyparser: Needed to parse the body of any requests that are sent to our API by a client. For example when a client passes their User Id to us we need this parser to extract their User Id from the request.
  • typeorm: This is an ‘Object Relational Mapping’ or ORM package. It allows us to create a model of relational data stored in our database and represent this as an object that we can use in our Javascript code.
  • pg: This is a database driver that is needed to connect to PostgreSQL.
  • class-validator: This package has functionality that we can use to validate objects and data such as checking if an email address is valid.
  • ts-node: Needed so we can run our Typescript code via Node.
  • tsconfig-paths: Allows us to map our paths to a base URL which makes things cleaner when referencing file paths in the code.

npm install koa koa-router koa-bodyparser typeorm pg class-validator ts-node tsconfig-paths --save

Creating the project structure

Lets create the basic project structure next. You will already have a node_modules folder where node stores our installed packages and you should also have 4 JSON files that contain configuration settings for our application. Create a new folder called src with 5 sub folders (controllers, databases, models, qa and routes) and 2 files (app.ts and server.ts) in this src directory.

Project Structure
Project Structure
  • routes: Whenever a client sends a request to our application they will specify a URL (my-website.com/users vs my-website.com/products). Routes are simply the way we tell our application how to handle these different requests and where specific requests or URL’s should be routed to in our application to be handles.
  • controllers: Generally the route logic in our application will pass requests to a controller. Controllers are where we write code to define what we want our application to do. For example we might have one controller with logic that is specific to working with users and another controller that has code that is specifically for working with products.
  • models: In this folder we will create a specification or model of the entities that we want to use in our application. This could include a model for what a user looks like or a product or any other entity that we want to create, store in our database and use in our application. Models are important because they create a specification that can be used to map between the data stored in our DB and the objects we work with in JavaScript.
  • databases: Code that initialises a connection to our database.
  • qa: We will store code here related to testing and Quality Assurance of our application and creating sample data.
  • app.ts: Used to create an instance of our application – its a simple file with only 3 lines of code.
  • server.ts: Initialises mode of the packages and functionality needed to make our server work. This file also opens the database connection and this is where we tells the server where our routes are stored.

Update app.ts as per below. These 3 lines of code are just creating a new instance of a KOA app and making it available to other parts of the application via the exports statement. We could of course store these 3 same lines of code in the server.ts file we are going to create. However, I think its good design to keep the main application initialisation separate.

//app.ts

import * as Koa from 'koa';
var app = new Koa();
module.exports = app;

To test the application update the server.ts file as below. Here are are creating a new app by requiring the “./app” that we exported in app.ts. We are also telling this app to respond to every request by setting the response body to “Welcome to my Server”. Finally we tell the app to listen on port 3000 and we kick all of this off by calling the bootstrap() function which we wrapped everything in.

//server.ts
var app = require('./app');

const bootstrap = async () => {

    //Respond with a message to all client requests
    app.use(async ctx => {
        ctx.body = "Welcome to my Server!";
    });

    //Tell the app to listen on port 3000
    app.listen(3000);
};

bootstrap();

Save these changes and then type npm start into the terminal to start your server. Open your internet browser and type localhost:3000 in the address bar and hit enter. If everything is working you should get a response from your server.

Server Response
Server Response

Before we start using our application to store data we need to get our database running so we can connect to it. You can use any DB that you want but I am using PostgreSQL. For this example I created a free database at www.elephantsql.com. Once you have set this up you can visit the database servers page and see the connection details that you need listed like below.

Elephant SQL
Elephant SQL

 

Under your databases folder create a file called postgres-db.ts and populate it as below (replacing with your server name, database, username and password).

//postgres-db.ts

/*
This file initializes your PostgreSQL database. You need to supply
the host name, username, password and database name for your database.
*/

import { createConnection } from 'typeorm';

export const postgresDB = async () => {

    return await createConnection({
        type     : 'postgres',
        host     : 'tINSERT SERVER NAME',
        port     :  5432,
        username : 'INSERT USER NAME',
        password : 'INSERT PASSWORD',
        database : 'INSERT DATABASE NAME',
        ssl: true,
        logging: ['query', 'error'],
        synchronize: true,
    }).then((connection) => {
        console.log('Database connection established');

        
    });

};

Finally, we need to add a couple of lines into our server.ts file to use the code we have written and tell the app to initialise the database.

//server.ts
import { postgresDB } from 'databases/postgres-db';

var app = require('./app');

const bootstrap = async () => {

    // Initialize the database
    await postgresDB();

    //Respond with a message to all client requests
    app.use(async ctx => {
        ctx.body = "Welcome to my Server!";
    });

    //Tell the app to listen on port 3000
    app.listen(3000);
};

bootstrap();

Save the changes and restart the server (if nodemon doesn’t do it for you). You should receive a message that the ‘Database connection established’.

Building out our Application

Great, at this point our application is in pretty good shape. You have setup your environment, installed dependencies, created a good project structure, created your database and run a test application to validate that everything is hanging together. Now, lets get on with building our application. We are going to focus on creating a User entity that is stored in our database and all of the necessary logic to handle querying, creating, updating and deleting Users. We will do this in a modular way and you will see that we can apply the same principles to create any other type of entity we need to handle in our application. I’ll run through the steps for this User Entity and you can repeat the same steps to add entities and complexity to your application. Lets get started and run through X steps.

  1. Create a model that describes what a User looks like and what fields exist for a User.
  2. Tell the database that this model exists and that you want to store the user in the database.
  3. Create the “routes” that a client can access to query, add, edit and delete users.
  4. Create controllers that will handle the clients request depending on the route they have requested.

1. Create a model

Create a new file called user.ts under our models directory based on the following.

//user.ts

//import type definitions from typeorm that describe the physical 
//charachteristics of fields that we will store in the database
import {
    Entity,
    PrimaryGeneratedColumn,
    Column,
    CreateDateColumn,
    UpdateDateColumn,
} from 'typeorm';

//Import functions from the class-valadiator package that we will
//use to validate data when someone is creating or editing a user
import { Length, IsEmail } from 'class-validator';

//This decorator (denoted by the @ symbol) tells type-orm that
//we want to call the database table users
@Entity('users')

//Export the User class so we can use it elsewhere in our project
export class User {

    @PrimaryGeneratedColumn('uuid')     //Tell Postgre to generate a Unique Key for this column
    id: string;                         //Name of the column is id and type is string

    @Column('text')                     
    name: string;

    @Column('text')
    @Length(5, 100)
    @IsEmail()
    email: string;

    @Column('text')
    hashedPassword: string;
    
    @CreateDateColumn()
    createdAt: Date;

    @UpdateDateColumn()
    updatedAt: Date;
}

2. Tell the database that this model exists

Create a new files under the databases directory called postgres-tables.ts that match the following. This file is simply importing the users model that we created above and creating an array called postgresTables that contains all of the tables we have (only one for now).

//postrgestables.ts

/*
This file simply imports our models and creates an array with a list of
the tables we want to include when we connect to Postgres. Its overkill to
keep this info in a seperate file when we only have one table but it will be
really neat and clean once our app grows to have tens and hundreds of tables
*/

import { User } from 'models/user';
export const postgresTables =[User,]

Update our postgresdb.ts file to tell it about the new User table we want to store our user data on in Postgres.

//postgres-db.ts

/*
This file initializes your PostgreSQL database. You need to supply
the host name, username, password and database name for your database.
*/

import { createConnection } from 'typeorm';
import { postgresTables } from './postgres-tables'

export const postgresDB = async () => {

    return await createConnection({
        type     : 'postgres',
        host     : 'tINSERT SERVER NAME',
        port     :  5432,
        username : 'INSERT USER NAME',
        password : 'INSERT PASSWORD',
        database : 'INSERT DATABASE NAME',
        ssl: true,
        entities: postgresTables,
        logging: ['query', 'error'],
        synchronize: true,
    }).then((connection) => {
        console.log('Database connection established');

        
    });

};

Save all the changes. If your app is still running then nodemon will restart the server. If not then type npm start to get the server running again. What will happen now is that your application will connect to the database. It will also create a table in the database for you that is based on the model you defined in the models/user.ts file. This is pretty cool – as your applications get more complex you might want to disable this option and manually create tables in PostgreSQL rather than having the application do it automatically. If you want to do this then you just need to go back to the postgre-db.ts file and change the synchronize: true setting to be false.

3. Create the routes

As I mentioned before routes are the different ways or URLs that clients can pass to your application. Depending on the route a client requests and their request type we will tell our application to behave in a particular way. If you are not familiar with different HTTP Request Types then just google it. At its most basic level there are 4 request types that we are really interested in.

  • Get: the client is requesting some information from us.
  • Post: the client is providing information to us to do something (typically used to create new data such as a new user)
  • Put: the client is providing information to us to update something (for example to update an existing user)
  • Del: the client is requesting that we delete something (for example deleting a user).

Ideally the next thing I would show you is how to use a Get request to retrieve a list of Users from our database. However, our database is empty at the moment so I am going to sidestep a little bit and instead show you how to create test data in the db using our application.

Sidestep: Creating Test Data

To start create a file called createTestData.ts under our QA folder. This file will just connect to the database and inserts 3 sample records in our users table.

import { BaseContext } from 'koa';
import {getConnection} from "typeorm";
import { User } from 'models/user';

//Creating a class so we can later extend it to include creation of more test data
export class TestData {

    //This handles creating test users. Seperate functions can be added for other test data later.
    public static async createTestUsers(ctx: BaseContext){
    try {
    await getConnection()
    .createQueryBuilder()
    .insert()
    .into(User)
    .values([
        { name: "Michael", email: "michael@osullivan.com", hashedPassword: "pass123" }, 
        { name: "Louise", email: "louise@osullivan.com", hashedPassword: "pass123" },
        { name: "Mary", email: "mary@osullivan.com", hashedPassword: "pass123" }
     ])
    .execute();

    //Return a success message if theer are no errors
    ctx.body = "Test users created successfully"
    
    //Catch any errors and return a 500 error status to the user is there are errors
    }catch (err) {
        // will only respond with JSON
        ctx.status = err.statusCode || err.status || 500;
        ctx.body = {
        message: err.message
    };
    }
}
};

Next create a file in our routes folder called qa-routes.ts as follows. This file specifies that when a client request hits the endpoint ‘/qa/users’ and the type of request is POST then we should call our function createTestUsers, that we created in the last file.

import * as Router from 'koa-router';
import createTestData = require('qa/createTestData');

export const qaRouter = new Router();

//Routes for the user entity
qaRouter.post('/qa/users', createTestData.TestData.createTestUsers);          //Create some test users

Finally we need to update the server.ts file to tell it to include the new routes. Lets also clean up the file a little bit whilst we are at it and remove the “Welcome to my Server!” default message from every request.

//server.ts
import { postgresDB } from 'databases/postgres-db';
import {qaRouter} from 'routes/qa-routes';

var app = require('./app');

const bootstrap = async () => {

    // Initialize the database
    await postgresDB();

    //Tell our application to use the router we have created to handle routes related to testing
    app.use(qaRouter.routes(), qaRouter.allowedMethods())
    
    //Tell the app to listen on port 3000
    app.listen(3000);
};

bootstrap();

To test this out we need to send a POST request to this endpoint (localhost:3000/qa/users). You can use any application you want to do this but I use Postman and its the most popular. You can download it from www.getpostman.com. Then send a request to your endpoint and you should get a response that “Test users created successfully”.

 

Postman Test Output
Postman Test Output

 

Creating Routes for the User Entity

Ok, now that we have some test data lets get back to building out our users entity by creating the routes we need. Lets start by creating an new file under our routes directory called rest-routes.ts. You may get an error because it is importing a controller that we create in the next step.

//rest-routes.ts

import * as Router from 'koa-router';
import controller = require('controllers');

export const restRouter = new Router();

//Routes for the user entity
restRouter.get('/users', controller.user.getUsers);             //Get all users in the database

Update the server.ts file to include the new route we have created. Lets also include koa-bodyparser in the server.ts file. This will be needed when we want to use information the client passes to us in their requests such as the details of a new user they want to create.

//server.ts
import { postgresDB } from 'databases/postgres-db';
import {qaRouter} from 'routes/qa-routes';
import {restRouter} from 'routes/rest-routes';
import * as bodyParser from 'koa-bodyparser';


var app = require('./app');

const bootstrap = async () => {

    // Initialize the database
    await postgresDB();

     // Enable bodyParser which is needed to work with information
    // passed to the server from the client requests 
    app.use(bodyParser());

    //Tell our application to use the router we have created to handle routes related to testing
    app.use(qaRouter.routes(), qaRouter.allowedMethods())

    //Tell our application to use the router we have created to handle routes for our rest api
    app.use(restRouter.routes(), restRouter.allowedMethods())

    //Tell the app to listen on port 3000
    app.listen(3000);
};

bootstrap();

The router we created and included in the server.ts file tells the application that any GET client request to the endpoint ‘/users’ should be sent to the getUsers() controller to handle. Lets create that controller next.

4.Create controllers

Create a new file called user.ts under the controllers directory. For now this will contain just one method getUsers that we can use to return a list of all the users in the database.

//controllers/user.ts

import { BaseContext } from 'koa';
import { getManager, Repository, Not, Equal } from 'typeorm';
import { validate, ValidationError } from 'class-validator';
import { User } from 'models/user';


export default class UserController {

    public static async getUsers (ctx: BaseContext) {

        // get a user repository to perform operations with user
        const userRepository: Repository<User> = getManager().getRepository(User);

        // load all users
        const users: User[] = await userRepository.find();

        // return OK status code and loaded users array
        ctx.status = 200;
        ctx.body = users;
    }

  }

Create a file called index.ts in the same controllers directory and populate it as follows. This is a bit of overkill when we only have one controller that we can import into our application directly. However, its good design practice and will make things much cleaner as we add more complexity to the application.

//controllers/index.ts

//export all controllers through this  index.js file. This is
//cleaner than importing the files individually in the routes file
export { default as user } from './user';

And that’s it – you can now send a GET request to ‘localhost:3000/users’ via Postman and you will get a list of users back in the response. A GET is the default type of client request that your internet browser sends so you can also just put ‘localhost:3000/users’ into the address bar of your internet browser to see the same results.

Adding Create, Update and Delete:

Lets extend the application to include the ability to get a single user by ID as well as the functionality to create, update and delete users. I won’t go through each of these buts its basically a case of extending the users.ts controller to have code to handle each type of action and then adding a corresponding router endpoint to the rest-routes-ts file. Here are the 2 completed files.

 

//controllers/user.ts

import { BaseContext } from 'koa';
import { getManager, Repository, Not, Equal } from 'typeorm';
import { validate, ValidationError } from 'class-validator';
import { User } from 'models/user';


export default class UserController {

    public static async getUsers (ctx: BaseContext) {

        // get a user repository to perform operations with user
        const userRepository: Repository<User> = getManager().getRepository(User);

        // load all users
        const users: User[] = await userRepository.find();

        // return OK status code and loaded users array
        ctx.status = 200;
        ctx.body = users;
    }

    public static async getUser (ctx: BaseContext) {

        // get a user repository to perform operations with user
        const userRepository: Repository<User> = getManager().getRepository(User);

        // load user by id
        const user: User = await userRepository.findOne(ctx.params.id);

        if (user) {
            // return OK status code and loaded user object
            ctx.status = 200;
            ctx.body = user;
        } else {
            // return a BAD REQUEST status code and error message
            ctx.status = 400;
            ctx.body = 'The user you are trying to retrieve doesn\'t exist in the db';
        }

    }

    public static async createUser (ctx: BaseContext) {

        // get a user repository to perform operations with user
        const userRepository: Repository<User> = getManager().getRepository(User);
        
        // build up entity user to be saved
        const userToBeSaved: User = new User();
  
        userToBeSaved.name = ctx.request.body.name
        userToBeSaved.email = ctx.request.body.email;
        userToBeSaved.hashedPassword = ctx.request.body.hashedPassword;

        //validate(ctx.request.body.name);

        // validate user entity
        const errors: ValidationError[] = await validate(userToBeSaved, { skipMissingProperties: true }); // errors is an array of validation errors
        if (errors.length > 0) {
            // return BAD REQUEST status code and errors array
            ctx.status = 400;
            ctx.body = errors;
        } else if ( await userRepository.findOne({ email: userToBeSaved.email}) ) {
            // return BAD REQUEST status code and email already exists error
            ctx.status = 400;
            ctx.body = 'The specified e-mail address already exists';
        } else {
            // save the user contained in the POST body
            const user = await userRepository.save(userToBeSaved);
            // return CREATED status code and updated user
            ctx.status = 201;
            ctx.body = user;
        }
    }

    public static async updateUser (ctx: BaseContext) {

        // get a user repository to perform operations with user
        const userRepository: Repository<User> = getManager().getRepository(User);

        // load the user by id
        const userToBeUpdated: User = await userRepository.findOne(ctx.params.id);

        // return a BAD REQUEST status code and error message if the user cannot be found
        if (!userToBeUpdated) {
            
            ctx.status = 400;
            ctx.body = 'The user you are trying to retrieve doesn\'t exist in the db';  
        } 

        if(ctx.request.body.name) {userToBeUpdated.name = ctx.request.body.name;}
        if(ctx.request.body.email) {userToBeUpdated.email = ctx.request.body.email;}
        if(ctx.request.body.hashedPassword) {userToBeUpdated.hashedPassword = ctx.request.body.hashedPassword;}

        // validate user entity
        const errors: ValidationError[] = await validate(userToBeUpdated); // errors is an array of validation errors
        if (errors.length > 0) {
            // return BAD REQUEST status code and errors array
            ctx.status = 400;
            ctx.body = errors;
        } else if ( !await userRepository.findOne(userToBeUpdated.id) ) {
            // check if a user with the specified id exists
            // return a BAD REQUEST status code and error message
            ctx.status = 400;
            ctx.body = 'The user you are trying to update doesn\'t exist in the db';
        } else if ( await userRepository.findOne({ id: Not(Equal(userToBeUpdated.id)) , email: userToBeUpdated.email}) ) {
            // return BAD REQUEST status code and email already exists error
            ctx.status = 400;
            ctx.body = 'The specified e-mail address already exists';
        } else {
            // save the user contained in the PUT body
            const user = await userRepository.save(userToBeUpdated);
            // return CREATED status code and updated user
            ctx.status = 201;
            ctx.body = user;
        }

    }

    public static async deleteUser (ctx: BaseContext) {

        // get a user repository to perform operations with user
        const userRepository: Repository<User> = getManager().getRepository(User);

        // load the user by id
        const userToRemove: User = await userRepository.findOne(ctx.params.id);

        if (!userToRemove) {
            // return a BAD REQUEST status code and error message
            ctx.status = 400;
            ctx.body = 'The user you are trying to delete doesn\'t exist in the db';
        } else {
            // the user is there so can be removed
            await userRepository.remove(userToRemove);
            // return a NO CONTENT status code
            ctx.status = 204;
        }

    }

  }

 

//routes/rest-routes.ts
import * as Router from 'koa-router';
import controller = require('controllers');

export const restRouter = new Router();

//Routes for the user entity
restRouter.get('/users', controller.user.getUsers);             //Get all users in the database
restRouter.get('/users/:id', controller.user.getUser);          //Get a single user by id
restRouter.post('/users', controller.user.createUser);          //Create a single user in the database
restRouter.put('/users/:id', controller.user.updateUser);       //Update a single user that matches the passed id
restRouter.delete('/users/:id', controller.user.deleteUser);    //Delete a single user that matches the passed id

Test it Out:

Lets test out the functionality for the different endpoints and request types we now support in our application.

Retrieve a list of all users:

  • Send a GET command to “localhost:3000/users”
  • Response: A JSON Object with a list of users including their id, name and password.

Retrieve a specific user

  • Send a GET command to “localhost:3000/users” and specify the users id at the end of the endpoint (e.g. localhost:3000/users/id)
  • You can get a users id by looking at the response from the first query to retrieve a list of all users.
  • Response: A JSON Object with details of that specific user.

Create a new user

  • Send a POST command to “localhost:3000/users”
  • Include a JSON object in the body of the request with details of the user you want to create.
  • {
        "name": "Joe Bloggs",
        "email": "joe@bloggs.com",
        "hashedPassword": "Pass456"
    }
  • Response: A JSON Object with the details of the user you created.

Update an existing user

  • Send a PUT command to “localhost:3000/users” and specify the users id at the end of the endpoint (e.g. localhost:3000/users/id)
  • Include a JSON object in the body of the request with details of for user you want to update.
  • {
        "name": "Joe Bloggs",
        "email": "joes-new-email@bloggs.com",
        "hashedPassword": "Pass456"
    }
  • Response: A JSON Object with the updated details of the user.

Delete a specific user

  • Send a DEL command to “localhost:3000/users” and specify the users id at the end of the endpoint (e.g. localhost:3000/users/id)
  • You can get a users id by looking at the response from the first query to retrieve a list of all users.
  • Response: Blank

Storing your code on GIT:

As a final step lets store our source code on GIT. If you are not familiar with GIT then checkout my article getting started with Git.

git init
git commit -m "first release of n4nite-rest-api"
git remote add origin https://github.com/infornite/n4nite-rest-api.git
git remote -v
git push origin master

That’s it you have a complete working application that is well designed and an approach that you can replicate to extend the complexity of your application by adding new entities. In the next post I will cover securing this API with user registration and authentication. As a last point I am including a note below on why I chose KOA as the framework to build this application.

Why KOA

In order to develop most applications with Node.js you need to use a framework which sits on top of Node. There are several frameworks. The most popular is probably express.js and it’s a great choice if you are starting web development. KOA.js is a reasonably new contender though it has been around a few years now and there are various articles and debates about Express vs KOA and comparisons of a whole host of other frameworks. For me, it came down to a choice between Express and KOA. I read a lot of the technical comparisons but I’m not advanced enough to make a reasonably considered comparison myself. In the end, for it came down to this for me; The team that originally built express spent thousands of hours putting it together. That same team then came along years later and invested thousands of hours to build KOA to take advantage of things that weren’t available when they designed express. I have to surmise that they wouldn’t have invested that time unless they thought there were some fundamental improvements that they could make. I don’t expect that Express is going to be replaced by KOA but as a newbie I though that KOA was the better framework to start with.

Credits

View story at Medium.com

https://github.com/javieraviles/node-typescript-koa-rest

View story at Medium.com

2,369 thoughts on “Building a REST API with Node, KOA and PostgreSQL

  1. จ้างปั้มไลค์, รับทำไลค์แฟนเพจจำนวนมาก, Up Like Fanpage, กดไลค์รูป, รับจ้างปั้มไลค์, รับสร้างแฟนเพจพร้อมยอดไลค์, จ้างไลค์รูป, ไลค์แฟนเพจเฟสบุ๊ค, ไลค์แฟนเพจราคาถูก, รับจ้างกดไลค์, ปั้มไลค์เฟสบุ๊ค, Add Like Fanpage, โกงไลค์, ปั้ม Like ฟรี, เพิ่มไลค์คนไทย, บริการเพิ่มไลค์เฟสบุ๊คให้แฟนเพจ, จ้างเพิ่มไลค์, ปั้มไลค์ครบวงจร, รับเพิ่มไลค์แฟนเพจ เป็นการโปรโมทแฟนเพจ เพื่อเพิ่มยอดขายสินค้าได้, ปั้มไลค์เพจ Facebook, ปั้มไลค์รูป, รับเพิ่ม Like Fanpage Facebook ราคาพิเศษ เหมาะสำหรับผู้ที่ต้องการเพิ่ม Like Fanpage ให้ดูเป็นความน่าเชื่อถือของร้าน, เพิ่ม Like, รับปั้มไลค์เพจ, ปั้มเพจเฟสบุ๊ค, เพิ่มไลค์แฟนเพจ, รับทำเพจสินค้าพร้อมยอดไลค์, รับปั้มไลค์รูป, ปั้มไลค์สถานะ, รับทำไลค์ครบวงจร, ปั้มไลค์ฟรี, ปั้มไลค์ราคาถูก, ปั้มรูป, ปั้มไลค์, ปั้มโพสต์, เพิ่มไลค์เพจ, บริการปั้มไลค์ฟรี, การเพิ่ม Like เป็นการเพิ่มโอกาสทางการขายสินค้าของคุณนั่นเอง ด้วยงานบริการเพิ่มไลค์แฟนเพจระดับมืออาชีพ ประสบการณ์การทำงานหลายปี, ปั้มเพจ, ปั้มไลค์มือถือ, รับจ้างเพิ่มไลค์, รับไลค์แฟนเพจ, Like Fanpage, ปั้มไลค์เพจฟรี, เพิ่มไลค์, จ้างไลค์, ไลค์แฟนเพจได้สูงสุดหนึ่งล้านไลค์, ไลค์เพจ, รับทำเพจเฟสบุ๊ค, ปั้มยอดไลค์เป็นคนไทย 100%, ปั้มไลค์เพจคนไทย, รับไลค์ครบวงจรทั่วไทย, ปั้มไลค์ทั่วไป, จ้างกดไลค์, ปั้มไลค์เพจ, ปั้มไลค์ง่ายๆ, ปั้มไลค์ Facebook, แฟนเพจพร้อมยอดไลค์, ปั้มไลค์รูป Facebook, กดไลค์, ไลค์แฟนเพจ, Pump Like, เพิ่มไลค์ฟรี, รับเพิ่มไลค์แฟนเพจเฟสบุ๊ค, ปั้มเพจ เหมาะสำหรับผู้ที่ต้องการยอดไลค์เพจเพจเยอะๆ, ปั้มไลค์รูปเฟส, ไลค์คนไทย 100%, รับเพิ่มไลค์, ปั้มไลค์แฟนเพจ, บริการปั้มไลค์แฟนเพจฟรี, ซื้อไลค์แฟนเพจ, เพิ่มไลค์เพจ ราคาถูก, บริการเพิ่ม Like ให้แฟนเพจของคุณ โดยทีมงานระดับมืออาชีพ ในระยะเวลาอันสั้นและราคาถูก รับประกันไลค์จากคนไทย 100%, กดไลค์แฟนเพจ, ปั่นไลค์, เพิ่มไลค์แฟนเพจ ราคาถูก, บริการเพิ่มไลค์แฟนเพจฟรี, กด Like, ปั้มไลค์ ในโทรศัพท์, รับ Like Fanpage, Auto Like

  2. Auto Like, แฮกไลค์, ปั้มไลค์แฟนเพจ, ปั้มไลค์คอมเม้น, ปั้มไลค์รูปภาพ, ระบบเพิ่มไลค์, ออโต้ไลค์, เว็บปั้มไลค์, Hack Like Facebook, ปั้มไลค์

  3. Status Auto Liker, Autoliker, auto liker, Fb Autoliker, Auto Like, Facebook Liker, Working Auto Liker, Photo Auto Liker, Increase Facebook Likes, auto like, Auto Liker, Facebook Autoliker, Photo Liker, Facebook Auto Liker, facebook auto liker, autoliker, autolike, Autoliker, Status Liker, Autoliker Facebook

  4. ปั้มไลค์เพจ, ปั๊มไลค์เพจ, เพิ่มไลค์แฟนเพจ, เพิ่มไลค์เพจ, ปั๊มไลค์เพจ, ไลค์เพจ, ปั้มเพจ, ปั้มไลค์แฟนเพจ, เพิ่มไลค์เพจ ราคาถูก, ปั๊มไลค์แฟนเพจ, ปั๊มไลค์เพจ facebook

  5. Hi, Glad you’re learning stuff with my posts.So, yeah GraphQL is something we definitely keep an eye on, but at the moment Core is focused on Gutenberg. No real news in this area so but hopefully some exploration could start in the next months.Loading…

  6. Thank a lot for sharing your knowlegde and spend some time writing the info, really thank, i’m already waiting the next post about user registration and authentication with the same tools, have a great day. regards

  7. First off I want to say fantastic blog! I had a quickquestion in which I’d like to ask if you do not mind.I was curious to know how you center yourself and clear your head prior to writing.I have had a difficult time clearing my thoughts in getting my thoughts out.I truly do take pleasure in writing but it just seems like the first 10 to 15 minutes are lost simply just tryingto figure out how to begin. Any recommendations or hints? Cheers!

  8. This makes some eloquent ideas-though I notice you may be generalizing. I hope to see you add some more detail, because you are a very eloquent writer and I like reading your articles.

  9. NEON has taken what DASH tried to be and made it even better. Masternodes earn 90 of the block reward and are not required to use third-party software such as Python and/or Sentinel, to run a Nucleon Masternode. Nucleon is the first coin to feature Internal Sentinel, which is hardcoded into the wallet and automatically run and will be fully configured for you.. inside the wallet! If you are a MINER, then there is even more in NEON for you because it uses the brand new, top of the line, VRX/Velocity Difficulty Retargeting Algorithm. This means blocks are reliable not only by difficulty, but also by actual time! https://neon.mealworms.biz

  10. Недорогой отель Владимирский находится рядом с центром Нижнего Новгорода. Ближайшая станция метро Ленинская находится в 640 м от гостиницы, что позволяет попасть в центр города за 10-15 минут. Гостиница располагается в Нижнем Новгороде рядом с ЖД вокзалом.

    Отель Нижний Новгород

  11. Недорогой отель Владимирский находится рядом с центром Нижнего Новгорода. Ближайшая станция метро Ленинская находится в 640 м от гостиницы, что позволяет попасть в центр города за 10-15 минут. Гостиница располагается в Нижнем Новгороде рядом с ЖД вокзалом.

    http://vladimir-otel.ru – Отель в Нижнем Новгороде

  12. Bonjour, J’ai lut votre texte avec beaucoup d’attention, c’était très agréable et instructif. Merci, je visterai régulièrement votre site pour y trouver de l’inspiration.

  13. First off I would like to say great blog! I had a quick
    question which I’d like to ask if you do not mind.
    I was interested to find out how you center yourself and clear
    your head before writing. I have had a tough time
    clearing my thoughts in getting my ideas out there.
    I truly do take pleasure in writing but it just seems like the first 10 to 15 minutes are wasted just trying to figure out how to begin. Any
    recommendations or hints? Appreciate it!

  14. Dear Sir/Madam,

    I have an important transaction that will benefit us both.i need your help in this transaction as you shall be rewarded for your help and efforts.
    Get back to me on my private email for more details: nuoshad28@gmail.com

    waiting for your reply.

    Thanks
    Ian

  15. Hey, how’s it going?

    I want to pass along some very important news that everyone needs to hear!

    In December of 2017, Donald Trump made history by recognizing Jerusalem as the captial of Israel. Why is this big news? Because by this the Jewish people of Israel are now able to press forward in bringing about the Third Temple prophesied in the Bible.

    The Jewish people deny Jesus as their Messiah and have stated that their Messiah has been identified and is waiting to be revealed. They say this man will rule the world under a one world religion called “spiritualism”.

    They even printed a coin to raise money for the Temple with Donald Trumps face on the front and with king Cyrus'(who built the second Temple) behind him. On the back of the coin is an image of the third Temple.

    The Bible says this false Messiah who seats himself in the Third Temple will be thee antichrist that will bring about the Great Tribulation, though the Jewish people believe he will bring about world peace. It will be a false peace for a period of time. You can watch interviews of Jewish Rabbi’s in Israel speaking of these things. They have their plans set in place. It is only years away!

    More importantly, the power that runs the world wants to put a RFID microchip in our body making us total slaves to them. This chip matches perfectly with the Mark of the Beast in the Bible, more specifically Revelation 13:16-18:

    He causes all, both small and great, rich and poor, free and slave, to receive a mark on their right hand or on their foreheads, and that no one may buy or sell except one who has the mark or the name of the beast, or the number of his name.

    Here is wisdom. Let him who has understanding calculate the number of the beast, for it is the number of a man: His number is 666.

    Referring to the last days, this could only be speaking of a cashless society, which we have yet to see, but are heading towards. Otherwise, we could still buy or sell without the mark amongst others if physical money was still currency. RFID microchip implant technology will be the future of a one world cashless society containing digital currency. It will be implanted in the right-hand or the forehead, and we cannot buy or sell without it! We must grow strong in Jesus. AT ALL COSTS, DO NOT TAKE IT!

    Then a third angel followed them, saying with a loud voice, “If anyone worships the beast and his image, and receives his mark on his forehead or on his hand, he himself shall also drink of the wine of the wrath of God, which is poured out full strength into the cup of His indignation. He shall be tormented with fire and brimstone in the presence of the holy angels and in the presence of the Lamb. And the smoke of their torment ascends forever and ever; and they have no rest day or night, who worship the beast and his image, and whoever receives the mark of his name.” (Revelation 14:9-11).

    People have been saying the end is coming for many years, but we need two key things. One, the Third Temple, and two, the technology for a cashless society to fulfill the prophecy of the Mark of the Beast.

    VISIT http://WWW.BIBLEFREEDOM.COM TO SEE PROOF FOR THESE THINGS AND MUCH MORE! TELL YOUR FRIENDS AND FAMILY. SHARE THIS MESSAGE!

  16. My name is Pete and I want to share a proven system with you that makes me money while I sleep! This system allows you to TRY the whole thing for F R E E for a whole 30 days! That’s right, you can finally change your future without giving up any sensitive information in advance! I signed up myself just a while ago and I’m already making a nice profit.

    In short, this is probably the BEST THING THAT EVER HAPPENED TO YOU IF YOU TAKE ACTION NOW!!!

    If you’re interested in knowing more about this system, go to http://globalviralmarketing.com/?ref=qkgWOPkN5RoC1NWh and try it out. Again, it’s FREE!

    You can thank me later

    /Pete

  17. Oh my goodness! Amazing article dude! Thank you so much, However I am going through troubles with your RSS. I don’t know the reason why I am unable to join it. Is there anybody getting the same RSS issues? Anybody who knows the answer can you kindly respond? Thanx!!

  18. Thanks for the tips you have shared here. Another thing I would like to talk about is that personal computer memory requirements generally increase along with other advancements in the know-how. For instance, when new generations of cpus are introduced to the market, there’s usually a corresponding increase in the scale calls for of both the laptop memory along with hard drive space. This is because software program operated by simply these processors will inevitably surge in power to make new know-how.

  19. Hey, how’s it going?

    I want to pass along some very important news that everyone needs to hear!

    In December of 2017, Donald Trump made history by recognizing Jerusalem as the captial of Israel. Why is this big news? Because by this the Jewish people of Israel are now able to press forward in bringing about the Third Temple prophesied in the Bible.

    The Jewish people deny Jesus as their Messiah and have stated that their Messiah has been identified and is waiting to be revealed. They say this man will rule the world under a one world religion called “spiritualism”.

    They even printed a coin to raise money for the Temple with Donald Trumps face on the front and with king Cyrus'(who built the second Temple) behind him. On the back of the coin is an image of the third Temple.

    The Bible says this false Messiah who seats himself in the Third Temple will be thee antichrist that will bring about the Great Tribulation, though the Jewish people believe he will bring about world peace. It will be a false peace for a period of time. You can watch interviews of Jewish Rabbi’s in Israel speaking of these things. They have their plans set in place. It is only years away!

    More importantly, the power that runs the world wants to put a RFID microchip in our body making us total slaves to them. This chip matches perfectly with the Mark of the Beast in the Bible, more specifically Revelation 13:16-18:

    He causes all, both small and great, rich and poor, free and slave, to receive a mark on their right hand or on their foreheads, and that no one may buy or sell except one who has the mark or the name of the beast, or the number of his name.

    Here is wisdom. Let him who has understanding calculate the number of the beast, for it is the number of a man: His number is 666.

    Referring to the last days, this could only be speaking of a cashless society, which we have yet to see, but are heading towards. Otherwise, we could still buy or sell without the mark amongst others if physical money was still currency. RFID microchip implant technology will be the future of a one world cashless society containing digital currency. It will be implanted in the right-hand or the forehead, and we cannot buy or sell without it! We must grow strong in Jesus. AT ALL COSTS, DO NOT TAKE IT!

    Then a third angel followed them, saying with a loud voice, “If anyone worships the beast and his image, and receives his mark on his forehead or on his hand, he himself shall also drink of the wine of the wrath of God, which is poured out full strength into the cup of His indignation. He shall be tormented with fire and brimstone in the presence of the holy angels and in the presence of the Lamb. And the smoke of their torment ascends forever and ever; and they have no rest day or night, who worship the beast and his image, and whoever receives the mark of his name.” (Revelation 14:9-11).

    People have been saying the end is coming for many years, but we need two key things. One, the Third Temple, and two, the technology for a cashless society to fulfill the prophecy of the Mark of the Beast.

    VISIT http://WWW.BIBLEFREEDOM.COM TO SEE PROOF FOR THESE THINGS AND MUCH MORE! TELL YOUR FRIENDS AND FAMILY. SHARE THIS MESSAGE!

  20. We offer you the opportunity to advertise your products and services.
    Hi! There is a good offers for you. I can send your commercial offers or messages through feedback forms. The advantage of this method is that the messages sent through the feedback forms are included in the white list. This method increases the chance that your message will be read. The same way you received this message.

    Sending via Feedback Forms to any domain zones of the world. (more than 1000 domain zones.).

    The cost of sending 1 million messages is $ 49 instead of $ 99.
    All us sites that have a feedback form. (10 million messages sent) – $349 instead of $649
    Domain zone .com – (12 million messages sent) – $399 instead of $699
    All domain zones in Europe- (8 million messages sent) – $ 299 instead of $599
    All sites in the world (25 million messages sent) – $499 instead of $999

    Discounts are valid until April 20
    Feedback and warranty!
    Delivery report!

    In the process of sending messages, we do not violate the rules of GDRP.
    This message is created automatically use our contacts for communication.

    Contact us.
    Telegram – @FeedbackFormEU
    Skype – FeedbackForm2019
    Email – feedbackform@make-success.com

    Thank you for your attention.

  21. Hi,

    I’ve been visiting your website a few times and decided to give you some positive feedback because I find it very useful. Well done.

    I was wondering if you as someone with experience of creating a useful website could help me out with my new site by giving some feedback about what I could improve?

    You can find my site by searching for “casino gorilla” in Google (it’s the gorilla themed online casino comparison).

    I would appreciate if you could check it out quickly and tell me what you think.

    casinogorilla.com

    Thank you for help and I wish you a great week!

  22. Hi, i think that i saw you visited my website thus i came to “return the favor”.I am trying to find
    things to improve my web site!I suppose its ok to use a few of
    your ideas!!

  23. It’s a shame you don’t have a donate button! I’d definitely donate
    to this fantastic blog! I suppose for now i’ll settle
    for book-marking and adding your RSS feed to my Google account.
    I look forward to brand new updates and will talk about this website with my Facebook group.
    Talk soon!

  24. I am not positive where you’re getting your information, but great topic.
    I needs to spend a while finding out more or understanding more.
    Thank you for wonderful info I used to be looking for this information for my mission.

  25. Have you ever thought about including a little bit more than just your articles?

    I mean, what you say is valuable and all. But just imagine if you added some great photos or video clips to give your posts more, “pop”!
    Your content is excellent but with pics and clips, this blog could undeniably be one of
    the greatest in its niche. Awesome blog!

  26. Hey there just wanted to give you a quick heads up. The words in your post seem to be running off the screen in Ie.
    I’m not sure if this is a format issue or something to
    do with browser compatibility but I figured I’d post to let you know.
    The design and style look great though! Hope you get the issue fixed soon. Cheers

  27. Its like you read my mind! You appear to know a lot about this, like you wrote the
    book in it or something. I think that you could do with some pics to drive the message home a little bit, but instead of that,
    this is great blog. A great read. I’ll definitely be back.

  28. hello there and thank you for your information – I have certainly picked up anything new from right here.
    I did however expertise some technical issues using
    this web site, as I experienced to reload the web site a lot of times previous to I could get it to
    load correctly. I had been wondering if your web host is OK?
    Not that I am complaining, but slow loading instances times will sometimes
    affect your placement in google and could damage your high-quality score if ads and marketing with
    Adwords. Anyway I’m adding this RSS to my e-mail and can look out for much more of your respective fascinating content.
    Ensure that you update this again very soon.

  29. Good post. I learn something totally new and challenging on sites I stumbleupon every day.
    It’s always useful to read through articles from other writers
    and use something from other websites.

  30. I needed to thank you for this excellent read!! I absolutely enjoyed every bit of
    it. I’ve got you book marked to look at new stuff you post…

  31. It’s really a nice and helpful piece of information. I’m
    glad that you shared this useful information with us.
    Please keep us up to date like this. Thank you for sharing.

  32. Woah! I’m really loving the template/theme of this site.
    It’s simple, yet effective. A lot of times it’s challenging to get that
    “perfect balance” between usability and visual appeal.
    I must say you have done a fantastic job with this. Also, the blog
    loads very fast for me on Firefox. Outstanding Blog!

  33. You can certainly see your enthusiasm within the work you write.
    The world hopes for more passionate writers such as you who aren’t
    afraid to mention how they believe. Always follow your heart.

  34. Howdy! Do you use Twitter? I’d like to follow you if that
    would be okay. I’m definitely enjoying your blog and look forward to new posts.

  35. Hmm is anyone else experiencing problems with the images on this blog loading?
    I’m trying to figure out if its a problem on my end or if it’s
    the blog. Any suggestions would be greatly appreciated.

  36. Howdy! I simply would like to give you a huge thumbs up
    for the excellent information you have right here on this
    post. I will be returning to your website for more soon.

  37. Do you mind if I quote a couple of your posts as long as I provide credit and sources back to your website?
    My blog is in the exact same area of interest as yours and my
    visitors would really benefit from a lot
    of the information you provide here. Please let me know if this alright with you.
    Thanks a lot!

  38. An outstanding share! I have just forwarded this onto a co-worker who had
    been doing a little research on this. And he actually bought me lunch simply because I stumbled upon it
    for him… lol. So allow me to reword this….
    Thanks for the meal!! But yeah, thanks for
    spending some time to talk about this topic here on your web site.

  39. Pretty part of content. I simply stumbled upon your website and in accession capital to assert that I get actually enjoyed
    account your blog posts. Anyway I’ll be subscribing in your augment or even I success you
    access persistently quickly.

  40. Hi outstanding website! Does running a blog like
    this take a large amount of work? I have absolutely no
    knowledge of coding but I had been hoping to start my own blog soon. Anyhow,
    if you have any ideas or tips for new blog owners please share.
    I know this is off topic however I simply wanted to ask.
    Appreciate it!

  41. Do you have a spam issue on this site; I
    also am a blogger, and I was wanting to know your situation; many of us have created some nice
    practices and we are looking to swap solutions with others, why
    not shoot me an email if interested.

  42. Hi there everybody, here every person is sharing such experience, so
    it’s good to read this blog, and I used to pay a visit this website everyday.

  43. Very nice post. I just stumbled upon your blog and wanted to say that I have
    truly enjoyed browsing your blog posts. In any case I will be subscribing to your feed and I
    hope you write again soon!

  44. Hi there Dear, are you truly visiting this web site daily, if so afterward you will without doubt
    take nice knowledge.

  45. My brother recommended I might like this web
    site. He used to be entirely right. This publish actually made my day.
    You cann’t imagine simply how so much time I had spent for this info!

    Thank you!

  46. I like the valuable info you supply to your articles.
    I will bookmark your blog and check once more right here regularly.
    I’m moderately certain I’ll be told a lot of new stuff proper right here!

    Best of luck for the next!

  47. Can I simply say what a relief to discover somebody that genuinely understands what they are talking about
    online. You actually realize how to bring a problem to light and make it important.

    More and more people must check this out and understand this side of your story.
    I was surprised you aren’t more popular since you surely have
    the gift.

  48. Hi there just wanted to give you a quick heads up.
    The words in your content seem to be running off the screen in Opera.
    I’m not sure if this is a format issue or something to do with internet browser compatibility but I
    thought I’d post to let you know. The design and style look great though!
    Hope you get the problem fixed soon. Kudos

  49. Hey! Quick question that’s completely off topic. Do you know how to make your site mobile friendly?
    My website looks weird when viewing from my apple iphone.
    I’m trying to find a theme or plugin that might be able to resolve this issue.

    If you have any recommendations, please share. With thanks!

  50. It’s perfect time to make some plans for the future and it’s
    time to be happy. I’ve read this post and if I could I wish to suggest you some interesting things or tips.

    Maybe you can write next articles referring to this article.
    I desire to read more things about it!

  51. of course like your website but you need to take
    a look at the spelling on several of your posts. Several of them are rife with spelling issues
    and I find it very bothersome to tell the reality on the other hand I will
    certainly come back again.

  52. Hey I know this is off topic but I was wondering if you knew of any widgets I could add to my blog that automatically tweet
    my newest twitter updates. I’ve been looking for a plug-in like this for quite some time and was hoping maybe you would have some experience with something like
    this. Please let me know if you run into anything.

    I truly enjoy reading your blog and I look forward to your new updates.

  53. Hi! I know this is somewhat off topic but I was wondering which blog platform are you using for this site?

    I’m getting tired of WordPress because I’ve had issues
    with hackers and I’m looking at options for another platform.
    I would be great if you could point me in the direction of a good platform.

  54. This design is steller! You certainly know how to keep a reader amused.

    Between your wit and your videos, I was almost moved to start my own blog (well, almost…HaHa!) Great job.
    I really loved what you had to say, and more than that, how you presented
    it. Too cool!

  55. I was suggested this blog by my cousin. I’m not sure whether this post is written by him as nobody else know such detailed about my trouble.
    You’re wonderful! Thanks!

  56. Do you mind if I quote a couple of your posts as long as I provide credit and sources back to your website?

    My blog is in the exact same niche as yours and my users would certainly benefit from a lot of the information you provide here.
    Please let me know if this alright with you.
    Cheers!

  57. Hi there! This is my first visit to your blog! We are a collection of volunteers
    and starting a new initiative in a community in the same niche.
    Your blog provided us useful information to work on. You have done a wonderful job!

  58. I every time used to study paragraph in news papers
    but now as I am a user of net thus from now I am using net for
    posts, thanks to web.

  59. My spouse and I absolutely love your blog and find almost all of your post’s to be just what I’m looking for.
    Does one offer guest writers to write content for you personally?

    I wouldn’t mind composing a post or elaborating on a lot of the subjects
    you write with regards to here. Again, awesome web
    log!

  60. Attractive component to content. I simply stumbled upon your blog and in accession capital to claim that I get actually loved account your blog posts.
    Anyway I will be subscribing in your augment
    or even I success you access persistently rapidly.

  61. Today, I went to the beach front with my children. I found a sea shell and gave it to
    my 4 year old daughter and said “You can hear the ocean if you put this to your ear.”
    She put the shell to her ear and screamed. There was a hermit crab inside and it
    pinched her ear. She never wants to go back! LoL I know this is entirely off topic but I had to tell someone!

  62. Hello there! This article couldn’t be written any better!
    Reading through this article reminds me of my previous roommate!
    He continually kept preaching about this.

    I am going to forward this information to him. Pretty sure he’ll have
    a good read. Thanks for sharing!

  63. My spouse and I absolutely love your blog and find the majority of your post’s to be just what I’m looking for.
    Would you offer guest writers to write content for you personally?
    I wouldn’t mind publishing a post or elaborating on some of the subjects you write about
    here. Again, awesome site!

  64. I must thank you for the efforts you have put in writing this
    website. I’m hoping to check out the same high-grade content by you in the future as well.

    In fact, your creative writing abilities
    has encouraged me to get my very own site now 😉

  65. Great beat ! I wish to apprentice while you amend your website, how
    can i subscribe for a blog site? The account aided me a acceptable deal.
    I had been tiny bit acquainted of this your broadcast provided bright clear idea

  66. Hey! I know this is kind of off topic but I was wondering which blog platform
    are you using for this website? I’m getting fed up of WordPress because I’ve had
    issues with hackers and I’m looking at options for another platform.
    I would be awesome if you could point me in the direction of a
    good platform.

  67. auto liker, Photo Liker, Photo Auto Liker, auto like, Autolike International, Working Auto Liker, Auto Like, Increase Likes, Auto Liker, Autolike, Status Liker, Status Auto Liker, Autoliker, Autoliker, autolike, autoliker, ZFN Liker

  68. I’m really enjoying the design and layout of your website.
    It’s a very easy on the eyes which makes it much more pleasant for me to come here and visit more often. Did you
    hire out a designer to create your theme?
    Exceptional work!

  69. Hey there! I’ve been following your website for some time now and finally got the courage to go ahead and give you a shout out from Porter Texas!
    Just wanted to tell you keep up the fantastic job!

  70. Does your blog have a contact page? I’m having trouble locating it but, I’d like to send you an email.

    I’ve got some ideas for your blog you might be interested in hearing.

    Either way, great blog and I look forward to seeing it develop over time.

  71. After looking over a handful of the articles on your web site,
    I truly like your technique of writing a blog.

    I bookmarked it to my bookmark webpage list and will be checking back soon. Please visit my web site too and tell me what you think.

  72. Sweet blog! I found it while surfing around on Yahoo News.
    Do you have any tips on how to get listed in Yahoo News?
    I’ve been trying for a while but I never seem to get there!
    Many thanks

  73. Hey there! I’ve been reading your web site for a while now and finally got the bravery to go ahead and give you a shout out from Dallas Tx!
    Just wanted to say keep up the excellent work!

  74. After exploring a number of the blog posts on your web
    site, I truly appreciate your technique of blogging.
    I book-marked it to my bookmark webpage list and will be checking
    back soon. Please check out my web site too and tell me your opinion.

  75. Whats up this is kinda of off topic but I was wanting
    to know if blogs use WYSIWYG editors or if you have to manually
    code with HTML. I’m starting a blog soon but have no coding know-how so I wanted to get guidance from someone with experience.
    Any help would be greatly appreciated!

  76. Congrats on registering your domain!

    The next step you can do for your website is to make sure listed in the search engines.
    Getting your website included in the search engines is the first you should take as a new webmaster or domain owner.

    Please register your website as soon as possible so your new domain is properly indexed.

    This Notice will expire at 11:59PM EST, 4 – Jun – 2019 Act now!

    Boost your website ranking in Google, Bing and Yahoo follow the link below :

    http://bucc.com.br/domain/

  77. On 21th anniversary of HostWebis.com we would like to offer you a 5€ discount code on our shared and reseller hosting, VPS, and dedicated servers. It includes free domain registration or transfer and the possibility to register your own .pt domain name!
    Don’t forget to use the coupon code 5gift when ordering.
    Thank you for your time and best of luck for your business.
    https://www.hostwebis.com

  78. Hello! mfosullivan.com

    We make available

    Sending your commercial proposal through the Contact us form which can be found on the sites in the contact partition. Feedback forms are filled in by our program and the captcha is solved. The superiority of this method is that messages sent through feedback forms are whitelisted. This method increases the odds that your message will be open.

    Our database contains more than 25 million sites around the world to which we can send your message.

    The cost of one million messages 99 USD

    FREE TEST mailing of 50,000 messages to any country of your choice.

    This message is automatically generated to use our contacts for communication.

    Contact us.
    Skype – live:contactform_18
    Email – ContactForm@make-success.com
    WhatsApp – +353899461815

  79. Fantastic beat ! I wish to apprentice while you amend your website,
    how can i subscribe for a weblog web site? The account aided me a acceptable deal.
    I have been a little bit familiar of this your broadcast offered
    bright transparent idea

  80. Excellent goods from you, man. I have understand your stuff previous to and you are just
    extremely great. I actually like what you’ve acquired here, certainly like what you’re saying
    and the way in which you say it. You make it entertaining and you still take care of to keep it
    smart. I can not wait to read far more from you. This is really a
    great website.

  81. Thanks , I’ve just been looking for info about this
    topic for a long time and yours is the best I have discovered so far.
    But, what concerning the conclusion? Are you positive about the supply?

  82. Thanks for the marvelous posting! I certainly enjoyed
    reading it, you will be a great author.I will make certain to bookmark
    your blog and will eventually come back later on. I want to encourage that you continue your
    great posts, have a nice weekend!

  83. Hello! mfosullivan.com

    We put up of the sale

    Sending your commercial proposal through the feedback form which can be found on the sites in the contact section. Contact form are filled in by our application and the captcha is solved. The advantage of this method is that messages sent through feedback forms are whitelisted. This method raise the probability that your message will be open. Mailing is done in the same way as you received this message.
    Your commercial proposal will be open by millions of site administrators and those who have access to the sites!

    The cost of sending 1 million messages is $ 49 instead of $ 99. (you can select any country or country domain)
    All USA – (10 million messages sent) – $399 instead of $699
    All Europe (7 million messages sent)- $ 299 instead of $599
    All sites in the world (25 million messages sent) – $499 instead of $999
    There is a possibility of FREE TEST MAILING.

    Discounts are valid until June 10.
    Feedback and warranty!
    Delivery report!
    In the process of sending messages we don’t break the rules GDRP.

    This message is automatically generated to use our contacts for communication.

    Contact us.
    Telegram – @FeedbackFormEU
    Skype – FeedbackForm2019
    Email – FeedbackForm@make-success.com
    WhatsApp – +44 7598 509161

    All the best

  84. Great items from you, man. I’ve consider your stuff previous to and you are simply extremely wonderful.

    I actually like what you have received here, really like what you’re saying and the best way in which you assert it.
    You make it entertaining and you still take care of to keep it smart.
    I cant wait to learn much more from you. This
    is really a wonderful website.

  85. Hey! I just wanted to ask if you ever have any issues with hackers?
    My last blog (wordpress) was hacked and I ended up losing
    several weeks of hard work due to no data backup.

    Do you have any methods to stop hackers?

  86. Fantastic beat ! I would like to apprentice while you amend your website, how can i subscribe for
    a blog web site? The account helped me a acceptable deal.

    I had been a little bit acquainted of this your broadcast
    provided bright clear concept

  87. Привет! команда СЕО для раскрутки и продвижения сайтов в поисковых серверах и соц интернет-сетях. И меня зовут Антон, я создатель большой группы маркетологов, разработчиков, линкбилдеров, копирайтеров, рерайтеров/копирайтеров, link builders, профессионалов, оптимизаторов, специалистов. Мы — команда амбициозных профи с 10-летним опытом работы в области фриланса. Наши квалифицированные специалисты несомненно помогут вашему любому вебсайту завладеть ТОП 10 в выдаче поиска каждой системе. Для вас мы предлагаем высококачественную раскрутку сайтов в поисковых сервисах! Все наши работники прошли громадный профессиональный путь, мы знаем, как грамотно организовывать ваш сервис, продвинуть его на первое место, преобразовывать трафик в заказы. Наша командапредоставляет вам лично бесплатное предложение по раскрутке любых веб-сайтов. Мы ждем Вас!

    seo продвижение сайта бесплатно бесплатный сео анализ

  88. I like the valuable information you supply to your articles.
    I will bookmark your weblog and take a look at again here frequently.
    I’m moderately sure I’ll be told lots of new stuff proper right here!
    Good luck for the following!

  89. Hi there just wanted to give you a quick heads up. The words in your
    article seem to be running off the screen in Safari.
    I’m not sure if this is a format issue or something to do with web
    browser compatibility but I figured I’d post to
    let you know. The design look great though! Hope you get the issue solved soon. Thanks

  90. Thanks a lot for sharing this with all folks you actually realize what you’re speaking about!
    Bookmarked. Please also seek advice from my web site =).

    We may have a hyperlink change arrangement between us

  91. Oh my goodness! Awesome article dude! Many thanks, However I am
    experiencing issues with your RSS. I don’t know the
    reason why I cannot join it. Is there anyone else getting the same RSS problems?
    Anybody who knows the solution can you kindly respond?
    Thanx!!

  92. Oh my goodness! Impressive article dude! Thanks, However I am experiencing problems with your RSS.
    I don’t know why I am unable to join it. Is there anyone else getting identical
    RSS problems? Anyone who knows the solution will you kindly respond?
    Thanx!!

  93. Hi there, i read your blog from time to time
    and i own a similar one and i was just curious if you get a lot of spam responses?
    If so how do you stop it, any plugin or anything you can advise?

    I get so much lately it’s driving me mad so any assistance is very much appreciated.

  94. Hey outstanding website! Does running a blog such as this
    take a large amount of work? I have no understanding of computer programming but I had been hoping to start my own blog
    soon. Anyhow, should you have any suggestions or tips for new blog owners
    please share. I know this is off subject nevertheless I simply needed
    to ask. Appreciate it!

  95. I’ll immediately snatch your rss as I can not find your e-mail subscription hyperlink or newsletter service.

    Do you’ve any? Please allow me recognise so that I may just subscribe.

    Thanks.

  96. You actually make it seem so easy with your presentation however I
    find this matter to be really one thing which I believe I would by no means understand.
    It seems too complex and extremely large for me.
    I’m having a look ahead on your next publish, I will
    attempt to get the dangle of it!

  97. I’m no longer positive where you are getting your information, but great topic.
    I must spend a while learning more or working out more.
    Thanks for excellent info I was looking for this info for
    my mission.

  98. Добрый вечер! Мы команда СЕО экспертов занимающихся продвижения и раскрутки интернет-ресурсов в любых типах поисковых системах, а также в соц интернет-сетях. Меня зовут Антон, я основатель компании маркетологов, линкбилдеров, профессионалов, разработчиков, специалистов, копирайтеров, link builders, рерайтеров/копирайтеров, оптимизаторов. Мы – команда высококлассных фрилансеров. Эта команда вашему любому веб-сайту подняться в ТОП 10 в поисковой выдаче различный системе. Для вас мы предлагаем лучшую раскрутку online-сайтов в поисковых сервисах! У всех работников представленной seo-команды за плечами гигантский высокопрофессиональный путь, мы знаем, как грамотно создавать ваш личный сервис, выдвигать его на первое место, перестроить web-трафик в заказы. У нас сейчас есть для Лично для вас бесплатное предложение по раскрутке всех ваших сайтов. Мы ждем Вас!

    бесплатный сео анализ сайта системы продвижения сайта бесплатно

  99. Heya! I just wanted to ask if you ever have any issues with hackers?
    My last blog (wordpress) was hacked and I ended up losing several weeks of
    hard work due to no data backup. Do you have any solutions to prevent hackers?

  100. Hello there, I do believe your website may be having web browser compatibility issues.
    Whenever I look at your site in Safari, it looks fine but when opening in IE, it has some
    overlapping issues. I just wanted to provide you
    with a quick heads up! Aside from that, wonderful website!

  101. Our purpose at vape4style.com is to deliver our customers along with the very best vaping experience achievable, helping them vape snappy!. Based in New York City and in service because 2015, we are actually a customized vaping warehouse store offering all sorts of vape mods, e-liquids, pure nicotine sodiums, case devices, containers, coils, and also other vaping extras, like batteries and outside battery chargers. Our e-juices are constantly new considering that we certainly not simply offer our products retail, however additionally distribute to nearby NYC shops along with provide wholesale options. This permits our company to regularly turn our stock, providing our clients and establishments with the best freshest supply possible.

    If you are actually a vaper or attempting to get off smoke, you remain in the best place. Intend to spare some cash in process? Hurry and join our email subscriber list to receive special nightclub VIP, vape4style price cuts, promos as well as cost-free giveaways!

    Our company are an unique Northeast Yihi representative. We are likewise licensed reps of Negative Drip, Port Vape, Charlie’s Chalk Dust, Beard Vape, SVRF through Saveur Vape, Ripe Vapes, Smok, Segeli, Lost Vape, Kangertech, Triton and many more. Don’t observe something you are actually searching for on our web site? Certainly not a problem! Only allow our team understand what you are seeking and also we will certainly discover it for you at a inexpensive price. Have a concern about a specific product? Our vape experts will be glad to deliver more information about everything our experts sell. Merely send us your inquiry or even phone our team. Our crew will definitely rejoice to assist!

    smok vaping device hardware store : Yihi SX Mini X Class

  102. Admiring the commitment you put into your website and in depth information you provide.
    It’s good to come across a blog every once in a while that isn’t
    the same out of date rehashed material. Wonderful
    read! I’ve bookmarked your site and I’m adding your RSS feeds to my Google account.

  103. I simply couldn’t leave your web site prior to suggesting that I extremely enjoyed the usual info
    an individual provide on your guests? Is gonna be back ceaselessly to inspect new posts

  104. Hello I am so delighted I found your site, I really found you by accident, while I was researching
    on Aol for something else, Anyways I am here now and would just like to say thanks for a marvelous post
    and a all round entertaining blog (I also love the theme/design), I
    don’t have time to browse it all at the minute but I have bookmarked it and also
    included your RSS feeds, so when I have time I will be back to
    read more, Please do keep up the great job.

  105. Domestic maid Fort Greene – starting a cleaning service

    Our specialists firms Clifton do spring general cleaning.

    Our company does spring garden cleaning not only in urban areas , but with joy we will help tidy up .

    Our General Partnership cleaning organization Woodlawn WHITAKER, is engaged spring cleaning 2018 in Midtown under the direction of WHEELER.

    Today cleaning with the onset of spring is chance to do cleaning work, private households and offices, apartments.
    Roads, courtyards, gardens, squares and other urban areas not only required clean up after winter Today, cleaning in the spring time is chance do cleaning work, rooms and also in my apartment.
    Roads, courtyards, parks, squares and urban territories not only clean up from the pollution caused by the winter, take out the garbage, and also prepare the territory for the summer. For this purpose should be restored damaged bardyurfs and pavements fix broken architectural small forms sculptures, flowerpots,artificial reservoirs,benches, fences, and so on, refresh fences, painting and other.
    Our firm does spring general cleaning in the district, but with joy we can tidy up .
    Our competent specialists Douglaston can hold spring cleaning.

  106. I like the helpful information you supply to your articles.
    I’ll bookmark your blog and take a look at once more here frequently.
    I am fairly certain I’ll be informed many new stuff proper here!
    Best of luck for the next!

  107. Hi, i believe that i saw you visited my blog thus i came to return the want?.I am attempting to find issues to improve my site!I suppose its
    ok to make use of some of your ideas!!

  108. Admiring the hard work you put into your blog and detailed information you provide.
    It’s awesome to come across a blog every once in a while that isn’t
    the same unwanted rehashed information. Great read!

    I’ve saved your site and I’m adding your RSS feeds to my Google account.

  109. I have been surfing online more than 4 hours today,
    yet I never found any interesting article like yours.
    It’s pretty worth enough for me. Personally, if all web owners and bloggers
    made good content as you did, the web will be a lot more useful than ever before.

  110. An outstanding share! I’ve just forwarded this onto a colleague who was conducting a little research on this.
    And he in fact bought me dinner because I discovered it for him…

    lol. So let me reword this…. Thank YOU for the meal!!
    But yeah, thanks for spending the time to discuss
    this matter here on your internet site.

  111. Excellent items from you, man. I have keep in mind your stuff previous to and you are just too excellent.

    I actually like what you’ve received here, really like what you’re stating and the way in which wherein you are saying it.

    You are making it entertaining and you still take care of to
    keep it sensible. I can not wait to read much more from
    you. This is really a tremendous site.

  112. I got this web site from my buddy who informed me about this web page and at the moment this time I am browsing this web page and reading very informative posts at this place.

  113. I have read a few good stuff here. Certainly value
    bookmarking for revisiting. I wonder how a lot
    effort you set to create the sort of fantastic informative web site.

  114. Amazing! This blog looks exactly like my old one! It’s on a
    totally different subject but it has pretty much the same layout and design. Excellent choice of colors!

  115. Hey there! This is kind of off topic but I need some advice from
    an established blog. Is it difficult to set up your own blog?
    I’m not very techincal but I can figure things out pretty quick.
    I’m thinking about making my own but I’m not sure where to
    start. Do you have any points or suggestions? Appreciate it

  116. You could certainly see your expertise within the article you write.
    The sector hopes for more passionate writers such as you who aren’t afraid to mention how they believe.

    At all times follow your heart.

  117. Hi! I know this is somewhat off topic but I was wondering
    which blog platform are you using for this site?
    I’m getting fed up of WordPress because I’ve had issues with hackers and I’m
    looking at options for another platform. I would be fantastic if you could point me
    in the direction of a good platform.

  118. Our experts are actually an exclusive Northeast Yihi representative. Our team are likewise authorized distributors of Poor Drip, Marina Vape, Charlie’s Chalk Dust, Beard Vape, SVRF through Saveur Vape, Ripe Vapes, Smok, Segeli, Shed Vape, Kangertech, Triton and also a lot more. Don’t see one thing you are actually trying to find on our internet site? Not a concern! Simply allow our company understand what you are actually seeking and we will certainly discover it for you at a reduced price. Possess a question regarding a certain product? Our vape professionals will be glad to supply additional information concerning anything we sell. Only send our team your question or phone our team. Our staff will certainly be glad to assist!

    If you are a vaper or making an effort to leave smoke cigarettes, you remain in the appropriate spot. Desire to save some amount of money in process? Hurry and join our e-mail subscriber list to acquire unique nightclub VIP, vape4style markdowns, promotions and complimentary giveaways! Yihi SX Mini G

    Our mission at vape4style.com is actually to supply our consumers with the very best vaping experience achievable, helping them vape snappy!. Located in NYC and in business due to the fact that 2015, our company are actually a customized vaping warehouse store offering all types of vape mods, e-liquids, smoking sodiums, husk bodies, tanks, coils, and various other vaping extras, including batteries as well as outside battery chargers. Our e-juices are actually regularly clean due to the fact that our company certainly not simply offer our items retail, however also distribute to neighborhood NYC shops as well as provide retail options. This allows our company to continuously turn our sell, offering our consumers and also stores along with one of the most best inventory possible.

  119. I do not even know how I ended up here, but I thought this
    post was great. I don’t know who you are but definitely you’re going to a famous blogger if you are not already 😉 Cheers!

  120. An interesting discussion is worth comment. There’s no doubt that that you should write more on this subject matter, it might not be a taboo matter but usually people don’t talk about these subjects. To the next! Kind regards!

  121. Sorry for making you review this message which is probably to be considered by you as spam. Yes, spamming is a bad thing.

    On the other hand, the very best way to find out something new, heretofore unknown, is to take your mind off your day-to-day problems as well as reveal passion in a subject that you may have considered as spam before. Right? jewelry ring

    We are a group of young men that have made a decision to begin our very own service and also make some money like several other individuals on Earth.

    What do we do? We offer our site visitors a large choice of wonderful handcrafted rings. All the rings are made by the best artisans from all over the USA.

    Have you ever before seen or worn an environment-friendly opal ring, timber ring, fire opal ring, Damascus ring, silver opal ring, Blue-green ring, blue opal ring, pink ring, meteorite ring, black ring or silver ring? This is only a tiny component of what you can always find in our shop.

    Made in the UNITED STATES, our handmade rings are not simply stunning and also original presents for, claim, a wedding event or birthday, yet additionally your talisman, a point that will absolutely bring you all the best in life.

    As payment for your time spent on reading this message, we offer you a 5% discount rate on any kind of product you are interested in.

    We are eagerly anticipating conference you in our shop!

  122. I’m truly enjoying the design and layout of your site. It’s a very easy on the eyes which makes it much more pleasant
    for me to come here and visit more often. Did you hire out a designer to create your
    theme? Superb work!

  123. Hello there, I found your web site by the use of Google even as looking for a comparable matter,
    your web site got here up, it appears good.
    I’ve bookmarked it in my google bookmarks.
    Hello there, simply became alert to your weblog thru Google, and located that it’s really informative.
    I am gonna be careful for brussels. I’ll be
    grateful in case you proceed this in future.
    Lots of other folks will be benefited from your writing.
    Cheers!

  124. Главный сервис Яндекс такси позволяет людям вызвать автомобиль когда и куда угодно. Сделать заказ авто вы можете тремя способами: по телефону через оператора, на сайте Яндекс такси, мобильное приложение. Вам нужно назвать адрес, ваш номер мобильного, время когда требуется автомобиль.

    Заказывают Я. такси с детским авто креслом для перевозки деток, вечером после встреч стоит прибегнуть к Яндекс такси, чем садиться в транспортное средство нетрезвым, в аэропорт или на вокзал удобнее пользоваться Я. такси ненужно думать где оставить свою машину. Оплата производится наличным или безналичным переводом. Время прибытия Я. такси составляет от трех до десяти минут примерно.

    Положительные моменты работы в Я. такси: Моментальная регистрация в приложение, Незначительная комиссия, Выплаты мгновенные, Постоянный поток заказов, Оператор круглыми сутками на связи.

    Для выполнения работ в Яндекс такси водителю следует оформиться лично и средство передвижения, все это займёт не больше 5 минут. Наша комиссия составит не больше 20 процентов. Вы можете без проблем получать заработную плату в любое время. У вас всегда будут заказы. В случае проблем сможете соединиться с круглосуточно функционирующей службой поддержки. Яндекс такси помогает гражданам быстро добраться до места назначения. Заказывая наше современное Яндекс такси вы приобретаете первоклассный сервис в г. Самара.

    яндекс такси вакансии диспетчер : яндекс такси работа водителем на своем авто

  125. Tadacip 20 Online Prix Рір‚вђ№рір‚вђ№de Priligy Online Propecia Rx cialis canada Effets Secondaires De Amoxil No Prescription

  126. Good day to you,
    My name is Barrister Wilfred Russell, a British lawyer. I have previously sent you a message regarding a transaction worth $ 10.5 million left by my late client before his tragic death.
    I am contacting you once again because after going through your profile, I strongly believe that you will be in a better position to execute this business transaction with me. Please if you are interested, I wish to point out that after the transaction I want 10% of this money to be donated among charity organizations while the remaining 90% will be shared equal by the both of us.
    This transaction is 100% risk free; please respond to me as soon as possible for more detailed information. Here is my email: wilfredruse@gmail.com
    Yours Faithfully,
    Barrister Wilfred Russell

  127. Howdy, i read your blog occasionally and i own a similar one and i
    was just curious if you get a lot of spam responses?

    If so how do you prevent it, any plugin or anything you can recommend?
    I get so much lately it’s driving me mad so any help
    is very much appreciated.

  128. Pretty section of content. I just stumbled upon your website and in accession capital to assert that I
    acquire actually enjoyed account your blog posts.
    Anyway I will be subscribing to your feeds and even I achievement you access
    consistently quickly.

  129. Hello there! This post could not be written any better! Going through
    this post reminds me of my previous roommate!
    He always kept preaching about this. I am going to forward this article
    to him. Pretty sure he’s going to have a good read. Thank you for
    sharing!

  130. A person essentially assist to make seriously
    articles I would state. That is the first time I frequented your website page
    and to this point? I surprised with the analysis
    you made to make this actual put up amazing. Magnificent
    task!

  131. Hi! mfosullivan.com

    We present oneself

    Sending your message through the feedback form which can be found on the sites in the contact section. Contact form are filled in by our program and the captcha is solved. The profit of this method is that messages sent through feedback forms are whitelisted. This method raise the probability that your message will be open.

    Our database contains more than 25 million sites around the world to which we can send your message.

    The cost of one million messages 49 USD

    FREE TEST mailing of 50,000 messages to any country of your choice.

    This message is automatically generated to use our contacts for communication.

    Contact us.
    Telegram – @FeedbackFormEU
    Skype FeedbackForm2019
    WhatsApp – +44 7598 509161
    Email – FeedbackForm@make-success.com

  132. Ciao! mfosullivan.com

    We propose

    Sending your commercial proposal through the feedback form which can be found on the sites in the Communication section. Feedback forms are filled in by our program and the captcha is solved. The profit of this method is that messages sent through feedback forms are whitelisted. This method improve the chances that your message will be read.

    Our database contains more than 25 million sites around the world to which we can send your message.

    The cost of one million messages 49 USD

    FREE TEST mailing of 50,000 messages to any country of your choice.

    This message is automatically generated to use our contacts for communication.

    Contact us.
    Telegram – @FeedbackFormEU
    Skype FeedbackForm2019
    Email – FeedbackForm@make-success.com
    WhatsApp – +44 7598 509161