200 OK status code

Use Harp’s 200 file to route a client-side app.

Why

If you’re writing a client-side application using a framework like Backbone, Angular, or Ember, you’ll want to do your routing client-side using HTML5 pushState. A 200 fallback file lets Harp respond with a 200 OK status (and your app shell) for any unmatched URL — leaving the client-side router to take over from there.

Usage

Add a 200.html file in your served directory. (200.ejs, 200.md, or 200.jade work too — they’ll compile to HTML.) When a request doesn’t match any other file, Harp returns the contents of the 200.* file with a 200 OK status code instead of falling through to a 404.

Example

Given the following directory structure:

mysite/
  |- 200.ejs
  |- app.js
  |- framework.js
  `- main.scss

The 200.ejs file is served when nothing else matches the request, but before falling through to a 404. Your client-side router can then pick up the URL and render the right view.

This works alongside static pages. If you had a client-side app but wanted your blog to remain static, your project might look like this:

mysite/
  |- _layout.ejs
  |- 200.ejs
  |- css/
  |   `- main.scss
  |- js/
  |   |- app.js
  |   `- framework.js
  `- blog/
      |- _data.json
      |- index.ejs
      |- my-post-1.md
      `- my-post-2.md

Visiting /blog returns the static blog. Visiting any URL that doesn’t match a real file (/dashboard/users/42, say) is served the 200.ejs fallback so your client-side router can handle it.

Cascading 200 files

200.* files cascade up the directory tree. When a request misses, Harp walks up from the request path, and at each directory level checks for a 200.* first and then a 404.*. The first match wins.

This means each section of your site can have its own client-side fallback:

mysite/
  |- 200.ejs                   <-- top-level fallback
  |- index.ejs
  |- admin/
  |   |- 200.ejs               <-- only for unmatched /admin/* URLs
  |   `- index.ejs
  `- blog/
      |- index.ejs
      `- my-post.md

A request like /admin/users/42 matches admin/200.ejs (deeper directory wins). A request like /missing-page walks up and is served the top-level 200.ejs. Requests under /blog/ that don’t match a real file also walk up to the top-level 200.ejs, since blog/ has no fallback of its own.

A 200.* and a 404.* in the same directory: the 200.* wins. Use one or the other per directory based on the behavior you want there.

Compile output

When you run harp <source> <build>, 200.* files are emitted as static 200.html in the corresponding output directory. To preserve the fallback behavior on a static host, configure your host to serve 200.html as the catch-all — most static hosts (Netlify, Vercel, Cloudflare Pages, S3 with routing rules) support this directly.

Client-side routers

There are lots of client-side routers and frameworks to play with: