Skip to content

Commit 3609e29

Browse files
committed
docs: add docs about routing
1 parent 0195407 commit 3609e29

9 files changed

+445
-7
lines changed

docs/01-getting-started/02-project-structure.md

+8-6
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ This page provides an overview of the file and folder structure of a Brisa proje
1010

1111
| | |
1212
| ------------------------------------------------------------------------ | ---------------------------------- |
13-
| [`pages`](/docs/pages/building-your-application/routing#pages) | Pages Router |
14-
| [`api`](/docs/pages/building-your-application/routing#api) | Api Router |
15-
| [`public`](/docs/app/building-your-application/optimizing/static-assets) | Static assets to be served |
16-
| [`middleware`](/docs/app/building-your-application/configuring/middleware) | Middleware |
17-
| [`layout`](/docs/app/building-your-application/configuring/layout) | Layout / Layouts |
18-
| [`websocket`](/docs/app/building-your-application/configuring/websocket) | Websocket |
13+
| [`pages`](/docs/building-your-application/routing#pages) | Pages Router |
14+
| [`api`](/docs/building-your-application/routing#api) | Api Router |
15+
| [`public`](/docs/building-your-application/optimizing/static-assets) | Static assets to be served |
16+
| [`middleware`](/docs/building-your-application/configuring/middleware) | Middleware |
17+
| [`layout`](/docs/building-your-application/configuring/layout) | Layout / Layouts |
18+
| [`websocket`](/docs/building-your-application/configuring/websocket) | Websocket |
19+
| [`i18n`](/docs/building-your-application/configuring/i18n) | Internationalization routing & translations |
20+
1921

2022

2123
## Top-level files

docs/02-app/02-layouts.md

-1
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
---
2+
title: Pages and Layouts
3+
description: Create your first page and shared layout with the Pages Router.
4+
---
5+
6+
The Pages Router has a file-system based router built on the concept of pages (like Next.js pages folder).
7+
8+
When a file is added to the `pages` directory, it's automatically available as a route.
9+
10+
In Brisa framework, a **page** is a [Brisa Component](/docs/components-details) exported from a `.js`, `.jsx`, `.ts`, or `.tsx` file in the `pages` directory. Each page is associated with a route based on its file name.
11+
12+
**Example**: If you create `pages/about.js` that exports a Brisa component like below, it will be accessible at `/about`.
13+
14+
```jsx
15+
export default function About() {
16+
return <div>About</div>
17+
}
18+
```
19+
20+
See the difference between React Components and Brisa Components [here](/docs/components-details).
21+
22+
## Index routes
23+
24+
The router will automatically route files named `index` to the root of the directory.
25+
26+
- `pages/index.js``/`
27+
- `pages/blog/index.js``/blog`
28+
29+
## Nested routes
30+
31+
The router supports nested files. If you create a nested folder structure, files will automatically be routed in the same way still.
32+
33+
- `pages/blog/first-post.js``/blog/first-post`
34+
- `pages/dashboard/settings/username.js``/dashboard/settings/username`
35+
36+
## Pages with Dynamic Routes
37+
38+
Brisa supports pages with dynamic routes. For example, if you create a file called `pages/posts/[id].js`, then it will be accessible at `posts/1`, `posts/2`, etc.
39+
40+
> To learn more about dynamic routing, check the [Dynamic Routing documentation](/docs/building-your-application/routing/dynamic-routes).
41+
42+
## Layout
43+
44+
The global layout is defined inside `/src/layout/index`. By default Brisa supports a default layout, but you can modify it here.
45+
46+
47+
```jsx filename="src/layout/index.js"
48+
import { RequestContext } from "brisa";
49+
50+
export default function Layout({ children }: { children: JSX.Element }, { route }: RequestContext) {
51+
return (
52+
<html>
53+
<head>
54+
<title id="title">My layout</title>
55+
<link rel="icon" href="favicon.ico" />
56+
</head>
57+
<body>
58+
{children}
59+
</body>
60+
</html>
61+
)
62+
}
63+
```
64+
65+
It must have the same structure: `html`, `head` and `body`. If for example you forget to put the `head`, you may have issues and you will be alerted with an error during development.
66+
67+
All the components of Brisa (pages and layouts included), apart from the props, receive a second argument which is the **context of the request**, apart from having access to the request, you have access to a series of extra information such as the **route** of the page. In the layouts, having access to the page route is very useful to **create different layouts**.
68+
69+
### Example of multi-layouts
70+
71+
```tsx filename="src/layout/index.js"
72+
import { type RequestContext } from "brisa";
73+
import UserLayout from './user-layout'
74+
import GlobalLayout from './global-layout'
75+
76+
export default function Layout({ children }: { children: JSX.Element }, { route }: RequestContext) {
77+
// pathname: /en/user/aralroca/settings or /es/usuario/pepe
78+
if(route.name.startsWith('/user/[username]')) {
79+
return <UserLayout>{children}<UserLayout>
80+
}
81+
82+
return <GlobalLayout>{children}</GlobalLayout>
83+
}
84+
```
85+
86+
## Data Fetching
87+
88+
Inside your layout, you can fetch data directly with `fetch`, in the same way that you can do it in pages:
89+
90+
```jsx filename="src/layout/index.js"
91+
import { RequestContext } from "brisa";
92+
93+
export default async function Layout({ children }: { children: JSX.Element }, { route }: RequestContext) {
94+
const data = await fetch(/* data url */).then(r => r.json());
95+
96+
return (
97+
<html>
98+
<head>
99+
<title id="title">My layout</title>
100+
<link rel="icon" href="favicon.ico" />
101+
</head>
102+
<body>
103+
{children}
104+
</body>
105+
</html>
106+
)
107+
}
108+
```
109+
110+
The `fetch` is directly native and has no wrapper to control the cache. We recommend that you do not do the same `fetch` in several places, but use the [`context`](/docs/building-your-application/data-fetching/request-context) to store the data and consume it from any component.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
title: Dynamic Routes
3+
description: Dynamic Routes are pages that allow you to add custom params to your URLs. Start creating Dynamic Routes and learn more here.
4+
---
5+
6+
When you don't know the exact segment names ahead of time and want to create routes from dynamic data, you can use Dynamic Segments that are filled in at request time.
7+
8+
## Convention
9+
10+
A Dynamic Segment can be created by wrapping a folder's name in square brackets: `[folderName]`. For example, `[id]` or `[slug]`.
11+
12+
Dynamic Segments can be accessed from [`request context`](/docs/building-your-application/data-fetching/request-context).
13+
14+
## Example
15+
16+
For example, a blog could include the following route `src/pages/blog/[slug].js` where `[slug]` is the Dynamic Segment for blog posts.
17+
18+
```jsx
19+
export default function Page(props, { route }) {
20+
return <p>Post: {route.query.slug}</p>
21+
}
22+
```
23+
24+
All components can access `route.query` in the same way, not just pages.
25+
26+
| Route | Example URL | `params` |
27+
| ---------------------- | ----------- | --------------- |
28+
| `pages/blog/[slug].js` | `/blog/a` | `{ slug: 'a' }` |
29+
| `pages/blog/[slug].js` | `/blog/b` | `{ slug: 'b' }` |
30+
| `pages/blog/[slug].js` | `/blog/c` | `{ slug: 'c' }` |
31+
32+
## Catch-all Segments
33+
34+
Dynamic Segments can be extended to **catch-all** subsequent segments by adding an ellipsis inside the brackets `[...folderName]`.
35+
36+
For example, `pages/shop/[...slug].js` will match `/shop/clothes`, but also `/shop/clothes/tops`, `/shop/clothes/tops/t-shirts`, and so on.
37+
38+
| Route | Example URL | `params` |
39+
| ------------------------- | ------------- | --------------------------- |
40+
| `pages/shop/[...slug].js` | `/shop/a` | `{ slug: ['a'] }` |
41+
| `pages/shop/[...slug].js` | `/shop/a/b` | `{ slug: ['a', 'b'] }` |
42+
| `pages/shop/[...slug].js` | `/shop/a/b/c` | `{ slug: ['a', 'b', 'c'] }` |
43+
44+
## Optional Catch-all Segments
45+
46+
Catch-all Segments can be made **optional** by including the parameter in double square brackets: `[[...folderName]]`.
47+
48+
For example, `pages/shop/[[...slug]].js` will **also** match `/shop`, in addition to `/shop/clothes`, `/shop/clothes/tops`, `/shop/clothes/tops/t-shirts`.
49+
50+
The difference between **catch-all** and **optional catch-all** segments is that with optional, the route without the parameter is also matched (`/shop` in the example above).
51+
52+
| Route | Example URL | `params` |
53+
| --------------------------- | ------------- | --------------------------- |
54+
| `pages/shop/[[...slug]].js` | `/shop` | `{}` |
55+
| `pages/shop/[[...slug]].js` | `/shop/a` | `{ slug: ['a'] }` |
56+
| `pages/shop/[[...slug]].js` | `/shop/a/b` | `{ slug: ['a', 'b'] }` |
57+
| `pages/shop/[[...slug]].js` | `/shop/a/b/c` | `{ slug: ['a', 'b', 'c'] }` |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
title: Linking and Navigating
3+
description: Learn how navigation works in Brisa.
4+
---
5+
6+
Brisa works with MPA, so we will use the native HTML navigation and you can use the `a` tag directly:
7+
8+
```jsx
9+
export default function Home() {
10+
return (
11+
<ul>
12+
<li>
13+
<a href="/">Home</a>
14+
</li>
15+
<li>
16+
<a href="/about">About Us</a>
17+
</li>
18+
<li>
19+
<a href="/blog/hello-world">Blog Post</a>
20+
</li>
21+
</ul>
22+
)
23+
}
24+
```
25+
26+
The example above uses multiple `a` tags. Each one maps a path (`href`) to a known page:
27+
28+
- `/``src/pages/index.js`
29+
- `/about``src/pages/about.js`
30+
- `/blog/hello-world``src/pages/blog/[slug].js`
31+
32+
33+
## Navigation to dynamic paths
34+
35+
You can also use interpolation to create the path, which comes in handy for [dynamic route segments](/docs/building-your-application/routing/dynamic-routes). For example, to show a list of posts which have been passed to the component as a prop:
36+
37+
```jsx
38+
export default function Posts({ posts }) {
39+
return (
40+
<ul>
41+
{posts.map((post) => (
42+
<li>
43+
<a href={`/blog/${encodeURIComponent(post.slug)}`}>
44+
{post.title}
45+
</a>
46+
</li>
47+
))}
48+
</ul>
49+
)
50+
}
51+
```
52+
53+
> [`encodeURIComponent`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) is used in the example to keep the path utf-8 compatible.
54+
55+
56+
## I18n navigation
57+
58+
If you have [i18n routing](/docs/routing/internationalization) enabled, during navigation you always have to forget about route translations and during the render of the page will be translated to correct translated page.
59+
60+
```jsx
61+
export default function Home() {
62+
return <a href="/about">About Us</a>
63+
}
64+
```
65+
66+
In English:
67+
68+
- `/about``/en/about``src/pages/about.js`
69+
70+
In Spanish:
71+
72+
- `/about``/es/sobre-nosotros``src/pages/about.js`
73+
74+
### Navigate to another locale
75+
76+
It is always possible to force a specific route in case you want to change the locale to another one:
77+
78+
```jsx
79+
export default function Home() {
80+
return <a href="/es/sobre-nosotros">About Us in Spanish</a>
81+
}
82+
```
83+
84+
## Imperative navigation
85+
86+
TODO
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
title: Custom Errors
3+
description: Override and extend the built-in Error page to handle custom errors.
4+
---
5+
6+
## 404 Page
7+
8+
To create a custom 404 page you can create a `src/pages/_404.js` file.
9+
10+
```jsx filename="src/pages/_404.js"
11+
export default function Custom404() {
12+
return <h1>404 - Page Not Found</h1>
13+
}
14+
```
15+
16+
> **Good to know**: In this page you can access to the `request context`, `fetch` data, change the `head` content (meta tags, etc), and change the `response headers`, in the same way of the rest of pages.
17+
18+
19+
## 500 Page
20+
21+
To customize the 500 page you can create a `src/pages/_500.js` file.
22+
23+
```jsx filename="src/pages/_500.js"
24+
export default function Custom500({ error }, requestContext) {
25+
return <h1>500 - {error.message}</h1>
26+
}
27+
```
28+
29+
> **Good to know**: In this page you can access to the `request context`, `fetch` data, change the `head` content (meta tags, etc), and change the `response headers`, in the same way of the rest of pages.
30+
31+
32+
### Errors in component-level
33+
34+
If you want to control errors at the component level instead of displaying a whole new page with the error, you can make the components have the error extension by adding the `ComponentName.error`:
35+
36+
```jsx
37+
export default function SomeComponent() {
38+
return /* some JSX */
39+
}
40+
41+
SomeComponent.error = ({ error }, requestContext) => {
42+
return <p>Oops! {error.message}</p>
43+
}
44+
```

0 commit comments

Comments
 (0)