Rendering Views
res.render fills a template with data and sends the resulting HTML.
Syntax
res.render('template', { key: value })Once a view engine is set, res.render(view, data) looks up the template, merges in your data object, and sends the HTML response.
The first argument is the template name (without extension); the second is the data available inside the template. This is the classic way to build server-rendered pages.
Example
app.set('view engine', 'ejs');
app.get('/profile/:user', (req, res) => {
res.render('profile', {
user: req.params.user,
posts: ['Hello world', 'Learning Express'],
});
});When to use it
- A product detail page calls res.render('product', item) to populate an EJS template with the database record and return HTML.
- A dashboard route fetches analytics data and calls res.render('dashboard', stats) to inject the data into a Pug template.
- An error handler calls res.render('errors/404') to serve a styled 404 HTML page instead of a plain JSON error.
More examples
Render with template variables
Fetches a user from the database and renders profile.ejs with the user object, or a 404 page if not found.
app.get('/profile/:id', async (req, res) => {
const user = await db.users.findById(req.params.id);
if (!user) return res.status(404).render('errors/404');
res.render('profile', { user });
});res.render with callback
Uses the optional callback form of res.render() to catch template compilation errors before sending the response.
app.get('/report', (req, res) => {
res.render('report', { data: [1, 2, 3] }, (err, html) => {
if (err) return res.status(500).send('Template error');
res.send(html); // send the rendered HTML string
});
});Shared layout data via res.locals
Populates res.locals in middleware so shared layout variables like appName are available to every rendered template.
// Middleware sets layout vars once
app.use((req, res, next) => {
res.locals.appName = 'SoundsCode';
res.locals.year = new Date().getFullYear();
next();
});
app.get('/home', (req, res) => {
res.render('home', { hero: 'Welcome!' });
// Template can access both hero AND appName / year
});
Discussion