feat(branding): brand kit architecture (Phase 1) #96
14 changed files with 41 additions and 4 deletions
feat(branding): add @brand vite alias + migrate in-app img consumers
vite-branding.ts is the shared resolver. Exports BRAND_DIR (absolute, defaults to ./branding/default) and brandAlias for spreading into each vite config's resolve.alias map. All 9 vite configs now spread brandAlias so `@brand/<file>` resolves to the active brand dir at build time. Migrates the four <img src="@/assets/logo.png"> consumers (Login.vue, LoginDemo.vue, AppSidebar.vue, MobileDrawer.vue) to @brand/logo.png. Unused Navbar.old.vue left as-is. Build verified: dist/assets/logo-<hash>.png emits from the aliased import. Future deployers point BRAND_DIR at their brand kit and the in-app logo follows automatically. Part of aiolabs/webapp#95. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
commit
eebb566323
|
|
@ -48,7 +48,7 @@ const isActive = (href: string) => {
|
|||
<div class="flex h-16 shrink-0 items-center">
|
||||
<router-link to="/" class="flex items-center gap-2">
|
||||
<img
|
||||
src="@/assets/logo.png"
|
||||
src="@brand/logo.png"
|
||||
alt="Logo"
|
||||
class="h-8 w-8"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ const navigateTo = (href: string) => {
|
|||
<SheetHeader class="px-6 py-4 border-b border-border">
|
||||
<SheetTitle class="flex items-center gap-2">
|
||||
<img
|
||||
src="@/assets/logo.png"
|
||||
src="@brand/logo.png"
|
||||
alt="Logo"
|
||||
class="h-8 w-8"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<!-- Logo and Title -->
|
||||
<div class="text-center space-y-6">
|
||||
<div class="flex justify-center">
|
||||
<img src="@/assets/logo.png" alt="Logo" class="h-24 w-24 sm:h-32 sm:w-32" />
|
||||
<img src="@brand/logo.png" alt="Logo" class="h-24 w-24 sm:h-32 sm:w-32" />
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<h1 class="text-3xl font-bold tracking-tight">Virtual Realm</h1>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<!-- Welcome Section -->
|
||||
<div class="text-center space-y-2 sm:space-y-4">
|
||||
<div class="flex justify-center">
|
||||
<img src="@/assets/logo.png" alt="Logo" class="h-34 w-34 sm:h-42 sm:w-42 lg:h-50 lg:w-50" />
|
||||
<img src="@brand/logo.png" alt="Logo" class="h-34 w-34 sm:h-42 sm:w-42 lg:h-50 lg:w-50" />
|
||||
</div>
|
||||
<div class="space-y-1 sm:space-y-3">
|
||||
<h1 class="text-2xl sm:text-3xl md:text-4xl font-bold tracking-tight">Welcome to the Virtual Realm</h1>
|
||||
|
|
|
|||
19
vite-branding.ts
Normal file
19
vite-branding.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import { resolve } from 'node:path'
|
||||
|
||||
/**
|
||||
* Absolute path to the active brand kit. Deployers point this at their
|
||||
* own `branding/<name>/` directory (see branding/README.md).
|
||||
*
|
||||
* Defaults to the committed aiolabs default brand. Used by vite configs
|
||||
* for the `@brand` import alias and by pwa-assets.config.ts.
|
||||
*/
|
||||
export const BRAND_DIR = resolve(process.env.BRAND_DIR ?? './branding/default')
|
||||
|
||||
/**
|
||||
* Spread into a vite config's `resolve.alias` map. Lets components
|
||||
* import deployer-provided assets via `@brand/<file>` instead of
|
||||
* hardcoding `@/assets/logo.png`.
|
||||
*/
|
||||
export const brandAlias = {
|
||||
'@brand': BRAND_DIR,
|
||||
} as const
|
||||
|
|
@ -5,6 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
|||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||
import { visualizer } from 'rollup-plugin-visualizer'
|
||||
import { brandAlias } from './vite-branding'
|
||||
|
||||
function chatHtmlPlugin(): Plugin {
|
||||
return {
|
||||
|
|
@ -103,6 +104,7 @@ export default defineConfig(({ mode }) => ({
|
|||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
...brandAlias,
|
||||
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
||||
'@/app.config': fileURLToPath(new URL('./src/chat-app/app.config.ts', import.meta.url)),
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { defineConfig } from 'vite'
|
|||
import Inspect from 'vite-plugin-inspect'
|
||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||
import { visualizer } from 'rollup-plugin-visualizer'
|
||||
import { brandAlias } from './vite-branding'
|
||||
|
||||
// https://vite.dev/config/
|
||||
//
|
||||
|
|
@ -43,6 +44,7 @@ export default defineConfig(({ mode }) => ({
|
|||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
...brandAlias,
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
|||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||
import { visualizer } from 'rollup-plugin-visualizer'
|
||||
import { brandAlias } from './vite-branding'
|
||||
|
||||
/**
|
||||
* Plugin to rewrite dev server requests to events.html
|
||||
|
|
@ -118,6 +119,7 @@ export default defineConfig(({ mode }) => ({
|
|||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
...brandAlias,
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
|||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||
import { visualizer } from 'rollup-plugin-visualizer'
|
||||
import { brandAlias } from './vite-branding'
|
||||
|
||||
function forumHtmlPlugin(): Plugin {
|
||||
return {
|
||||
|
|
@ -103,6 +104,7 @@ export default defineConfig(({ mode }) => ({
|
|||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
...brandAlias,
|
||||
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
||||
'@/app.config': fileURLToPath(new URL('./src/forum-app/app.config.ts', import.meta.url)),
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
|||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||
import { visualizer } from 'rollup-plugin-visualizer'
|
||||
import { brandAlias } from './vite-branding'
|
||||
|
||||
/**
|
||||
* Plugin to rewrite dev server requests to libra.html
|
||||
|
|
@ -110,6 +111,7 @@ export default defineConfig(({ mode }) => ({
|
|||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
...brandAlias,
|
||||
// ORDER MATTERS — @rollup/plugin-alias is first-match-wins.
|
||||
// The more specific @/app.config remap must precede the @ prefix
|
||||
// alias, otherwise '@/app.config' matches '@' first and resolves
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
|||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||
import { visualizer } from 'rollup-plugin-visualizer'
|
||||
import { brandAlias } from './vite-branding'
|
||||
|
||||
function marketHtmlPlugin(): Plugin {
|
||||
return {
|
||||
|
|
@ -103,6 +104,7 @@ export default defineConfig(({ mode }) => ({
|
|||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
...brandAlias,
|
||||
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
||||
'@/app.config': fileURLToPath(new URL('./src/market-app/app.config.ts', import.meta.url)),
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
|||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||
import { visualizer } from 'rollup-plugin-visualizer'
|
||||
import { brandAlias } from './vite-branding'
|
||||
|
||||
function restaurantHtmlPlugin(): Plugin {
|
||||
return {
|
||||
|
|
@ -110,6 +111,7 @@ export default defineConfig(({ mode }) => ({
|
|||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
...brandAlias,
|
||||
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
||||
'@/app.config': fileURLToPath(new URL('./src/restaurant-app/app.config.ts', import.meta.url)),
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
|||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||
import { visualizer } from 'rollup-plugin-visualizer'
|
||||
import { brandAlias } from './vite-branding'
|
||||
|
||||
function tasksHtmlPlugin(): Plugin {
|
||||
return {
|
||||
|
|
@ -103,6 +104,7 @@ export default defineConfig(({ mode }) => ({
|
|||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
...brandAlias,
|
||||
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
||||
'@/app.config': fileURLToPath(new URL('./src/tasks-app/app.config.ts', import.meta.url)),
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
|||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||
import { visualizer } from 'rollup-plugin-visualizer'
|
||||
import { brandAlias } from './vite-branding'
|
||||
|
||||
/**
|
||||
* Plugin to rewrite dev server requests to wallet.html
|
||||
|
|
@ -109,6 +110,7 @@ export default defineConfig(({ mode }) => ({
|
|||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
...brandAlias,
|
||||
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
||||
'@/app.config': fileURLToPath(new URL('./src/wallet-app/app.config.ts', import.meta.url)),
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue