Static files
Static files are those the browser receives as they are, without processing on the server: CSS styles, images, fonts, client-side scripts. You do not write a route for each file: the built-in express.static() middleware serves a whole folder.
The public folder
Create a public/ folder in the project root, with a stylesheet public/css/style.css inside:
body {
max-width: 720px;
margin: 0 auto;
font-family: system-ui, sans-serif;
}Enabling it
Add one line to src/app.js before the routes:
// src/app.js
app.use(express.static('public'));Open http://localhost:3000/css/style.css and the browser shows the file. The folder name public is not part of the address: the file public/images/logo.png is available at /images/logo.png.
Using it on a page
In HTML write addresses from the site root, starting with a slash:
<link rel="stylesheet" href="/css/style.css">
<img src="/images/logo.png" alt="Blog logo">Then the styles and the image load on any blog page — both on /posts and on /posts/2.
An address prefix
If the files should live under a separate address, pass it as the first argument:
// src/app.js
app.use('/static', express.static('public'));Now the styles are at /static/css/style.css, and /css/style.css no longer works.
An absolute path
The path 'public' is resolved from the folder Node.js was started in. If you start the server from another place, the files are not found. It is more reliable to build the path from the location of app.js itself:
// src/app.js
import path from 'node:path';
const publicDir = path.join(import.meta.dirname, '..', 'public');
app.use(express.static(publicDir));import.meta.dirname is the folder of the current module, here src/. The two dots go one level up, to the project root.
Caching
The maxAge option lets the browser keep the files and not request them again:
// src/app.js
app.use(express.static('public', { maxAge: '1d' }));The browser takes the files from its cache for a day. Better not to enable this during development: CSS changes would not show up at once.
Common mistake
Everything in public/ is available to anyone who knows the address. Do not put the .env file, the database, the server source code or user-uploaded documents that must stay private there. public/ is only for things you are happy to show the whole internet.