Color Mode

Template Engines, Partials, and Layouts

In this assignment, you will transform your static HTML website into a dynamic, maintainable application using the EJS templating engine. You'll learn why templating engines are essential for modern web development, how to create reusable components called partials, and how to organize your views for better maintainability.

By the end of this assignment, you'll understand how templating engines solve real problems that static HTML cannot address, and you'll have the foundation for building scalable web applications.

The Problem with Static HTML

Your current Express application works, but it has several significant limitations that become apparent as websites grow larger. Consider what happens when you want to make a simple change, like updating your navigation menu or changing the copyright year in your footer.

With static HTML files, you would need to open every single HTML file and make the same change in each one. Miss one file, and your site becomes inconsistent. Add ten more pages, and you have ten more places where changes must be made perfectly. This approach doesn't scale and leads to maintenance nightmares.

Static HTML also cannot adapt to different situations. You cannot change content based on who's visiting, what time it is, or data from a database. Every visitor sees exactly the same thing, which severely limits what your application can do.

Templating engines solve these problems by separating your content from your layout, allowing you to create reusable components, and enabling dynamic content generation. This assignment will show you how.

Understanding Templating Engines

A templating engine is a tool that combines templates (HTML with special syntax) and data to produce final HTML that gets sent to the browser. Think of it like a mail merge in a word processor: you have a template with placeholders, and the engine fills in those placeholders with actual data.

EJS (Embedded JavaScript) is one of many templating engines available for Express. It allows you to embed JavaScript directly in your HTML using special tags, making it easy to create dynamic content while keeping your templates readable.

Here's how the process works: when someone visits your website, Express finds the appropriate EJS template, combines it with any data you provide, processes the special EJS syntax, and sends the resulting HTML to the user's browser. The user never sees the EJS code – only the final HTML.

Preparation

We'll be building on your Express application from the previous assignment. Before we begin, let's make one small addition to improve your development experience.

Add Development Environment Configuration

Add NODE_ENV=development to your .env file (on a new line after your PORT setting). This tells your application that it's running in development mode, which will be useful for features like debugging and live reloading in future assignments:


        NODE_ENV=development
        PORT=3000
    

Then, in your server.js file, add this variable alongside your existing PORT variable:


        const NODE_ENV = process.env.NODE_ENV || 'production';
        const PORT = process.env.PORT || 3000;
    

The default of production ensures your application runs securely if the environment variable isn't set, which is exactly what you want when deploying to a live server.

Assignment Instructions

1. Install and Configure EJS

First, install the EJS templating engine using pnpm:


        pnpm add ejs
    

Next, configure Express to use EJS by adding these lines to your server.js file. Place them in your middleware configuration section just after your public static directory configuration:


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

        // Tell Express where to find your templates
        app.set('views', path.join(__dirname, 'src/views'));
    

The first line tells Express to use EJS for processing templates. The second line specifies where your template files are located. Express will automatically look for .ejs files in this directory when you render views.

Configuration Order Matters

These configuration calls must come before your routes because Express needs to know about the templating engine before it tries to render any templates. Think of it as setting up the kitchen before you start cooking.

2. Understanding Partials

Before we start creating templates, let's understand the concept of partials. A partial is a reusable template fragment that contains code you want to use in multiple places. Think of partials as the template equivalent of functions in programming – they let you write something once and use it everywhere.

For example, instead of copying your navigation menu into every page template, you create one navigation partial and include it wherever you need it. Change the navigation once, and it updates everywhere automatically.

Create a partials directory inside your src/views directory. This is where we'll store our reusable template components.

3. Create Header and Footer Partials

Now let's create our first partials. These will contain the common elements that appear on every page.

Create the Header Partial

Create src/views/partials/header.ejs with the following content:


        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title><%= title %></title>
            <link rel="stylesheet" href="/css/main.css">
        </head>
        <body>
            <header>
                <nav>
                    <ul>
                        <li><a href="/">Home</a></li>
                        <li><a href="/about">About</a></li>
                        <li><a href="/products">Products</a></li>
                    </ul>
                </nav>
            </header>
    

Notice the <%= title %> syntax. This is EJS telling the template engine to insert the value of a variable called title. The <%= %> tags mean "output this value into the HTML."

Create the Footer Partial

Create src/views/partials/footer.ejs with this content:


            <footer>
                <p>&copy; 2025 My Express App.</p>
            </footer>
        </body>
        </html>
    

Together, these partials provide the complete HTML structure that every page needs, but they leave room in the middle for page-specific content.

4. Convert Static HTML to EJS Templates

Now comes the transformation. We'll convert your static HTML files into dynamic EJS templates that use the partials we just created.

Rename Your HTML Files

First, rename your existing HTML files to use the .ejs extension:

Replace Content with Template Structure

Now edit each .ejs file to use this simple structure:


        <%- include('partials/header') %>
        <main>
            <h1><%= title %></h1>
            <!-- Put your page-specific content here -->
        </main>
        <%- include('partials/footer') %>
    

The <%- include() %> syntax tells EJS to insert the contents of another template file. The %- means "include this content without escaping it" (since we want to include raw HTML).

For example, your home.ejs might look like this:


        <%- include('partials/header') %>
        <main>
            <h1><%= title %></h1>
            <p>Welcome to my Express application! This site demonstrates the power of templating engines.</p>
            <img src="https://picsum.photos/600/400" alt="Random image">
        </main>
        <%- include('partials/footer') %>
    
Don't Duplicate HTML Structure

When converting your files, remove all the HTML structure elements like <!DOCTYPE html>, <html>, <head>, <body>, etc. These are now handled by your partials. Include only the unique content for each page within the <main> tags.

5. Update Your Routes to Use Templates

Now we need to update your routes to render EJS templates instead of sending static HTML files. The key change is switching from res.sendFile() to res.render().

Update your routes in server.js to look like this:


        /**
         * Routes
         */
        app.get('/', (req, res) => {
            const title = 'Welcome Home';
            res.render('home', { title });
        });

        app.get('/about', (req, res) => {
            const title = 'About Me';
            res.render('about', { title });
        });

        app.get('/products', (req, res) => {
            const title = 'Our Products';
            res.render('products', { title });
        });
    

Here's what changed:

Understanding Data Passing

When you write res.render('home', { title }), you're passing an object with a title property to the template. Inside the EJS template, <%= title %> outputs the value of that property. The property names in your data object must match the variable names used in your templates.

6. Test Your Templated Application

Your project structure should now look like this:


        [project-root]
        ├── public/
        │   └── css/
        │       └── main.css
        ├── src/
        │   └── views/
        │       ├── partials/
        │       │   ├── header.ejs
        │       │   └── footer.ejs
        │       ├── about.ejs
        │       ├── home.ejs
        │       └── products.ejs
        ├── .env
        └── server.js
    

Start your server with pnpm run dev and test each page:

If everything works correctly, you've successfully converted from static HTML to dynamic templates! Now try changing something in your header partial and refresh the page – you'll see the change reflected on all pages immediately.

Understanding EJS Syntax

Now that you have a working templated application, let's review some the EJS syntax you've been using:

These simple tags give you powerful capabilities for creating dynamic content while keeping your templates readable and maintainable.

Key Concepts Summary

By completing this assignment, you've solved the problems we identified with static HTML:

These benefits will become even more apparent as you add more features and pages to your application.

Check Your Understanding

Practice what you've learned by completing this coding challenge. You'll create a new route and template that displays student information, applying the core concepts from this assignment: using res.render(), passing data to templates, including partials, and using EJS syntax to display dynamic content.

Type your solutions into the code editor below. When finished, use the copy-to-clipboard button in the upper-right corner to copy your code, then paste it into your AI of choice for feedback.


        /**
         * Using the skills you learned in this assignment, complete the following tasks:
         * 1. Complete the route handler for the '/student' route ensuring to render the 'student' template
         *    with the appropriate data object containing a student's name, id, email, and address
         * 2. Complete the student.ejs template ensuring it includes the header and footer partials
         *    and displays the student's information (name, id, email, address) correctly
         */

        // File: server.js (Route Handler)
        app.get('/student', (req, res) => {
            ...
            res.render('...', { ... });
        });

        // File: /src/views/student.ejs (View Template)
        <%- ... %>
            <main>
                <div class="student-info">
                    <h1>Student Information</h1>
                    <p>Name: ...</p>
                    <p>Id #: ...</p>
                    <p>Email: ...</p>
                    <p>Address: ...</p>
                </div>
            </main>
        <%- ... %>
    

Explore Further

To deepen your understanding of templating concepts, try these optional enhancements:

These exercises will help you understand how templating engines enable more sophisticated dynamic content generation.