Routing

The skeleton of every application is routing. This page will introduce you to the fundamental concepts of routing for the web and how to handle routing in Previous.js.

Terminology

First, you will see these terms being used throughout the documentation. Here's a quick reference:

  • Tree: A convention for visualizing a hierarchical structure. For example, a component tree with parent and children components, a folder structure, etc.
  • Subtree: Part of a tree, starting at a new root (first) and ending at the leaves (last).
  • Root: The first node in a tree or subtree, such as a root layout.
  • Leaf: Nodes in a subtree that have no children, such as the last segment in a URL path.

  • URL Segment: Part of the URL path delimited by slashes.
  • URL Path: Part of the URL that comes after the domain (composed of segments).

Folders and Files

Previous.js uses a file-system based router where:

  • Folders are used to define routes. A route is a single path of nested folders, following the file-system hierarchy from the root folder down to a final leaf folder that includes a page.js file. See Defining Routes.
  • Files are used to create UI that is shown for a route segment. See special files.

Nested Routes

To create a nested route, you can nest folders inside each other. For example, you can add a new /dashboard/settings route by nesting two new folders in the app directory.

The /dashboard/settings route is composed of three segments:

  • / (Root segment)
  • dashboard (Segment)
  • settings (Leaf segment)

Creating Routes

Each folder in a route represents a route segment. Each route segment is mapped to a corresponding segment in a URL path.

The special file page.js is used to make route segments publicly accessible.

In this example, the /dashboard/analytics URL path is not publicly accessible because it does not have a corresponding page.js file. This folder could be used to store components, stylesheets, images or other files.

Good to know

You can use .js and .html extensions to create conents in layouts and pages.

File Conventions

Previous.js provides a set of special files to create UI with specific behavior in nested routes:

layout Shared UI for a segment and its children
page Unique UI of a route and make routes publicly accessible
route Server-side API endpoint

Good to know

You can use .js and .html extensions to create conents in layouts and pages.

Project organization

In addition to special files, you have the option to put your own files (e.g. components, styles, tests, etc) inside folders in the app directory.

This is because while folders define routes, only the contents returned by page.js or route.js are publicly addressable.

Private Folders

Private folders can be created by prefixing a folder with an underscore: _folderName

This indicates the folder is a private implementation detail and should not be considered by the routing system, thereby opting the folder and all its subfolders out of routing.

Since files in the app directory can be safely colocated by default, private folders are not required for colocation. However, they can be useful for:

  • Separating UI logic from routing logic.
  • Consistently organizing internal files across a project and the Previous.js ecosystem.
  • Sorting and grouping files in code editors.
  • Avoiding potential naming conflicts with future Previous.js file conventions.

Good to know

All files in app/ directory will only can be used in server side. If you want to use components in both client and server side use components/ top-level folder. Learn more about using Components.

Linking and Navigating

Each link on your website can be created using the HTML tag <a>. Previous.js will provide automatic prefetching and client-side navigation between routes.

return {
  content: (props) => {
    return `<a href="/dashboard">Dashboard</a>`;
  }
}

Good to know

The client-side navigation will only be available with path urls like /dashboard. If you use a full domain urls like https://acme.com/path the link will be opened using the default browser navigation.

The default behavior of the Previous.js App Router is to scroll to the top of a new route or to maintain the scroll position for backwards and forwards navigation.

If you'd like to scroll to a specific id on navigation, you can append your URL with a hash link (#id) or just pass a hash link to the href prop.

return {
  content: (props) => {
    return `<a href="#section-10">Section 10</a>`;
  }
}

Dynamic Routes

Dynamic Routes can be used to programmatically generate route segments from dynamic data.

A Dynamic Segment can be created by wrapping a folder's name in square brackets: [folderName]. For example, [id] or [slug].

Dynamic Segments are passed as the params prop to layout, page, route.

For example, a blog could include the following route app/blog/[slug]/page.js where [slug] is the Dynamic Segment for blog posts.

return {
  content: ({ params }) => {
    return `<div>My Post: ${params.slug}</div>`;
  }
}
Route Example URL params
app/blog/[slug]/page.js /blog/a { slug: 'a' }
app/blog/[slug]/page.js /blog/b { slug: 'b' }
app/blog/[slug]/page.js /blog/c { slug: 'c' }

If you need more params in your route create as many directories with square brackets as you need.

Request Data

Use data prop to access to the request data from the URL query string (GET) or the form body (POST).

For example, this route shows the value of test set as GET parameter:

return {
  content: ({ data }) => {
    return `<div>Hello ${data.name || 'Anonymous'}!</div>`;
  }
}

So you can call this route by /hello?name=David and the result will looks like:

...

<div>Hello David!</div>

...

You can get the same result by sending a POST with name=David in the form body.

Good to know

POST parameters will override GET parameters if using the same name.

Redirections

Using the router we can setup any redirection to other paths in our app.

For example, we can redirect any request from the url /blog to the first slug by creating a app/blog/page.js with the following script:

return {
  redirect: "/blog/a"
}

This allows control which page will be rendered in certain situations avoiding a 404 Page Not Found.