Getting Started

This guide will cover a few basic concepts about Curi so that you can be confident integrating Curi into your application.

The Router#

A Curi router is created using the default export function from the @curi/core package. This function takes a history object and a routes array.

import curi from '@curi/core';
import Browser from '@hickory/browser';
import routes from './routes';

const history = Browser();
const router = curi(history, routes);
Note: This function also accepts an options object. You can read about its properties in the @curi/core documentation.

The History Object#

A router facilitates navigation between locations. Curi does this using a history object, which comes from the Hickory library. There are a few different types of history objects that you can make; which one you should use depends on where your application will be running.

  • Browser History - If you are building a website that will be hosted on a dynamic server (it can respond to requests for any location), you should use the @hickory/browser package.

    npm install @hickory/browser
    import Browser from '@hickory/browser';
    const browserHistory = Browser();
  • Hash History - If you are building a website that will be hosted on a static file server, you will need to use the @hickory/hash package. The paths for your routes will be encoded in the hash section of the URL. This isn't as "pretty" as the paths you get with @hickory/browser, but is a necessary solution for statically hosted websites.

    npm install @hickory/hash
    import Hash from '@hickory/hash';
    const hashHistory = Hash();
  • In Memory History - If your application is not running in a browser, you should use an in-memory history. This is what you would use when building a mobile application with React Native, writing a NodeJS backend for your server, or when writing tests that run in NodeJS.

    npm install @hickory/in-memory
    import InMemory from '@hickory/in-memory';
    const memoryHistory = InMemory();

The Routes Array#

Routes are objects with two required properties: a name string and a path string.

Note: Paths can be any valid path-to-regexp string. It is just important that you do not begin the string with a forward slash (/). Forward slashes are fine anywhere else in the path. (this/is/fine, but /this/is/not).
const routes = [
    name: 'Home',
    path: '', // matches the pathname /

With Curi, you never have to write a pathname string yourself. Route names are used to generate pathnames for you, so you just need to know the name of the route you want to link to. This also means that all routes must have unique names.

const pathname = router.route.pathname("Home"); // pathname === '/'

How route matching works and the other route properties are explained more in-depth in the All About Routes guide.


Whenever navigation happens, Curi will create a response object, which provides data about the route that it matched. The property values of the response object can be modified through the matching route's response() function.

The response object is used to render your application. The response's body property provides a convenient way to specify what you should render.

// a React examples
import Home from './components/Home';

const routes = [
    name: 'Home',
    path: '',
    response() {
      // set response.body to be the imported
      // Home component
      return {
        body: Home

function render({ response }) {
  // when response.body === Home, this is the same as <Home />
  return <response.body />;


Curi can match routes synchronously or asynchronously. Before we go further, we should quickly cover how this is determined and what is means for your application with the Sync or Async Guide.