Rebrand from Casera/MyCrib to honeyDue

Total rebrand across all Go API source files:
- Go module path: casera-api -> honeydue-api
- All imports updated (130+ files)
- Docker: containers, images, networks renamed
- Email templates: support email, noreply, icon URL
- Domains: casera.app/mycrib.treytartt.com -> honeyDue.treytartt.com
- Bundle IDs: com.tt.casera -> com.tt.honeyDue
- IAP product IDs updated
- Landing page, admin panel, config defaults
- Seeds, CI workflows, Makefile, docs
- Database table names preserved (no migration needed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-03-07 06:33:38 -06:00
parent 793e50ce52
commit 4976eafc6c
189 changed files with 831 additions and 831 deletions

View File

@@ -10,7 +10,7 @@ import (
"github.com/rs/zerolog/log"
"gopkg.in/gomail.v2"
"github.com/treytartt/casera-api/internal/config"
"github.com/treytartt/honeydue-api/internal/config"
)
// EmailService handles sending emails
@@ -140,17 +140,17 @@ func (s *EmailService) SendEmailWithEmbeddedImages(to, subject, htmlBody, textBo
}
// ──────────────────────────────────────────────────────────────────────────────
// Casera "Warm Sage" Email Design System
// Matching the web landing page: casera.app
// honeyDue "Warm Sage" Email Design System
// Matching the web landing page: honeyDue.treytartt.com
// ──────────────────────────────────────────────────────────────────────────────
// emailIconURL is the URL for the email icon
const emailIconURL = "https://casera.app/images/icon.png"
const emailIconURL = "https://honeyDue.treytartt.com/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:
// baseEmailTemplate wraps all email content in the honeyDue shell:
// cream background → white card with warm shadow → sage brand stripe at top
func baseEmailTemplate() string {
return `<!DOCTYPE html>
@@ -238,10 +238,10 @@ func emailHeader(subtitle string) string {
<table role="presentation" cellspacing="0" cellpadding="0" border="0">
<tr>
<td style="vertical-align: middle; padding-right: 14px;">
<img src="%s" alt="Casera" width="44" height="44" style="display: block; border-radius: 12px; border: 0;" />
<img src="%s" alt="honeyDue" width="44" height="44" style="display: block; border-radius: 12px; border: 0;" />
</td>
<td style="vertical-align: middle;">
<p style="font-family: %s; font-size: 22px; font-weight: 800; color: #2D3436; margin: 0; letter-spacing: -0.5px;">Casera</p>
<p style="font-family: %s; font-size: 22px; font-weight: 800; color: #2D3436; margin: 0; letter-spacing: -0.5px;">honeyDue</p>
</td>
</tr>
</table>
@@ -276,8 +276,8 @@ func emailFooter(year int) string {
<table role="presentation" width="100%%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td style="padding: 24px 48px 32px 48px; text-align: center;">
<p style="font-family: %s; font-size: 12px; color: #8A8F87; margin: 0;">&copy; %d Casera. All rights reserved.</p>
<p style="font-family: %s; font-size: 12px; margin: 8px 0 0 0;"><a href="mailto:support@casera.app" style="color: #6B8F71; text-decoration: none;">support@casera.app</a></p>
<p style="font-family: %s; font-size: 12px; color: #8A8F87; margin: 0;">&copy; %d honeyDue. All rights reserved.</p>
<p style="font-family: %s; font-size: 12px; margin: 8px 0 0 0;"><a href="mailto:honeydue@treymail.com" style="color: #6B8F71; text-decoration: none;">honeydue@treymail.com</a></p>
</td>
</tr>
</table>`, emailDivider(), emailFontStack, year, emailFontStack)
@@ -395,7 +395,7 @@ func emailTipCard(number, title, description, accentColor, bgColor, titleColor s
// SendWelcomeEmail sends a welcome email with verification code
func (s *EmailService) SendWelcomeEmail(to, firstName, code string) error {
subject := "Welcome to Casera - Verify Your Email"
subject := "Welcome to honeyDue - Verify Your Email"
name := firstName
if name == "" {
@@ -413,7 +413,7 @@ func (s *EmailService) SendWelcomeEmail(to, firstName, code string) error {
%s
<p style="font-family: %s; font-size: 13px; line-height: 1.6; color: #8A8F87; margin: 16px 0 0 0;">If you didn't create a Casera account, you can safely ignore this email.</p>
<p style="font-family: %s; font-size: 13px; line-height: 1.6; color: #8A8F87; margin: 16px 0 0 0;">If you didn't create a honeyDue account, you can safely ignore this email.</p>
</td>
</tr>
</table>
@@ -427,7 +427,7 @@ func (s *EmailService) SendWelcomeEmail(to, firstName, code string) error {
htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent)
textBody := fmt.Sprintf(`Welcome to Casera!
textBody := fmt.Sprintf(`Welcome to honeyDue!
Hi %s,
@@ -437,9 +437,9 @@ Your verification code: %s
This code expires in 24 hours.
If you didn't create a Casera account, you can safely ignore this email.
If you didn't create a honeyDue account, you can safely ignore this email.
- The Casera Team
- The honeyDue Team
`, name, code)
return s.SendEmail(to, subject, htmlBody, textBody)
@@ -447,7 +447,7 @@ If you didn't create a Casera account, you can safely ignore this email.
// SendAppleWelcomeEmail sends a welcome email for Apple Sign In users (no verification needed)
func (s *EmailService) SendAppleWelcomeEmail(to, firstName string) error {
subject := "Welcome to Casera!"
subject := "Welcome to honeyDue!"
name := firstName
if name == "" {
@@ -471,21 +471,21 @@ func (s *EmailService) SendAppleWelcomeEmail(to, firstName string) error {
%s
<p style="font-family: %s; font-size: 13px; line-height: 1.6; color: #8A8F87; margin: 24px 0 0 0;">Questions? Reach out anytime at <a href="mailto:support@casera.app" style="color: #6B8F71; text-decoration: none; font-weight: 600;">support@casera.app</a></p>
<p style="font-family: %s; font-size: 13px; line-height: 1.6; color: #8A8F87; margin: 24px 0 0 0;">Questions? Reach out anytime at <a href="mailto:honeydue@treymail.com" style="color: #6B8F71; text-decoration: none; font-weight: 600;">honeydue@treymail.com</a></p>
</td>
</tr>
</table>
%s`,
emailHeader("Welcome to Casera!"),
emailHeader("Welcome to honeyDue!"),
emailFontStack, name,
emailCalloutBox(features),
emailButton("Open Casera", "casera://home", "#C4856A"),
emailButton("Open honeyDue", "honeydue://home", "#C4856A"),
emailFontStack,
emailFooter(time.Now().Year()))
htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent)
textBody := fmt.Sprintf(`Welcome to Casera!
textBody := fmt.Sprintf(`Welcome to honeyDue!
Hi %s,
@@ -496,9 +496,9 @@ Your account is ready! Here's what you can do:
- Contractor Directory: Keep your trusted pros organized
- Document Storage: Store warranties, manuals, and important records
Questions? Reach out anytime at support@casera.app
Questions? Reach out anytime at honeydue@treymail.com
- The Casera Team
- The honeyDue Team
`, name)
return s.SendEmail(to, subject, htmlBody, textBody)
@@ -506,7 +506,7 @@ Questions? Reach out anytime at support@casera.app
// SendGoogleWelcomeEmail sends a welcome email for Google Sign In users (no verification needed)
func (s *EmailService) SendGoogleWelcomeEmail(to, firstName string) error {
subject := "Welcome to Casera!"
subject := "Welcome to honeyDue!"
name := firstName
if name == "" {
@@ -530,21 +530,21 @@ func (s *EmailService) SendGoogleWelcomeEmail(to, firstName string) error {
%s
<p style="font-family: %s; font-size: 13px; line-height: 1.6; color: #8A8F87; margin: 24px 0 0 0;">Questions? Reach out anytime at <a href="mailto:support@casera.app" style="color: #6B8F71; text-decoration: none; font-weight: 600;">support@casera.app</a></p>
<p style="font-family: %s; font-size: 13px; line-height: 1.6; color: #8A8F87; margin: 24px 0 0 0;">Questions? Reach out anytime at <a href="mailto:honeydue@treymail.com" style="color: #6B8F71; text-decoration: none; font-weight: 600;">honeydue@treymail.com</a></p>
</td>
</tr>
</table>
%s`,
emailHeader("Welcome to Casera!"),
emailHeader("Welcome to honeyDue!"),
emailFontStack, name,
emailCalloutBox(features),
emailButton("Open Casera", "casera://home", "#C4856A"),
emailButton("Open honeyDue", "honeydue://home", "#C4856A"),
emailFontStack,
emailFooter(time.Now().Year()))
htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent)
textBody := fmt.Sprintf(`Welcome to Casera!
textBody := fmt.Sprintf(`Welcome to honeyDue!
Hi %s,
@@ -555,9 +555,9 @@ Your account is ready! Here's what you can do:
- Contractor Directory: Keep your trusted pros organized
- Document Storage: Store warranties, manuals, and important records
Questions? Reach out anytime at support@casera.app
Questions? Reach out anytime at honeydue@treymail.com
- The Casera Team
- The honeyDue Team
`, name)
return s.SendEmail(to, subject, htmlBody, textBody)
@@ -565,7 +565,7 @@ Questions? Reach out anytime at support@casera.app
// SendPostVerificationEmail sends a welcome email after user verifies their email address
func (s *EmailService) SendPostVerificationEmail(to, firstName string) error {
subject := "You're All Set! Getting Started with Casera"
subject := "You're All Set! Getting Started with honeyDue"
name := firstName
if name == "" {
@@ -584,13 +584,13 @@ func (s *EmailService) SendPostVerificationEmail(to, firstName string) error {
<table role="presentation" width="100%%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td class="email-body" style="padding: 0 48px 40px 48px;">
<p style="font-family: %s; font-size: 16px; line-height: 1.7; color: #4B5563; margin: 0 0 24px 0;">Hi %s, your email is verified and you're ready to go! Here's how to get the most out of Casera:</p>
<p style="font-family: %s; font-size: 16px; line-height: 1.7; color: #4B5563; margin: 0 0 24px 0;">Hi %s, your email is verified and you're ready to go! Here's how to get the most out of honeyDue:</p>
%s
%s
<p style="font-family: %s; font-size: 13px; line-height: 1.6; color: #8A8F87; margin: 24px 0 0 0;">Questions or feedback? We'd love to hear from you at <a href="mailto:support@casera.app" style="color: #6B8F71; text-decoration: none; font-weight: 600;">support@casera.app</a></p>
<p style="font-family: %s; font-size: 13px; line-height: 1.6; color: #8A8F87; margin: 24px 0 0 0;">Questions or feedback? We'd love to hear from you at <a href="mailto:honeydue@treymail.com" style="color: #6B8F71; text-decoration: none; font-weight: 600;">honeydue@treymail.com</a></p>
</td>
</tr>
</table>
@@ -598,7 +598,7 @@ func (s *EmailService) SendPostVerificationEmail(to, firstName string) error {
emailHeader("You're all set!"),
emailFontStack, name,
tips,
emailButton("Get Started", "casera://home", "#C4856A"),
emailButton("Get Started", "honeydue://home", "#C4856A"),
emailFontStack,
emailFooter(time.Now().Year()))
@@ -608,7 +608,7 @@ func (s *EmailService) SendPostVerificationEmail(to, firstName string) error {
Hi %s,
Your email is verified and you're ready to go! Here's how to get the most out of Casera:
Your email is verified and you're ready to go! Here's how to get the most out of honeyDue:
1. ADD YOUR PROPERTY
Start by adding your home. You can manage multiple properties and share access with family.
@@ -625,9 +625,9 @@ Upload warranties, manuals, insurance policies. Find them instantly instead of d
5. SAVE YOUR CONTRACTORS
Keep your trusted plumber, electrician, and other pros organized and one tap away.
Questions? support@casera.app
Questions? honeydue@treymail.com
- The Casera Team
- The honeyDue Team
`, name)
return s.SendEmail(to, subject, htmlBody, textBody)
@@ -635,7 +635,7 @@ Questions? support@casera.app
// SendVerificationEmail sends an email verification code
func (s *EmailService) SendVerificationEmail(to, firstName, code string) error {
subject := "Casera - Verify Your Email"
subject := "honeyDue - Verify Your Email"
name := firstName
if name == "" {
@@ -677,7 +677,7 @@ This code expires in 24 hours.
If you didn't request this, you can safely ignore this email.
- The Casera Team
- The honeyDue Team
`, name, code)
return s.SendEmail(to, subject, htmlBody, textBody)
@@ -685,7 +685,7 @@ If you didn't request this, you can safely ignore this email.
// SendPasswordResetEmail sends a password reset email
func (s *EmailService) SendPasswordResetEmail(to, firstName, code string) error {
subject := "Casera - Password Reset Request"
subject := "honeyDue - Password Reset Request"
name := firstName
if name == "" {
@@ -727,7 +727,7 @@ This code expires in 15 minutes.
If you didn't request a password reset, please ignore this email. Your password will remain unchanged.
- The Casera Team
- The honeyDue Team
`, name, code)
return s.SendEmail(to, subject, htmlBody, textBody)
@@ -735,7 +735,7 @@ If you didn't request a password reset, please ignore this email. Your password
// SendPasswordChangedEmail sends a password changed confirmation email
func (s *EmailService) SendPasswordChangedEmail(to, firstName string) error {
subject := "Casera - Your Password Has Been Changed"
subject := "honeyDue - Your Password Has Been Changed"
name := firstName
if name == "" {
@@ -761,7 +761,7 @@ func (s *EmailService) SendPasswordChangedEmail(to, firstName string) error {
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"),
emailAlertBox("Wasn't you?", "If you didn't make this change, contact us immediately at honeydue@treymail.com or reset your password right away.", "#C4856A", "#FDF3EE", "#A06B52"),
emailFooter(time.Now().Year()))
htmlBody := fmt.Sprintf(baseEmailTemplate(), subject, bodyContent)
@@ -772,9 +772,9 @@ Hi %s,
Your password was successfully changed on %s.
If you didn't make this change, contact us immediately at support@casera.app or reset your password right away.
If you didn't make this change, contact us immediately at honeydue@treymail.com or reset your password right away.
- The Casera Team
- The honeyDue Team
`, name, changeTime)
return s.SendEmail(to, subject, htmlBody, textBody)
@@ -783,7 +783,7 @@ If you didn't make this change, contact us immediately at support@casera.app or
// SendTaskCompletedEmail sends an email notification when a task is completed
// images parameter is optional - pass nil or empty slice if no images
func (s *EmailService) SendTaskCompletedEmail(to, recipientName, taskTitle, completedByName, residenceName string, images []EmbeddedImage) error {
subject := fmt.Sprintf("Casera - Task Completed: %s", taskTitle)
subject := fmt.Sprintf("honeyDue - Task Completed: %s", taskTitle)
name := recipientName
if name == "" {
@@ -872,7 +872,7 @@ Task: %s
Completed by: %s
Completed on: %s%s
- The Casera Team
- The honeyDue Team
`, name, residenceName, taskTitle, completedByName, completedTime, imagesText)
// Use embedded images method if we have images, otherwise use simple send
@@ -884,7 +884,7 @@ Completed on: %s%s
// SendTasksReportEmail sends a tasks report email with PDF attachment
func (s *EmailService) SendTasksReportEmail(to, recipientName, residenceName string, totalTasks, completed, pending, overdue int, pdfData []byte) error {
subject := fmt.Sprintf("Casera - Tasks Report for %s", residenceName)
subject := fmt.Sprintf("honeyDue - Tasks Report for %s", residenceName)
name := recipientName
if name == "" {
@@ -942,7 +942,7 @@ func (s *EmailService) SendTasksReportEmail(to, recipientName, residenceName str
emailHeader("Tasks report"),
emailFontStack, name, residenceName,
emailCalloutBox(statRow),
emailButton("Open Casera", "casera://tasks", "#6B8F71"),
emailButton("Open honeyDue", "honeydue://tasks", "#6B8F71"),
emailFontStack,
emailFooter(time.Now().Year()))
@@ -958,7 +958,7 @@ Total: %d | Completed: %d | Pending: %d | Overdue: %d
The full report is attached as a PDF.
- The Casera Team
- The honeyDue Team
`, residenceName, name, residenceName, totalTasks, completed, pending, overdue)
// Create filename with timestamp
@@ -978,7 +978,7 @@ The full report is attached as a PDF.
// SendNoResidenceOnboardingEmail sends an onboarding email to users who haven't created a residence
func (s *EmailService) SendNoResidenceOnboardingEmail(to, firstName, baseURL, trackingID string) error {
subject := "Get started with Casera - Add your first property"
subject := "Get started with honeyDue - Add your first property"
name := firstName
if name == "" {
@@ -998,7 +998,7 @@ func (s *EmailService) SendNoResidenceOnboardingEmail(to, firstName, baseURL, tr
<table role="presentation" width="100%%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td class="email-body" style="padding: 0 48px 40px 48px;">
<p style="font-family: %s; font-size: 16px; line-height: 1.7; color: #4B5563; margin: 0 0 24px 0;">Hi %s, you haven't added your first property yet. It only takes a minute and unlocks everything Casera has to offer:</p>
<p style="font-family: %s; font-size: 16px; line-height: 1.7; color: #4B5563; margin: 0 0 24px 0;">Hi %s, you haven't added your first property yet. It only takes a minute and unlocks everything honeyDue has to offer:</p>
%s
@@ -1013,7 +1013,7 @@ func (s *EmailService) SendNoResidenceOnboardingEmail(to, firstName, baseURL, tr
emailHeader("Add your first property"),
emailFontStack, name,
emailCalloutBox(features),
emailButton("Add Your First Property", "casera://add-property", "#C4856A"),
emailButton("Add Your First Property", "honeydue://add-property", "#C4856A"),
emailFontStack,
trackingPixel,
emailFooter(time.Now().Year()))
@@ -1031,9 +1031,9 @@ You haven't added your first property yet. It only takes a minute!
- Store important documents
- Manage contractors
Open the Casera app and tap + to get started.
Open the honeyDue app and tap + to get started.
- The Casera Team
- The honeyDue Team
`, name)
return s.SendEmail(to, subject, htmlBody, textBody)
@@ -1041,7 +1041,7 @@ Open the Casera app and tap + to get started.
// SendNoTasksOnboardingEmail sends an onboarding email to users who have a property but no tasks
func (s *EmailService) SendNoTasksOnboardingEmail(to, firstName, baseURL, trackingID string) error {
subject := "Stay on top of home maintenance with Casera"
subject := "Stay on top of home maintenance with honeyDue"
name := firstName
if name == "" {
@@ -1077,7 +1077,7 @@ func (s *EmailService) SendNoTasksOnboardingEmail(to, firstName, baseURL, tracki
emailHeader("Create your first task"),
emailFontStack, name,
emailCalloutBox(features),
emailButton("Create Your First Task", "casera://add-task", "#C4856A"),
emailButton("Create Your First Task", "honeydue://add-task", "#C4856A"),
emailFontStack,
trackingPixel,
emailFooter(time.Now().Year()))
@@ -1098,7 +1098,7 @@ Great job adding your property! Now set up your first task. Here are some ideas:
Set up recurring tasks and we'll remind you when they're due.
- The Casera Team
- The honeyDue Team
`, name)
return s.SendEmail(to, subject, htmlBody, textBody)