npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@robmarr/nighthawk

v0.3.0

Published

A client-side wrapper for the Express router

Readme

Express' Router for the Browser

NPM Version NPM Downloads Build Status js-happiness-style Sauce Test Status

The Express Router is great! It is reliable and really simple. With Express 5.0 the router module was pulled out into a stand-alone package, so I figured, why not see if it runs in the browser. Sure enough, it did! So this is a wrapper around the Express Router package that layers on browser push state based location updates. I was heavily influenced by Page.js and use a very similar method to transparently catch page changes events.

NOTE: Requires HTML5 history api, aka pushState. This module does not support hash based routing.

Usage

$ npm install --save nighthawk

browser.js:

var Nighthawk = require('nighthawk');

// Create your router
var router = Nighthawk();

// Register your routes
router.get('/', function(req, res) {
	alert('Hi from your nighthawk router!');
});
router.get('/:foo', function(req, res) {
	alert('You visited /' + req.params.foo);
});

router.listen();

Setting A Base Path

Nighthawk supports service applications that are not hosted at the root of your domain via base. To set a base path just pass it in to the router constructor. For example:

var Nighthawk = require('nighthawk');

var router = new Nighthawk({
	base: '/foo'
});

// Optionally you can also set the base path
// with `router.base('/foo')`.

router.get('/bar', function(req, res) {
	alert('You are not at /foo/bar');
});
router.listen();

If have routes which match your base path but require full server rendered page refreshes, you can use the reloadOnUnhandled option to have Nighthawk force the browser to reload from the server with the new route when the final handler is hit. By setting this option to true, the final handler will force the browser to reload the page from the server via window.location = <new url>.

Parsing Querystring's

Nighthawk can setup querystirng parsing for you, just pass the desired parsing funciton as queryParser. For example:

var router = new Nighthawk({
	queryParser: require('querystring').parse

	// Or for extended parsing like in express
	queryParser: require('qs').parse
});

Note: The parseQuerystring option is deprecated as of 2.1.0, and will be removed in 3.0.0.

Listen Options

There are a few options you can pass to the listen call:

  • popstate: When false, Nighthawk will not listen for popstate events
  • interceptClicks: When false, Nighthawk will not listen for link click events
  • dispatch: When false, Nighthawk will not process the initial route on listen

Manually change url and run middleware stack

In case you have some event on the page which is not a normal link click or popstate, you can call router.changeRoute('/your/url'), and the Nighthawk instance will run the route processing. This is helpful for things like form submissions and actions which should prompt users to login.

What happens when history is not supported?

It just falls back to basic HTML link behavior. Thats the great thing about this pattern, it builds on top of basic building blocks of the web. Also, if it is not supported, your route will still run, so you can still use Nighthawk to kick off your application in unsupported browsers.

Why use Nighthawk?

Unlike some other recent front-end routing libraries (react-router, angular-ui-router & ember router) 1, this package requires no special integration points into your links and no special methods to call to change routes. It layers transparently over your existing application and catches link clicks which cause route changes.

But I have to learn a new library!! No you dont. This library directly uses the Express router, so if you know Express you already know Nighthawk. All the middleware patterns you know from Express on the server are valid with Nighthawk. If you load data on the backend with a middleware, you can can use a module like nets to re-use the same middleware on the front-end.

Nighthawk is also relatively small, weighing in at 19kb minified and gzipped. If you are using browserify you are probably already bundling modules like buffer and url, so if you don't count those we only add 9kb total. This is a fair bit smaller than other comparable libraries for front-end routing. You can see for yourself by running npm run size, which will open a breakdown of where the file size comes from and display some file size stats.

Run the examples

$ npm run example-basic
$ npm run example-basedir
$ npm run example-redirect

Visit http://localhost:1234.

Tests

$ npm test

[1]: In opinionated frameworks this is not really that big of a deal because you are already tied down to an ecosystem that probably works really well. But in a "pick your own adventure" style application it is much nicer to have less coupling.