---
title: Links the build can check
description: Link between pages with Link, check route patterns at build time, and control early loading.
sidebar: { label: Pages and links }
---

Last page, `pages/blog/[slug].tsrx` became the route `/blog/:slug`. Now link to it.

A typo in a link often hides until someone clicks it. With the router, a wrong route pattern stops the build.

The router writes a list of your routes at build time. Every pattern link must match an entry in that list. On a click, the browser keeps the page it has. The router asks the server for the next page and swaps in only the page area.

Click a link inside the page.

<AppLinkFigure />

Notice that the address bar changes, but the whole page loads only once.

## Link to a page

```tsrx pages/index.tsrx
import { Link } from '@markless/router';

export default function Home() @{
	<nav>
		<Link href="/about">About</Link>
		<Link href="/blog/[slug]" params={{ slug: 'hello' }}>First post</Link>
	</nav>
}
```

`Link` renders a real `<a href>`. For the second link, the build writes `href="/blog/hello"` and drops `params`. A plain `<a>` with a pattern and `params` works the same way.

## What the build checks

| You wrote | Result |
| --- | --- |
| `href="/blog/[slug]"` with `params={{ slug }}` | builds, and `href` becomes the real URL |
| `href="/blog/[id]"` (no such route) | `Typed route error: /blog/[id] does not match any route in pages/.` |
| `href="/blog/[slug]"` with no `params` | `Typed route error: /blog/[slug] requires params:` |
| `href="/abuot"` | the build passes, and a type check flags it |

The router writes route types to `.output/markless/router/types/routes.d.ts`. The file `markless-router-env.d.ts` in your app root points TypeScript at them.

## Loading before the click

A link to one of your pages starts to load that page early. A pointer over it, a focus, or a press starts the load. When the page is idle, a few visible links load too. Links to `api/` endpoints never load early.

| Prop | Effect |
| --- | --- |
| `prefetch={false}` | nothing loads before the click |
| `replace` | replaces the history entry instead of adding one |
| `scroll={false}` | keeps the scroll position |

Back and Forward bring back each page and its scroll position. Plain `<a>` links to your pages navigate the same way. If the fetch fails, the browser loads the URL normally.

:::warning[Does my page change data on each visit?]
Some pages do work on each request, like a one-time token or a view counter. Set `prefetch={false}` on links to them. Then only a real click requests the page.
:::

**Next:** How does a page wait for slow data? [Data loading →](/apps/data-loading)
