{"id":15645279,"url":"https://github.com/wesleytodd/nighthawk","last_synced_at":"2025-04-30T08:22:46.918Z","repository":{"id":26762272,"uuid":"30220204","full_name":"wesleytodd/nighthawk","owner":"wesleytodd","description":"A wrapper around Express' router for the browser","archived":false,"fork":false,"pushed_at":"2019-08-18T00:49:54.000Z","size":91,"stargazers_count":55,"open_issues_count":4,"forks_count":7,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-27T02:18:29.686Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wesleytodd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-02-03T02:16:45.000Z","updated_at":"2023-04-20T10:19:13.000Z","dependencies_parsed_at":"2022-09-07T09:11:56.221Z","dependency_job_id":null,"html_url":"https://github.com/wesleytodd/nighthawk","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesleytodd%2Fnighthawk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesleytodd%2Fnighthawk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesleytodd%2Fnighthawk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wesleytodd%2Fnighthawk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wesleytodd","download_url":"https://codeload.github.com/wesleytodd/nighthawk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251666903,"owners_count":21624395,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-03T12:05:41.913Z","updated_at":"2025-04-30T08:22:46.893Z","avatar_url":"https://github.com/wesleytodd.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# Express' Router for the Browser\n\n[![NPM Version][npm-image]][npm-url]\n[![NPM Downloads][downloads-image]][downloads-url]\n[![Build Status](https://travis-ci.org/wesleytodd/nighthawk.svg?branch=master)](https://travis-ci.org/wesleytodd/nighthawk)\n[![js-happiness-style](https://img.shields.io/badge/code%20style-happiness-brightgreen.svg)](https://github.com/JedWatson/happiness)\n[![Sauce Test Status](https://saucelabs.com/buildstatus/wesleytodd123)](https://saucelabs.com/u/wesleytodd123)\n\nThe 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, \nso I figured, why not see if it runs in the browser.  Sure enough, it did!  So this is a wrapper around the [Express Router](https://github.com/pillarjs/router) \npackage that layers on browser push state based location updates.  I was heavily influenced by [Page.js](https://visionmedia.github.io/page.js/) and use a \nvery similar method to transparently catch page changes events.\n\n**NOTE**: Requires HTML5 `history` api, aka `pushState`.  This module does not support hash based routing.\n\n## Usage\n\n```\n$ npm install --save nighthawk\n```\n\n`browser.js`:\n\n```javascript\nvar Nighthawk = require('nighthawk');\n\n// Create your router\nvar router = Nighthawk();\n\n// Register your routes\nrouter.get('/', function(req, res) {\n\talert('Hi from your nighthawk router!');\n});\nrouter.get('/:foo', function(req, res) {\n\talert('You visited /' + req.params.foo);\n});\n\nrouter.listen();\n```\n\n### Setting A Base Path\n\nNighthawk 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 \nthe router constructor.  For example:\n\n```javascript\nvar Nighthawk = require('nighthawk');\n\nvar router = new Nighthawk({\n\tbase: '/foo'\n});\n\n// Optionally you can also set the base path\n// with `router.base('/foo')`.\n\nrouter.get('/bar', function(req, res) {\n\talert('You are not at /foo/bar');\n});\nrouter.listen();\n```\n\nIf have routes which match your base path but require full server rendered page refreshes, you\ncan use the `reloadOnUnhandled` option to have Nighthawk force the browser to reload from the server with the new\nroute when the final handler is hit.  By setting this option to true, the final handler will force the browser to\nreload the page from the server via `window.location = \u003cnew url\u003e`.\n\n### Parsing Querystring's\n\nNighthawk can setup querystirng parsing for you, just pass the desired parsing funciton as `queryParser`.  For example:\n\n```javascript\nvar router = new Nighthawk({\n\tqueryParser: require('querystring').parse\n\n\t// Or for extended parsing like in express\n\tqueryParser: require('qs').parse\n});\n```\n\n*Note:* The `parseQuerystring` option is deprecated as of `2.1.0`, and will be removed in `3.0.0`.\n\n### Listen Options\n\nThere are a few options you can pass to the `listen` call:\n\n- `popstate`: When `false`, Nighthawk will not listen for `popstate` events\n- `interceptClicks`: When `false`, Nighthawk will not listen for link `click` events\n- `dispatch`: When `false`, Nighthawk will not process the initial route on listen\n\n### Manually change url and run middleware stack\n\nIn case you have some event on the page which is not a normal link click or popstate, you can\ncall `router.changeRoute('/your/url')`, and the Nighthawk instance will run the route processing.\nThis is helpful for things like form submissions and actions which should prompt users to login.\n\n### What happens when `history` is not supported?\n\nIt 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, \nif it is not supported, your route will still run, so you can still use Nighthawk to kick off your application in unsupported browsers.\n\n### Why use Nighthawk?\n\nUnlike some other recent front-end routing libraries _(react-router, angular-ui-router \u0026 ember router)_ \u003csup\u003e[1](#fn1)\u003c/sup\u003e, this \npackage requires no special integration points into your links and no special methods to call to change routes.  It layers transparently over your existing \napplication and catches link clicks which cause route changes.\n\n*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\nthe 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\na module like [`nets`](use://github.com/maxogden/nets) to re-use the same middleware on the front-end.\n\nNighthawk is also relatively small, weighing in at 19kb minified and gzipped.  If you are using browserify you are probably already bundling modules like `buffer` \nand `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 \ncan 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.\n\n## Run the examples\n\n```\n$ npm run example-basic\n$ npm run example-basedir\n$ npm run example-redirect\n```\n\nVisit [http://localhost:1234](http://localhost:1234).\n\n## Tests\n\n```\n$ npm test\n```\n\n\u003ca name=\"fn1\" href=\"#fn1\"\u003e[1]\u003c/a\u003e: In opinionated frameworks this is not really that big of a deal because you are already tied down \nto an ecosystem that probably works really well.  But in a \"pick your own adventure\" style application it is much nicer to have less coupling.\n\n[npm-image]: https://img.shields.io/npm/v/nighthawk.svg\n[npm-url]: https://npmjs.org/package/nighthawk\n[downloads-image]: https://img.shields.io/npm/dm/nighthawk.svg\n[downloads-url]: https://npmjs.org/package/nighthawk\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwesleytodd%2Fnighthawk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwesleytodd%2Fnighthawk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwesleytodd%2Fnighthawk/lists"}