Links the build can check
Link between pages with Link, check route patterns at build time, and control early loading.
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.
What happens when you click a link to your own page?
Click a link inside the page, like About or First post. Watch the address bar and the dashed page area.
Home
Welcome. Pick a page above.
import { Link } from '@markless/router'; export default function Nav() @{ <nav> <Link href="/">Home</Link> <Link href="/about">About</Link> <Link href="/blog/[slug]" params={{ slug: 'hello' }}>First post</Link> (the build writes /blog/hello) </nav>}- Nothing yet. Click a link in the page.
Simplified. This needs a multi-page app made with the router. Markless itself does not need a server. A real link starts its request early, when you point at it, focus it, or press it. The click then uses that same request. The router's own tests check this.
Notice that the address bar changes, but the whole page loads only once.
Link to a page
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.
Next: How does a page wait for slow data? Data loading →
