Skip to content
A friendly, proven starting place for your next hapi plugin or deployment
Branch: pal
Clone or download
Latest commit 5243ac2 Jan 21, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
lib hapi v17, take one Dec 12, 2017
server Safer, cleaner server defaults. Closes #68 Dec 4, 2018
.eslintrc.json Fixed eslint semver, updated eslintrc for v5 Aug 30, 2018
.gitignore Don't ignore package-lock.json since this is potentially application … Nov 14, 2017

hapi pal

the pal boilerplate

A friendly, proven starting place for your next hapi plugin or deployment

Slack: hapihour/hapipal

Lead Maintainer - Devin Ivy


  • Supports hapi v18+
  • Setup with hpal-debug hapi CLI debugging tools.
  • Provides conventions for building plugins by mapping the entire hapi plugin API onto files and folders, using haute-couture.
  • Designed to allow you to deploy your plugin on its own or as part of a larger application.
  • Textbook integrations with Objection ORM, Swagger UI, and more via flavors.
  • Fully setup with a lab test suite and eslint configuration.
  • Powerful, 12factor-oriented deployment configuration using confidence and dotenv.
  • Up-to-date versions of all dependencies.
  • Follows established hapi best practices out of the box.
  • The code is minimal and completely generic– no need to find-and-replace with your project name to get started.

Getting Started

If you're interested to hear about why we came together to create pal, check out our Medium article Introducing hapi pal.

Below is a simple tutorial to create your first route. For a more in-depth look at the pal ecosystem, database integration, etc. see our official starting guide.

npx hpal new my-project
cd ./my-project
npm install
(click to expand)

The npx command comes with npm 5.2+ and higher. Here you can find instructions for older npm versions.

npm install --global hpal
hpal new my-project
cd ./my-project
npm install

Going forward, any instructions that use npx can directly use your global installation of hpal instead. Just replace CLI instructions that say npx hpal with hpal.

(click to expand)

Perhaps you'd like to perform a manual installation without any fancy CLI tools—that's possible too! Here you can find instructions for installation using only git.

git clone --depth=1 --origin=pal --branch=pal my-project
cd my-project
git checkout --orphan master # New branch without history
npm init
npm install

Make your first commit to init project history

git add --all
git commit -m "Init commit"

Creating your first route

Here we'll will pick-up where we left off (inside a new pal project folder with all dependencies installed) and create a route that serves a random quotation.

# First, consider installing hpal globally,
npm install --global hpal
# or locally to your project,
npm install --save-dev hpal
npx hpal make route random-quotation
# Wrote lib/routes/random-quotation.js

Now open the newly-created file in your favorite text editor. You should find something like this indicating which parts of the route configuration you need to fill-in, and the signature of a route handler.

// lib/routes/random-quotation.js
'use strict';

module.exports = {
    method: '',
    path: '',
    options: {
        handler: async (request, h) => {}

Let's fill-in the method and path so that the route we hit is at get /random-quotation, and write the handler to serve a random quotation from a list. Our handler doesn't need to do anything asynchronous or use the response toolkit, so the route handler's signature appears a little simpler than before.

// lib/routes/random-quotation.js
'use strict';

module.exports = {
    method: 'get',
    path: '/random-quotation',
    options: {
        handler: (request) => {

            const quotations = [
                    quotation: 'I would rather fish any day than go to heaven.',
                    saidBy: 'Cornelia "Fly Rod" Crosby'
                    quotation: 'I want a turkey nut yogurt cane!',
                    saidBy: 'Stimpy'
                    quotation: 'Streams make programming in node simple, elegant, and composable.',
                    saidBy: 'substack'

            const randomIndex = Math.floor(Math.random() * quotations.length);

            return quotations[randomIndex];

Now start your server and try hitting it in-browser or over curl.

npm start
# Server started at
curl http://localhost:3000/random-quotation
# {"quotation":"I would rather fish any day than go to heaven.","saidBy":"Cornelia \"Fly Rod\" Crosby"}

This common practice of restarting the server and curling can be simplified by leveraging hpal-debug's curl command, which allows you to hit a route using its name without having a started server!

npx hpal run debug:curl random-quotation
# { quotation: 'I want a turkey nut yogurt cane!', saidBy: 'Stimpy' }

And that's it! Keep in mind that if you run into anything along the way that's unfamiliar to you, you can always search the hapi API documentation using hpal.

npx hpal docs route.options.handler


hapi pal makes it easy to use the boilerplate as a jumping-off point for several different types of projects, which we call "flavors" (🍭 🍟 🍩 🍗). Flavors may be mixed and matched, or skipped altogether. Only utilize them if they'll be useful to you!

They're simple little buggers. We've simply tagged commits that we think will contain useful code patches depending on what direction you'd like to take your project.

NOTE Since flavors are just tagged commits, please be aware that you may experience merge conflicts when mixing flavors together

Pull down the latest flavors

If you used the hpal CLI to create a new project then this should already be done for you. But you can always do it manually as well– simply pull down git tags from the pal remote.

git fetch pal --tags

Use some flavors

git cherry-pick flavor-one flavor-two

Available flavors


git cherry-pick swagger [view]

Integrates hapi-swagger onto the server with some reasonable default configuration.

Custom Swagger

git cherry-pick custom-swagger [view]

Integrates hapi-swagger onto the server with some reasonable default configuration, and also includes an editable handlebars template for swagger-ui.

Objection ORM

git cherry-pick objection [view]

Integrates Objection ORM into your server and plugin using the hapi plugin schwifty. This is a great way to get started with a SQL-oriented plugin. Adds a models/ directory to your plugin where Objection models should be placed, and a migrations/ directory where your migrations should be placed. Configured to work with SQLite out of the box.

Using the knex CLI

We've added an npm script for knex so that you can avoid writing the whole path to the knex CLI (node_modules/.bin/knex) when running commands. To use the knex CLI, you may write your commands as npm run knex -- <knex-command>.

For example, to create a new migration,

npm run knex -- migrate:make my-first-migration


git cherry-pick deployment [view]

By default all deployment-oriented dependencies are placed in package.json's devDependencies. This flavor pulls all the default deployment dependencies up into dependencies. This is useful when you want to use pal primarily as a deployment rather than a harness to author an application plugin. Note that the other flavors always place their deployment-oriented dependencies in devDependencies, and that you will have to pull those into dependencies separately.

Templated Site

git cherry-pick templated-site [view]

Sets-up handlebars templating with a useful layout and openly serves the lib/public directory, which contains folders to place javascript and CSS. This flavor additionally introduces three npm scripts: one to minify front-end javascript (npm run build:js) with uglify; one to minify CSS with PostCSS/cssnano (npm run build:css); and one to do both (npm run build). Lastly, this flavor introduces a plugin option developmentMode that controls whether the minified or un-minified javascript and CSS are served on the page. The developmentMode is configured to be active when NODE_ENV is not production.

Fancy Templated Site

git cherry-pick fancy-templated-site [view]

Building on top of the templated site flavor, this flavor also incorporates browserify, Sass, and Browsersync. As such, there are two new npm scripts: one to pre-build javascript from nodejs-style to ES5 using browserify and Babel (npm run prebuild:js); and one to pre-build CSS from SCSS using node-sass. When developmentMode is active browser-sync will rebuild SCSS and nodejs-style javascript, then reload the page or stylesheets as necessary.


Note: most of the time you'll be pulling in flavors at the time you install the pal boilerplate, in which case you don't need to worry much about flavor versioning.

It's worth noting that over time these flavor tags may point to different commits. The flavors are updated to keep-up with the latest pal boilerplate. For this reason, as flavor tags move, we leave static versioned tags for your convenience. Tags are named as such,



  • <flavor-name> - the name of this flavor. Identical to the unversioned tag for this flavor.
  • <major> - the major version of the flavor, identical to the major version of the pal boilerplate that it is compatible with.
  • <minor> - the minor version of the flavor, bumped when a feature is added to the flavor (rare), but more typically when its dependencies are updated.
  • <patch> - the patch version of the flavor, bumped when a bug is fixed in the flavor, or the flavor requires update to account for bugs in the version of the pal boilerplate with which it is compatible.

For example the first version of the "custom swagger" flavor is,


You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.