SwLink
SwLink is the framework's unified link component. It automatically distinguishes resource file links from route links —
no need to manually decide between <a> and <NuxtLink>:
- Resource file extensions (pdf / zip / mp4 / apk, etc.) → renders a native
<a href>, handled by the browser for download/preview - All other paths → renders
<NuxtLink>, going through Nuxt's routing system
Security attributes are also handled automatically: target="_blank" adds rel="noopener noreferrer";
external links (https://) additionally get nofollow.
When to use SwLink
For page / resource navigation, default to SwLink (renders a real <a href>, friendly to SEO / crawlers / a11y). Only reach for something else when you hit one of these named exceptions:
| Case | Use |
|---|---|
| Trusted external link that should pass SEO weight (dofollow) | Native <a href rel="noopener"> (SwLink forces nofollow on https external links) |
Need NuxtLink custom slot for fully custom rendering | <NuxtLink custom v-slot> |
Same-page anchor #id | Native <a href="#id"> |
| Pure interaction with no URL navigation (toggle / dialog / submit) | SwButton (that's not a link) |
Anti-patterns: ① @click + router.push / navigateTo for a page navigation that could be <a href> → loses SEO; ② <a @click> (no href) for pure interaction → loses a11y. See the framework dev standards "Link / navigation selection" for the full guide.
Basic Usage
Basic Link
External links & automatic rel
External / new-window (rel auto-managed)
Disabled state
Disabled state (business class)
Resource File Links
Pass a path with a resource extension — the component automatically renders as a native <a>:
<!-- Auto-renders as <a href="/files/guide.pdf" target="_blank"> -->
<SwLink to="/files/guide.pdf" target="_blank">Download PDF</SwLink>
<!-- Video file, browser plays/downloads directly -->
<SwLink to="/video/intro.mp4" target="_blank">Watch Video</SwLink>
Route Links with Query Params
Two params shapes (object / string)
Pass query parameters via the params prop:
<!-- Object form → /search?kw=nuxt&page=1 -->
<SwLink to="/search" :params="{ kw: 'nuxt', page: 1 }">Search</SwLink>
<!-- String form → /player?url=https://... -->
<SwLink to="/player" params="https://cdn.example.com/video.m3u8">Play</SwLink>
Default visual & overrides
Override the default look (color / underline / button-like)
SwLink ships a default text-link look: primary color (var(--primary)) + no underline + hover brightness feedback (filter: brightness(0.92), the house style).
To change the link color, set the CSS variable --sw-link-color (on the link or any ancestor) — it applies via the custom-property cascade, independent of rule specificity / load order:
<style scoped>
/* ✅ Recolor via the variable: muted footer links, white links on a dark banner, etc. */
.sw-app-footer {
--sw-link-color: var(--muted-foreground);
}
/* or set it on the link element itself */
.my-link {
--sw-link-color: var(--primary-foreground);
}
</style>
⚠️ Do not override color with
.sw-link { color: … }— it ties the framework default.sw-linkrule at specificity(0,2,0), so the winner depends on CSS source order, which differs betweennuxt dev(HMR) andnuxt build(Vite bundling) → the same code flips link color between dev and prod (framework#170). Always recolor via--sw-link-color.
Other visual overrides (e.g. an always-on underline for links inside long prose, WCAG 1.4.1) need higher specificity in your scoped CSS to avoid the same specificity tie:
<style scoped>
.my-article .sw-link {
text-decoration: underline;
}
</style>
Button-looking navigation stays out of the component: apply your own button class (consistent with SwButton's zero-visual philosophy).
Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
to | string | '' | Target URL or route path | |
target | '_self' | '_blank' | '_self' | How the link opens | |
title | string | '' | Native title attribute (tooltip on hover) | |
params | Record<string, string | number | boolean> | string | '' | Query params; string wraps as query.url, object as query | |
track | LinkTrackProp | undefined | Built-in tracking (opt-in, zero behavior when omitted) — see "Built-in tracking" below |
Built-in tracking (:track)
Exposure and click tracking for content cards / nav items can be reported automatically — the business side only fills in business fields:
<SwLink to="/movie/123" :track="{
exposure: { event: 'appPageitemExposure', payload: { item_id: '123', item_type: 'video', item_name: 'Title', parent_item_id: '', page_key: 'home', page_name: 'Home' } },
click: { event: 'appPageitemClick', payload: { item_id: '123', item_type: 'video', item_name: 'Title', parent_item_id: '', position: 1, page_key: 'home', page_name: 'Home' } },
}">
<MovieCard :movie="movie" />
</SwLink>
| Field | Timing | Typical events |
|---|---|---|
track.exposure | Once on viewport entry (IntersectionObserver ≥50% visible, via useExposure) | appPageitemExposure / recommendListView |
track.click | On click (fire-and-forget, never blocks navigation) | appPageitemClick / recommendListClick / navigation |
eventis constrained to theWebSdkEventunion (typos caught by TS) and explicitly chosen by the business — the same card usesrecommendList*in a recommendation feed andappPageitem*in a plain list; the component never guesses semantics.payloadis passed through as-is; reporting goes throughuseTracker(silent no-op when the tracker gate is off).- Escape hatch: with your own tracking SDK, skip
:track— native click events still fall through, and exposure timing is available viauseExposure.
Slots
| Name | Description |
|---|---|
default | Link text or custom content |
Notes
- Resource extension detection: pdf / zip / rar / docx / xlsx / pptx / jpg / png / gif / svg / xml /
m3u8 / ts / key / mp4 / mp3 / webm / apk / json / gz / tar / mobileprovision / txt / exe.
Matched extensions render as
<a href>; everything else uses<NuxtLink>. - Auto rel handling:
target="_blank"automatically addsrel="noopener noreferrer"; external links (https://) additionally getnofollow— no manual setup needed. - External route links: For
https://URLs,<NuxtLink>natively supports external navigation. SwLink handles these correctly — resource extension detection takes priority over external-link detection.