-
-
Notifications
You must be signed in to change notification settings - Fork 494
✨ Add branding page #2102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ Add branding page #2102
Conversation
WalkthroughThis PR introduces a new Branding control panel page allowing admins to view and manage primary colors, dark mode colors, logos, and white-label addon status. The feature includes navigation updates, localization entries, and a supporting query for white-label addon detection. Changes
Sequence Diagram(s)sequenceDiagram
actor Admin
participant Page as BrandingPage
participant LoadData as loadData()
participant Auth as Authorization
participant Queries as Branding Queries
participant License as License Service
participant UI as Render Components
Admin->>Page: Navigate to /control-panel/branding
Page->>LoadData: Call loadData()
LoadData->>Auth: Check admin role
alt Admin verified
LoadData->>Queries: Query branding data (colors, logos)
LoadData->>Queries: hasWhiteLabelAddon()
Queries->>License: loadInstanceLicense()
License-->>Queries: License data with whiteLabelAddon flag
Queries-->>LoadData: Branding data + addon status
LoadData-->>Page: Return branding data
Page->>UI: Render SettingsPage with Colors & Logos sections
UI-->>Admin: Display branding configuration UI
else Not admin
Auth-->>Page: Redirect or error
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/web/src/app/[locale]/control-panel/branding/page.tsx (1)
60-67: Variable shadowing:hasWhiteLabelAddonshadows the imported function.The destructured variable
hasWhiteLabelAddonon line 66 shadows the imported function of the same name from line 26. Consider renaming the variable to avoid confusion.🔎 Proposed fix
export default async function BrandingPage() { const { primaryColor, primaryColorDark, logoUrl, logoIconUrl, - hasWhiteLabelAddon, + hasWhiteLabelAddon: whiteLabelEnabled, } = await loadData(); return ( <SettingsPage> ... <SettingsPageContent> - {!hasWhiteLabelAddon ? ( + {!whiteLabelEnabled ? ( <Alert variant="primary">
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
apps/web/public/locales/en/app.jsonapps/web/src/app/[locale]/control-panel/branding/page.tsxapps/web/src/app/[locale]/control-panel/page.tsxapps/web/src/app/[locale]/control-panel/sidebar.tsxapps/web/src/features/branding/queries.ts
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Use dayjs for date handling
Use react-query for data fetching
Prefer implicit return values over explicit return values
Use zod for form validation
Create separate import statements for types
Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
Prefer double quotes for strings over single quotes
Only add comments when it is necessary to explain code that isn't self-explanatory
**/*.{ts,tsx}: Only create named interfaces when they're reused or complex
When TypeScript errors occur for missing i18n keys, runpnpm i18n:scaninstead of manually adding keys
Files:
apps/web/src/app/[locale]/control-panel/branding/page.tsxapps/web/src/app/[locale]/control-panel/sidebar.tsxapps/web/src/app/[locale]/control-panel/page.tsxapps/web/src/features/branding/queries.ts
**/*.{tsx,css,config.ts}
📄 CodeRabbit inference engine (.cursorrules)
Use tailwindcss for styling
Files:
apps/web/src/app/[locale]/control-panel/branding/page.tsxapps/web/src/app/[locale]/control-panel/sidebar.tsxapps/web/src/app/[locale]/control-panel/page.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use react-hook-form for form handling
All text in the UI should be translated using either the Trans component or the useTranslation hook
Prefer composable components in the style of shadcn UI over large monolithic components
DropdownMenuItem is a flex container with a preset gap so there is no need to add margins to the children
The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size
Keep the props of a component as minimal as possible. Pass only the bare minimum amount of information needed to it
All text in the UI should be translatable
Use the component in client components from @/components/trans with thedefaultsprop to provide the default text
Always use a composable patterns when building components
Usecn()from @rallly/ui to compose classes
Add the "use client" directive to the top of any .tsx file that requires client-side javascript
Files:
apps/web/src/app/[locale]/control-panel/branding/page.tsxapps/web/src/app/[locale]/control-panel/sidebar.tsxapps/web/src/app/[locale]/control-panel/page.tsx
**/*.{ts,tsx,json}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx,json}: i18n keys are in camelCase
i18nKeys should describe the message in camelCase. Ex. "lastUpdated": "Last Updated"
If the i18nKey is not intended to be reused, prefix it with the component name in camelCase
Files:
apps/web/src/app/[locale]/control-panel/branding/page.tsxapps/web/src/app/[locale]/control-panel/sidebar.tsxapps/web/src/app/[locale]/control-panel/page.tsxapps/web/public/locales/en/app.jsonapps/web/src/features/branding/queries.ts
**/*
📄 CodeRabbit inference engine (.cursorrules)
Always use kebab-case for file names
Files:
apps/web/src/app/[locale]/control-panel/branding/page.tsxapps/web/src/app/[locale]/control-panel/sidebar.tsxapps/web/src/app/[locale]/control-panel/page.tsxapps/web/public/locales/en/app.jsonapps/web/src/features/branding/queries.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Biome for code formatting with indent of 2 spaces and double quotes
Files:
apps/web/src/app/[locale]/control-panel/branding/page.tsxapps/web/src/app/[locale]/control-panel/sidebar.tsxapps/web/src/app/[locale]/control-panel/page.tsxapps/web/src/features/branding/queries.ts
**/*.{tsx,ts}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{tsx,ts}: Prefer inline prop types over named interfaces for simple component props (e.g.,function Component({ prop }: { prop: string })instead of defining a separate interface)
Always use theuseDialoghook from@rallly/ui/dialogfor managing dialog state instead of manualuseStatefor open/close state
Use TanStack Query with tRPC for server state management
Use React Context for client state (auth, preferences, etc.)
Use react-hook-form with Zod validation for form state management
Use TailwindCSS with custom design system for styling
Files:
apps/web/src/app/[locale]/control-panel/branding/page.tsxapps/web/src/app/[locale]/control-panel/sidebar.tsxapps/web/src/app/[locale]/control-panel/page.tsxapps/web/src/features/branding/queries.ts
apps/web/src/app/**
📄 CodeRabbit inference engine (CLAUDE.md)
Use Next.js App Router conventions for route handlers
Files:
apps/web/src/app/[locale]/control-panel/branding/page.tsxapps/web/src/app/[locale]/control-panel/sidebar.tsxapps/web/src/app/[locale]/control-panel/page.tsx
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/web/.cursor/rules/better-auth.md)
apps/web/**/*.{ts,tsx,js,jsx}: When using the username plugin, require all sign up endpoints to accept ausername(used for login, normalized) and an optionaldisplayUsername(raw, for display purposes).
When using the username plugin, all username values must be normalized according to the configuration function before storage or comparison (default: lowercase).
Whenever updating a user's username, always check for uniqueness and apply the normalization procedure.
Login endpoints or forms supporting username authentication must allow signing in with username and password, not just email.
Files:
apps/web/src/app/[locale]/control-panel/branding/page.tsxapps/web/src/app/[locale]/control-panel/sidebar.tsxapps/web/src/app/[locale]/control-panel/page.tsxapps/web/src/features/branding/queries.ts
**/*.ts
📄 CodeRabbit inference engine (.cursorrules)
On the server use the
getTranslationsfunction from @/i18n/server to get the translations
Files:
apps/web/src/features/branding/queries.ts
apps/web/src/features/**
📄 CodeRabbit inference engine (CLAUDE.md)
Organize features in
apps/web/src/features/[feature]/directory structure
Files:
apps/web/src/features/branding/queries.ts
🧠 Learnings (2)
📚 Learning: 2025-11-25T11:03:55.173Z
Learnt from: CR
Repo: lukevella/rallly PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T11:03:55.173Z
Learning: Applies to **/*.tsx : The size and colour of an icon should be set by wrapping it with the <Icon> component from rallly/ui/icon which will give it the correct colour and size
Applied to files:
apps/web/src/app/[locale]/control-panel/sidebar.tsxapps/web/src/app/[locale]/control-panel/page.tsx
📚 Learning: 2025-11-25T11:04:05.725Z
Learnt from: CR
Repo: lukevella/rallly PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T11:04:05.725Z
Learning: Applies to **/*.{tsx,ts} : Use React Context for client state (auth, preferences, etc.)
Applied to files:
apps/web/src/features/branding/queries.ts
🧬 Code graph analysis (4)
apps/web/src/app/[locale]/control-panel/branding/page.tsx (4)
apps/web/src/features/branding/queries.ts (4)
getPrimaryColor(16-18)getLogoUrl(44-46)hasWhiteLabelAddon(52-55)getLogoIconUrl(48-50)apps/web/src/env.ts (1)
env(6-210)packages/ui/src/alert.tsx (2)
Alert(71-71)AlertDescription(71-71)apps/web/src/app/[locale]/control-panel/page.tsx (1)
generateMetadata(146-150)
apps/web/src/app/[locale]/control-panel/sidebar.tsx (1)
apps/web/src/app/[locale]/control-panel/nav-item.tsx (1)
NavItem(7-24)
apps/web/src/app/[locale]/control-panel/page.tsx (3)
packages/ui/src/tile.tsx (2)
Tile(79-79)TileTitle(79-79)packages/emails/src/components/styled-components.tsx (1)
Link(73-80)apps/web/src/app/components/page-icons.tsx (1)
PageIcon(50-62)
apps/web/src/features/branding/queries.ts (1)
apps/web/src/features/licensing/data.ts (1)
loadInstanceLicense(24-43)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Integration tests
🔇 Additional comments (6)
apps/web/public/locales/en/app.json (1)
566-578: LGTM!The new i18n keys follow camelCase convention and provide appropriate translations for the branding feature. The
setEnvironmentVariablekey correctly uses the<env />component placeholder for dynamic content rendering.apps/web/src/features/branding/queries.ts (1)
52-55: LGTM!The
hasWhiteLabelAddonfunction correctly loads the instance license and safely returns thewhiteLabelAddonflag with afalsedefault when the license is absent or the property is undefined.apps/web/src/app/[locale]/control-panel/page.tsx (1)
113-125: LGTM!The Branding tile follows the established pattern of other tiles in the grid, using
PageIconto wrap the icon andTransfor internationalization. The structure is appropriately simple, consistent with the Settings tile.apps/web/src/app/[locale]/control-panel/sidebar.tsx (1)
54-57: LGTM!The new Branding nav item follows the existing pattern in this sidebar file, using direct
className="size-4"on the icon consistent with other menu items.apps/web/src/app/[locale]/control-panel/branding/page.tsx (2)
41-58: LGTM!The
SetEnvironmentVariableAlertcomponent is well-designed with inline prop types, proper use of theTranscomponent for interpolation, and appropriate styling for the environment variable code display.
202-207: LGTM!The
generateMetadatafunction correctly usesgetTranslationfrom@/i18n/serverfor server-side translation, following the coding guidelines.
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.