Build a Full Stack App in 40 Minutes

Published 7/26/2016

Building a full stack web applicationmeaning that you write the front-end, back-end and database codemay seem out of reach to a new developer, but it doesn't have to be.

With this tutorial, I will guide you through building an "Idea Keeper," essentially a form that takes an input, saves it to a database and displays it on the page. I estimate that you can follow these instructions and complete the app in about forty minutes. I admit I won't be able to cover many of the technologies that we will use in depth, but I will do my best to explain each part of the process and give you a general overview of how things are working together. This will be a great opportunity to get your hands dirty with every part of the web stack.

How exactly are we doing this?

Let's get a little more specific about what we're going to do before we jump into the details. We are going to use JavaScript for the entire application, front to back. We will use vanilla JavaScript, HTML and CSS to create the part of the app that will run in the client/browser. Then, we will use Node (an environment that allows us to write JavaScript outside of the browser) and Express (a framework that makes writing server-side JavaScript in Node much more pleasant). We will use SQLite, a very lightweight file-based database to store our data and we will also use Knex, a tool to communicate with our database using JavaScript. These last three technologies run code on the server. There are few other modules that we'll need, but I'll explain those when we get to them.

Step 0 - Installations

    • Download and install Atom: Atom is a text editor that we will write our code in.
    • Find your Terminal: The terminal is application that allows you to interact with you computer via a command line interface. To open the terminal on OSX, press `CMD + SPACEBAR` and start typing "terminal". Select the Terminal program to open it and you should see a box that looks like this:

    • Install Homebrew: Homebrew is a package manager that makes it easy to install other packages. Once this command completes successfully, you will be able to use `brew` as a command to install other things. Run the line in the terminal:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    • Install Node: As I mentioned above, Node is a runtime. This is going to allow you to write JavaScript for the back-end of your project. This is the environment in which you will create your server. Node also comes with another package manager called npm, which we will use in the next section. Run the following line to use Homebrew to install Node:
brew install node
  • Install Sqlite: As I mentioned in the introduction, Sqlite is a file-based database. It is commonly used for development and testing and it's the easiest database to get started with.
brew install sqlite3

Step 1 - Create the Project Structure

Now that you've installed the global development requirement, enter the following commands, one line at a time:

cd
mkdir ideaKeeper
cd ideaKeeper
mkdir public
mkdir db
touch server.js
cd public
touch index.html main.css client.js
cd ../db
touch knex.js
cd ..
atom . 

What did we just do?

We quickly created a bunch of directories and files. The first line, cd, is the command to change directories and without a directory specified, this command takes you to your home directory.

After that, we used mkdir to make a directory. We then navigated through different directories using cd. We then made more directories using mkdir again and created files using the touch command.

What about those dots? Well, two dots means that you are moving up one level in your file system. One dot means your referring to the directory that you're in. On that last line, you're telling Atom, your text editor to open everything in the directory that you're currently in.

Step 2 - Install Project Dependencies

Now that you've created your project structure, let's install some project dependencies. Make sure that you're in the root of your project folder by typing pwd (Meaning "print working directory").

You should see something like this in your prompt:

If you aren't in your project root, use cd and cd .. to navigate down and up directories, respectively, until you are in the "ideaKeeper" directory.

Once there, type the following:

npm init

This command initializes your new package manager (npm) and creates a file named package.json, that will keep track of all your project dependencies. When you enter the init command, you will be prompted to fill out a form via the command line:

For our purposes- buiding an app in 40 minutes, you don't need to worry about filling in or changing any of the initial values. Hit enter to choose the default values through the end of the form.

Now, we will install all of the project dependencies with one line of code and I'll explain what these are when we start using them. For the moment, enter the following line into the terminal:

npm install express body-parser sqlite knex --save

That command did two things. It installed the dependencies into your project and it also noted them as dependencies in the package.json file, which acts as a dependency inventory for your project. You can open that file up with Atom and check it out.

Step 3 - Write your Client Side Code

Client-side or front-end refers to the code that runs in the client, as opposed to the server.

I'm going to do less explaining here, but I encourage you to look up snippets of code and keywords that are new to you.

I generally like to start with writing some basic HTML. It is the structure of the interface that the user sees and allows you to test the functionality of the app fairly easily. Copy the following code into the index.html file:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>20 Minute Full Stack App - Idea Keeper</title>
    <link rel="stylesheet" href="/main.css">
  </head>
  <body>
    <h1>The Idea Keeper</h1>
    <form name="ideaForm" action="/ideas" method="post">
      <input type="test" name="idea" size="40" placeholder="Add an Idea">
      <button type="submit">Submit</button>
    </form>

    <ul></ul>

    <script src="https://code.jquery.com/jquery-3.1.0.min.js" ></script>
    <script type="text/javascript" src=/client.js></script>
    </body>
</html> 

Next, were going to add some simple styling to our page. Copy the following into the main.css file:

body {
  padding: 30px;
  background-color: #84888a;
  font-family: Arial, sans-serif;
  color: #fff;
}

form {
  display: flex;
  flex-direction: column;
  width: 300px;
  max-width: 90%;
}

input {
  font-size: 1.2em;
  padding: 5px;
  margin-bottom: 10px;
}

button {
  padding: 10px;
  background-color: #0f5f74;
  border: none;
  color: #fff;
}

button:hover {
  box-shadow: 3px 2px 3px #6a7988;
}

Finally, we'll add some functionality to the client-side and I'll do a little more explaining on this one. Copy the following code into your client.js file:

$(document).ready(function(){
  getIdeas();
});

function getIdeas(){
  $.get('/ideas', function(data){
    console.log(data);
    renderData(data);
  });
}

function renderData(data){
  for (var i = 0; i < data.length; i++) {
    $('ul').append('<li>' + data[i].idea + '</li>');
  }
}   

You will notice three blocks of code in the JavaScript file. The first $(document).ready() function delays running any code until the HTML is loaded. Once the page is loaded, that function calls getIdeas, which is the function that sends a request to the server (which we haven't created yet) and passes the response from that server into the next function, renderData. That last function attaches the data to the page.

Step 4 - The Server

While the client.js file is asking the server very nicely for some data, it's not much use without a server that sends the data to it. Let's create that now.

The entry point for our project is server.js, so that's where we will create the server and write the bulk of our server-side code. Open up server.js now and copy the following code into it:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var knex = require('./db/knex');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(__dirname + '/public'));

app.get('/ideas', function(req, res) {
  knex('ideas').select()
  .then(function(data){
    res.send(data);
  });
});

app.post('/ideas', function(req, res) {
  knex('ideas').insert(req.body)
  .then(function(id){
    res.redirect('/');
  });
});

app.listen(3000, function(){
  console.log('Listening on Port 3000');
});

That's a lot, I know. Let's go through what this code is doing.

  • Lines 1 and 2 are setting up the Express application, meaning that there is some behind-the-scenes magic happening.
  • Lines 3 and 4 are bringing in some of those dependencies that you installed in step 2. `body-parser` is the module that allows you to read the data that the client sends over in a request. knex is the tool that allows you to write JavaScript in order to interact with your database.
  • Line 6 mounts BodyParser as middleware, meaning that every request that comes into the server has to pass through this module.
  • Line 7 makes it possible for the server to send static files to the browser.
  • The two blocks of code between lines 9 and 21 are called routes and they handle different types of requests with different types of responses. We'll come back to those in a bit.
  • On line 23, we are binding a server to Port 3000 on our computer and making it avialable at localhost:3000 when we run it. We'll come back to this.

Step 5 - Set up the Database

In the last section, where we set up the server, we actually had a few database interactions included in the code and we breezed over them because we had not yet set up the database. Let's set up the Sqlite database now and connect all the dots.

Go back to the terminal and cd into the db/ folder that we created at the start of the project with the cd db/ command.

To create a Sqlite database type sqlite3 ideas.db into the terminal. This will create the ideas.db file and open the Sqlite3 interactive tool. Now, type the following lines into the sqlite> prompt, one at a time.

create table ideas(idea varchar(255));
insert into ideas values("Make a cool app!");
select * from ideas;

Your terminal should output Make a cool app!

We've just created a database and a table called ideas with a column/field called idea in that database. We then inserted a record into the ideas table and selected all of the records from the table (just to prove they exist). Exit the Sqlite tool by pressing CTRL + D.

Navigate back up to the root of your project by typing cd .. and initialize your Knex configuration by typing: knex init.

Go back to your project in Atom. You will notice two new files. The first is the ideas.db file which should be in your db/ directory. You don't need to do anything with this one. Just confirm that it is there. The other file is the knexfile.js, which will be in the root of the project.

Open knexfile.js and replace the existing code with the code below:

module.exports = {

  development: {
    client: 'sqlite3',
    connection: {
      filename: 'db/ideas.db'
    },
    useNullAsDefault: true
  }

};

These are your configuration settings for Knex. Next, open the knex.js file in the db/ directory. Make it look like this:

var config = require('../knexfile')['development'];
var knex = require('knex')(config);

module.exports = knex;

This file is taking your configuration settings from knexfile.js and using them to make an instance of Knex. Do you remember requiring Knex in your main server.js file? Go back and look at that file. The two files that you just created (knexfile.js and knex.js) are doing the setup to make that Knex instance available to your application.

Let's go back to server.js and talk about how we're interacting with the database. Remember these two blocks in the middle of the code?

app.get('/ideas', function(req, res) {
  knex('ideas').select()
  .then(function(data){
    res.send(data);
  });
});

app.post('/ideas', function(req, res) {
  knex('ideas').insert(req.body)
  .then(function(id){
    res.redirect('/');
  });
}); 

These are routes. They handle specific types of requests that come in from the client. Inside of them, we are using Knex to talk to our database. I won't get into the nitty gritty here, but I will roughly explain what is happening.

In the first route, we are selecting everything from the database and sending back to the client. In the second route, we are inserting the data that came in through the request (the form data) into the ideas table in the database. Then, we are redirecting back to the index.

Now, go back to the terminal and type: node server.js

Open your browser and navigate to localhost:3000

Voila! You should be seeing this:

You should be able to submit a new idea now and display it on the page.

We did it!

We just built a full stack application from beginning to end! It has a front-end that communicates with a back-end that communicates with a database. I hope you had fun building it, feel better about your coding skills and are curious about building more apps with more features. As a next step, try adding some features. How would you approach building edit and delete functionality for the app?

Want to learn more?

Galvanize offers an 8-Week part time workshop, as well as a 24-week full-time program in Web Development that teaches you how to make an impact as a contributing member of a development team.

Learn About our Immersive Programs Register for a Workshop

Sign up to get updates direct to your inbox