Core concept · Paths
Use paths that know about the project.
@pathto(...) does two useful things at once: it calculates the correct relative path from the output currently being built, and it verifies that the tracked name or concrete local path you referenced actually exists.
A hard-coded relative URL can be syntactically valid HTML while pointing nowhere. @pathto lets Nift catch many of those mistakes while you build.
Tracked page links
When the argument is a tracked name, Nift resolves the target output relative to the page currently being generated.
<nav>
<a href="@pathto('/')">Home</a>
<a href="@pathto('about')">About</a>
<a href="@pathto('docs')">Documentation</a>
<a href="@pathto('docs/commands')">Commands</a>
</nav>
The same header can appear at different depths
Imagine one shared header being used to build all of these outputs:
public/index.html
public/about.html
public/docs/index.html
public/docs/guides/install/index.html
A literal link such as ../../about.html can only be correct from particular locations. The same @pathto('about') expression can be reused everywhere because Nift knows which output it is currently writing.
Concrete local files
If the argument is not a tracked name, Nift can resolve an existing file path directly. This is extremely useful for project-owned frontend assets.
Stylesheets
<link
rel="stylesheet"
href="@pathto('public/assets/css/site.css')">
JavaScript / compiled TypeScript
<script
type="module"
src="@pathto('public/assets/js/app.js')"></script>
It does not matter whether app.js was authored directly or produced by TypeScript, Vite, esbuild, Rollup or another tool. The final local file exists, so Nift can reference it.
Images
<img
src="@pathto('public/assets/images/team.jpg')"
alt="The team">
<img
src="@pathto('public/assets/images/logo.svg')"
alt="Example company">
Responsive images
<picture>
<source
media="(min-width: 900px)"
srcset="@pathto('public/assets/images/hero-large.webp')">
<img
src="@pathto('public/assets/images/hero-small.webp')"
alt="Product interface">
</picture>
Favicons and metadata images
<link
rel="icon"
href="@pathto('public/favicon.svg')">
<meta
property="og:image"
content="@pathto('public/assets/images/social-card.png')">
Video and audio
<video
controls
poster="@pathto('public/assets/video/poster.jpg')">
<source
src="@pathto('public/assets/video/demo.mp4')"
type="video/mp4">
</video>
Downloads
<a
href="@pathto('public/downloads/product-guide.pdf')"
download>
Download the product guide
</a>
What happens when the file is missing?
Suppose the template contains:
<img
src="@pathto('public/assets/images/product-shot.webp')"
alt="Product screenshot">
If that path does not exist, Nift reports the unresolved target during the build. Without the project-aware check, a browser would only discover the problem after somebody requests the generated page.
Hard-coded relative paths vs project-aware paths
| Hard-coded | Project-aware |
|---|---|
../../assets/css/site.css | @pathto('public/assets/css/site.css') |
| You count directory depth manually. | Nift calculates it from the current output. |
| A typo may survive the build. | The referenced tracked/local target must resolve. |
| Shared partials become fragile as nesting changes. | The same partial can be reused across output depths. |
When ordinary URLs are still the right answer
@pathto is for targets Nift can know about: tracked outputs and local project files. External URLs remain ordinary URLs:
<a href="https://example.com">External site</a>
<script src="https://cdn.example.com/library.js"></script>
If the target belongs to this repository/project, consider @pathto. If the target lives elsewhere on the web, use its normal URL.