How to Develop and Deploy Your First Full-Stack Web App Using a Static Site and Node.js

Are you a front-end developer looking to expand your skills and deploy your first full-stack web app? Converting a static site to use Node.js on the back-end is a great place to start.

In this step-by-step guide, I‘ll show you how to take a static site (HTML, CSS and client-side JS) and enhance it with Node.js to create a dynamic, database-driven web app. You‘ll learn how to install Node.js, convert HTML pages to use a templating engine, integrate a MongoDB database, and deploy your app on DigitalOcean with a custom domain name and SSL certificate.

By the end of this tutorial, you‘ll have a working full-stack web app live on the internet that you can use as a base for your own projects. Let‘s get started!

Overview of the Tech Stack

Here‘s an overview of the technologies we‘ll be using:

  • Front-end: HTML, CSS, JavaScript
  • Back-end: Node.js with Express.js framework
  • Database: MongoDB
  • Templating Engine: EJS (Embedded JavaScript)
  • Hosting: DigitalOcean droplet running Ubuntu Linux
  • Version Control: Git and GitHub

This is similar to the popular MEAN (MongoDB, Express, Angular, Node) and MERN (MongoDB, Express, React, Node) stacks but instead of Angular or React, we‘re using a templating language called EJS.

EJS lets you generate dynamic HTML pages on the server by embedding JavaScript code in your HTML. This allows you to insert content that changes based on user input, query parameters, or data from your database.

Some benefits of this architecture:

  • Node.js allows you to use JavaScript on the back-end, so you can reuse front-end skills and share code between client and server.
  • Express provides a minimal, flexible web app framework for Node.js making it easy to define routes and implement features like user authentication.
  • MongoDB is a NoSQL database that stores data in flexible, JSON-like documents, which is a good fit for Node.js applications.
  • EJS is a simple templating language that lets you generate HTML dynamically while still writing semantic templates.
  • Hosting on a cloud platform like DigitalOcean allows you to deploy your app quickly and scale resources as your app grows in usage.

Now that you have an overview of the components, let‘s jump into setting up your development environment.

Setting up your Development Environment

Before we start coding, you‘ll need to install Node.js and MongoDB on your local computer.

Installing Node.js is straightforward. Visit the official Node.js website at https://nodejs.org and download the installer for your operating system. I recommend choosing the LTS (Long Term Support) version for stability. Run the installer with the default options and you‘ll have Node.js and npm (Node Package Manager) set up.

To verify the installation, open a terminal window and run:

node -v
npm -v

You should see the version numbers printed out, indicating Node.js and npm are working.

Next, install MongoDB by following the official documentation for your operating system: https://docs.mongodb.com/manual/administration/install-community/

After installing, make sure the MongoDB service is running. On Mac, you can use brew services start mongodb-community. On Windows, MongoDB should be running as a service.

Now you‘re ready to start building your app!

Creating a Basic Express App

Let‘s start by creating a basic Express app to serve your static site. Create a new folder for your project and initialize it as a Node.js app by running:

npm init -y

This will create a package.json file with some default configuration.

Next, install Express by running:

npm install express

Create a file called server.js and add the following code:

const express = require(‘express‘);
const app = express();
const port = 3000;

app.use(express.static(‘public‘));

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

This code:

  1. Imports the Express module
  2. Creates an Express app
  3. Serves static files from a folder called "public"
  4. Starts the server listening on port 3000

Create a folder called "public" and put your static site files (HTML, CSS, client-side JS, images) inside it.

Now run the app with:

node server.js

Visit http://localhost:3000 in your browser and you should see your static site being served by Node.js!

Converting HTML to EJS Templates

To make your pages dynamic, you‘ll need to convert your HTML files to use a templating engine. We‘ll use EJS (Embedded JavaScript).

First, install EJS as a project dependency:

npm install ejs

Next, create a folder called "views" and move your HTML files into it. Rename the .html file extensions to .ejs.

Update your server.js file to use EJS as the view engine:

app.set(‘view engine‘, ‘ejs‘);

Change your routes to use res.render() to render EJS templates instead of serving static HTML files. For example:

app.get(‘/‘, (req, res) => {
  res.render(‘index‘);
});

This will render the index.ejs template when a user visits the root URL.

You can now embed JavaScript directly in your EJS templates to dynamically insert content. For example:

Then in your route handler:

app.get(‘/‘, (req, res) => {
  res.render(‘index‘, { name: ‘John‘ });
});

When you visit the page, you‘ll see "Welcome, John!" displayed on the page. The <%= %> tags output the value of the name variable into the HTML.

You can also use <% %> tags to execute JavaScript code for things like loops and conditionals.

EJS also supports partials, which allow you to reuse chunks of HTML across multiple pages. Partials are prefixed with an underscore, like _header.ejs, and can be included in other templates like:

<%- include(‘_header‘) %>

Converting your static site to use EJS makes it much easier to dynamically insert content, reuse code, and integrate with data from your Node.js back-end and database.

Adding a MongoDB Database

To store data for your app, we‘ll add a MongoDB database using the Mongoose ODM (Object Document Mapper) library.

First, install Mongoose in your project:

npm install mongoose

Next, add code in your server.js file to connect to your MongoDB database:

const mongoose = require(‘mongoose‘);

mongoose.connect(‘mongodb://localhost/myapp‘, {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

Replace ‘myapp‘ with the desired name for your database.

Now define a schema and model for the data you want to store. For example, to store blog posts:

const postSchema = new mongoose.Schema({
  title: String,
  content: String,
  date: { type: Date, default: Date.now }
});

const Post = mongoose.model(‘Post‘, postSchema);

You can then query the database in your route handlers. For example, to fetch all posts for a blog index page:

app.get(‘/‘, async (req, res) => {
  const posts = await Post.find();
  res.render(‘index‘, { posts });
});

And in your EJS template, loop through and display the posts:

<% posts.forEach(post => { %>
  <h2><%= post.title %></h2>
  <p><%= post.content %></p>
  <p><%= post.date.toDateString() %></p>
<% }) %>

Now you have a fully functioning full-stack app with a Node.js back-end and MongoDB database powering dynamic EJS templates!

You‘ll probably also want to implement features like user signup, login, and content management forms. I recommend looking into Passport.js for authentication and express-validator for form validation.

Deploying Your App to DigitalOcean

Once your app is working locally, you‘ll want to deploy it so others can access it on the public internet. We‘ll use DigitalOcean to host our app.

First, sign up for a DigitalOcean account at https://cloud.digitalocean.com and add a payment method to get some free credits.

Then, create a new Ubuntu Linux droplet. For this demo, the cheapest $5/month droplet will be sufficient.

Follow DigitalOcean‘s guide to connect to your new server via SSH: https://www.digitalocean.com/docs/droplets/how-to/connect-with-ssh/

Once you‘re connected, update the server‘s packages:

sudo apt update
sudo apt upgrade

Then follow DigitalOcean‘s guides to install Node.js and MongoDB on your droplet:

Next, clone your project‘s Git repository or copy your project files to the server. Make sure to run npm install to install the dependencies on the production server.

Then use a process manager like PM2 to keep your app running in the background:

npm install pm2 -g
pm2 start server.js

Finally, configure Nginx as a reverse proxy so you can access your app on port 80 instead of 3000:

sudo apt install nginx
sudo nano /etc/nginx/sites-available/default

Update the location block to proxy requests to your Node.js app:

location / {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection ‘upgrade‘;
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
}

Restart Nginx with:

sudo service nginx restart

Now you should be able to visit your droplet‘s IP address in a web browser and see your app!

Configuring a Domain Name and SSL

Accessing your site via an IP address isn‘t very professional, so let‘s configure a custom domain name.

First, buy a domain name from a registrar like Namecheap or Google Domains.

Then, in your domain registrar‘s control panel, create an A record that points your domain to your DigitalOcean droplet‘s IP address.

Wait a few minutes for the DNS changes to propagate. You should now be able to access your app via the domain name!

To enable HTTPS, we‘ll use Let‘s Encrypt to get a free SSL certificate.

First, install Certbot:

sudo add-apt-repository ppa:certbot/certbot
sudo apt install python-certbot-nginx

Then run Certbot:

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Follow the prompts and Certbot will automatically configure your Nginx config to use HTTPS.

Your site is now more secure and will get an SEO boost from using HTTPS. Certbot will automatically renew your certificate when needed.

Improving Performance and Maintainability

Congratulations, you‘ve deployed your first full-stack web app!

Here are some additional tips to improve your app‘s performance, scalability and maintainability:

  • Use a tool like Gulp or Webpack to minify and bundle your client-side JavaScript and CSS files.
  • Implement caching in your database queries and use a tool like Redis for server-side caching.
  • Use a CDN like Cloudflare to serve static assets and improve page load times.
  • Monitor your app for errors and performance issues using a tool like PM2 or New Relic.
  • Write unit tests for your server-side code using a testing framework like Jest or Mocha.
  • Use Git branches and pull requests to manage new features and bug fixes.
  • Implement a CI/CD pipeline using a tool like Travis or Jenkins to automatically test and deploy new code changes.
  • Back up your database regularly and have a disaster recovery plan in place.
  • Keep your dependencies up-to-date and monitor for security vulnerabilities.
  • Implement logging with a tool like Winston or Bunyan.
  • Refactor your code to keep your routes, models and view templates clean and maintainable as your app grows in complexity.

I hope this guide has been helpful in getting you started on your journey as a full-stack developer!

Building and deploying your own web app is a fantastic learning experience and an impressive addition to your portfolio. Stay curious and keep experimenting with new tools and techniques.

Similar Posts