Skip to content

Commit a51e4bd

Browse files
committed
docs: document new object-syntax links
1 parent d363746 commit a51e4bd

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

CONTRIBUTING.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ This focus helps guide our project decisions as a community and what we choose t
3939
- [Import order](#import-order)
4040
- [Naming conventions](#naming-conventions)
4141
- [Vue components](#vue-components)
42+
- [Internal linking](#internal-linking)
4243
- [RTL Support](#rtl-support)
4344
- [Localization (i18n)](#localization-i18n)
4445
- [Approach](#approach)
@@ -278,6 +279,79 @@ const props = defineProps<{
278279
279280
Ideally, extract utilities into separate files so they can be unit tested. 🙏
280281

282+
### Internal linking
283+
284+
Always use **object syntax with named routes** for internal navigation. This makes links resilient to URL structure changes and provides type safety via `unplugin-vue-router`.
285+
286+
```vue
287+
<!-- Good: named route -->
288+
<NuxtLink :to="{ name: 'settings' }">Settings</NuxtLink>
289+
290+
<!-- Bad: string path -->
291+
<NuxtLink to="/settings">Settings</NuxtLink>
292+
```
293+
294+
The same applies to programmatic navigation:
295+
296+
```typescript
297+
// Good
298+
navigateTo({ name: 'compare' })
299+
router.push({ name: 'search' })
300+
301+
// Bad
302+
navigateTo('/compare')
303+
router.push('/search')
304+
```
305+
306+
For routes with parameters, pass them explicitly:
307+
308+
```vue
309+
<NuxtLink :to="{ name: '~username', params: { username } }">Profile</NuxtLink>
310+
<NuxtLink :to="{ name: 'org', params: { org: orgName } }">Organization</NuxtLink>
311+
```
312+
313+
Query parameters work as expected:
314+
315+
```vue
316+
<NuxtLink :to="{ name: 'compare', query: { packages: pkg.name } }">Compare</NuxtLink>
317+
```
318+
319+
#### Package routes
320+
321+
For package links, use the auto-imported `packageRoute()` utility from `app/utils/router.ts`. It handles scoped/unscoped packages and optional versions:
322+
323+
```vue
324+
<!-- Links to /package/vue -->
325+
<NuxtLink :to="packageRoute('vue')">vue</NuxtLink>
326+
327+
<!-- Links to /package/@nuxt/kit -->
328+
<NuxtLink :to="packageRoute('@nuxt/kit')">@nuxt/kit</NuxtLink>
329+
330+
<!-- Links to /package/vue/v/3.5.0 -->
331+
<NuxtLink :to="packageRoute('vue', '3.5.0')">vue@3.5.0</NuxtLink>
332+
```
333+
334+
> [!IMPORTANT]
335+
> Never construct package URLs as strings. The route structure uses separate `org` and `name` params, and `packageRoute()` handles the splitting correctly.
336+
337+
#### Available route names
338+
339+
| Route name | URL pattern | Parameters |
340+
| ----------------- | --------------------------------- | ------------------------- |
341+
| `index` | `/` | &mdash; |
342+
| `about` | `/about` | &mdash; |
343+
| `compare` | `/compare` | &mdash; |
344+
| `privacy` | `/privacy` | &mdash; |
345+
| `search` | `/search` | &mdash; |
346+
| `settings` | `/settings` | &mdash; |
347+
| `package` | `/package/:org?/:name` | `org?`, `name` |
348+
| `package-version` | `/package/:org?/:name/v/:version` | `org?`, `name`, `version` |
349+
| `code` | `/package-code/:path+` | `path` (array) |
350+
| `docs` | `/package-docs/:path+` | `path` (array) |
351+
| `org` | `/org/:org` | `org` |
352+
| `~username` | `/~:username` | `username` |
353+
| `~username-orgs` | `/~:username/orgs` | `username` |
354+
281355
## RTL Support
282356

283357
We support `right-to-left` languages, we need to make sure that the UI is working correctly in both directions.

0 commit comments

Comments
 (0)