Written by: Thiago Nunes Batista
Published on 12/03/2025
Last updated: 12/03/2025
Nuxt uses a file-based routing system, meaning that every file
or directory
you create inside the /pages
folder will be turned into a page in your Nuxt site, and a URL will be generated for that page based on the file name, as shown in the table below:
File | Route |
---|---|
pages/index.vue | / |
pages/links.vue | /links |
pages/tools/cpf-generator | /tools/cpf-generator |
This is the foundation of Nuxt routing, and in this article, you will dive deeper into the key routing concepts in Nuxt.
Nuxt’s routing system is called File System Routing
, where every file created inside the /pages
folder becomes a page.
For example, consider the folder structure below:
/*
/pages
about.vue
contact.vue
privacy-policy.vue
*/
Based on these files, assuming the base URL is https://onlinestore.com
, Nuxt will generate the following URLs:
https://onlinestore.com/about
https://onlinestore.com/contact
https://onlinestore.com/privacy-policy
To understand dynamic routes, imagine the following scenario: you have an online store called "Online Store," and within this store, you have several products. The product pages are identical, only displaying different content.
"A Person Using Laptop" by Mart Production , licensed by Pexels
To handle this, you can use Nuxt's dynamic routes, allowing you to create a single page file that will be used for all products. This can be done in two ways:
Parameter Location | File | Route |
---|---|---|
Directory Name | pages/products/[productSlug]/index.vue | /products/productSlug |
File Name | pages/products/[productSlug].vue | /products/productSlug |
Notice that the name used is "productSlug" and it is enclosed in brackets: [
and ]
. This is Nuxt’s syntax, and the chosen name is the parameter name we can use in our code.
Regardless of whether you place the parameter in the directory name or the file name, the final result will be the same.
Given the above product page structure, imagine that a user is accessing a product page for a "Cool T-shirt" from a brand called "X," where the slug
for the t-shirt is cool-tshirt-brand-x
:https://onlinestore.com/products/cool-tshirt-brand-x
.
"A Man Shopping for Clothes at a Sneaker Shop" by RDNE Stock project , licensed by Pexels
We can capture the product slug as follows:
<script setup>
const route = useRoute();
const slug = route.params.productSlug;
</script>
But what is a slug, and why was "productSlug" used?
A slug
is similar to an id
; it serves as a unique identifier for pages or resources on a website. The slug cool-tshirt-brand-x
was chosen to create a user-friendly identifier that improves navigation and SEO.
This slug will be used to retrieve the product details from the store’s database and display the "Cool T-shirt" information to the user.
Nested routes are useful when structuring pages that share the same layout but display different content. A common example is the admin panel of the Online Store, which may have sections such as Orders, Products, and Settings.
Consider the following directory and file structure:
/pages
/admin
index.vue
orders.vue
products.vue
settings.vue
Here, when the user accesses https://onlinestore.com/admin
, the index.vue
file inside the admin
folder is loaded. The other pages can be accessed as follows:
https://onlinestore.com/admin/orders -> Orders
https://onlinestore.com/admin/products -> Products
https://onlinestore.com/admin/settings -> Settings
If all these pages share the same navigation menu, it's best to create a layout.vue
file inside the /admin
folder and use <NuxtPage />
to load dynamic content, preventing code duplication.
The layout file in /pages/admin/layout.vue
would look like this:
<template>
<div>
<nav>
<NuxtLink to="/admin/orders">Orders</NuxtLink>
<NuxtLink to="/admin/products">Products</NuxtLink>
<NuxtLink to="/admin/settings">Settings</NuxtLink>
</nav>
<NuxtPage />
</div>
</template>
This way, all pages inside /admin
will inherit this structure, allowing smooth navigation without reloading the entire interface.
Query parameters are used to pass additional information in the URL without modifying the base route.
The structure is: ?
+ parameter name
+ =
+ parameter value
:
?parameter_name=parameter_value
To add more parameters, use &
:
?parameter_name=parameter_value&second_parameter_name=second_parameter_value
In Nuxt, we can capture these parameters as follows:
<script setup>
// Instantiating a variable to receive route information
const route = useRoute();
// Storing the "category" parameter in the productCategory variable
const productCategory = route.query.category;
</script>
This allows us to manipulate data or even call an API using this information.
"Question Marks on Paper Crafts" by Leeloo The First , licensed by Pexels
Some common use cases for query parameters in the Online Store include:
https://onlinestore.com/tshirts?orderBy=cheapest
https://onlinestore.com/tshirts?color=blue&size=m
https://onlinestore.com/promotions?page=2
https://onlinestore.com/tshirts?name=cool-tshirt
This enables dynamic search functionalities without requiring different pages for each search term.
https://onlinestore.com/promotions?viewMode=grid
Nuxt’s routing system simplifies page creation and organization, making development more intuitive. From basic to dynamic and nested routes, its file-based structure enhances maintainability and improves user experience.
With query parameters, you can further customize navigation effortlessly. Armed with this knowledge, you can efficiently structure any Nuxt application, ensuring well-organized URLs and a smooth navigation flow.