Build a Node.js Interactive Web-Based Simple Survey App

Written by

in

In today’s digital landscape, gathering feedback is crucial for understanding your audience, improving your product, or simply gauging opinions. Surveys offer a direct and efficient way to collect this valuable information. But building a survey application from scratch can seem daunting, especially for beginners. This tutorial provides a step-by-step guide to building a simple, interactive, web-based survey application using Node.js, Express, and a touch of HTML and JavaScript. We’ll break down the process into manageable chunks, explaining each concept in clear, concise language, and providing plenty of code examples. By the end, you’ll have a functional survey app and a solid understanding of fundamental web development principles.

Why Build a Survey App with Node.js?

Node.js is an excellent choice for this project for several reasons:

  • JavaScript Everywhere: If you’re familiar with JavaScript (and you probably are if you’re reading this!), you’ll be able to use the same language for both the front-end (browser) and back-end (server) of your application. This simplifies development and reduces the learning curve.
  • Non-Blocking I/O: Node.js is built on an event-driven, non-blocking I/O model, making it highly efficient for handling multiple requests concurrently. This is particularly beneficial for web applications that need to respond to user interactions quickly.
  • Large Ecosystem: Node.js boasts a vast ecosystem of modules (available via npm, the Node Package Manager) that can streamline development. We’ll leverage some of these modules in this tutorial.
  • Scalability: Node.js applications are generally scalable, meaning they can handle increasing amounts of traffic as your survey app gains popularity.

Creating a survey app allows you to:

  • Gather Feedback: Collect opinions on products, services, or any topic you choose.
  • Improve Decision-Making: Make data-driven decisions based on the responses you receive.
  • Engage Your Audience: Interact with your users and show them you value their input.

Project Setup: Prerequisites and Tools

Before we dive into the code, let’s make sure you have the necessary tools installed:

  • Node.js and npm: Download and install Node.js from the official website (https://nodejs.org/). npm (Node Package Manager) comes bundled with Node.js. Verify the installation by running `node -v` and `npm -v` in your terminal.
  • Code Editor: Choose a code editor you’re comfortable with. Popular options include Visual Studio Code (VS Code), Sublime Text, Atom, or WebStorm.
  • Basic HTML, CSS, and JavaScript Knowledge: A fundamental understanding of these web technologies is required. Don’t worry if you’re not an expert; we’ll keep the HTML and CSS simple.

Step-by-Step Guide: Building the Survey App

1. Project Initialization and Dependencies

Let’s create a new project directory and initialize it with npm. Open your terminal and run the following commands:

mkdir survey-app
cd survey-app
npm init -y

This creates a `survey-app` directory, navigates into it, and initializes a `package.json` file with default settings. Next, we’ll install the required dependencies. We’ll use Express.js for our web server and a templating engine (we’ll use EJS, but you can choose another one like Pug/Jade or Handlebars) to render HTML dynamically.

npm install express ejs

This command installs `express` and `ejs` and adds them as dependencies in your `package.json` file.

2. Setting Up the Express Server

Create a file named `app.js` (or `index.js`, or whatever you prefer) in your project directory. This will be our main server file. Paste the following code into `app.js`:

const express = require('express');
const app = express();
const port = 3000; // Or any port you prefer

// Set the view engine to EJS
app.set('view engine', 'ejs');

// Middleware to serve static files (CSS, JavaScript, images)
app.use(express.static('public'));

// Middleware to parse URL-encoded bodies (for form data)
app.use(express.urlencoded({ extended: true }));

// Define routes (we'll add these later)
app.get('/', (req, res) => {
  res.render('index', { surveyData: null }); // Render the index.ejs view
});

app.post('/submit', (req, res) => {
  // Handle form submission (we'll add this later)
  console.log('Survey submitted:', req.body);
  res.send('Thank you for your submission!');
});

// Start the server
app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

Let’s break down this code:

  • `const express = require(‘express’);`: Imports the Express.js module.
  • `const app = express();`: Creates an Express application instance.
  • `const port = 3000;`: Defines the port the server will listen on.
  • `app.set(‘view engine’, ‘ejs’);`: Configures EJS as the view engine. This tells Express to use EJS files to render dynamic HTML.
  • `app.use(express.static(‘public’));`: Serves static files (CSS, JavaScript, images) from the `public` directory. Create a folder named `public` in your project’s root directory.
  • `app.use(express.urlencoded({ extended: true }));`: This middleware parses URL-encoded request bodies. This is crucial for handling form data submitted by the user. The `extended: true` option allows for more complex data structures in the form.
  • `app.get(‘/’, …)`: Defines a route for the root path (`/`). When a user visits the root, this route handler will render the `index.ejs` view. We’ll create this view file shortly.
  • `app.post(‘/submit’, …)`: Defines a route for handling form submissions. When a user submits the survey form, this route handler will be triggered. For now, it just logs the submitted data to the console and sends a thank-you message.
  • `app.listen(port, …)`: Starts the server and listens for incoming requests on the specified port.

3. Creating the Views (EJS Templates)

Create a directory named `views` in your project’s root directory. Inside the `views` directory, create a file named `index.ejs`. This will contain the HTML for your survey form. Paste the following code into `index.ejs`:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple Survey</title>
    <link rel="stylesheet" href="/style.css"> <!-- Link to your CSS file -->
</head>
<body>
    <div class="container">
        <h2>Simple Survey</h2>
        <form action="/submit" method="POST">
            <div class="form-group">
                <label for="question1">How satisfied are you with our service?</label>
                <select id="question1" name="question1">
                    <option value="very-satisfied">Very Satisfied</option>
                    <option value="satisfied">Satisfied</option>
                    <option value="neutral">Neutral</option>
                    <option value="dissatisfied">Dissatisfied</option>
                    <option value="very-dissatisfied">Very Dissatisfied</option>
                </select>
            </div>

            <div class="form-group">
                <label for="question2">What could we improve?</label>
                <textarea id="question2" name="question2" rows="4" cols="50"></textarea>
            </div>

            <button type="submit">Submit Survey</button>
        </form>
    </div>
</body>
</html>

This EJS template defines the structure of our survey form. Let’s break it down:

  • `<!DOCTYPE html>`, `<html>`, `<head>`, `<body>`: Standard HTML structure.
  • `<title>Simple Survey</title>`: Sets the title of the page.
  • `<link rel=”stylesheet” href=”/style.css”>`: Links to a CSS file (we’ll create this shortly) to style the form.
  • `<div class=”container”>`: A container to hold the form content.
  • `<h2>Simple Survey</h2>`: The main heading.
  • `<form action=”/submit” method=”POST”>`: The form element. The `action` attribute specifies the URL to which the form data will be submitted (`/submit`). The `method=”POST”` attribute indicates that the data will be sent using the POST method.
  • `<div class=”form-group”>`: Groups the label and input/select/textarea elements.
  • `<label>`: Labels for the form fields.
  • `<select>`: A dropdown selection for the first question.
  • `<textarea>`: A text area for the second question.
  • `<button type=”submit”>`: The submit button.

Now, let’s create a basic CSS file to style our form. In the `public` directory (created earlier), create a file named `style.css`. Add the following CSS rules:

body {
    font-family: Arial, sans-serif;
    background-color: #f4f4f4;
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
}

.container {
    background-color: #fff;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    width: 80%;
    max-width: 600px;
}

h2 {
    text-align: center;
    margin-bottom: 20px;
}

.form-group {
    margin-bottom: 15px;
}

label {
    display: block;
    margin-bottom: 5px;
    font-weight: bold;
}

select, textarea {
    width: 100%;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 4px;
    box-sizing: border-box;
    margin-bottom: 10px;
}

button {
    background-color: #4CAF50;
    color: white;
    padding: 12px 20px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    width: 100%;
}

button:hover {
    background-color: #45a049;
}

This CSS provides basic styling for the form, including fonts, colors, spacing, and button styles. Feel free to customize the CSS to match your preferences.

4. Running the Application

Now, let’s run our application. Open your terminal, navigate to your project directory (`survey-app`), and run the following command:

node app.js

This will start the Node.js server. You should see a message in the terminal indicating that the server is running (e.g., “Server is running on http://localhost:3000”). Open your web browser and go to `http://localhost:3000`. You should see the survey form rendered in your browser.

5. Handling Form Submissions

Currently, when you submit the form, the data is logged to the console, and a “Thank you” message is displayed. Let’s enhance this by:

  • Accessing the form data: The `req.body` object in the `/submit` route handler will contain the data submitted by the user.
  • Storing the data (temporarily): For simplicity, we’ll store the survey responses in an array in memory. In a real-world application, you’d likely store the data in a database (like MongoDB, PostgreSQL, or MySQL).
  • Displaying a confirmation page: We’ll create a new EJS template to display the submitted data.

Modify your `app.js` file to include the following changes:

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

app.set('view engine', 'ejs');
app.use(express.static('public'));
app.use(express.urlencoded({ extended: true }));

// Store survey responses (in-memory - for demonstration purposes)
const surveyResponses = [];

app.get('/', (req, res) => {
  res.render('index', { surveyData: null });
});

app.post('/submit', (req, res) => {
  const response = {
    question1: req.body.question1,
    question2: req.body.question2
  };
  surveyResponses.push(response);
  console.log('Survey submitted:', response);
  res.redirect('/thankyou'); // Redirect to the thank you page
});

app.get('/thankyou', (req, res) => {
    res.render('thankyou', { surveyResponses: surveyResponses });
});

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

Here’s what changed:

  • `const surveyResponses = [];`: An array to store the survey responses.
  • Inside the `/submit` route:
    • We create a `response` object using the data from `req.body`.
    • We push the `response` object into the `surveyResponses` array.
    • `res.redirect(‘/thankyou’);`: After successfully processing the form data, we redirect the user to the `/thankyou` route.
  • We added a new route, `app.get(‘/thankyou’, …)`:
    • This route renders a new EJS template, `thankyou.ejs`, and passes the `surveyResponses` data to it.

Now, create a new file named `thankyou.ejs` in your `views` directory. Add the following code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Thank You</title>
    <link rel="stylesheet" href="/style.css">
</head>
<body>
    <div class="container">
        <h2>Thank You for Your Submission!</h2>
        <p>Here's what you submitted:</p>
        <ul>
            <% surveyResponses.forEach(response => { %>
                <li>
                    <p><strong>Satisfaction:</strong> <%= response.question1 %></p>
                    <p><strong>Feedback:</strong> <%= response.question2 %></p>
                </li>
            <% }); %>
        </ul>
    </div>
</body>
</html>

This `thankyou.ejs` template displays the user’s submitted responses. The `<% surveyResponses.forEach(…) %>` block iterates through the `surveyResponses` array and displays each response in a list. The `<%= … %>` syntax is used to embed JavaScript variables (like `response.question1`) into the HTML.

Restart your server (Ctrl+C in the terminal to stop it, then `node app.js` to restart). Now, when you submit the survey, you will be redirected to the thank you page, which will display the data you submitted.

Common Mistakes and How to Fix Them

During development, you might encounter some common issues. Here’s a troubleshooting guide:

  • Server Not Running: If you can’t access your survey in the browser, double-check that the Node.js server is running correctly. Look for the “Server is running” message in your terminal. If the server is not running, start it using `node app.js`.
  • Incorrect File Paths: Ensure that your file paths in the `app.js` and `index.ejs` are correct. For example, the link to `style.css` in `index.ejs` should match the location of your CSS file in the `public` directory.
  • Missing Dependencies: If you get an error message about missing modules, make sure you have installed all the required dependencies using `npm install` (e.g., `npm install express ejs`). Check your `package.json` file to confirm that the dependencies are listed.
  • Form Data Not Being Received: If you’re not receiving the form data in the `/submit` route, make sure you have the `app.use(express.urlencoded({ extended: true }));` middleware configured in your `app.js` file. Also, verify that the `name` attributes of your form fields in `index.ejs` match the keys you’re trying to access in `req.body` (e.g., `name=”question1″`).
  • EJS Rendering Errors: If you see errors related to EJS, double-check the syntax in your EJS templates (`index.ejs` and `thankyou.ejs`). Make sure you’re using the correct EJS tags (e.g., `<% %>` for control flow, `<%= %>` for outputting values).
  • CSS Not Applying: Ensure that you’ve correctly linked your CSS file in your HTML (`<link rel=”stylesheet” href=”/style.css”>`) and that the CSS file is located in the `public` directory. Also, check your browser’s developer tools (usually accessed by right-clicking on the page and selecting “Inspect”) to see if any CSS errors are reported. You might need to clear your browser cache or hard-refresh the page (Ctrl+Shift+R or Cmd+Shift+R) to see the changes.
  • Debugging: Use `console.log()` statements to debug your code. For example, `console.log(req.body)` in your `/submit` route will help you see the data being submitted. You can also use your browser’s developer tools to inspect network requests, view console messages, and debug JavaScript.

Enhancements and Next Steps

This simple survey app provides a foundation. Here are some ideas for enhancements:

  • Database Integration: Instead of storing the survey responses in memory, store them in a database (like MongoDB, PostgreSQL, or MySQL). This will allow you to persist the data and analyze it later.
  • More Complex Questions: Add different types of questions, such as multiple-choice questions, rating scales, and date pickers.
  • Validation: Implement form validation to ensure that users provide valid input.
  • User Authentication: If you want to restrict access to the survey or personalize the experience, add user authentication.
  • Data Visualization: Use a charting library (like Chart.js or D3.js) to visualize the survey results.
  • Styling: Improve the styling of your application using CSS frameworks like Bootstrap or Tailwind CSS.
  • Error Handling: Implement more robust error handling to gracefully handle unexpected situations.
  • Deployment: Deploy your application to a cloud platform (like Heroku, AWS, or Google Cloud) so that others can access it.

Key Takeaways

  • Node.js for Web Development: Node.js is a powerful platform for building web applications, especially those requiring real-time updates or handling multiple concurrent requests.
  • Express.js for Routing and Middleware: Express.js simplifies the creation of web servers with its routing and middleware capabilities.
  • EJS for Dynamic HTML: EJS allows you to generate HTML dynamically, making it easy to create interactive web pages.
  • Form Handling: Understanding how to handle form submissions is essential for building interactive web applications.
  • Project Structure: Organize your project with a clear structure (e.g., `views`, `public`) to improve maintainability and readability.

Frequently Asked Questions (FAQ)

1. How do I deploy this application?

You can deploy your application to a cloud platform like Heroku, AWS, or Google Cloud. The process involves setting up an account, installing the necessary tools (e.g., the Heroku CLI), pushing your code to the platform’s repository, and configuring the environment variables. Each platform has its own documentation that provides detailed instructions.

2. How can I add more questions to the survey?

To add more questions, you’ll need to modify both the `index.ejs` and `app.js` files. In `index.ejs`, add more `<div class=”form-group”>` elements with appropriate labels and input fields (e.g., `<input type=”text”>`, `<select>`, `<textarea>`) for each question. Make sure each input field has a unique `name` attribute. In `app.js`, update the `/submit` route to access the new data from `req.body` and store it accordingly (e.g., in your `response` object).

3. How do I store the survey responses in a database?

To store the survey responses in a database, you’ll need to install a database driver (e.g., `mongoose` for MongoDB, `pg` for PostgreSQL, or `mysql` for MySQL). Then, you’ll need to connect to your database, define a schema for your survey responses, and modify the `/submit` route to insert the data into the database. This typically involves using the database driver’s methods (e.g., `insert`, `save`) to save the data. Remember to handle potential errors during database operations.

4. How can I style the application more effectively?

You can use CSS frameworks like Bootstrap or Tailwind CSS to quickly style your application. These frameworks provide pre-built components and styling options that can significantly reduce the amount of CSS code you need to write. Alternatively, you can write your own custom CSS rules to style the application. Consider using a CSS preprocessor like Sass or Less to organize your CSS code more efficiently.

Building this simple survey application provides a solid foundation for understanding web development with Node.js. By starting with a basic project and gradually adding features, you can gain valuable skills and build more complex and interactive web applications. The key is to break down the problem into smaller, manageable steps, understand the core concepts, and practice consistently. The ability to gather and analyze feedback is a valuable skill in any field, and with this knowledge, you are well on your way to building powerful and useful web applications that can help you do just that. Continue to experiment, explore different technologies, and never stop learning – the world of web development is constantly evolving, offering endless opportunities for growth and innovation.