diff --git a/internal/services/email_service.go b/internal/services/email_service.go index b1f9717..09fb23d 100644 --- a/internal/services/email_service.go +++ b/internal/services/email_service.go @@ -139,15 +139,30 @@ func (s *EmailService) SendEmailWithEmbeddedImages(to, subject, htmlBody, textBo return nil } -// baseEmailTemplate returns the styled email wrapper +// ────────────────────────────────────────────────────────────────────────────── +// Casera "Warm Sage" Email Design System +// Matching the web landing page: casera.app +// ────────────────────────────────────────────────────────────────────────────── + +// emailIconURL is the URL for the email icon +const emailIconURL = "https://casera.app/images/icon.png" + +// emailFontStack — Outfit via Google Fonts with progressive fallback +const emailFontStack = "Outfit, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif" + +// baseEmailTemplate wraps all email content in the Casera shell: +// cream background → white card with warm shadow → sage brand stripe at top func baseEmailTemplate() string { return ` - + + + %s + + - - + + +
- - - `, year) + + %s + +
- - %s + @@ -172,41 +228,171 @@ func baseEmailTemplate() string { ` } -// emailIconURL is the URL for the email icon -const emailIconURL = "https://casera.app/images/icon.png" - -// emailHeader returns the gradient header section with logo -func emailHeader(title string) string { +// emailHeader renders the clean white header: logo + brand name + subtitle +func emailHeader(subtitle string) string { return fmt.Sprintf(` - - - - `, emailIconURL, title) +
+ + + + + + + + + + + + + + + + + + + + +
- - + +
- -
- Casera +
-

Casera

-

%s

-
`, emailIconURL, emailFontStack, emailFontStack, subtitle) } -// emailFooter returns the footer section +// emailDivider renders a subtle stone-colored horizontal rule +func emailDivider() string { + return ` + + + + +
+ + + + +
 
+
` +} + +// emailFooter renders the footer with copyright func emailFooter(year int) string { return fmt.Sprintf(` - -
-

© %d Casera. All rights reserved.

-

Never miss home maintenance again.

-
+ + + +
+

© %d Casera. All rights reserved.

+

support@casera.app

+
`, emailDivider(), emailFontStack, year, emailFontStack) } +// emailButton renders a pill-shaped CTA button (matches landing page hero) +func emailButton(text, href, bgColor string) string { + return fmt.Sprintf(` + + + + +
+ + %s + +
`, href, bgColor, href, bgColor, emailFontStack, text) +} + +// emailCodeBox renders a verification/reset code in a prominent box +func emailCodeBox(code, expiryText string) string { + return fmt.Sprintf(` + + + + +
+ + + + +
+

%s

+

%s

+
+
`, code, emailFontStack, expiryText) +} + +// emailCalloutBox renders a linen-background callout with optional accent border +func emailCalloutBox(content string) string { + return fmt.Sprintf(` + + + + +
+ %s +
`, content) +} + +// emailAlertBox renders a warning/info box with colored left accent +func emailAlertBox(title, body, accentColor, bgColor, titleColor string) string { + return fmt.Sprintf(` + + + + +
+

%s

+

%s

+
`, bgColor, accentColor, emailFontStack, titleColor, title, emailFontStack, body) +} + +// emailFeatureItem renders a single feature with an icon badge (matches landing page cards) +func emailFeatureItem(emoji, title, description, badgeBg, badgeColor string) string { + return fmt.Sprintf(` + + + + + +
+ + + + +
%s
+
+

%s

+

%s

+
`, badgeBg, emoji, emailFontStack, badgeColor, title, emailFontStack, description) +} + +// emailTipCard renders a numbered tip card with brand-colored accent (for post-verification) +func emailTipCard(number, title, description, accentColor, bgColor, titleColor string) string { + return fmt.Sprintf(` + + + + +
+ + + + + +
+ + + + +
+

%s

+
+
+

%s

+

%s

+
+
`, bgColor, bgColor, accentColor, emailFontStack, number, emailFontStack, titleColor, title, emailFontStack, description) +} + +// ────────────────────────────────────────────────────────────────────────────── +// Email template methods +// ────────────────────────────────────────────────────────────────────────────── + // SendWelcomeEmail sends a welcome email with verification code func (s *EmailService) SendWelcomeEmail(to, firstName, code string) error { subject := "Welcome to Casera - Verify Your Email" @@ -217,50 +403,43 @@ func (s *EmailService) SendWelcomeEmail(to, firstName, code string) error { } bodyContent := fmt.Sprintf(` - %s - - - -

Hi %s,

-

Thank you for creating a Casera account! To complete your registration, please verify your email address by entering the code below:

- - - + %s + +
-
-

%s

-

This code will expire in 24 hours

+
- -

If you didn't create a Casera account, you can safely ignore this email.

- -

Best regards,
The Casera Team

- - - %s`, - emailHeader("Welcome!"), - name, code, + %s`, + emailHeader("Verify your email"), + emailFontStack, name, + emailFontStack, + emailCodeBox(code, "Expires in 24 hours"), + emailFontStack, emailFooter(time.Now().Year())) htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent) - textBody := fmt.Sprintf(` -Welcome to Casera! + textBody := fmt.Sprintf(`Welcome to Casera! Hi %s, -Thank you for creating a Casera account. To complete your registration, please verify your email address by entering the following code: +Welcome! Verify your email to get started. -%s +Your verification code: %s -This code will expire in 24 hours. +This code expires in 24 hours. If you didn't create a Casera account, you can safely ignore this email. -Best regards, -The Casera Team +- The Casera Team `, name, code) return s.SendEmail(to, subject, htmlBody, textBody) @@ -275,56 +454,51 @@ func (s *EmailService) SendAppleWelcomeEmail(to, firstName string) error { name = "there" } - bodyContent := fmt.Sprintf(` - %s - - - -

Hi %s,

-

Thank you for joining Casera! Your account has been created and you're ready to start managing your properties.

+ features := emailFeatureItem("🏠", "Manage Properties", "Track all your homes and rentals in one place", "#EDF2ED", "#2D3436") + + emailFeatureItem("✅", "Task Management", "Never miss maintenance with smart scheduling", "#EDF2ED", "#2D3436") + + emailFeatureItem("👷", "Contractor Directory", "Keep your trusted pros organized", "#FDF3EE", "#2D3436") + + emailFeatureItem("📄", "Document Storage", "Store warranties, manuals, and important records", "#FEF3C7", "#2D3436") - - + bodyContent := fmt.Sprintf(` + %s + +
-
-

Here's what you can do with Casera:

-

🏠 Manage Properties - Track all your homes and rentals in one place

-

Task Management - Never miss maintenance with smart scheduling

-

👷 Contractor Directory - Keep your trusted pros organized

-

📄 Document Storage - Store warranties, manuals, and important records

+
- -

If you have any questions, feel free to reach out to us at support@casera.app.

- -

Best regards,
The Casera Team

- - - %s`, - emailHeader("Welcome!"), - name, + %s`, + emailHeader("Welcome to Casera!"), + emailFontStack, name, + emailCalloutBox(features), + emailButton("Open Casera", "casera://home", "#C4856A"), + emailFontStack, emailFooter(time.Now().Year())) htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent) - textBody := fmt.Sprintf(` -Welcome to Casera! + textBody := fmt.Sprintf(`Welcome to Casera! Hi %s, -Thank you for joining Casera! Your account has been created and you're ready to start managing your properties. +Your account is ready! Here's what you can do: -Here's what you can do with Casera: - Manage Properties: Track all your homes and rentals in one place - Task Management: Never miss maintenance with smart scheduling - Contractor Directory: Keep your trusted pros organized - Document Storage: Store warranties, manuals, and important records -If you have any questions, feel free to reach out to us at support@casera.app. +Questions? Reach out anytime at support@casera.app -Best regards, -The Casera Team +- The Casera Team `, name) return s.SendEmail(to, subject, htmlBody, textBody) @@ -339,56 +513,51 @@ func (s *EmailService) SendGoogleWelcomeEmail(to, firstName string) error { name = "there" } - bodyContent := fmt.Sprintf(` - %s - - - -

Hi %s,

-

Thank you for joining Casera! Your account has been created and you're ready to start managing your properties.

+ features := emailFeatureItem("🏠", "Manage Properties", "Track all your homes and rentals in one place", "#EDF2ED", "#2D3436") + + emailFeatureItem("✅", "Task Management", "Never miss maintenance with smart scheduling", "#EDF2ED", "#2D3436") + + emailFeatureItem("👷", "Contractor Directory", "Keep your trusted pros organized", "#FDF3EE", "#2D3436") + + emailFeatureItem("📄", "Document Storage", "Store warranties, manuals, and important records", "#FEF3C7", "#2D3436") - - + bodyContent := fmt.Sprintf(` + %s + +
-
-

Here's what you can do with Casera:

-

🏠 Manage Properties - Track all your homes and rentals in one place

-

Task Management - Never miss maintenance with smart scheduling

-

👷 Contractor Directory - Keep your trusted pros organized

-

📄 Document Storage - Store warranties, manuals, and important records

+
- -

If you have any questions, feel free to reach out to us at support@casera.app.

- -

Best regards,
The Casera Team

- - - %s`, - emailHeader("Welcome!"), - name, + %s`, + emailHeader("Welcome to Casera!"), + emailFontStack, name, + emailCalloutBox(features), + emailButton("Open Casera", "casera://home", "#C4856A"), + emailFontStack, emailFooter(time.Now().Year())) htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent) - textBody := fmt.Sprintf(` -Welcome to Casera! + textBody := fmt.Sprintf(`Welcome to Casera! Hi %s, -Thank you for joining Casera! Your account has been created and you're ready to start managing your properties. +Your account is ready! Here's what you can do: -Here's what you can do with Casera: - Manage Properties: Track all your homes and rentals in one place - Task Management: Never miss maintenance with smart scheduling - Contractor Directory: Keep your trusted pros organized - Document Storage: Store warranties, manuals, and important records -If you have any questions, feel free to reach out to us at support@casera.app. +Questions? Reach out anytime at support@casera.app -Best regards, -The Casera Team +- The Casera Team `, name) return s.SendEmail(to, subject, htmlBody, textBody) @@ -403,102 +572,62 @@ func (s *EmailService) SendPostVerificationEmail(to, firstName string) error { name = "there" } + tips := emailTipCard("1", "Add Your Property", "Start by adding your home. You can manage multiple properties and share access with family.", "#6B8F71", "#EDF2ED", "#2D3436") + + emailTipCard("2", "Set Up Recurring Tasks", "Create tasks for HVAC filter changes, gutter cleaning, lawn care. We'll remind you when they're due.", "#C4856A", "#FDF3EE", "#2D3436") + + emailTipCard("3", "Track Maintenance History", "Complete tasks with notes and photos. Invaluable for warranty claims or when selling your home.", "#D97706", "#FEF3C7", "#2D3436") + + emailTipCard("4", "Store Important Documents", "Upload warranties, manuals, insurance policies. Find them instantly instead of digging through drawers.", "#6B8F71", "#F2EFE9", "#2D3436") + + emailTipCard("5", "Save Your Contractors", "Keep your trusted plumber, electrician, and other pros organized and one tap away.", "#C4856A", "#FDF3EE", "#2D3436") + bodyContent := fmt.Sprintf(` - %s - - - -

Hi %s,

-

Your email is now verified and your Casera account is ready to go! Here are some tips to help you get the most out of the app.

- - - + %s + +
-
-

🏠 Start with Your Property

-

Add your home or rental property to begin tracking everything in one place. You can add multiple properties and even share access with family members or co-owners.

+
- - - - - - -
-

📅 Set Up Recurring Tasks

-

Create recurring tasks for regular maintenance like HVAC filter changes, gutter cleaning, or lawn care. Casera will remind you when they're due so nothing falls through the cracks.

-
- - - - - - -
-

📝 Track Your Maintenance History

-

When you complete a task, add notes and photos to build a maintenance history. This is invaluable for warranty claims, selling your home, or just remembering when something was last serviced.

-
- - - - - - -
-

📄 Store Important Documents

-

Upload warranties, appliance manuals, insurance policies, and receipts. When you need them, they'll be right at your fingertips instead of buried in a drawer somewhere.

-
- - - - - - -
-

👷 Save Your Contractors

-

Add your trusted plumber, electrician, and other service providers to your contractor list. You'll never have to dig through old emails or papers to find their contact info again.

-
- -

We're excited to have you on board. If you have any questions or feedback, we'd love to hear from you at support@casera.app.

- -

Happy homeowning!
The Casera Team

- - - %s`, - emailHeader("You're Verified!"), - name, + %s`, + emailHeader("You're all set!"), + emailFontStack, name, + tips, + emailButton("Get Started", "casera://home", "#C4856A"), + emailFontStack, emailFooter(time.Now().Year())) htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent) - textBody := fmt.Sprintf(` -You're All Set! Getting Started with Casera + textBody := fmt.Sprintf(`You're All Set! Hi %s, -Your email is now verified and your Casera account is ready to go! Here are some tips to help you get the most out of the app. +Your email is verified and you're ready to go! Here's how to get the most out of Casera: -1. START WITH YOUR PROPERTY -Add your home or rental property to begin tracking everything in one place. You can add multiple properties and even share access with family members or co-owners. +1. ADD YOUR PROPERTY +Start by adding your home. You can manage multiple properties and share access with family. 2. SET UP RECURRING TASKS -Create recurring tasks for regular maintenance like HVAC filter changes, gutter cleaning, or lawn care. Casera will remind you when they're due so nothing falls through the cracks. +Create tasks for HVAC filter changes, gutter cleaning, lawn care. We'll remind you when they're due. -3. TRACK YOUR MAINTENANCE HISTORY -When you complete a task, add notes and photos to build a maintenance history. This is invaluable for warranty claims, selling your home, or just remembering when something was last serviced. +3. TRACK MAINTENANCE HISTORY +Complete tasks with notes and photos. Invaluable for warranty claims or when selling your home. 4. STORE IMPORTANT DOCUMENTS -Upload warranties, appliance manuals, insurance policies, and receipts. When you need them, they'll be right at your fingertips instead of buried in a drawer somewhere. +Upload warranties, manuals, insurance policies. Find them instantly instead of digging through drawers. 5. SAVE YOUR CONTRACTORS -Add your trusted plumber, electrician, and other service providers to your contractor list. You'll never have to dig through old emails or papers to find their contact info again. +Keep your trusted plumber, electrician, and other pros organized and one tap away. -We're excited to have you on board. If you have any questions or feedback, we'd love to hear from you at support@casera.app. +Questions? support@casera.app -Happy homeowning! -The Casera Team +- The Casera Team `, name) return s.SendEmail(to, subject, htmlBody, textBody) @@ -514,50 +643,41 @@ func (s *EmailService) SendVerificationEmail(to, firstName, code string) error { } bodyContent := fmt.Sprintf(` - %s - - - -

Hi %s,

-

Please use the following code to verify your email address:

- - - + %s + +
-
-

%s

-

This code will expire in 24 hours

+
- -

If you didn't request this, you can safely ignore this email.

- -

Best regards,
The Casera Team

- - - %s`, - emailHeader("Verify Your Email"), - name, code, + %s`, + emailHeader("Verify your email"), + emailFontStack, name, + emailFontStack, + emailCodeBox(code, "Expires in 24 hours"), + emailFontStack, emailFooter(time.Now().Year())) htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent) - textBody := fmt.Sprintf(` -Verify Your Email + textBody := fmt.Sprintf(`Verify Your Email Hi %s, -Please use the following code to verify your email address: +Here's your verification code: %s -%s - -This code will expire in 24 hours. +This code expires in 24 hours. If you didn't request this, you can safely ignore this email. -Best regards, -The Casera Team +- The Casera Team `, name, code) return s.SendEmail(to, subject, htmlBody, textBody) @@ -573,58 +693,41 @@ func (s *EmailService) SendPasswordResetEmail(to, firstName, code string) error } bodyContent := fmt.Sprintf(` - %s - - - -

Hi %s,

-

We received a request to reset your password. Use the following code to complete the reset:

- - - + %s + +
-
-

%s

-

This code will expire in 15 minutes

+
- - - - - - -
-

Security Notice

-

If you didn't request a password reset, please ignore this email. Your password will remain unchanged.

-
- -

Best regards,
The Casera Team

- - - %s`, - emailHeader("Password Reset"), - name, code, + %s`, + emailHeader("Reset your password"), + emailFontStack, name, + emailFontStack, + emailCodeBox(code, "Expires in 15 minutes"), + emailAlertBox("Didn't request this?", "If you didn't request a password reset, please ignore this email. Your password will remain unchanged.", "#C4856A", "#FDF3EE", "#A06B52"), emailFooter(time.Now().Year())) htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent) - textBody := fmt.Sprintf(` -Password Reset Request + textBody := fmt.Sprintf(`Password Reset Request Hi %s, -We received a request to reset your password. Use the following code to complete the reset: +Use this code to reset your password: %s -%s +This code expires in 15 minutes. -This code will expire in 15 minutes. +If you didn't request a password reset, please ignore this email. Your password will remain unchanged. -SECURITY NOTICE: If you didn't request a password reset, please ignore this email. Your password will remain unchanged. - -Best regards, -The Casera Team +- The Casera Team `, name, code) return s.SendEmail(to, subject, htmlBody, textBody) @@ -642,44 +745,36 @@ func (s *EmailService) SendPasswordChangedEmail(to, firstName string) error { changeTime := time.Now().UTC().Format("January 2, 2006 at 3:04 PM UTC") bodyContent := fmt.Sprintf(` - %s - - - -

Hi %s,

-

Your Casera password was successfully changed on %s.

- - - + %s + +
-
-

Didn't make this change?

-

If you didn't change your password, please contact us immediately at support@casera.app or reset your password.

+
- -

Best regards,
The Casera Team

- - - %s`, - emailHeader("Password Changed"), - name, changeTime, + %s`, + emailHeader("Password changed"), + emailFontStack, name, + emailFontStack, changeTime, + emailAlertBox("Wasn't you?", "If you didn't make this change, contact us immediately at support@casera.app or reset your password right away.", "#C4856A", "#FDF3EE", "#A06B52"), emailFooter(time.Now().Year())) htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent) - textBody := fmt.Sprintf(` -Password Changed + textBody := fmt.Sprintf(`Password Changed Hi %s, -Your Casera password was successfully changed on %s. +Your password was successfully changed on %s. -DIDN'T MAKE THIS CHANGE? If you didn't change your password, please contact us immediately at support@casera.app or reset your password. +If you didn't make this change, contact us immediately at support@casera.app or reset your password right away. -Best regards, -The Casera Team +- The Casera Team `, name, changeTime) return s.SendEmail(to, subject, htmlBody, textBody) @@ -701,78 +796,83 @@ func (s *EmailService) SendTaskCompletedEmail(to, recipientName, taskTitle, comp imagesHTML := "" imagesText := "" if len(images) > 0 { - imagesHTML = ` - - - - - ` + photoLabel := "Photo" + if len(images) > 1 { + photoLabel = "Photos" + } + imagesHTML = fmt.Sprintf(` +

Completion %s

`, emailFontStack, photoLabel) for i, img := range images { imagesHTML += fmt.Sprintf(` - - - `, img.ContentID, i+1) + Completion photo %d`, img.ContentID, i+1) } - imagesHTML += ` -
-

Completion Photo` + func() string { - if len(images) > 1 { - return "s" - } - return "" - }() + `:

-
- Completion photo %d -
` - imagesText = fmt.Sprintf("\n\n[%d completion photo(s) attached]", len(images)) } - bodyContent := fmt.Sprintf(` - %s - - - -

Hi %s,

-

A task has been completed at %s:

- - - + // Task detail card + taskCard := fmt.Sprintf(` +
- + +
-

%s

-

Completed by: %s
Completed on: %s

+
+ + + + + +
+ + + + +
+

+
+
+

%s

+

Completed by %s
%s

+
+ %s +
`, + emailFontStack, + emailFontStack, taskTitle, + emailFontStack, completedByName, completedTime, + imagesHTML) + + bodyContent := fmt.Sprintf(` + %s + + + +
- %s - -

Best regards,
The Casera Team

- - - %s`, - emailHeader("Task Completed!"), - name, residenceName, taskTitle, completedByName, completedTime, - imagesHTML, + %s`, + emailHeader("Task completed!"), + emailFontStack, name, residenceName, + taskCard, emailFooter(time.Now().Year())) htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent) - textBody := fmt.Sprintf(` -Task Completed! + textBody := fmt.Sprintf(`Task Completed! Hi %s, -A task has been completed at %s: +A task at %s has been completed: Task: %s Completed by: %s Completed on: %s%s -Best regards, -The Casera Team +- The Casera Team `, name, residenceName, taskTitle, completedByName, completedTime, imagesText) // Use embedded images method if we have images, otherwise use simple send @@ -791,72 +891,74 @@ func (s *EmailService) SendTasksReportEmail(to, recipientName, residenceName str name = "there" } - bodyContent := fmt.Sprintf(` - %s - - - -

Hi %s,

-

Here's your tasks report for %s. The full report is attached as a PDF.

- - - - -
-

Summary

- + // Build stat cells + statRow := fmt.Sprintf(` +
- - - - -
-

%d

-

Total

+
+

%d

+

Total

-

%d

-

Completed

+
+

%d

+

Done

-

%d

-

Pending

+
+

%d

+

Pending

-

%d

-

Overdue

+
+

%d

+

Overdue

+
`, + emailFontStack, totalTasks, + emailFontStack, + emailFontStack, completed, + emailFontStack, + emailFontStack, pending, + emailFontStack, + emailFontStack, overdue, + emailFontStack) + + bodyContent := fmt.Sprintf(` + %s + + + +
- -

Open the attached PDF for the complete list of tasks with details.

- -

Best regards,
The Casera Team

- - - %s`, - emailHeader("Tasks Report"), - name, residenceName, totalTasks, completed, pending, overdue, + %s`, + emailHeader("Tasks report"), + emailFontStack, name, residenceName, + emailCalloutBox(statRow), + emailButton("Open Casera", "casera://tasks", "#6B8F71"), + emailFontStack, emailFooter(time.Now().Year())) htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent) - textBody := fmt.Sprintf(` -Tasks Report for %s + textBody := fmt.Sprintf(`Tasks Report for %s Hi %s, -Here's your tasks report for %s. The full report is attached as a PDF. +Here's your report for %s: -Summary: -- Total Tasks: %d -- Completed: %d -- Pending: %d -- Overdue: %d +Total: %d | Completed: %d | Pending: %d | Overdue: %d -Open the attached PDF for the complete list of tasks with details. +The full report is attached as a PDF. -Best regards, -The Casera Team +- The Casera Team `, residenceName, name, residenceName, totalTasks, completed, pending, overdue) // Create filename with timestamp @@ -885,67 +987,53 @@ func (s *EmailService) SendNoResidenceOnboardingEmail(to, firstName, baseURL, tr trackingPixel := fmt.Sprintf(``, baseURL, trackingID) + features := emailFeatureItem("🏠", "Track All Your Homes", "Manage single-family homes, apartments, or investment properties", "#EDF2ED", "#2D3436") + + emailFeatureItem("📅", "Never Miss Maintenance", "Set up recurring tasks with smart reminders", "#EDF2ED", "#2D3436") + + emailFeatureItem("📄", "Store Documents", "Keep warranties, manuals, and records in one place", "#FEF3C7", "#2D3436") + + emailFeatureItem("👷", "Manage Contractors", "Keep your trusted pros organized and accessible", "#FDF3EE", "#2D3436") + bodyContent := fmt.Sprintf(` - %s - - - -

Hi %s,

-

We noticed you haven't added your first property to Casera yet. Adding a property is the first step to staying on top of your home maintenance!

- - - - - - -
-

Why add a property?

-

🏠 Track all your homes - Manage single-family homes, apartments, or investment properties

-

📅 Never miss maintenance - Set up recurring tasks with smart reminders

-

📄 Store important documents - Keep warranties, manuals, and records in one place

-

👷 Manage contractors - Keep your trusted pros organized and accessible

-
- - - - - - -
- Add Your First Property -
- -

Just open the Casera app and tap the + button to get started. It only takes a minute!

- -

Best regards,
The Casera Team

%s - - - %s`, - emailHeader("Get Started!"), - name, + + + + + +
+ %s`, + emailHeader("Add your first property"), + emailFontStack, name, + emailCalloutBox(features), + emailButton("Add Your First Property", "casera://add-property", "#C4856A"), + emailFontStack, trackingPixel, emailFooter(time.Now().Year())) htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent) - textBody := fmt.Sprintf(` -Get started with Casera - Add your first property + textBody := fmt.Sprintf(`Add Your First Property Hi %s, -We noticed you haven't added your first property to Casera yet. Adding a property is the first step to staying on top of your home maintenance! +You haven't added your first property yet. It only takes a minute! -Why add a property? -- Track all your homes: Manage single-family homes, apartments, or investment properties -- Never miss maintenance: Set up recurring tasks with smart reminders -- Store important documents: Keep warranties, manuals, and records in one place -- Manage contractors: Keep your trusted pros organized and accessible +- Track all your homes +- Never miss maintenance +- Store important documents +- Manage contractors -Just open the Casera app and tap the + button to get started. It only takes a minute! +Open the Casera app and tap + to get started. -Best regards, -The Casera Team +- The Casera Team `, name) return s.SendEmail(to, subject, htmlBody, textBody) @@ -962,69 +1050,55 @@ func (s *EmailService) SendNoTasksOnboardingEmail(to, firstName, baseURL, tracki trackingPixel := fmt.Sprintf(``, baseURL, trackingID) + features := emailFeatureItem("🌡️", "HVAC Filter Replacement", "Monthly or quarterly", "#EDF2ED", "#2D3436") + + emailFeatureItem("💧", "Water Heater Flush", "Annually", "#EDF2ED", "#2D3436") + + emailFeatureItem("🌿", "Lawn Care", "Weekly or bi-weekly", "#EDF2ED", "#2D3436") + + emailFeatureItem("🕶", "Gutter Cleaning", "Seasonal", "#FEF3C7", "#2D3436") + + emailFeatureItem("🔥", "Smoke Detector Test", "Monthly", "#FDF3EE", "#2D3436") + bodyContent := fmt.Sprintf(` - %s - - - -

Hi %s,

-

Great job adding your property to Casera! Now it's time to set up your first maintenance task and start tracking your home care.

- - - - - - -
-

Task ideas to get you started:

-

🌡️ HVAC Filter Replacement - Monthly or quarterly

-

💧 Water Heater Flush - Annually

-

🌿 Lawn Care - Weekly or bi-weekly

-

🕶 Gutter Cleaning - Seasonal

-

🔥 Smoke Detector Test - Monthly

-
- - - - - - -
- Create Your First Task -
- -

Set up recurring tasks and Casera will remind you when they're due. No more forgotten maintenance!

- -

Best regards,
The Casera Team

%s - - - %s`, - emailHeader("Track Your Tasks!"), - name, + + + + + +
+ %s`, + emailHeader("Create your first task"), + emailFontStack, name, + emailCalloutBox(features), + emailButton("Create Your First Task", "casera://add-task", "#C4856A"), + emailFontStack, trackingPixel, emailFooter(time.Now().Year())) htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent) - textBody := fmt.Sprintf(` -Stay on top of home maintenance with Casera + textBody := fmt.Sprintf(`Create Your First Task Hi %s, -Great job adding your property to Casera! Now it's time to set up your first maintenance task and start tracking your home care. +Great job adding your property! Now set up your first task. Here are some ideas: -Task ideas to get you started: - HVAC Filter Replacement: Monthly or quarterly - Water Heater Flush: Annually - Lawn Care: Weekly or bi-weekly - Gutter Cleaning: Seasonal - Smoke Detector Test: Monthly -Set up recurring tasks and Casera will remind you when they're due. No more forgotten maintenance! +Set up recurring tasks and we'll remind you when they're due. -Best regards, -The Casera Team +- The Casera Team `, name) return s.SendEmail(to, subject, htmlBody, textBody)