Welcome back. In our previous lesson, we established a crucial server-side pattern: using the HX-Request header to allow a single Express route to serve either a full HTML document or a targeted HTML fragment. This laid the groundwork for creating efficient, dynamic user interfaces.
Today, we'll build upon that foundation by focusing on how to organize your Node.js project to support this pattern at scale. A well-structured project is essential for maintainability, especially as you begin migrating more complex features from a component-based framework like React. Our goal is to logically separate the full-page templates from the reusable, swappable partials that HTMX will interact with.
This process is conceptually similar to organizing a component library in a modern front-end framework. Just as you would break down a UI into discrete, reusable components, we will break down our server-rendered views into a hierarchy of layouts, pages, and partials.
The Anatomy of a Server-Rendered UI
In a server-rendered architecture, it's helpful to think of your views in three distinct categories:
-
Layouts: These are the outermost shells of your application. A layout typically contains the
<html>,<head>, and<body>tags, and often includes the site-wide header, navigation, and footer. It acts as a wrapper that provides a consistent structure across multiple pages. -
Views (or Pages): These are the main content templates for specific routes. For example,
index.ejswould contain the content for your home page, anduser-profile.ejsfor a user's profile page. When a full page is requested, this view is rendered inside a layout. -
Partials: These are small, reusable (and often swappable) snippets of HTML. A partial could be anything from a single item in a list (
todo-item.ejs) to a form (edit-user-form.ejs) or a section of a dashboard (sales-chart.ejs). These are the primary targets for your HTMX requests.
This separation of concerns is the key to building clean, scalable hypermedia applications. The following tutorial provides an excellent, practical guide to implementing this structure in an Express and EJS project.
Node.js Express EJS Layouts and Partials Tutorial
The video "Node.js Express EJS Layouts and Partials Tutorial" by Raddy is a concise walkthrough of the setup process. It uses a helpful package called express-ejs-layouts to streamline the management of layouts and partials.
Please watch the following segments to understand the core mechanics: Setup and Basic Layout: This covers installing express-ejs-layouts, configuring it in app.js, and understanding how the <%- body %> tag works to inject page content into a main layout file. Customizing Layouts: Here, you'll see how to create a layouts sub-directory and set a new default layout, which is a common practice for better organization. Creating Partials: This section demonstrates creating a partials folder and using <%- include(...) %> to pull in reusable components like a header and footer into your main layout. Per-Route Layouts: This advanced tip shows how you can specify a different layout for a particular route, offering more flexibility.
The article that accompanies this video, "NodeJs Express EJS Layouts and Partials", provides the same information in a textual format, which you can use as a quick reference for code snippets and the final project structure.
A Recommended Project Structure
Based on the principles from the video, a robust and conventional structure for your views directory would look like this:
views/
├── layouts/
│ └── main.ejs # The main application shell with header/footer includes
├── partials/
│ ├── header.ejs # Reusable header component
│ ├── footer.ejs # Reusable footer component
│ └── item.ejs # A swappable HTML fragment for one item
├── index.ejs # The view for the homepage
└── items.ejs # The view for the list of items
Here's how the pieces fit together:
- A full-page request to
/itemswould renderitems.ejsinsidelayouts/main.ejs. - The
layouts/main.ejsfile would use<%- include('../partials/header.ejs') %>to pull in the header. - The
items.ejsfile might loop through data and use<%- include('partials/item.ejs', {item: item}) %>to render each item in the list. - An HTMX request to add a new item would use the logic from our previous lesson to render only
partials/item.ejsand send that fragment back to the client.
The two images below show common variations of this structure in real-world projects.


From Structure to Strategy
With the file structure in place, the next step is to think strategically about how to decompose your UI into these partials. This is where your experience with component-based architecture becomes directly relevant. You must identify the logical units of your interface that will change in response to user actions.
The following article, which describes building a TodoMVC app with HTMX, offers a superb case study in this type of thinking.
I've built the TodoMVC app with HTMX and lived to tell the story - DEV Community
This article provides a real-world example of breaking down a familiar application into server-rendered partials for use with HTMX. The author uses EJS, making the examples directly applicable.
Please read the section titled The page's parts. As you read, analyze the author's five EJS templates (index.ejs, todos.ejs, todo-list.ejs, footer.ejs, single-todo.ejs). Consider why each boundary was chosen and what responsibility each partial has. For example, why is single-todo.ejs a separate partial? Why are the list and footer bundled into todos.ejs?
The key insight is that the granularity of your partials determines the precision of your UI updates. You could re-render an entire list, or just a single row, or even just a status badge within that row. The "hypermedia-tv" video on HTMX application structure makes this point eloquently. It advises you to "start to think of these little bits that you might want to swap out and you isolate them into their own file, give them their own route to hit it."
This is the essence of the hypermedia approach: creating a web of addressable UI fragments that can be requested and swapped into place, driven entirely by the server.
Conclusion
In this lesson, we have moved from the "why" of partials to the "how" and "where". You now have a clear mental model and a practical file structure for building server-rendered applications that are both scalable and perfectly suited for HTMX.
Here are the main takeaways:
- A Three-Tier Template Hierarchy: Organize your EJS files into
layouts(the outer shell),views(the main page content), andpartials(reusable, swappable fragments). - Tooling for Simplicity: Use the
express-ejs-layoutspackage to manage this hierarchy cleanly within your Express application. - The
<%- body %>and<%- include() %>Tags: These are the EJS mechanisms for injecting page content into layouts and including partials within other templates, respectively. - Strategic Decomposition: The way you break your UI into partials directly impacts the efficiency and user experience of your HTMX interactions. Think in terms of "swappable units."
We have now completed the server-side setup. Our Express application is configured with a templating engine, can serve static assets, can distinguish between full and partial requests, and has a logical structure for managing templates.
In the next module, we will shift our focus to the client side. You'll learn the core HTMX attributes—hx-get, hx-post, hx-target, and hx-swap—that initiate requests and instruct the browser on how to handle the HTML fragments our server is now perfectly poised to deliver.
Can't find a good explanation? Sign up and we'll make it for you
Sign up