Routing

Aleph.js has a file-system based router built on the concept of pages.
When a file(.js, .jsx, .ts, .tsx, .mjs, .md) is added to the pages directory it's automatically available as a route.

Index Routes

The router will automatically route files named index to the root of the directory.

  • pages/index.tsx β†’ /
  • pages/blog/index.tsx β†’ /blog

Dynamic Routes

To match a dynamic segment you can use the bracket syntax or segment starts with $:

  • pages/blog/[slug].tsx (pages/blog/$slug.tsx) β†’ /blog/:slug (/blog/hello-world)
  • pages/[username]/settings.tsx β†’ /:username/settings (/foo/settings)
  • pages/post/[...all].tsx β†’ /post/* (/post/2020/id/title)

Nested Routes

The router supports nested routes like:

  • pages/blog.tsx
  • pages/blog/index.tsx
  • pages/blog/[slug].tsx

This router will match /blog and /blog/:slug, and blog.tsx will be the parent component of index.tsx and [slug].tsx, ensure blog.tsx renders the child components, you can also add some public components:

// blog.tsx
import React from "https://esm.sh/react"
import BlogHeader from "../components/blog-header.tsx"

export default function Blog({ Page, pageProps }) {
  return (
    <>
      <BlogHeader />
      <Page ...pageProps />
    </>
  )
}

Linking Between Pages

A React Component called Link is provided to do this client-side route redirects between pages, similarly to a SPA(single-page application).

import React from "https://esm.sh/react"
import { Link } from "https://deno.land/x/aleph/mod.ts"

export default function Nav() {
  return (
    <ul>
      <li>
        <Link to="/">Home</Link>
      </li>
      <li>
        <Link to="/about">About</Link>
      </li>
      <li>
        <Link to="/blog/hello-world">Hello World</Link>
      </li>
    </ul>
  )
}

In the example above we have three links, each one maps a path (to) to the specify page:

  • / β†’ pages/index.tsx
  • /about β†’ pages/about.tsx
  • /blog/hello-world β†’ pages/blog/[slug].tsx

Use the redirect function

you can also redirect page with the redirect function:

import React, { useCallback } from "https://esm.sh/react"
import { redirect } from "https://deno.land/x/aleph/mod.ts"

export default function Link({to, replace, children}) {
  const onClick = useCallback(e => {
    e.preventDefault()
    redirect(to, replace)
  }, [to, replace])

  return (
    <a href={to} onClick={onClick}>{children}</a>
  )
}

Use the Router

To access the Router object in a React component you can use the useRouter hook:

import { useRouter } from "https://deno.land/x/aleph/mod.ts"

// hypothetically current location patname is '/post/hello-world?theme=dark'
export default function Component({ href, children }) {
  const {
    pathname, // string, should be '/post/hello-world'
    pagePath, // string, should be '/post/[slug]'
    params,   // object, should be {slug: 'hello-world'}
    query     // URLSearchParams, `query.get('theme')` sholud be 'dark'
  } = useRouter()
  ...
}

I18N

Aleph.js don't provide I18N function directly, but the routing supports the locale prefix, you need to config the locale list in aleph.config.js:

export default {
  defaultLocale: 'en',
  locales: ['en', 'zh-CN'],
  ...
}

then all the routes will match paths with 'zh-CN' prefix, even the zh-CN don't exist in the pages dir:

  • pages/index.tsx β†’ / and /zh-CN (pathname is /)
  • pages/blog.tsx β†’ /blog and /zh-CN/blog (pathname is /blog)

Now you can access the locale in the Router object with useRouter hook:

import React from "https://esm.sh/react"
import { useRouter } from "https://deno.land/x/aleph/mod.ts"

export default function Page() {
  const { locale } = useRouter()

  if (locale === 'zh-CN') {
    return <h1>δ½ ε₯½δΈ–η•Œ</h1>
  }
  return <h1>Hello World</h1>
}

And the SSG will generate all the pages in the locale list with the prefix.