Your First Page
Time to create your first page with Vuero.
INFO
Explore the src/components/pages
folder of demo project to help you build your own pages.
Routes folder structure
As seen in the previous section, Vuero uses Unplugin Vue Router to manage routes generation from the src/pages
folder. This means that you only need to create a new .vue
file in the src/pages
folder to create a new page in your application.
src/pages/
├── index.vue # Home page
├── [...all].vue # Catch all route (404)
├── auth.vue # Auth layout
├── auth/
│ ├── index.vue
│ └── signup.vue
├── app.vue # App layout
└── app/
├── index.vue
└── [slug].vue # Route with dynamic parameter
Useful links:
Pages features
Route parameters
When using dynamic routes, you can access the route parameters using the useRoute
composable from Vue Router.
<script setup lang="ts">
// note that you don't need to import useRoute from vue-router
const route = useRoute()
</script>
<template>
<div>
<h1>slug: {{ route.params.slug }}</h1>
</div>
</template>
Useful links:
Page metadata
Page metadata are static content that will be used in vue router routes, it can be used to set information like if the page is public or private, the layout to use, the title, the meta tags, etc. Later we can use this metadata in router guards to protect routes or in the layout to render the correct content. (see Plugin Guide for more information about router guards)
<script setup lang="ts">
import MyLayout from '/@src/layouts/my-layout.vue'
definePage({
// all child pages will inherit this metadata
meta: {
requiresAuth: true,
},
})
</script>
<template>
<MyLayout>
<slot />
</MyLayout>
</template>
Equivalent in Nuxt quickstarter
<script setup lang="ts">
definePageMeta({
// all child pages will inherit this metadata
layout: 'my-layout',
requiresAuth: true,
})
</script>
<template>
<div>
<!-- NuxtPage is used instead of RouterView -->
<NuxtPage />
</div>
</template>
Useful links:
Head tags
To manage the head tags of a page, Vuero use @unhead/vue
which provide composables with fully typed head tags.
<script setup lang="ts">
useHead({
titleTemplate: (title?: string) => !title ? 'My App' : `${title} - My App`,
link: [
{
rel: 'icon',
href: '/favicon.svg',
type: 'image/svg+xml',
},
],
meta: [
// Critical Tags
{ charset: 'utf-8' },
{
name: 'viewport',
content: 'width=device-width, initial-scale=1, shrink-to-fit=no',
},
],
})
</script>
<template>
<div>
<Suspense>
<RouterView />
</Suspense>
</div>
</template>
The common place to set global head tags is in the global app component in src/VueroApp.vue
if using SSR.
When using client only setup, you need to set critical head tags directly in the src/index.html
because they will not be interpreted by client until the Vue app is mounted.
Useful links:
Data Loader (experimental)
Unplugin Vue Router introduce a new feature called Data Loader which allow you to load data before rendering the page. This is useful when you need to fetch data from an API or a database.
<script lang="ts">
import { defineBasicLoader } from 'unplugin-vue-router/data-loaders/basic'
export const usePageData = defineBasicLoader(async (to) => {
const slug = to.params.slug
const page = await fetch(`https://api.example.com/pages/${slug}`)
.then(res => res.json())
return {
page,
}
}, {
// used for SSR only
key: 'app-slug-data',
})
</script>
<script setup lang="ts">
const route = useRoute()
const { data, isLoading } = usePageData()
</script>
<template>
<div>
<h1>slug: {{ route.params.slug }}</h1>
<div v-if="isLoading">Loading...</div>
<div v-else>{{ data.page }}</div>
</div>
</template>
Useful links: