Friday | 08 DEC 2023

Express Starter Kit

A quick interlude that may never end in the sequelize notes. This is a set of snippets that I copy and paste for each of my node projects.

I start off with using express to generate the directory structure and I use ejs for the views.

express --view=ejs projectName
cd projectName

I delete the files in the public folder as I have my own names for them that I prefer.

rm -rf public
mkdir public
mkdir public/css
mkdir public/js

I then delete the templates that come by default.

rm views/*

Also delete the user route.

rm routes/users.js

Next step is to do an npm install.

npm install

Next, I need to install some packages that I would like:

npm install dotenv hpp helmet method-override

Helmet will add extra headers to make things secure and hpp will stop arrays from being sent in query field of the request.

I also use nodemon during development but I have that installed globally so we just need to add a start-dev script to package.json:

  "scripts": {
    "start": "node ./bin/www",
    "start-dev": "nodemon ./bin/www"

Now we can update app.js to include these packages.

var express = require('express');
var methodOverride = require('method-override');
var helmet = require('helmet');
var hpp = require('hpp');

Next we set up helmet and hpp, and change the delimiter for ejs.

Comment out helmet and hpp if you have issues with local development and content security.

if (process.env.ENV === "production") app.use(helmet());

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.set('view options', {
    delimiter: '?',

Next, we need to set up the method-override package:

app.use(methodOverride(function (req, res) {
    if (req.body && typeof req.body === 'object' && '_method' in req.body) {
        var method = req.body._method
        delete req.body._method
        return method

Lastly, we need to set up the error handler.

// error handler
app.use(async function(err, req, res, next) {
    if (process.env.ENV !== "production") {
    return res.render('404');

The .env file:


The .gitignore:


Now, for the views, I like to have a meta file, header file, footer file, a base and a 404.

Comment out the CSP line.

The meta file:

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

<? if (locals.title) { ?>
    <title><?= title ?></title>
<? } else { ?>
    <title>new project</title>
<? } ?>

<link rel="icon" href="data:;base64,=">
<link rel="stylesheet" href="/css/style.css">

Some blank header and footer files:

touch views/header.ejs
touch views/footer.ejs

The base:

<!doctype html>
<html lang="en">
        <?- include('meta'); ?>
            <?- include('header'); ?>
            <?- include('footer'); ?>

The 404:

<!doctype html>
<html lang="en">
        <?- include('meta'); ?>
        <?- include('header'); ?>
            <i>Sorry, something has gone wrong.</i>
        <?- include('footer'); ?>

I also create a css file:

touch public/css/style.css

This is all some basic stuff that I often have to do. I'll update this as time goes on.