Menu
CoddyTech

HTML Pages

Part of the Express Basics section of Coddy's Node.js journey. Lesson 10 of 23.

Recipe Box now turns the HTML-string and escaping exercises into a page. Build one link per recipe. A link’s href chooses its destination, and the text between its tags is the label the reader sees.

const link = `<a href="/books/${book.id}">${escapeHtml(book.title)}</a>`;

The helper is provided in html.js. Apply it to each title, while keeping your own link tags as markup. Use map to build the links and join them into one string. Sending the array directly inside a template string would put commas between the links. res.send gives the completed page to the browser.

<ul> holds the list and <li> wraps each item. Unescaped markup can change a page or run a script in a visitor’s browser; escape each title even when it came from your own data file.

challenge icon

Challenge

Easy

This step opens the course’s prepared Recipe Box project, rather than your project files from Status Codes (including server.js). Your earlier work stays in its own lesson. Read the supplied files before editing server.js. This copy contains Recipe Box routes, status codes and the shared html.js helper.

The home page becomes a real page: a list of every recipe, each one a link to its own page.

  1. In server.js, import the supplied escapeHtml helper from ./html.js.
  2. Change the / route so it sends an HTML page instead of the welcome text. The page holds one link per recipe, going to that recipe's page and showing its title, like this for recipe 2: <a href="/recipes/2">Pancakes</a>. A list works well: each link in an <li> item, all inside one <ul>. You can start with a heading, <h1>Recipe Box</h1>.
  3. Pass every title through escapeHtml before it goes into the page. Fish & Chips then reaches the page as Fish &amp; Chips, which the browser shows as Fish & Chips.
  4. Build the items with map and join them with an empty string. If you put an array into a template string as it is, commas appear between the items.

Try it: Press Run and send /. The response is drawn as a page with four links. Click Fish & Chips: the page for /recipes/4 opens and shows Fish & Chips.

Try it yourself

import express from 'express';
import { recipes } from './data.js';

const app = express();

app.get('/', (req, res) => {
    res.send('Welcome to Recipe Box');
});

// type('text') sends plain text, so each title shows on its own line.
app.get('/recipes', (req, res) => {
    const { tag } = req.query;
    const list = tag ? recipes.filter((recipe) => recipe.tags.includes(tag)) : recipes;
    res.type('text').send(list.map((recipe) => recipe.title).join('\n'));
});

app.get('/recipes/:id', (req, res) => {
    const recipe = recipes.find((r) => r.id === Number(req.params.id));
    if (!recipe) {
        res.status(404).send('No such recipe');
        return;
    }
    res.send(recipe.title);
});

app.get('/api/recipes', (req, res) => {
    res.json(recipes);
});

app.get('/api/recipes/:id', (req, res) => {
    const recipe = recipes.find((r) => r.id === Number(req.params.id));
    if (!recipe) {
        res.status(404).json({ error: 'No such recipe' });
        return;
    }
    res.json(recipe);
});

app.get('/about', (req, res) => {
    res.send('Recipe Box collects family recipes.');
});

app.listen(3000, () => {
    console.log('Recipe Box is running on port 3000');
});
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Express Basics

Practice on your own: Express playground