Skip to content

The Express Application Object

The app object returned by express() is the anchor of every Express program. This lesson covers the configuration and data-sharing methods on app that go beyond simple routing.

What Is the Application Object?

Calling express() returns a single application object, conventionally named app. It is both a function (used to configure routes and middleware) and an object with methods for storing settings (app.set/app.get) and shared data (app.locals).

Note that app.get() is overloaded: with two arguments where the first looks like a path (app.get('/users', handler)) it registers a route, but with a single string argument (app.get('view engine')) it reads a setting instead.

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

app.set('view engine', 'ejs');
app.set('trust proxy', 1);

console.log(app.get('view engine')); // "ejs"

app.set(key, value) stores a setting, and the single-argument form of app.get(key) reads it back, this is unrelated to routing.

Application Settings Syntax

app.set(name, value);   // store a setting
app.get(name);          // read a setting (1 argument)
app.get(path, handler); // register a GET route (2+ arguments)
app.locals.title = 'My App';
  • app.set() configures behavior like the view engine, view directory, or proxy trust.
  • app.locals holds variables available to every rendered template, for the app's whole lifetime.
  • app.enable(name)/app.disable(name) are shortcuts for boolean settings.
  • app.mountpath shows the path a sub-app or router was mounted at.

Application Object Cheatsheet

The most commonly used methods and properties on the app object.

Method / Property Example Purpose
app.set() app.set('view engine', 'ejs') Stores an app-wide setting
app.get() app.get('view engine') Reads an app-wide setting
app.locals app.locals.siteName = 'Shop' Data available to all views
app.enable() app.enable('trust proxy') Sets a boolean setting to true
app.route() app.route('/users').get(...).post(...) Chains multiple methods on one path
app.listen() app.listen(3000) Starts the HTTP server

app.set() and app.get() for Settings

Common settings include 'view engine' and 'views' (for template rendering), 'trust proxy' (for correctly reading client IPs behind a load balancer), and 'json spaces' (for pretty-printing JSON in development).

app.set('views', './views');
app.set('view engine', 'pug');

if (process.env.NODE_ENV === 'development') {
  app.set('json spaces', 2);
}

app.locals vs res.locals

app.locals is set once and persists for the life of the application, good for static data like a site name or build version. res.locals is scoped to a single request/response cycle, useful for values computed by middleware (like the current user) that a later template needs to read.

app.locals.appName = 'My Shop';

app.use((req, res, next) => {
  res.locals.user = req.user || null;
  next();
});

Both are automatically available inside templates rendered with res.render().

Common Mistakes

  • Confusing app.get(path, handler) (a route) with app.get(settingName) (reading a setting).
  • Storing per-request data in app.locals instead of res.locals, leaking data between unrelated requests.
  • Forgetting to set 'trust proxy' when deployed behind a reverse proxy, breaking req.ip and secure cookies.
  • Re-creating the app object multiple times instead of exporting and reusing a single instance.

Key Takeaways

  • app is both a callable function and an object with configuration methods.
  • app.set()/app.get() (single-argument form) manage app-wide settings.
  • app.locals is app-lifetime data; res.locals is per-request data.
  • Export a single app instance and import it wherever routes or tests need it.

Pro Tip

Set app.set('trust proxy', 1) as soon as you deploy behind Nginx, Heroku, or any load balancer, otherwise req.ip, rate limiting, and secure cookies can silently misbehave.