Conversation
…ers/crud.tsx Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…te.tsx Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…improve config management in StackAdminInterface
There was a problem hiding this comment.
Greptile Summary
This PR implements project logo upload functionality for the Stack Auth platform. The changes add support for two types of project logos: a standard square logo (logoUrl) and a full horizontal logo with text (fullLogoUrl).
The implementation spans the entire stack:
Database Layer: A new migration adds nullable logoUrl and fullLogoUrl TEXT columns to the Project table, following the same pattern used for team profile images.
Backend API: The project management system is extended to handle logo uploads through the existing S3 infrastructure. The maximum file size limit is increased from 300KB to 1MB to accommodate higher quality logos. Logo processing leverages the existing image validation pipeline using Sharp for format validation, dimension checking, and metadata extraction.
Frontend Components: A new LogoUpload component provides a comprehensive upload interface with client-side image compression using the browser-image-compression library. The component handles file selection, validation, base64 conversion, and provides proper loading states and error handling.
Schema & Types: Logo fields are integrated throughout the type system, from database schemas to TypeScript interfaces. The fields are consistently defined as nullable/optional to maintain backward compatibility with existing projects.
Dashboard Integration: The project settings page now includes a dedicated "Project Logo" section where administrators can upload and manage both logo variants with appropriate descriptions and recommendations.
The feature follows established patterns in the codebase for image handling and integrates seamlessly with the existing project configuration system. Projects can now have custom branding that will be displayed in login pages and emails.
Confidence score: 4/5
- This PR is safe to merge with minimal risk of breaking existing functionality
- Score reflects well-structured implementation following established patterns, though there are minor issues with error handling and component logic
- Pay close attention to the LogoUpload component for the disabled attribute issue and consider the base64 file size validation logic in images.tsx
13 files reviewed, 4 comments
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
packages/stack-shared/src/schema-fields.ts (1)
437-438: Consider using different example values to distinguish logo types.Both logo schemas use identical example values ('https://example.com/logo.png'), which doesn't help illustrate the distinction between regular and full logos.
packages/template/src/lib/stack-app/projects/index.ts (1)
21-22: Consider usingstring | nullinstead ofstring | null | undefinedfor consistency.The logo URL fields use
string | null | undefinedwhile other nullable fields in the same type (likedescription) usestring | null. This creates inconsistency in the type definitions.
🧹 Nitpick comments (4)
apps/dashboard/package.json (1)
37-37: Pin or lock the new dependency version for reproducible buildsAdding
"browser-image-compression": "^2.0.2"means any2.xminor/patch will be pulled on fresh installs. Consider pinning ("2.0.2") or usingpnpm.overridesto avoid silent breakage from upstream changes.apps/backend/prisma/schema.prisma (1)
22-23: Consider length-limiting the new TEXT columns
logoUrlandfullLogoUrlcan theoretically store multi-MB data. If you only expect standard HTTP URLs, avarchar(1024)(or similar) reduces risk of unexpected bloat / abuse and keeps indexes smaller if you ever add one.apps/backend/prisma/migrations/20250801204029_logo_url/migration.sql (1)
1-5: Combine consecutiveALTER TABLEstatements into onePostgreSQL allows adding both columns in a single
ALTER TABLE … ADD COLUMN … , ADD COLUMN …which runs faster and acquires the lock only once:ALTER TABLE "Project" ADD COLUMN "logoUrl" TEXT, ADD COLUMN "fullLogoUrl" TEXT;Not critical but improves migration performance on large tables.
apps/dashboard/src/components/logo-upload.tsx (1)
10-18: Optimize image URL validation.The function fetches the blob after making a HEAD request, which is redundant and inefficient. The HEAD request already provides the content-type header.
Apply this diff to optimize the validation:
export async function checkImageUrl(url: string) { try { const res = await fetch(url, { method: 'HEAD' }); - const buff = await res.blob(); - return buff.type.startsWith('image/'); + const contentType = res.headers.get('content-type'); + return contentType?.startsWith('image/') ?? false; } catch (e) { return false; } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (13)
apps/backend/prisma/migrations/20250801204029_logo_url/migration.sql(1 hunks)apps/backend/prisma/schema.prisma(1 hunks)apps/backend/src/lib/config.tsx(1 hunks)apps/backend/src/lib/images.tsx(1 hunks)apps/backend/src/lib/projects.tsx(5 hunks)apps/backend/src/s3.tsx(2 hunks)apps/dashboard/package.json(1 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-settings/page-client.tsx(2 hunks)apps/dashboard/src/components/logo-upload.tsx(1 hunks)packages/stack-shared/src/interface/crud/projects.ts(2 hunks)packages/stack-shared/src/schema-fields.ts(3 hunks)packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts(1 hunks)packages/template/src/lib/stack-app/projects/index.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{ts,tsx}: TypeScript with strict types, prefertypeoverinterface
Avoid casting toany; Prefer making changes to the API so thatanycasts are unnecessary to access a property or method
Files:
apps/backend/src/lib/config.tsxpackages/template/src/lib/stack-app/apps/implementations/admin-app-impl.tsapps/backend/src/lib/images.tsxpackages/stack-shared/src/interface/crud/projects.tsapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-settings/page-client.tsxapps/backend/src/s3.tsxpackages/template/src/lib/stack-app/projects/index.tspackages/stack-shared/src/schema-fields.tsapps/backend/src/lib/projects.tsxapps/dashboard/src/components/logo-upload.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{js,jsx,ts,tsx}: 2-space indentation, spaces in braces, semicolons required
Return promises withreturn await, no floating promises
Proper error handling for async code with try/catch
Use helper functions:yupXyz()for validation,getPublicEnvVar()for env
Switch cases must use blocks
Files:
apps/backend/src/lib/config.tsxpackages/template/src/lib/stack-app/apps/implementations/admin-app-impl.tsapps/backend/src/lib/images.tsxpackages/stack-shared/src/interface/crud/projects.tsapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-settings/page-client.tsxapps/backend/src/s3.tsxpackages/template/src/lib/stack-app/projects/index.tspackages/stack-shared/src/schema-fields.tsapps/backend/src/lib/projects.tsxapps/dashboard/src/components/logo-upload.tsx
**/*.{jsx,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
**/*.{jsx,tsx}: React Server Components preferred where applicable
No direct 'use' imports from React (use React.use instead)
Files:
apps/backend/src/lib/config.tsxapps/backend/src/lib/images.tsxapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-settings/page-client.tsxapps/backend/src/s3.tsxapps/backend/src/lib/projects.tsxapps/dashboard/src/components/logo-upload.tsx
🧠 Learnings (4)
📚 Learning: applies to **/*.{ts,tsx} : avoid casting to `any`; prefer making changes to the api so that `any` ca...
Learnt from: CR
PR: stack-auth/stack-auth#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-28T23:25:51.701Z
Learning: Applies to **/*.{ts,tsx} : Avoid casting to `any`; Prefer making changes to the API so that `any` casts are unnecessary to access a property or method
Applied to files:
apps/backend/src/lib/config.tsxpackages/template/src/lib/stack-app/projects/index.ts
📚 Learning: applies to **/*.{js,jsx,ts,tsx} : use helper functions: `yupxyz()` for validation, `getpublicenvvar(...
Learnt from: CR
PR: stack-auth/stack-auth#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-28T23:25:51.701Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use helper functions: `yupXyz()` for validation, `getPublicEnvVar()` for env
Applied to files:
apps/backend/src/lib/config.tsxapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-settings/page-client.tsxpackages/stack-shared/src/schema-fields.tsapps/backend/src/lib/projects.tsx
📚 Learning: applies to **/*.{jsx,tsx} : no direct 'use' imports from react (use react.use instead)...
Learnt from: CR
PR: stack-auth/stack-auth#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-28T23:25:51.701Z
Learning: Applies to **/*.{jsx,tsx} : No direct 'use' imports from React (use React.use instead)
Applied to files:
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-settings/page-client.tsxapps/dashboard/src/components/logo-upload.tsx
📚 Learning: applies to **/*.{ts,tsx} : typescript with strict types, prefer `type` over `interface`...
Learnt from: CR
PR: stack-auth/stack-auth#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-28T23:25:51.701Z
Learning: Applies to **/*.{ts,tsx} : TypeScript with strict types, prefer `type` over `interface`
Applied to files:
packages/template/src/lib/stack-app/projects/index.ts
🧬 Code Graph Analysis (2)
packages/template/src/lib/stack-app/projects/index.ts (2)
packages/template/src/lib/stack-app/project-configs/index.ts (1)
AdminProjectConfigUpdateOptions(74-96)packages/stack-shared/src/interface/crud/projects.ts (1)
ProjectsCrud(182-182)
apps/backend/src/lib/projects.tsx (1)
apps/backend/src/s3.tsx (1)
uploadAndGetUrl(86-105)
⏰ 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). (9)
- GitHub Check: docker
- GitHub Check: all-good
- GitHub Check: lint_and_build (latest)
- GitHub Check: build (22.x)
- GitHub Check: restart-dev-and-test
- GitHub Check: docker
- GitHub Check: setup-tests
- GitHub Check: build (22.x)
- GitHub Check: Security Check
🔇 Additional comments (18)
apps/backend/src/lib/config.tsx (1)
12-12: 👍 Removed unused type import
PrismaClientTransactionwas not referenced anywhere in this file, so dropping it reduces bundle size and TS noise.packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts (1)
116-117: LGTM! Logo URL mappings are correctly implemented.The new
logoUrlandfullLogoUrlproperties are properly mapped from the CRUD data following the established pattern in the codebase.packages/stack-shared/src/interface/crud/projects.ts (2)
68-69: LGTM! Logo URL fields properly added to read schema.The new logo URL fields are correctly defined with appropriate nullable and optional modifiers, following the established schema patterns.
117-118: LGTM! Logo URL fields correctly added to update schema.The logo URL fields in the update schema are consistent with the read schema and properly configured for optional updates.
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-settings/page-client.tsx (1)
4-4: LGTM! Project logo UI properly implemented.The LogoUpload components are well-configured with appropriate labels, descriptions, and update handlers. The UI structure follows the established patterns in the codebase, and the descriptive text clearly explains the purpose of each logo type.
Also applies to: 67-91
apps/backend/src/s3.tsx (2)
39-39: LGTM! Image size limit appropriately increased.The 1MB limit aligns with the
MAX_IMAGE_SIZE_BASE64_BYTESconstant and is reasonable for logo images.
88-88: LGTM! Project logos folder support added correctly.The addition of 'project-logos' to the folder name union enables the new project logo upload functionality and follows the established naming pattern.
packages/stack-shared/src/schema-fields.ts (2)
14-14: LGTM! Image size constant improves consistency.The
MAX_IMAGE_SIZE_BASE64_BYTESconstant centralizes the image size limit definition, promoting consistency across the codebase.
519-519: LGTM! Profile image schema updated for consistency.The update to use
MAX_IMAGE_SIZE_BASE64_BYTESmaintains consistency with the new centralized size limit approach.packages/template/src/lib/stack-app/projects/index.ts (2)
47-48: LGTM!The logo URL fields in update options correctly use
string | nulltyping, which is appropriate for update operations where fields can be set or cleared.
56-57: LGTM!The logo URL field mappings correctly transform camelCase to snake_case and follow the existing pattern in the function.
apps/backend/src/lib/projects.tsx (4)
1-1: LGTM!The import of
uploadAndGetUrlis necessary for the new logo upload functionality.
52-53: LGTM!The logo URL fields are correctly added to the query result and properly mapped from database column names to CRUD interface field names.
82-90: LGTM!The logo upload processing correctly handles conditional uploads only when fields are provided, uses the appropriate "project-logos" folder, and stores results for database operations.
103-104: LGTM!The logo URL fields are correctly included in both database create and update operations, ensuring uploaded logos are properly persisted.
Also applies to: 135-136
apps/dashboard/src/components/logo-upload.tsx (3)
20-29: LGTM!The component props are well-typed and comprehensive, with appropriate state management for upload status and error handling.
31-72: LGTM!The upload logic is comprehensive with proper image compression, validation, error handling, and cleanup. The SVG format preservation and reasonable size constraints (1MB, 800px) are well-implemented.
87-134: LGTM!The UI rendering is well-implemented with proper conditional rendering, accessibility features, and appropriate styling differences between logo types. Error handling and loading states are properly managed.
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-settings/page-client.tsx
Outdated
Show resolved
Hide resolved
|
Claude finished @fomalhautb's task —— View job PR Review: Project Logo Upload FeatureTodo List:
This PR implements a solid foundation for project logo upload functionality. The feature is well-structured and follows established patterns in the codebase. Here's my detailed analysis: ✅ StrengthsDatabase Design
Backend Implementation
Frontend Components
Type Safety & Schema
|
|
Claude finished @fomalhautb's task —— View job PR Review: Project Logo Upload FeatureTodo List:
This PR implements a solid foundation for project logo upload functionality. The feature is well-structured and follows established patterns in the codebase. Here's my detailed analysis: ✅ StrengthsDatabase Design
Backend Implementation
Frontend Components
Type Safety & Schema
|
…/project-settings/page-client.tsx Co-authored-by: Konsti Wohlwend <n2d4xc@gmail.com>
|
Claude finished @fomalhautb's task —— View job PR Review: Project Logo Upload FeatureTodo List:
This PR implements a solid foundation for project logo upload functionality. The feature is well-structured and follows established patterns in the codebase. Here's my detailed analysis: ✅ StrengthsDatabase Design
Backend Implementation
Frontend Components
Type Safety & Schema
|
Important
Add support for uploading and managing project logos with image compression and validation in project settings.
logoUrl,fullLogoUrl) inProjectmodel.LogoUploadcomponent inlogo-upload.tsxfor image upload with compression and validation.logoUrlandfullLogoUrlcolumns toProjecttable inmigration.sql.schema.prismato include new fields inProjectmodel.createOrUpdateProjectWithLegacyConfig()inprojects.tsxto handle logo uploads.images.tsxands3.tsx.browser-image-compressiondependency inpackage.json.LogoUploadcomponent inpage-client.tsxfor project settings.AdminProjecttype inprojects/index.tsto include logo URLs.projects.test.tsand others to verify logo upload functionality.This description was created by
for 1b0cdbf. You can customize this summary. It will automatically update as commits are pushed.
Summary by CodeRabbit
New Features
Improvements
Dependencies