Guide
Profile
Handle user profiles and avatar uploads
UNuxt provides user profile management with avatar uploads powered by Cloudinary.
Display user profile
Access user data through the session:
components/ProfileCard.vue
<script setup lang="ts">
const { user } = useUserSession()
</script>
<template>
<UCard>
<div class="flex items-center gap-4">
<UAvatar :src="user.image" :alt="user.name" size="xl" />
<div>
<h2 class="font-semibold">{{ user.name }}</h2>
<p class="text-muted">{{ user.email }}</p>
</div>
</div>
</UCard>
</template>
Update profile information
Allow users to update their profile details:
pages/settings/profile.vue
<script setup lang="ts">
const { user, fetch: refreshSession } = useUserSession()
const state = reactive({
name: user.value?.name || '',
email: user.value?.email || ''
})
async function updateProfile() {
await $fetch('/api/user/profile', {
method: 'PATCH',
body: state
})
await refreshSession()
}
</script>
<template>
<UForm :state="state" @submit="updateProfile">
<UFormField label="Name" name="name">
<UInput v-model="state.name" />
</UFormField>
<UFormField label="Email" name="email">
<UInput v-model="state.email" type="email" />
</UFormField>
<UButton type="submit">Save Changes</UButton>
</UForm>
</template>
Upload avatars with Cloudinary
Configure Cloudinary for image uploads:
.env
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
CLOUDINARY_API_SECRET=your-api-secret
Create an upload handler:
server/api/user/avatar.post.ts
import { v2 as cloudinary } from 'cloudinary'
export default defineEventHandler(async (event) => {
const formData = await readFormData(event)
const file = formData.get('avatar') as File
const buffer = await file.arrayBuffer()
const base64 = Buffer.from(buffer).toString('base64')
const result = await cloudinary.uploader.upload(
`data:${file.type};base64,${base64}`,
{
folder: 'avatars',
transformation: [
{ width: 200, height: 200, crop: 'fill' }
]
}
)
// Update user record with new avatar URL
await updateUserAvatar(event.context.user.id, result.secure_url)
return { url: result.secure_url }
})
Handle avatar upload in the UI
Create an avatar upload component:
components/AvatarUpload.vue
<script setup lang="ts">
const { user, fetch: refreshSession } = useUserSession()
const uploading = ref(false)
async function handleUpload(event: Event) {
const input = event.target as HTMLInputElement
const file = input.files?.[0]
if (!file) return
uploading.value = true
const formData = new FormData()
formData.append('avatar', file)
await $fetch('/api/user/avatar', {
method: 'POST',
body: formData
})
await refreshSession()
uploading.value = false
}
</script>
<template>
<div class="flex items-center gap-4">
<UAvatar :src="user.image" :alt="user.name" size="xl" />
<label>
<UButton as="span" :loading="uploading">
Change Avatar
</UButton>
<input
type="file"
accept="image/*"
class="hidden"
@change="handleUpload"
/>
</label>
</div>
</template>