Learning Outcomes

  • describe the essential features of a RESTful API
  • utilize the Feathers framework to implement a RESTful API for an application
  • incorporate a database (MongoDB) into a web application



Video walk through of this lab.

Fork this project: https://gitlab.com/langarabrian/rest2.

Remove the fork relationship, make the project private, and clone YOUR COPY of the project into your Cloud Shell environment.

Change to the project directory (e.g. cd rest2).

Install the dependencies and start the application:

npm install
PORT=8080 npm run dev

Preview the running application and verify that the signup page appears in the browser.

Stop the application with Ctrl-C.

Create REST Service Backend

Install the feathers CLI:

npm i -g @feathersjs/cli

Create a new service for the application to manage “signups”:

feathers generate service

Answer the questions as follows:

What kind of service is it? Mongoose
What is the name of the service? signups
Which path should the service be registered on? /signups
What is the database connection string? MONGODBURI

MONGODBURI is an environment variable containing the MongoDB connection string. You will have to set this before running the application, e.g.

export MONGODBURI='mongodb+srv://...'

The generated file, src/mongoose.js, is missing a connection setting. Add useUnifiedTopology: true to the list of mongodb connection settings.

In your editor, open up src/models/signups.model.ts.

There is currently a Mongoose schema definition for signups that looks something like this:

  const schema = new Schema({
    text: { type: String, required: true }
  }, {
    timestamps: true

Edit it so that it looks like this:

  const schema = new Schema({
    firstName: { type: String, required: true },
    lastName: { type: String, required: true },
    email: { type: String, required: true },
    country: { type: String, required: true },
    province: { type: String, required: true },
    postalCode: { type: String, required: true }
  }, {
    timestamps: true

Create REST Client Frontend

In public/index.html add the following lines toward the end of the file after bootstrap.min.js but before form-validation.js:

<script type="text/javascript"
<script src="//unpkg.com/@feathersjs/client@^3.0.0/dist/feathers.js"></script>

In public/form-validation.js add the following code at the beginning of the load event listener to set up the signups service in the client:

    // Set up FeathersJS app
    var app = feathers();

    // Set up REST client
    var restClient = feathers.rest();

    // Configure an AJAX library with that client

    // Connect to the `signups` service
    const signups = app.service('signups');

A little further down in public/form-validation.js there is code to validate the form fields and nothing else:

      form.addEventListener('submit', function (event) {
        if (form.checkValidity() === false) {
      }, false)

Modify it as follows to use the signups service to create a new signup when the form is valid:

      form.addEventListener('submit', function (event) {
        if (form.checkValidity()) {
            firstName: $('#firstName').val(),
            lastName: $('#lastName').val(),
            email: $('#email').val(),
            country: $('#country').val(),
            province: $('#province').val(),
            postalCode: $('#postalCode').val()
        } else {
      }, false);

Re-start the backend:

PORT=8080 npm run dev

Preview the applicaition and load in its own browser tab.

Fill out the form and submit.

You can verify that the data got added to the MongoDB database by looking at the collection in the MongoDB Atlas console.

Read Data from REST Service

Next, we will modify the client-side app so that it displays all the current signups in the table at the bottom of the page.

First, at the top of public/form_validation.js add a function at the very top of the file that adds a single row to the table:

// Adds a signup row to the table
const addSignup = signup => {
  $('#signups > tbody:last-child').append(

Then, add a function that will fetch the all of the signups from the server and then add them one at a time to the table:

// Shows the signups
const showSignups = async signupService => {
  // Find the latest 25 signups. They will come with the newest first
  const signups = await signupService.find({
    query: {
      $sort: { createdAt: -1 },
      $limit: 25

  // We want to show the newest signup last

Finally, call the showSignups function on page load. In the load event listener, add the following code just after the connection to the signups service has been established.

    // Show existing signups in the table


  1. Add the required code to public/form_validation.js to immediately add the form data to the table at the bottom of the page.
  2. Add the required code to public/form_validation.js and public/index.html to display a “Delete” button at the end of each row in the table. When the “Delete” button is clicked, the corresponding row should be deleted from the table and you should invoke the correct Feathers service method to delete the document from the MongoDB collection.
  3. Implement CI/CD (.gitlab-ci.yml) for the project so that the application will be deployed to Google Cloud Run.
  4. Stage, commit, and push the changes.