Appearance
Login Layout ​
File Information ​
- Path:
app/layouts/login-layout.vue - Purpose: Layout for authentication pages with brand branding
- Used For: Login, forgot password, reset password, and public pages
Overview ​
The login-layout provides a centered, branded layout for authentication and public pages. It includes brand logo/name display, centered content area, and "Powered by Collage" footer branding.
Structure ​
vue
<template>
<v-app>
<div class="main">
<div class="signin-screen customscrollbar">
<div class="signin-screen-table">
<div class="signin-screen-table-cell">
<div class="signin-screen-content">
<!-- Brand Logo/Name -->
<div class="signin-screen-title">
<img v-if="logo" :src="logo" class="brand-logo" />
<h1 v-else>{{ brandName }}</h1>
</div>
<!-- Page Content -->
<NuxtPage />
</div>
</div>
<!-- Powered by Collage Footer -->
<div class="powered-by-collage">
<AsyncIcon name="faviconIcon" />
<p>Powered by <a href="https://www.collage.inc">Collage</a></p>
</div>
</div>
</div>
</div>
</v-app>
</template>Components ​
Brand Display ​
- Logo: Displays brand logo if available
- Brand Name: Falls back to brand name text if no logo
- Loading State: Skeleton loader during brand data fetch
Powered by Collage Footer ​
- Icon: Collage favicon icon
- Link: Link to Collage website
- Styling: Centered, subtle branding
Features ​
Brand Integration ​
The layout loads brand details similar to collage-layout:
typescript
onMounted(async () => {
nextTick(() => (contentLoading.value = false))
try {
if (!appDataStore.brand) {
await appDataStore.fetchBrandDetails(route.params.brand_name as string)
await nextTick()
brand.value = appDataStore.brand || {}
} else {
brand.value = appDataStore.brand || {}
}
logo.value = appDataStore.logo || "/Collage-labinc-dark12c.svg"
} catch (error) {
console.error("Failed to load brand details:", error)
}
})SEO Configuration ​
Sets up SEO metadata with brand information:
typescript
useHead({
title: () => `${brand.value?.brand_name || brandName.value} Brand Portal by Collage Inc`,
link: computed(() => [
{
rel: "icon",
type: "image/svg+xml",
href: faviconUrl.value,
},
]),
})
useSeoMeta({
ogImage: logo.value || "/Collage-labinc-dark12c.svg",
ogImageWidth: "1200",
ogImageHeight: "630",
ogImageAlt: `${brand.value?.brand_name || brandName.value} Logo`,
ogTitle: `${brand.value?.brand_name || brandName.value} Brand Portal by Collage Inc`,
})Dynamic Favicon ​
Watches for favicon changes and updates the DOM:
typescript
if (import.meta.client) {
watch(faviconUrl, (newFavicon) => {
if (newFavicon) {
let link = document.querySelector('link[rel="icon"]') as HTMLLinkElement
if (!link) {
link = document.createElement('link')
link.rel = 'icon'
link.type = 'image/svg+xml'
document.head.appendChild(link)
}
link.href = newFavicon
}
}, { immediate: true })
}Loading States ​
Provides skeleton loaders during brand data fetch:
vue
<v-skeleton-loader
v-if="contentLoading"
type="image"
class="logoSkeleton"
/>Usage ​
In Authentication Page ​
vue
<script setup lang="ts">
definePageMeta({
layout: 'login-layout'
})
</script>
<template>
<div class="login-form">
<!-- Login form content -->
</div>
</template>Pages Using This Layout ​
- Login (
[brand_name]/login.vue) - Forgot Password (
[brand_name]/forgot-password.vue) - Reset Password (
[brand_name]/reset-password.vue) - Generate Password (
[brand_name]/generate-password.vue) - Public shared asset pages
Styling ​
Uses global SCSS classes:
.signin-screen- Main login screen container.signin-screen-table- Table layout for centering.signin-screen-table-cell- Table cell for vertical centering.signin-screen-content- Content area.signin-screen-title- Brand logo/name area.brand-logo- Brand logo styling.powered-by-collage- Footer branding.customscrollbar- Custom scrollbar styling
See Styling - Login for detailed styles.
Dependencies ​
useAppDataStore()- App data store for brand informationuseRoute()- Route for brand name parameterAsyncIcon- Icon component for footer
Related Documentation ​
- Layouts Overview - All layouts
- Pages - Login - Login page documentation
- Styling - Login - Login page styles
- Components - AsyncIcon - Icon component