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 usecomponents/
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 likehttps://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
.