Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
✨ No issues found! Your code is sparkling clean! ✨ 🗒️ View all ignored comments in this repo
Need help? Join our Discord for support! |
There was a problem hiding this comment.
Greptile Summary
This PR introduces a major migration from the legacy email template system to a new TSX-based email template architecture. The changes consolidate email template functionality by removing the experimental email-templates-new pages and integrating their features into the main email-templates system.
Key Changes:
-
New Email Template Architecture: The system now uses TSX components for email templates instead of document-based configurations. Templates are stored as TSX source code in tenancy configuration and rendered using React components.
-
Template Management Consolidation: The separate
email-templates-newdirectory has been removed, and all functionality has been merged into the mainemail-templatessystem. Navigation and routing have been updated to use template IDs instead of template types. -
Enhanced Error Handling: A new
RequiresCustomEmailServererror prevents users from editing email templates when using shared email servers, enforcing the business requirement that custom templates need dedicated SMTP configurations. -
Template Rendering Pipeline: The new system separates themes from templates, with
getActiveEmailTheme()handling theme retrieval andrenderEmailWithTemplate()providing enhanced validation for required components like subject and notification categories. -
Test Updates: E2E tests have been updated to handle the new email format where OTP codes are embedded in JSON structures (
"otp":"[CODE]") rather than plain text, reflecting the structured data approach of the new template system.
The migration maintains backward compatibility while providing a more flexible foundation for email customization with better React integration and developer experience.
Confidence score: 4/5
• This PR appears safe to merge with extensive refactoring but may need careful monitoring due to the complexity of the email system changes
• The score reflects the comprehensive nature of the changes spanning multiple systems (templates, routing, rendering, validation) which increases risk despite thorough implementation
• The backend route handler in apps/backend/src/app/api/latest/internal/email-templates/[templateId]/route.tsx needs attention for proper error handling validation
16 files reviewed, 2 comments
WalkthroughThis update overhauls the email template and theme editing system, refactoring both backend and frontend logic. It introduces support for nullable and "false" theme IDs, restructures template and theme handling, and consolidates UI components. Several frontend components are deleted or replaced, and backend validation, error handling, and API contracts are updated to match the new model. Test cases and type definitions are revised accordingly. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant DashboardUI
participant AdminAPI
participant EmailRendering
participant TenancyConfig
User->>DashboardUI: Edit email template
DashboardUI->>AdminAPI: PATCH /email-templates/:id (tsxSource, themeId)
AdminAPI->>TenancyConfig: Validate themeId (nullable/false allowed)
AdminAPI->>EmailRendering: getEmailThemeForTemplate(tenancy, themeId)
EmailRendering->>TenancyConfig: Retrieve theme or fallback
EmailRendering-->>AdminAPI: Return theme TSX source
AdminAPI->>EmailRendering: Render email with template + theme
EmailRendering-->>AdminAPI: Rendered HTML/subject/text
AdminAPI-->>DashboardUI: Save result or error
DashboardUI-->>User: Show preview, success, or error
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
...src/app/(main)/(protected)/projects/[projectId]/email-templates/[templateId]/page-client.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (3)
apps/backend/src/app/api/latest/emails/render-email/route.tsx (1)
43-43: Use thehasfunction for safe object property checking.The current
inoperator is vulnerable to prototype pollution. For consistency with the codebase and to address the prototype pollution concern from the past review, use thehasfunction from the utils.- if (body.theme_id && !(body.theme_id in tenancy.completeConfig.emails.themes)) { + if (body.theme_id && !has(tenancy.completeConfig.emails.themes, body.theme_id)) {You'll need to import the
hasfunction:+import { has } from '@stackframe/stack-shared/dist/utils/objects';apps/backend/src/lib/emails.tsx (1)
19-31: Well-implemented template retrieval with proper error handling.The
getNewEmailTemplatefunction correctly:
- Uses Maps for efficient lookups
- Provides clear error messages for missing templates
- Implements the suggested default case handling from previous reviews
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/[templateId]/page-client.tsx (1)
105-134: Fix the broken theme selection logic.The helper functions don't correctly handle the
string | undefined | falsetype mapping to select values. The current implementation will break theme selection because:
themeIdToSelectString(false)returns"false"but the SelectItem uses"false-sentinel"themeIdToSelectString(undefined)returns"null"but the SelectItem uses"undefined-sentinel"Apply this fix to properly handle the type transformations:
-function themeIdToSelectString(themeId: string | undefined | false): string { - return JSON.stringify(themeId ?? null); -} -function selectStringToThemeId(value: string): string | undefined | false { - return JSON.parse(value) ?? undefined; -} +function themeIdToSelectString(themeId: string | undefined | false): string { + if (themeId === false) return "false-sentinel"; + if (themeId === undefined) return "undefined-sentinel"; + return themeId; +} +function selectStringToThemeId(value: string): string | undefined | false { + if (value === "false-sentinel") return false; + if (value === "undefined-sentinel") return undefined; + return value; +}Alternatively, follow the previous suggestion to use named constants:
+const NO_THEME_SENTINEL = "no-theme"; +const PROJECT_THEME_SENTINEL = "project-theme"; + function themeIdToSelectString(themeId: string | undefined | false): string { - return JSON.stringify(themeId ?? null); + if (themeId === false) return NO_THEME_SENTINEL; + if (themeId === undefined) return PROJECT_THEME_SENTINEL; + return themeId; } function selectStringToThemeId(value: string): string | undefined | false { - return JSON.parse(value) ?? undefined; + if (value === NO_THEME_SENTINEL) return false; + if (value === PROJECT_THEME_SENTINEL) return undefined; + return value; }And update the SelectItems:
- <SelectItem value={"false-sentinel"}>No theme</SelectItem> - <SelectItem value={"undefined-sentinel"}>Project theme</SelectItem> + <SelectItem value={NO_THEME_SENTINEL}>No theme</SelectItem> + <SelectItem value={PROJECT_THEME_SENTINEL}>Project theme</SelectItem>
🧹 Nitpick comments (2)
apps/backend/src/lib/emails.tsx (1)
353-377: Consider validating email subject before sending.The new TSX-based rendering approach with theme support is well-implemented. However, defaulting the subject to an empty string (line 374) when missing could mask template configuration errors.
Consider adding validation to ensure subject is not empty:
+ if (!result.data.subject) { + throw new StackAssertionError("Email template rendered without subject", { + templateType: options.templateType, + templateId: template.id, + }); + } await sendEmail({ tenancyId: options.tenancy.id, emailConfig: await getEmailConfig(options.tenancy), to: options.email, - subject: result.data.subject ?? "", + subject: result.data.subject, html: result.data.html, text: result.data.text, });apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/[templateId]/page-client.tsx (1)
36-38: Consider renaming for clarity.The function name
handleThemeUpdateis misleading since it updates the code content, not the theme. Consider renaming tohandleCodeUpdateorhandleToolCallUpdate.- const handleThemeUpdate = (toolCall: ToolCallContent) => { + const handleCodeUpdate = (toolCall: ToolCallContent) => { setCurrentCode(toolCall.args.content); };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (38)
apps/backend/src/app/api/latest/emails/render-email/route.tsx(3 hunks)apps/backend/src/app/api/latest/internal/email-templates/[templateId]/route.tsx(4 hunks)apps/backend/src/lib/email-rendering.tsx(2 hunks)apps/backend/src/lib/emails.tsx(3 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates-new/[templateId]/page-client.tsx(0 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates-new/page-client.tsx(0 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates-new/page.tsx(0 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/[templateId]/page-client.tsx(1 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/[type]/page-client.tsx(0 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/[type]/page.tsx(0 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/page-client.tsx(1 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/page.tsx(1 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-themes/[themeId]/page-client.tsx(2 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx(1 hunks)apps/dashboard/src/components/email-preview.tsx(2 hunks)apps/dashboard/src/components/vibe-coding/index.ts(0 hunks)apps/dashboard/src/components/vibe-coding/preview-panel.tsx(0 hunks)apps/dashboard/src/components/vibe-coding/template-preview.tsx(0 hunks)apps/dashboard/src/components/vibe-coding/vibe-assistant-chat.tsx(0 hunks)apps/dashboard/src/components/vibe-coding/vibe-code-editor-layout.tsx(0 hunks)apps/dashboard/src/components/vibe-coding/vibe-code-editor.tsx(0 hunks)apps/dashboard/src/components/vibe-coding/vibe-preview-panel.tsx(0 hunks)apps/e2e/tests/backend/endpoints/api/v1/auth/otp/send-sign-in-code.test.ts(2 hunks)apps/e2e/tests/backend/endpoints/api/v1/auth/otp/sign-in.test.ts(3 hunks)apps/e2e/tests/backend/endpoints/api/v1/auth/password/reset.test.ts(1 hunks)apps/e2e/tests/backend/endpoints/api/v1/auth/password/send-reset-code.test.ts(1 hunks)apps/e2e/tests/backend/endpoints/api/v1/auth/password/sign-up.test.ts(1 hunks)apps/e2e/tests/backend/endpoints/api/v1/contact-channels/legacy-send-verification-code.test.ts(1 hunks)apps/e2e/tests/backend/endpoints/api/v1/contact-channels/send-verification-code.test.ts(1 hunks)apps/e2e/tests/backend/endpoints/api/v1/contact-channels/verify.test.ts(1 hunks)apps/e2e/tests/backend/endpoints/api/v1/internal/email.test.ts(3 hunks)apps/e2e/tests/backend/endpoints/api/v1/internal/projects.test.ts(1 hunks)apps/e2e/tests/backend/endpoints/api/v1/render-email.test.ts(1 hunks)packages/stack-shared/src/helpers/emails.ts(1 hunks)packages/stack-shared/src/interface/admin-interface.ts(2 hunks)packages/stack-shared/src/known-errors.tsx(2 hunks)packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts(3 hunks)packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts(2 hunks)
💤 Files with no reviewable changes (12)
- apps/dashboard/src/components/vibe-coding/index.ts
- apps/dashboard/src/components/vibe-coding/vibe-preview-panel.tsx
- apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates-new/page.tsx
- apps/dashboard/src/components/vibe-coding/vibe-code-editor-layout.tsx
- apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/[type]/page-client.tsx
- apps/dashboard/src/components/vibe-coding/template-preview.tsx
- apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/[type]/page.tsx
- apps/dashboard/src/components/vibe-coding/preview-panel.tsx
- apps/dashboard/src/components/vibe-coding/vibe-assistant-chat.tsx
- apps/dashboard/src/components/vibe-coding/vibe-code-editor.tsx
- apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates-new/page-client.tsx
- apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates-new/[templateId]/page-client.tsx
🧰 Additional context used
🧬 Code Graph Analysis (5)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-themes/[themeId]/page-client.tsx (2)
apps/dashboard/src/components/email-preview.tsx (1)
EmailPreview(91-122)packages/stack-shared/src/helpers/emails.ts (1)
previewTemplateSource(1-14)
apps/e2e/tests/backend/endpoints/api/v1/auth/password/reset.test.ts (1)
packages/stack-shared/src/utils/errors.tsx (1)
throwErr(10-19)
apps/backend/src/app/api/latest/emails/render-email/route.tsx (3)
packages/stack-shared/src/schema-fields.ts (1)
templateThemeIdSchema(375-375)packages/stack-shared/src/utils/errors.tsx (1)
StatusError(141-250)apps/backend/src/lib/email-rendering.tsx (1)
getEmailThemeForTemplate(23-32)
packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts (1)
packages/template/src/lib/stack-app/common.ts (1)
AsyncStoreProperty(8-10)
apps/backend/src/lib/emails.tsx (6)
apps/backend/src/lib/tenancies.tsx (1)
Tenancy(50-50)packages/stack-emails/src/utils.tsx (1)
EMAIL_TEMPLATES_METADATA(38-97)packages/stack-shared/src/helpers/emails.ts (1)
DEFAULT_TEMPLATE_IDS(107-113)packages/stack-shared/src/utils/errors.tsx (1)
StackAssertionError(67-83)apps/backend/src/lib/email-rendering.tsx (2)
getEmailThemeForTemplate(23-32)renderEmailWithTemplate(49-113)packages/stack-shared/src/utils/objects.tsx (1)
filterUndefined(368-370)
🪛 Gitleaks (8.27.2)
packages/stack-shared/src/helpers/emails.ts
79-79: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ 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: Security Check
🔇 Additional comments (46)
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/page.tsx (1)
3-5: LGTM! Title update aligns with feature consolidation.The metadata title change from "Email Settings" to "Email Templates" accurately reflects the page's specific functionality and aligns with the broader email templates system refactoring.
apps/e2e/tests/backend/endpoints/api/v1/render-email.test.ts (1)
167-167: LGTM! Test updated for new dynamic subject extraction.The subject expectation change from static "mock subject" to "Mock subject, undefined" correctly reflects the new email rendering logic that dynamically extracts subjects from template components. The "undefined" value is appropriate since the test template lacks a
<Subject>component.apps/e2e/tests/backend/endpoints/api/v1/auth/password/sign-up.test.ts (1)
25-25: LGTM! Test updated for new JSX-based email subject format.The subject expectation change correctly reflects the new TSX-based email rendering system that captures raw JSX template expressions for subjects instead of static strings.
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-themes/[themeId]/page-client.tsx (2)
5-5: LGTM! Import updated for component simplification.The removal of
PreviewPanelfrom the imports aligns with the UI consolidation efforts in the email templates and themes system.
50-54: LGTM! Direct EmailPreview rendering simplifies the component hierarchy.The removal of the
PreviewPanelwrapper and direct use ofEmailPreviewwiththemeTsxSourceandtemplateTsxSourceprops streamlines the preview functionality and aligns with the UI consolidation mentioned in the PR objectives.apps/e2e/tests/backend/endpoints/api/v1/contact-channels/verify.test.ts (1)
21-21: LGTM! Test filter updated for new email subject format.The subject filtering logic correctly updated to match the new JSX-based email subject format, maintaining test functionality while adapting to the email rendering system changes.
apps/e2e/tests/backend/endpoints/api/v1/internal/projects.test.ts (1)
507-507: LGTM! Improved test determinism.Replacing the dynamically generated UUID with a fixed invalid string makes the test more deterministic while still effectively validating the invalid email theme error handling.
apps/e2e/tests/backend/endpoints/api/v1/auth/password/send-reset-code.test.ts (1)
27-27: LGTM! Test snapshots updated for new dynamic email subjects.The updated test expectations correctly reflect the new email rendering system that uses JSX templates with dynamic
projectDisplayNamesubstitution instead of static subject strings.Also applies to: 33-33
apps/e2e/tests/backend/endpoints/api/v1/contact-channels/legacy-send-verification-code.test.ts (1)
55-55: LGTM! Consistent test snapshot updates.The email subject expectations have been correctly updated to match the new JSX template format with dynamic
projectDisplayNamesubstitution.Also applies to: 61-61
apps/e2e/tests/backend/endpoints/api/v1/contact-channels/send-verification-code.test.ts (1)
42-42: LGTM! Test expectations aligned with new email rendering.The snapshot updates correctly reflect the new dynamic email subject format using JSX templates.
Also applies to: 48-48
apps/e2e/tests/backend/endpoints/api/v1/auth/password/reset.test.ts (1)
28-28: Tests aligned with template implementation
- Verified in
packages/stack-shared/src/helpers/emails.tsthat the Password Reset template (alongside Magic Link, Team Invitation, Sign-In Invitation) uses string concatenation for<Subject value="…">, while Email Verification is the only one using a template literal.- The updated snapshot and message-filtering in
apps/e2e/tests/backend/endpoints/api/v1/auth/password/reset.test.tscorrectly match the Password Reset template’s concatenation syntax.- No changes needed.
apps/e2e/tests/backend/endpoints/api/v1/internal/email.test.ts (3)
58-58: LGTM: Consistent test update.The subject format update is consistent with the first test case and properly reflects the new dynamic subject rendering behavior.
105-105: LGTM: Complete test consistency.All three test cases now use the consistent mock subject format, ensuring comprehensive test coverage of the new email rendering behavior.
43-43: Mock subject format verifiedI confirmed that the test’s mock subject string:
"Mock subject,
<Subject value={\"Sign in to \" + projectDisplayName + \": Your code is \" + otp} />"exactly matches the
tsxSourcein the OTP email template defined inpackages/stack-shared/src/helpers/emails.ts. No further changes required.apps/dashboard/src/components/email-preview.tsx (2)
47-47: LGTM: Enhanced type flexibility for theme handling.The expanded type
string | null | falseprovides better semantic representation of theme states:
string: specific theme IDnull: explicitly unset themefalse: theme disabledThis aligns with the broader theme management improvements across the system.
72-72: LGTM: Consistent type expansion.The type update maintains consistency with the function parameter and ensures proper theme ID handling throughout the component.
apps/e2e/tests/backend/endpoints/api/v1/auth/otp/send-sign-in-code.test.ts (2)
10-10: LGTM: Consistent email subject format update.The subject format change is consistent with other email test updates and properly reflects the new JSX-based email template rendering.
102-104: Regex extraction matches email body format
Therender-email.test.tssnapshot confirms that the plain-text body ends with a JSON payload containing"otp":"3SLSWZ". Therefore the/\"otp\":\"([A-Z0-9]{6})\"/pattern insend-sign-in-code.test.tswill reliably capture the 6-character code.• Verified in apps/e2e/tests/backend/endpoints/api/v1/render-email.test.ts: variables include
"otp":"<CODE>"
• No changes required to the current extraction regexpackages/stack-shared/src/known-errors.tsx (2)
1394-1402: LGTM: Well-structured new known error.The
RequiresCustomEmailServererror follows the established pattern with:
- Clear, descriptive error code
- Appropriate 400 status code
- Informative message guiding users to configure custom SMTP
- Proper constructor structure
This supports the email template customization workflow effectively.
1517-1517: LGTM: Proper error export.The new error is correctly added to the KnownErrors export, making it available throughout the system.
apps/backend/src/app/api/latest/internal/email-templates/[templateId]/route.tsx (5)
4-4: LGTM: Consistent schema import.Adding
templateThemeIdSchemaimport ensures consistent validation across email-related endpoints.
24-24: LGTM: Enhanced theme ID validation.Using
templateThemeIdSchema.nullable()provides proper validation for the expanded theme ID types (string | null | false).
35-37: LGTM: Appropriate security restriction.The custom email server check prevents users with shared SMTP configurations from editing templates, which is a sensible security restriction. The new
RequiresCustomEmailServererror provides clear guidance.
42-42: LGTM: Improved theme retrieval.Using
getActiveEmailTheme(tenancy)provides better error handling and centralized theme logic compared to direct property access.
62-66: LGTM: Cleaner configuration structure.The nested object structure under
emails.templates.${templateId}is more organized than separate keys and groups related template properties logically.apps/e2e/tests/backend/endpoints/api/v1/auth/otp/sign-in.test.ts (2)
200-206: Updated OTP extraction aligns with new email format.The regex pattern change correctly adapts to the new JSON-like structure in email bodies, moving from a generic pattern to a specific
"otp":"XXXXXX"format. The use of optional chaining for safe access to the captured group is appropriate.
273-289: Consistent OTP extraction pattern applied.The regex pattern change is consistently applied throughout the test file, maintaining the same JSON-like structure matching and safe access pattern as the earlier occurrence.
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx (1)
253-268: Navigation path consolidation looks good.The changes consistently update email template paths from
/emails/templates/to/email-templates/and introduce a React component for dynamic breadcrumb labels. The regex patterns, href paths, and breadcrumb configuration are all properly aligned.apps/backend/src/app/api/latest/emails/render-email/route.tsx (4)
1-4: Imports support the theme handling refactoring.The new imports for
getEmailThemeForTemplate,renderEmailWithTemplate, andtemplateThemeIdSchemaare necessary for the updated theme handling and validation logic.
20-20: Schema update improves theme ID validation.The change from
yupString()totemplateThemeIdSchema.nullable()provides better validation for theme IDs, allowing for null values and ensuring UUID format when a string is provided.
37-37: Explicit undefined check improves validation precision.The change from a truthy check to an explicit
=== undefinedcomparison is more precise and correctly handles the new nullable theme ID schema wherenullandfalseare valid values.
46-49: Theme source retrieval refactoring improves architecture.The use of
getEmailThemeForTemplatecentralizes theme retrieval logic and handles the various theme ID types (string, null, false, undefined) appropriately. The Map usage for templateList is also appropriate.packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts (2)
37-37: Type expansion improves theme ID flexibility.The updated type for
themeIdto includenullandfalsevalues provides better support for different theme states - explicitly disabled themes (false) and unset themes (null) in addition to string IDs.
85-85: Method signature consistent with type updates.The
updateNewEmailTemplatemethod signature update maintains consistency with theemailPreviewtype changes, ensuring the API properly handles all theme ID states.apps/backend/src/lib/email-rendering.tsx (4)
1-10: Imports support safe theme handling functionality.The new imports provide the necessary utilities for theme retrieval with proper error handling (
StackAssertionError) and safe object access (has,get) that addresses prototype pollution concerns.
11-21: Robust active theme retrieval with safe object access.The
getActiveEmailThemefunction properly uses thehasandgetutility functions to avoid prototype pollution, includes comprehensive error handling with context for debugging, and provides a centralized mechanism for active theme retrieval.
23-32: Flexible theme retrieval handles multiple scenarios.The
getEmailThemeForTemplatefunction elegantly handles different theme ID types:
- String IDs for specific themes with safe object access
falsefor explicitly disabling themesnull/undefinedfor falling back to active themesThe implementation uses safe utility functions and provides appropriate fallback behavior.
60-60: Improved subject extraction from template components.The regex-based subject extraction
templateComponent.match(/<Subject\s+[^>]*\/>/g)?.[0]is more robust than static strings, properly extracting Subject component tags from the template source for better mock rendering.apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/page-client.tsx (1)
14-40: LGTM! Clean refactoring to use template IDs.The changes from
EmailTemplateTypetostringfor template identification and navigation are consistent throughout the component. The simplified UI focusing on display names and edit buttons aligns well with the new template management architecture.packages/stack-shared/src/helpers/emails.ts (1)
78-113: Excellent refactoring for template ID standardization.The introduction of constants for template IDs and the
DEFAULT_TEMPLATE_IDSmapping improves code maintainability and ensures consistent references across the codebase. This change supports the enhanced email template handling mentioned in the PR objectives.Note: The static analysis warning about a "Generic API Key" on line 79 is a false positive - these are UUID identifiers for email templates, not API keys.
packages/stack-shared/src/interface/admin-interface.ts (1)
402-402: Good type expansion for explicit theme handling.The expanded
themeIdtypes (string | null | false) provide clearer semantics:
string: Use specific themenull: Use default/active themefalse: Use empty/no themeThis aligns well with the enhanced theme handling logic introduced in the email rendering system.
Also applies to: 460-460
packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts (1)
59-59: Consistent implementation of expanded theme ID types.The cache keys and method signatures have been properly updated to handle the expanded
themeIdtypes (string | null | false | undefined). This maintains type safety throughout the admin app implementation.Also applies to: 482-487, 503-504
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/[templateId]/page-client.tsx (4)
1-19: LGTM! Clean import structure.The imports are well-organized and include all necessary dependencies for the email template editing functionality.
20-34: LGTM! Proper state management and change tracking.The component correctly initializes state from the template data and properly tracks unsaved changes with appropriate cleanup.
40-51: LGTM! Excellent error handling.The save handler properly handles specific known errors and provides appropriate user feedback while re-throwing unexpected errors.
54-97: LGTM! Well-structured component layout.The render logic properly handles the missing template case and provides a clean three-pane editing interface with appropriate state management.
Note: If you accept the suggestion to rename
handleThemeUpdatetohandleCodeUpdate, remember to update line 90 as well.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/backend/src/lib/emails.tsx (1)
19-31: Excellent implementation addresses previous review concerns.The new
getNewEmailTemplatefunction properly handles the default case issue raised in previous reviews by throwing an explicit error for unknown template types. The use of Map for O(1) lookups is also a good performance choice.However, there's a potential issue with the error handling logic:
Consider simplifying the logic by removing the nested conditional:
export function getNewEmailTemplate(tenancy: Tenancy, type: keyof typeof EMAIL_TEMPLATES_METADATA) { const templateList = new Map(Object.entries(tenancy.completeConfig.emails.templates)); - const defaultTemplateIdsMap = new Map(Object.entries(DEFAULT_TEMPLATE_IDS)); - const defaultTemplateId = defaultTemplateIdsMap.get(type); - if (defaultTemplateId) { - const template = templateList.get(defaultTemplateId); - if (!template) { - throw new StackAssertionError(`Default email template not found: ${type}`); - } - return template; - } - throw new StackAssertionError(`Unknown email template type: ${type}`); + const defaultTemplateId = DEFAULT_TEMPLATE_IDS[type]; + if (!defaultTemplateId) { + throw new StackAssertionError(`Unknown email template type: ${type}`); + } + + const template = templateList.get(defaultTemplateId); + if (!template) { + throw new StackAssertionError(`Default email template not found: ${type}`); + } + return template; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/backend/src/lib/emails.tsx(3 hunks)
⏰ 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: lint_and_build (latest)
- GitHub Check: restart-dev-and-test
- GitHub Check: docker
- GitHub Check: setup-tests
- GitHub Check: all-good
- GitHub Check: docker
- GitHub Check: build (22.x)
- GitHub Check: build (22.x)
- GitHub Check: Security Check
🔇 Additional comments (5)
apps/backend/src/lib/emails.tsx (5)
5-5: Import addition looks good.The addition of
EMAIL_TEMPLATES_METADATAimport aligns with the new template handling approach.
15-16: New imports support the refactored email rendering system.The imports of
getEmailThemeForTemplate,renderEmailWithTemplate, andDEFAULT_TEMPLATE_IDSare consistent with the new TSX-based rendering pipeline mentioned in the AI summary.
353-376: Rendering logic is robust with proper error handling.The new rendering approach using
renderEmailWithTemplatewith structured variables (user, project, variables) is well-designed. The error handling properly throws aStackAssertionErrorwith context for debugging.The variable structure is clean and follows good practices by separating concerns between user data, project data, and extra variables.
382-384: Email sending properly handles nullable subject.The fallback to empty string for missing subject is appropriate, ensuring the email can still be sent even if subject rendering fails.
353-353: getEmailThemeForTemplate handles null and false theme IDs correctlyThe implementation in apps/backend/src/lib/email-rendering.tsx already covers all cases:
- For a valid string ID that exists in
themeList, it returns the corresponding theme.- If
templateThemeId === false, it returnsemptyEmailTheme.- For
nullorundefined, it falls back togetActiveEmailTheme.No changes required here.
a68c1b1 to
16c74fb
Compare
<!-- Make sure you've read the CONTRIBUTING.md guidelines: https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md --> <!-- ELLIPSIS_HIDDEN --> ---- > [!IMPORTANT] > Remove `stack-emails` package and legacy templates, updating email template handling across backend, frontend, and tests. > > - **Removal**: > - Remove `stack-emails` package and associated legacy email template handling. > - Delete legacy email template files and related code in `packages/stack-emails`. > - **Backend Changes**: > - Update `sendEmailFromTemplate()` in `emails.tsx` to use new template system. > - Modify `admin-interface.ts` to update email template handling methods. > - **Frontend Changes**: > - Update email template management in `page-client.tsx` and `sidebar-layout.tsx`. > - Modify `useEmailTemplates()` and related functions in `admin-app-impl.ts`. > - **Testing**: > - Update tests in `email-templates.test.ts` to reflect new email template handling. > - **Configuration**: > - Remove `@stackframe/stack-emails` from `package.json` dependencies. > - Update `docker.compose.yaml` to use specific Inbucket version. > > <sup>This description was created by </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=stack-auth%2Fstack-auth&utm_source=github&utm_medium=referral)<sup> for dedaa9c. You can [customize](https://app.ellipsis.dev/stack-auth/settings/summaries) this summary. It will automatically update as commits are pushed.</sup> <!-- ELLIPSIS_HIDDEN -->
There was a problem hiding this comment.
Actionable comments posted: 2
📜 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 (107)
apps/backend/package.json(0 hunks)apps/backend/src/app/api/latest/email-templates/[type]/route.tsx(0 hunks)apps/backend/src/app/api/latest/email-templates/crud.tsx(0 hunks)apps/backend/src/app/api/latest/email-templates/route.tsx(0 hunks)apps/backend/src/app/api/latest/internal/email-templates/temp/[projectId]/route.tsx(0 hunks)apps/backend/src/app/api/latest/internal/email-templates/temp/convert.tsx(0 hunks)apps/backend/src/lib/email-rendering.tsx(2 hunks)apps/backend/src/lib/emails.tsx(2 hunks)apps/dashboard/package.json(1 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/[templateId]/page-client.tsx(1 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/page-client.tsx(3 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/migrations/templates-migration/page-client.tsx(0 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/migrations/templates-migration/page.tsx(0 hunks)apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx(2 hunks)apps/dashboard/src/components/vibe-coding/code-editor.tsx(2 hunks)apps/dashboard/src/components/vibe-coding/dts/index.ts(1 hunks)apps/dashboard/src/components/vibe-coding/dts/util-dts.ts(1 hunks)apps/dashboard/tailwind.config.ts(0 hunks)apps/e2e/tests/backend/endpoints/api/v1/auth/otp/send-sign-in-code.test.ts(2 hunks)apps/e2e/tests/backend/endpoints/api/v1/auth/password/reset.test.ts(1 hunks)apps/e2e/tests/backend/endpoints/api/v1/internal/email-templates.test.ts(2 hunks)docker/dependencies/docker.compose.yaml(1 hunks)packages/stack-emails/.eslintrc.cjs(0 hunks)packages/stack-emails/CHANGELOG.md(0 hunks)packages/stack-emails/LICENSE(0 hunks)packages/stack-emails/package.json(0 hunks)packages/stack-emails/src/editor/blocks/block-button.tsx(0 hunks)packages/stack-emails/src/editor/blocks/block-columns-container.tsx(0 hunks)packages/stack-emails/src/editor/blocks/block-container.tsx(0 hunks)packages/stack-emails/src/editor/blocks/block-divider.tsx(0 hunks)packages/stack-emails/src/editor/blocks/block-heading.tsx(0 hunks)packages/stack-emails/src/editor/blocks/block-image.tsx(0 hunks)packages/stack-emails/src/editor/blocks/block-spacer.tsx(0 hunks)packages/stack-emails/src/editor/blocks/block-text.tsx(0 hunks)packages/stack-emails/src/editor/document-core/builders/buildBlockComponent.tsx(0 hunks)packages/stack-emails/src/editor/document-core/builders/buildBlockConfigurationDictionary.ts(0 hunks)packages/stack-emails/src/editor/document-core/builders/buildBlockConfigurationSchema.ts(0 hunks)packages/stack-emails/src/editor/document-core/index.ts(0 hunks)packages/stack-emails/src/editor/documents/blocks/columns-container/columns-container-editor.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/columns-container/columns-container-props-schema.ts(0 hunks)packages/stack-emails/src/editor/documents/blocks/container/container-editor.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/container/container-props-schema.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/email-layout/email-layout-editor.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/email-layout/email-layout-props-schema.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/helpers/block-wrappers/editor-block-wrapper.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/helpers/block-wrappers/reader-block-wrapper.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/helpers/block-wrappers/tune-menu.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/helpers/editor-children-ids/add-block-menu/block-button.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/helpers/editor-children-ids/add-block-menu/blocks-menu.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/helpers/editor-children-ids/add-block-menu/buttons.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/helpers/editor-children-ids/add-block-menu/index.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/helpers/editor-children-ids/index.tsx(0 hunks)packages/stack-emails/src/editor/documents/blocks/helpers/font-family.ts(0 hunks)packages/stack-emails/src/editor/documents/blocks/helpers/t-style.ts(0 hunks)packages/stack-emails/src/editor/documents/blocks/helpers/zod.ts(0 hunks)packages/stack-emails/src/editor/documents/editor/core.tsx(0 hunks)packages/stack-emails/src/editor/documents/editor/editor-block.tsx(0 hunks)packages/stack-emails/src/editor/documents/editor/editor-context.tsx(0 hunks)packages/stack-emails/src/editor/editor.tsx(0 hunks)packages/stack-emails/src/editor/email-builder/blocks/columns-container/columns-container-props-schema.ts(0 hunks)packages/stack-emails/src/editor/email-builder/blocks/columns-container/columns-container-reader.tsx(0 hunks)packages/stack-emails/src/editor/email-builder/blocks/container/container-props-schema.tsx(0 hunks)packages/stack-emails/src/editor/email-builder/blocks/container/container-reader.tsx(0 hunks)packages/stack-emails/src/editor/email-builder/blocks/email-layout/email-layout-props-schema.tsx(0 hunks)packages/stack-emails/src/editor/email-builder/blocks/email-layout/email-layout-reader.tsx(0 hunks)packages/stack-emails/src/editor/email-builder/index.ts(0 hunks)packages/stack-emails/src/editor/email-builder/reader/core.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/index.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/button-sidebar-panel.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/columns-container-sidebar-panel.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/container-sidebar-panel.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/divider-sidebar-panel.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/heading-sidebar-panel.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/base-sidebar-panel.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/color-input/base-color-input.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/color-input/index.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/column-widths-input.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/font-family.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/font-size-input.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/font-weight-input.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/padding-input.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/raw/raw-slider-input.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/single-toggle-group.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/slider-input.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/text-align-input.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/text-dimension-input.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/text-input.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/style-inputs/multi-style-property-panel.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/style-inputs/single-style-property-panel.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/image-sidebar-panel.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/spacer-sidebar-panel.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/text-sidebar-panel.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/index.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/settings-panel.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/toggle-inspector-panel-button.tsx(0 hunks)packages/stack-emails/src/editor/sidebar/variables-panel.tsx(0 hunks)packages/stack-emails/src/editor/template-panel/download-json/index.tsx(0 hunks)packages/stack-emails/src/editor/template-panel/import-json/import-json-dialog.tsx(0 hunks)packages/stack-emails/src/editor/template-panel/import-json/index.tsx(0 hunks)packages/stack-emails/src/editor/template-panel/import-json/validateJsonStringValue.ts(0 hunks)packages/stack-emails/src/editor/template-panel/index.tsx(0 hunks)packages/stack-emails/src/globals.d.ts(0 hunks)packages/stack-emails/src/templates/email-verification.tsx(0 hunks)packages/stack-emails/src/templates/empty.tsx(0 hunks)packages/stack-emails/src/templates/magic-link-old.tsx(0 hunks)packages/stack-emails/src/templates/magic-link.tsx(0 hunks)packages/stack-emails/src/templates/password-reset.tsx(0 hunks)
⛔ Files not processed due to max files limit (8)
- packages/stack-emails/src/templates/sign-in-invitation.tsx
- packages/stack-emails/src/templates/team-invitation.tsx
- packages/stack-emails/src/utils.tsx
- packages/stack-emails/tsconfig.json
- packages/stack-emails/vitest.config.ts
- packages/stack-shared/src/interface/admin-interface.ts
- packages/template/src/lib/stack-app/apps/implementations/admin-app-impl.ts
- packages/template/src/lib/stack-app/apps/interfaces/admin-app.ts
💤 Files with no reviewable changes (94)
- packages/stack-emails/.eslintrc.cjs
- apps/backend/src/app/api/latest/email-templates/route.tsx
- packages/stack-emails/src/globals.d.ts
- packages/stack-emails/LICENSE
- packages/stack-emails/src/editor/document-core/builders/buildBlockConfigurationDictionary.ts
- packages/stack-emails/src/editor/blocks/block-container.tsx
- packages/stack-emails/src/editor/template-panel/download-json/index.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/text-align-input.tsx
- packages/stack-emails/src/templates/empty.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/raw/raw-slider-input.tsx
- apps/backend/package.json
- packages/stack-emails/src/editor/documents/blocks/container/container-props-schema.tsx
- packages/stack-emails/src/editor/email-builder/blocks/container/container-reader.tsx
- packages/stack-emails/CHANGELOG.md
- packages/stack-emails/src/editor/sidebar/toggle-inspector-panel-button.tsx
- packages/stack-emails/src/editor/template-panel/import-json/index.tsx
- packages/stack-emails/src/editor/documents/blocks/helpers/t-style.ts
- packages/stack-emails/src/editor/sidebar/variables-panel.tsx
- apps/dashboard/tailwind.config.ts
- packages/stack-emails/src/editor/document-core/builders/buildBlockConfigurationSchema.ts
- packages/stack-emails/src/editor/document-core/builders/buildBlockComponent.tsx
- apps/backend/src/app/api/latest/email-templates/[type]/route.tsx
- packages/stack-emails/src/editor/email-builder/blocks/columns-container/columns-container-reader.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/divider-sidebar-panel.tsx
- apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/migrations/templates-migration/page.tsx
- packages/stack-emails/src/editor/email-builder/blocks/container/container-props-schema.tsx
- packages/stack-emails/src/editor/documents/blocks/helpers/font-family.ts
- packages/stack-emails/src/editor/documents/blocks/helpers/editor-children-ids/add-block-menu/block-button.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/base-sidebar-panel.tsx
- packages/stack-emails/src/editor/documents/blocks/columns-container/columns-container-props-schema.ts
- packages/stack-emails/src/editor/email-builder/blocks/email-layout/email-layout-props-schema.tsx
- packages/stack-emails/src/editor/documents/editor/editor-context.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/style-inputs/multi-style-property-panel.tsx
- packages/stack-emails/src/editor/email-builder/index.ts
- packages/stack-emails/src/editor/documents/blocks/container/container-editor.tsx
- packages/stack-emails/src/editor/template-panel/import-json/import-json-dialog.tsx
- packages/stack-emails/src/editor/documents/blocks/helpers/zod.ts
- packages/stack-emails/src/editor/documents/blocks/helpers/block-wrappers/editor-block-wrapper.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/single-toggle-group.tsx
- packages/stack-emails/src/templates/email-verification.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/container-sidebar-panel.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/slider-input.tsx
- packages/stack-emails/src/editor/documents/blocks/helpers/editor-children-ids/add-block-menu/index.tsx
- packages/stack-emails/src/editor/documents/editor/editor-block.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/spacer-sidebar-panel.tsx
- packages/stack-emails/src/editor/sidebar/index.tsx
- packages/stack-emails/src/editor/documents/blocks/helpers/block-wrappers/tune-menu.tsx
- packages/stack-emails/src/editor/blocks/block-divider.tsx
- apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/migrations/templates-migration/page-client.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/font-weight-input.tsx
- packages/stack-emails/src/editor/documents/blocks/helpers/block-wrappers/reader-block-wrapper.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/image-sidebar-panel.tsx
- packages/stack-emails/src/editor/template-panel/import-json/validateJsonStringValue.ts
- packages/stack-emails/src/editor/template-panel/index.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/heading-sidebar-panel.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/text-sidebar-panel.tsx
- packages/stack-emails/src/templates/password-reset.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/color-input/index.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/color-input/base-color-input.tsx
- packages/stack-emails/src/editor/documents/blocks/columns-container/columns-container-editor.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/text-input.tsx
- packages/stack-emails/src/editor/sidebar/settings-panel.tsx
- apps/backend/src/app/api/latest/email-templates/crud.tsx
- packages/stack-emails/src/editor/documents/blocks/email-layout/email-layout-props-schema.tsx
- packages/stack-emails/src/editor/blocks/block-text.tsx
- packages/stack-emails/src/editor/documents/blocks/helpers/editor-children-ids/add-block-menu/buttons.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/text-dimension-input.tsx
- packages/stack-emails/src/editor/blocks/block-image.tsx
- packages/stack-emails/package.json
- apps/backend/src/app/api/latest/internal/email-templates/temp/[projectId]/route.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/columns-container-sidebar-panel.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/style-inputs/single-style-property-panel.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/font-size-input.tsx
- packages/stack-emails/src/editor/documents/blocks/helpers/editor-children-ids/index.tsx
- packages/stack-emails/src/editor/editor.tsx
- packages/stack-emails/src/editor/documents/blocks/helpers/editor-children-ids/add-block-menu/blocks-menu.tsx
- packages/stack-emails/src/editor/email-builder/blocks/email-layout/email-layout-reader.tsx
- packages/stack-emails/src/templates/magic-link-old.tsx
- packages/stack-emails/src/editor/blocks/block-heading.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/index.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/column-widths-input.tsx
- packages/stack-emails/src/editor/documents/blocks/email-layout/email-layout-editor.tsx
- packages/stack-emails/src/editor/document-core/index.ts
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/font-family.tsx
- packages/stack-emails/src/editor/blocks/block-spacer.tsx
- packages/stack-emails/src/templates/magic-link.tsx
- packages/stack-emails/src/editor/blocks/block-button.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/button-sidebar-panel.tsx
- packages/stack-emails/src/editor/email-builder/blocks/columns-container/columns-container-props-schema.ts
- apps/backend/src/app/api/latest/internal/email-templates/temp/convert.tsx
- packages/stack-emails/src/editor/sidebar/configuration-panel/input-panels/helpers/inputs/padding-input.tsx
- packages/stack-emails/src/editor/blocks/block-columns-container.tsx
- packages/stack-emails/src/editor/documents/editor/core.tsx
- packages/stack-emails/src/editor/email-builder/reader/core.tsx
✅ Files skipped from review due to trivial changes (4)
- apps/dashboard/package.json
- docker/dependencies/docker.compose.yaml
- apps/dashboard/src/components/vibe-coding/dts/index.ts
- apps/dashboard/src/components/vibe-coding/dts/util-dts.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- apps/e2e/tests/backend/endpoints/api/v1/auth/password/reset.test.ts
- apps/e2e/tests/backend/endpoints/api/v1/auth/otp/send-sign-in-code.test.ts
- apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/page-client.tsx
- apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/[templateId]/page-client.tsx
- apps/backend/src/lib/email-rendering.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{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/dashboard/src/components/vibe-coding/code-editor.tsxapps/e2e/tests/backend/endpoints/api/v1/internal/email-templates.test.tsapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsxapps/backend/src/lib/emails.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/dashboard/src/components/vibe-coding/code-editor.tsxapps/e2e/tests/backend/endpoints/api/v1/internal/email-templates.test.tsapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsxapps/backend/src/lib/emails.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/dashboard/src/components/vibe-coding/code-editor.tsxapps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsxapps/backend/src/lib/emails.tsx
apps/e2e/**/*.test.{ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
Import test utilities from
/apps/e2e/test/helpers.ts
Files:
apps/e2e/tests/backend/endpoints/api/v1/internal/email-templates.test.ts
**/*.test.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (CLAUDE.md)
Prefer inline snapshot testing with
expect(response).toMatchInlineSnapshot(...)
Files:
apps/e2e/tests/backend/endpoints/api/v1/internal/email-templates.test.ts
🧠 Learnings (3)
apps/dashboard/src/components/vibe-coding/code-editor.tsx (4)
Learnt from: CR
PR: stack-auth/stack-auth#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-28T23:25:51.691Z
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
Learnt from: CR
PR: stack-auth/stack-auth#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-28T23:25:51.691Z
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.691Z
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.691Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : 2-space indentation, spaces in braces, semicolons required
apps/e2e/tests/backend/endpoints/api/v1/internal/email-templates.test.ts (3)
Learnt from: CR
PR: stack-auth/stack-auth#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-28T23:25:51.691Z
Learning: Applies to apps/e2e/**/*.test.{ts,tsx} : Import test utilities from /apps/e2e/test/helpers.ts
Learnt from: CR
PR: stack-auth/stack-auth#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-28T23:25:51.691Z
Learning: Applies to **/*.test.{js,jsx,ts,tsx} : Prefer inline snapshot testing with expect(response).toMatchInlineSnapshot(...)
Learnt from: CR
PR: stack-auth/stack-auth#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-28T23:25:51.691Z
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
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx (1)
Learnt from: CR
PR: stack-auth/stack-auth#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-28T23:25:51.691Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use helper functions: yupXyz() for validation, getPublicEnvVar() for env
🧬 Code Graph Analysis (3)
apps/dashboard/src/components/vibe-coding/code-editor.tsx (1)
apps/dashboard/src/components/vibe-coding/dts/index.ts (1)
dtsBundles(5-9)
apps/e2e/tests/backend/endpoints/api/v1/internal/email-templates.test.ts (1)
apps/e2e/tests/backend/backend-helpers.ts (1)
niceBackendFetch(107-165)
apps/backend/src/lib/emails.tsx (5)
apps/backend/src/lib/tenancies.tsx (1)
Tenancy(50-50)packages/stack-shared/src/helpers/emails.ts (1)
DEFAULT_TEMPLATE_IDS(108-114)packages/stack-shared/src/utils/errors.tsx (1)
StackAssertionError(67-83)apps/backend/src/lib/email-rendering.tsx (2)
getEmailThemeForTemplate(23-32)renderEmailWithTemplate(49-136)packages/stack-shared/src/utils/objects.tsx (1)
filterUndefined(368-370)
⏰ 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). (7)
- GitHub Check: docker
- GitHub Check: restart-dev-and-test
- GitHub Check: lint_and_build (latest)
- GitHub Check: docker
- GitHub Check: all-good
- GitHub Check: build (22.x)
- GitHub Check: Security Check
🔇 Additional comments (5)
apps/dashboard/src/components/vibe-coding/code-editor.tsx (2)
6-6: LGTM! Improved type safety with proper imports.The import of
dtsBundlesreplaces previous inline declarations and aligns with the coding guidelines to avoidanycasts by providing proper TypeScript declaration bundles.
96-98: Excellent improvement to type definitions!These changes replace generic type declarations with comprehensive TypeScript declaration bundles for arktype functionality. The implementation maintains consistency with existing
addExtraLibcalls and enhances the Monaco editor's type checking capabilities.apps/backend/src/lib/emails.tsx (1)
307-349: LGTM! Well-structured refactoring to the new template rendering system.The changes properly implement the new TSX-based template rendering approach with:
- Type-safe template type parameter using
keyof typeof DEFAULT_TEMPLATE_IDS- Clear separation of template and theme retrieval
- Comprehensive error handling with debugging context
- Proper handling of optional user display name
apps/e2e/tests/backend/endpoints/api/v1/internal/email-templates.test.ts (1)
5-95: LGTM! Tests properly validate the new email template API behavior.The test updates correctly verify:
- Rejection of template updates when using shared email configuration with the new
REQUIRES_CUSTOM_EMAIL_SERVERerror- Successful template updates with custom email configuration
- The new TSX-based template format using
tsx_source- Mock rendering response structure
apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx (1)
250-322: LGTM! Navigation updates properly reflect the new email templates structure.The changes correctly update:
- Navigation paths from
/email-templates-new/to/email-templates/- Breadcrumb generation for the simplified route structure
- Hook usage from
useNewEmailTemplates()touseEmailTemplates()All changes are consistent with the removal of the legacy email template system.
Important
This PR enhances email template management with customizable themes, UI improvements, and refactoring across backend and frontend components.
page-client.tsx.page-client.tsx.route.tsx.page-client.tsx.page-client.tsx.email-rendering.tsx.send-sign-in-code.test.ts.vibe-coding/index.ts.vibe-coding/index.ts.admin-interface.ts.This description was created by
for a4eaa52. You can customize this summary. It will automatically update as commits are pushed.
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Refactor
Chores
@stackframe/stack-emailspackage and related dependencies and components.