Quick start
This guide will help you understand the boilerplate by building a simple feature. We'll create a protected page that displays user information.
Goal
By the end of this guide, you'll have:
- Created a new protected page
- Added it to the navigation menu
- Fetched and displayed user data
- Used shadcn-vue components for the UI
Let's get started!
Step 1: Create a protected page
Create a new file at app/pages/profile.vue:
<script setup lang="ts">
// This page requires authentication
definePageMeta({
middleware: 'auth',
})
const userStore = useUserStore()
const { user } = storeToRefs(userStore)
useSeoMeta({
title: 'Profile',
description: 'View your profile information',
})
</script>
<template>
<div class="base-container py-8">
<h1 class="text-4xl font-bold mb-2">Your profile</h1>
<p class="text-muted-foreground mb-8">View and manage your account information</p>
<Card v-if="user" class="max-w-2xl">
<CardHeader>
<CardTitle>Account information</CardTitle>
<CardDescription> Your account details and settings </CardDescription>
</CardHeader>
<CardContent class="space-y-4">
<div class="grid grid-cols-2 gap-4">
<div>
<p class="text-sm font-medium text-muted-foreground">Name</p>
<p class="text-base">{{ user.name }}</p>
</div>
<div>
<p class="text-sm font-medium text-muted-foreground">Email</p>
<p class="text-base">{{ user.email }}</p>
</div>
<div>
<p class="text-sm font-medium text-muted-foreground">Email verified</p>
<p class="text-base">{{ user.emailVerified ? 'Yes' : 'No' }}</p>
</div>
<div>
<p class="text-sm font-medium text-muted-foreground">Member since</p>
<p class="text-base">{{ new Date(user.createdAt).toLocaleDateString() }}</p>
</div>
</div>
</CardContent>
<CardFooter>
<Button as-child>
<NuxtLink to="/settings"> Edit profile </NuxtLink>
</Button>
</CardFooter>
</Card>
</div>
</template>
middleware: 'auth' in definePageMeta ensures only authenticated users can access this page. Unauthenticated users will be redirected to the login page.Step 2: Add to navigation
Open app/components/header/MainHeader.vue and add the profile link to the navigationItems array:
const navigationItems = [
{
label: 'Dashboard',
icon: Home,
to: '/dashboard',
requiresAuth: true,
},
{
label: 'Profile',
icon: User,
to: '/profile',
requiresAuth: true,
},
// ... other items
]
Don't forget to import the User icon at the top of the file:
import { User, Home /* other icons */ } from 'lucide-vue-next'
Step 3: Test your page
- Start the dev server (if not already running):
pnpm dev
- Log in to your application at http://localhost:3000/auth/login
- Navigate to your new page - Click "Profile" in the header menu
- See your data - You should see your account information displayed in a card
What you learned
Through this quick example, you've seen how to:
- ✅ Create a protected page with
definePageMeta - ✅ Use the user store to access authentication state
- ✅ Use shadcn-vue components (Card, Button)
- ✅ Add navigation items to the header menu
- ✅ Follow the boilerplate's conventions
Key concepts explained
Page metadata
definePageMeta({
middleware: 'auth',
})
This tells Nuxt to run the auth middleware before rendering the page. The middleware is defined in app/middleware/auth.global.ts and automatically redirects unauthenticated users.
User store
const userStore = useUserStore()
const { user } = storeToRefs(userStore)
The user store (Pinia) holds the current user's authentication state. Using storeToRefs ensures reactivity when accessing store properties.
Shadcn-vue components
The boilerplate includes 170+ pre-built UI components. They're automatically imported, so you can use them directly:
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
</CardHeader>
<CardContent>
Content here
</CardContent>
</Card>
Next steps
Now that you understand the basics, explore more features:
Challenge: Extend the feature
Try adding these enhancements on your own:
- Add an avatar - Display the user's image if available
- Show subscription status - Use the
useSubscriptioncomposable to display plan info - Add a button - Create a button to change the user's email
- Style improvements - Customize the card appearance with Tailwind classes