Express.js • Student Learning Page

Static Files & Form Data

Learn how Express serves HTML, images and other static resources, and how a simple registration/login application receives and stores form data.

1. What are Static Files?

Static files are files that clients download as they are from the server.

📄 HTML

Pages such as index.html, register.html and login.html.

🎨 CSS

Stylesheets used to control how a webpage looks.

🖼️ Images

Images can be placed inside the static directory and served to the browser.

ELI10 idea: Think of public as a cupboard. express.static() tells Express, “If a visitor asks for a file, look in this cupboard and give it to them.”

2. Using express.static()

Syntax

app.use(express.static('directory_name'));

directory_name is the path to the folder containing static files, such as public or assets.

app.use(express.static('public'));
Important: Express looks up files relative to the static directory, so the directory name itself is not part of the URL.

Step 1 — Create a public folder

Create a folder named public in the project directory. Put static files such as index.html and images inside it.

Step 2 — Create server.js

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

// Serve static files from the "public" folder
app.use(express.static('public'));

// Optional route
app.get('/', (req, res) => {
  res.send('Welcome to my static website!');
});

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

What happens when a file is requested?

Browser requests file
→
Express checks public/
→
File exists?
→
Send file

If the requested file is not found, Express returns a 404 error indicating that the resource is unavailable.

Step 3 & 4 — Run and test

node server.js

Then visit:

http://localhost:3000/index.html
Middleware Setup

express.static is built-in Express middleware for serving static files.

Directory Path

It receives the directory containing static assets.

Request Handling

Express searches that directory for the requested file.

File Delivery

If found, Express sends it to the client with the appropriate content type.

3. Handling Form Data in Express

A form sends information from the browser to the server. Express can read that information and use it in a route.

Core idea: The form submits data → Express reads req.body → the server can store or process the data.

Step 1 — Install the packages

npm install express body-parser

The source material then uses Express's URL-encoded middleware to read form data:

app.use(express.urlencoded({ extended: true }));

Step 2 — Serve the HTML pages

const express = require("express");
const fs = require("fs");
const app = express();

app.use(express.urlencoded({ extended: true }));
app.use(express.static("public"));

4. Registration Route

The registration route receives username, password and email, reads existing users from user.json, checks whether the username already exists, and then stores the new user.

app.post("/register", (req, res) => {
  const username = req.body.username;
  const password = req.body.password;
  const email = req.body.email;

  fs.readFile("user.json", "utf8", (err, data) => {
    if (err) {
      return res.send("Error reading user.json");
    }

    let users = JSON.parse(data);

    const existingUser = users.find(
      user => user.username === username
    );

    if (existingUser) {
      return res.send(`
        <h2>Username already exists!</h2>
        <a href="/register.html">Go Back</a>
      `);
    }

    const newUser = {
      username: username,
      password: password,
      email: email
    };

    users.push(newUser);

    fs.writeFile(
      "user.json",
      JSON.stringify(users, null, 4),
      (err) => {
        if (err) {
          return res.send("Error storing user data");
        }

        res.send(`
          <h2>Registration Successful!</h2>
          <p>Welcome, ${username}</p>
          <p>Please login using your username and password.</p>
          <a href="/login.html">Go to Login</a>
        `);
      }
    );
  });
});

Registration page: public/register.html

<!DOCTYPE html>
<html lang="en">
<head>
  <title>User Registration and Login</title>
</head>
<body>
  <h1>User Registration</h1>

  <form action="/register" method="POST">
    <label>Username:</label>
    <input type="text" name="username" required>

    <label>Password:</label>
    <input type="password" name="password" required>

    <label>Email:</label>
    <input type="email" name="email" required>

    <button type="submit">Register</button>
  </form>
</body>
</html>

5. Login Route

The login route reads the submitted username and password, loads user.json, and searches for a matching user.

app.post("/login", (req, res) => {
  const username = req.body.username;
  const password = req.body.password;

  fs.readFile("user.json", "utf8", (err, data) => {
    if (err) {
      return res.send("Error reading user.json");
    }

    const users = JSON.parse(data);

    const user = users.find(
      user =>
        user.username === username &&
        user.password === password
    );

    if (user) {
      res.send(`
        <h2>Login Successful!</h2>
        <p>Welcome ${user.username}</p>
        <p>Email: ${user.email}</p>
      `);
    } else {
      res.send(`
        <h2>Login Failed!</h2>
        <p>Invalid username or password.</p>
        <a href="/">Try Again</a>
      `);
    }
  });
});

app.listen(3000, () => {
  console.log("Server started on port 3000");
});

Login page: public/login.html

<html>
<body>
  <h1>User Login</h1>

  <form action="/login" method="POST">
    <label>Username:</label>
    <input type="text" name="username" required>

    <label>Password:</label>
    <input type="password" name="password" required>

    <button type="submit">Login</button>
  </form>
</body>
</html>
Learning note: The source example stores passwords directly in user.json. This is suitable for understanding the request/response flow, but a real application should not store plain-text passwords.

6. Complete Application Flow

localhost:3000
→
register.html
or login.html
Registration
→
POST /register
→
Read user.json
→
Add user
→
Write user.json
Login
→
POST /login
→
Read user.json
→
Find username
→
Check password
Match → Login Success
or
No Match → Login Failed

📁 Suggested project structure from the source example

project/
├── server.js
├── user.json
└── public/
    ├── register.html
    └── login.html

🧠 Mind Map

Express.js

Server application

express.static()

Serves static files

express.urlencoded()

Reads URL-encoded form data

POST /register

Creates and stores a user

POST /login

Checks submitted credentials

user.json

Stores the example's user data

7. Quick Self-Check

1. Which Express middleware serves static files?

2. Which property is used in the example to read submitted form fields?

3. Which HTTP method is used by the registration form?