From e4e80986fee429177a825afcd0e9201a01e787c9 Mon Sep 17 00:00:00 2001 From: JOY <5027251+JOY@users.noreply.github.com> Date: Sat, 26 Sep 2026 01:18:35 +0700 Subject: [PATCH 1/2] feat(branding): replace the remaining hardcoded Documenso strings (batch 2) Sweep the residual hardcoded brand strings the catalogs cannot reach: - 2FA TOTP issuer ('Documenso' / 'Documenso Email 2FA' -> Crove Sign), visible in authenticator apps. - SMTP identity fallbacks: FROM_NAME, FROM_ADDRESS and the duplicated per-flow fallbacks (noreply@documenso.com -> noreply@sign.crove.com). - SUPPORT_EMAIL default (support@documenso.com -> support@dos.ai, overridable via NEXT_PUBLIC_SUPPORT_EMAIL) and the password-reset 'contact us' mailto links now use the constant instead of a hardcoded hi@documenso.com. - OIDC provider label, the platform option in the envelope sender dropdown, the embed completed-fallback name, branding upsell demo rows (noreply@app.documenso.com -> noreply@sign.crove.com), the email-domains upsell 'Sending from' string, and the embed v2 staging hint (dropped the documenso staging URL). Trans-wrapped strings are intentionally untouched: the branding patch rewrites their msgstr at runtime. The @documenso package scope and PDF synthetic placeholder emails are out of scope (internal/data-shape risk) and stay tracked on ROADMAP phase 7. --- .../dialogs/envelope-distribute-dialog.tsx | 2 +- .../components/embed/embed-document-completed.tsx | 2 +- .../general/settings-upsell/branding-upsell.tsx | 12 ++++++------ .../general/settings-upsell/email-domains-upsell.tsx | 4 ++-- .../app/routes/embed+/v2+/authoring+/_layout.tsx | 2 +- packages/email/templates/reset-password.tsx | 5 +++-- packages/lib/constants/app.ts | 2 +- packages/lib/constants/auth.ts | 2 +- packages/lib/constants/email.ts | 4 ++-- .../2fa/email/generate-2fa-credentials-from-email.ts | 2 +- packages/lib/server-only/2fa/setup-2fa.ts | 2 +- .../lib/server-only/auth/send-forgot-password.ts | 4 ++-- packages/lib/server-only/auth/send-reset-password.ts | 2 +- 13 files changed, 23 insertions(+), 22 deletions(-) diff --git a/apps/remix/app/components/dialogs/envelope-distribute-dialog.tsx b/apps/remix/app/components/dialogs/envelope-distribute-dialog.tsx index 0cd5e3c4ce..b791a4745a 100644 --- a/apps/remix/app/components/dialogs/envelope-distribute-dialog.tsx +++ b/apps/remix/app/components/dialogs/envelope-distribute-dialog.tsx @@ -359,7 +359,7 @@ export const EnvelopeDistributeDialog = ({ ))} - Documenso + Crove Sign diff --git a/apps/remix/app/components/embed/embed-document-completed.tsx b/apps/remix/app/components/embed/embed-document-completed.tsx index da11e59efd..be94ca76b5 100644 --- a/apps/remix/app/components/embed/embed-document-completed.tsx +++ b/apps/remix/app/components/embed/embed-document-completed.tsx @@ -18,7 +18,7 @@ export const EmbedDocumentCompleted = ({ name, signature }: EmbedDocumentComplet
diff --git a/apps/remix/app/components/general/settings-upsell/branding-upsell.tsx b/apps/remix/app/components/general/settings-upsell/branding-upsell.tsx index f74432cf77..966460fcfe 100644 --- a/apps/remix/app/components/general/settings-upsell/branding-upsell.tsx +++ b/apps/remix/app/components/general/settings-upsell/branding-upsell.tsx @@ -8,27 +8,27 @@ import { useTimedCycle } from './use-timed-cycle'; const DEMO_BRANDS = [ { - name: 'Documenso', + name: 'Crove Sign', letter: 'D', - domain: 'noreply@app.documenso.com', + domain: 'noreply@sign.crove.com', accent: '#A2E771', ink: '#162C07', tint: '#F2FBEA', sheen: 'rgba(162, 231, 113, 0.32)', }, { - name: 'Documenso', + name: 'Crove Sign', letter: 'D', - domain: 'noreply@app.documenso.com', + domain: 'noreply@sign.crove.com', accent: '#387BC7', ink: '#ffffff', tint: '#EDF3FA', sheen: 'rgba(56, 123, 199, 0.28)', }, { - name: 'Documenso', + name: 'Crove Sign', letter: 'D', - domain: 'noreply@app.documenso.com', + domain: 'noreply@sign.crove.com', accent: '#9747F5', ink: '#ffffff', tint: '#F4EDFE', diff --git a/apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx b/apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx index 183ad3b80e..ed1126036e 100644 --- a/apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx +++ b/apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx @@ -92,7 +92,7 @@ export const EmailDomainsUpsell = () => { )} - {isBranded ? Sending from your domain : Sending from app.documenso.com} + {isBranded ? Sending from your domain : Sending from Crove Sign} @@ -174,7 +174,7 @@ export const EmailDomainsUpsell = () => { transition={{ duration: 0.28, ease: EASE }} className="truncate" > - {isBranded ? brandedSender.email : 'noreply@app.documenso.com'} + {isBranded ? brandedSender.email : 'noreply@sign.crove.com'}
diff --git a/apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx b/apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx index 87ded302a7..75a9883036 100644 --- a/apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx +++ b/apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx @@ -194,7 +194,7 @@ export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
  • If you are using staging, ensure that you have set the host prop on the embedding component to the - staging domain (https://stg-app.documenso.com) + staging domain configured on your embedding component
  • diff --git a/packages/email/templates/reset-password.tsx b/packages/email/templates/reset-password.tsx index ce76690239..b008b9425b 100644 --- a/packages/email/templates/reset-password.tsx +++ b/packages/email/templates/reset-password.tsx @@ -1,3 +1,4 @@ +import { SUPPORT_EMAIL } from '@documenso/lib/constants/app'; import type { TPasswordChangeSource } from '@documenso/lib/jobs/definitions/emails/send-password-reset-success-email'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; @@ -58,7 +59,7 @@ export const ResetPasswordTemplate = ({ Didn't request a password change? We are here to help you secure your account, just{' '} - + contact us . @@ -73,7 +74,7 @@ export const ResetPasswordTemplate = ({ If this was you, no action is needed. If it wasn't, reset your password immediately and{' '} - + contact us . diff --git a/packages/lib/constants/app.ts b/packages/lib/constants/app.ts index 7a47b2021d..83ec2aed3a 100644 --- a/packages/lib/constants/app.ts +++ b/packages/lib/constants/app.ts @@ -93,7 +93,7 @@ export const IS_DOCUMENSO_CLOUD = () => env('NEXT_PUBLIC_IS_DOCUMENSO_CLOUD') == export const API_V2_BETA_URL = '/api/v2-beta'; export const API_V2_URL = '/api/v2'; -export const SUPPORT_EMAIL = env('NEXT_PUBLIC_SUPPORT_EMAIL') ?? 'support@documenso.com'; +export const SUPPORT_EMAIL = env('NEXT_PUBLIC_SUPPORT_EMAIL') ?? 'support@dos.ai'; export const USE_INTERNAL_URL_BROWSERLESS = () => env('NEXT_PUBLIC_USE_INTERNAL_URL_BROWSERLESS') === 'true'; diff --git a/packages/lib/constants/auth.ts b/packages/lib/constants/auth.ts index f995c339fe..f0f61ef138 100644 --- a/packages/lib/constants/auth.ts +++ b/packages/lib/constants/auth.ts @@ -16,7 +16,7 @@ export const SALT_ROUNDS = 12; export const TIMING_SAFE_DUMMY_PASSWORD_HASH = '$2y$12$eAJ6CR54acEljh1J/AN.peIPUd19yidDQRKhynGQriewBgzF1bQdm'; export const IDENTITY_PROVIDER_NAME: Record = { - DOCUMENSO: 'Documenso', + DOCUMENSO: 'Crove Sign', GOOGLE: 'Google', MICROSOFT: 'Microsoft', OIDC: 'OIDC', diff --git a/packages/lib/constants/email.ts b/packages/lib/constants/email.ts index a6742c5a86..61e683b32e 100644 --- a/packages/lib/constants/email.ts +++ b/packages/lib/constants/email.ts @@ -1,7 +1,7 @@ import { env } from '../utils/env'; -export const FROM_ADDRESS = env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@documenso.com'; -export const FROM_NAME = env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso'; +export const FROM_ADDRESS = env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@sign.crove.com'; +export const FROM_NAME = env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Crove Sign'; export const DOCUMENSO_INTERNAL_EMAIL = { name: FROM_NAME, diff --git a/packages/lib/server-only/2fa/email/generate-2fa-credentials-from-email.ts b/packages/lib/server-only/2fa/email/generate-2fa-credentials-from-email.ts index 7e67b5eb0c..426fd35961 100644 --- a/packages/lib/server-only/2fa/email/generate-2fa-credentials-from-email.ts +++ b/packages/lib/server-only/2fa/email/generate-2fa-credentials-from-email.ts @@ -4,7 +4,7 @@ import { createTOTPKeyURI } from 'oslo/otp'; import { DOCUMENSO_ENCRYPTION_KEY } from '../../../constants/crypto'; -const ISSUER = 'Documenso Email 2FA'; +const ISSUER = 'Crove Sign Email 2FA'; export type GenerateTwoFactorCredentialsFromEmailOptions = { envelopeId: string; diff --git a/packages/lib/server-only/2fa/setup-2fa.ts b/packages/lib/server-only/2fa/setup-2fa.ts index 515d017793..4d40da83ed 100644 --- a/packages/lib/server-only/2fa/setup-2fa.ts +++ b/packages/lib/server-only/2fa/setup-2fa.ts @@ -11,7 +11,7 @@ type SetupTwoFactorAuthenticationOptions = { user: Pick; }; -const ISSUER = 'Documenso'; +const ISSUER = 'Crove Sign'; export const setupTwoFactorAuthentication = async ({ user }: SetupTwoFactorAuthenticationOptions) => { const key = DOCUMENSO_ENCRYPTION_KEY; diff --git a/packages/lib/server-only/auth/send-forgot-password.ts b/packages/lib/server-only/auth/send-forgot-password.ts index c29d92b543..d951e64511 100644 --- a/packages/lib/server-only/auth/send-forgot-password.ts +++ b/packages/lib/server-only/auth/send-forgot-password.ts @@ -57,8 +57,8 @@ export const sendForgotPassword = async ({ userId }: SendForgotPasswordOptions) name: user.name || '', }, from: { - name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso', - address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@documenso.com', + name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Crove Sign', + address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@sign.crove.com', }, subject: i18n._(msg`Forgot Password?`), html, diff --git a/packages/lib/server-only/auth/send-reset-password.ts b/packages/lib/server-only/auth/send-reset-password.ts index e87537f3f2..01ef26d9ac 100644 --- a/packages/lib/server-only/auth/send-reset-password.ts +++ b/packages/lib/server-only/auth/send-reset-password.ts @@ -51,7 +51,7 @@ export const sendResetPassword = async ({ userId, source }: SendResetPasswordOpt }, from: { name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso', - address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@documenso.com', + address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@sign.crove.com', }, subject, html, From 126c41f992556e13572f6705f7d0ed096bd97a02 Mon Sep 17 00:00:00 2001 From: JOY <5027251+JOY@users.noreply.github.com> Date: Sat, 26 Sep 2026 01:28:12 +0700 Subject: [PATCH 2/2] fix(branding): address batch 2 review leftovers - send-reset-password FROM_NAME fallback and the email-domains upsell unbranded sender name still said Documenso while their sibling values were already rebranded. - Passkey/WebAuthn rpName (packages/lib/utils/authenticator.ts) is the same catalog-unreachable class. - Reword the embed staging hint phrasing, align branding upsell demo letters, document NEXT_PUBLIC_SUPPORT_EMAIL in .env.example. --- .env.example | 6 ++++-- .../components/general/settings-upsell/branding-upsell.tsx | 6 +++--- .../general/settings-upsell/email-domains-upsell.tsx | 2 +- apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx | 2 +- packages/lib/server-only/auth/send-reset-password.ts | 2 +- packages/lib/utils/authenticator.ts | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index b0635076bc..371366b55d 100644 --- a/.env.example +++ b/.env.example @@ -131,9 +131,11 @@ NEXT_PRIVATE_SMTP_SECURE= # OPTIONAL: if this is true and NEXT_PRIVATE_SMTP_SECURE is false then TLS is not used even if the server supports STARTTLS extension NEXT_PRIVATE_SMTP_UNSAFE_IGNORE_TLS= # REQUIRED: Defines the sender name to use for the from address. -NEXT_PRIVATE_SMTP_FROM_NAME="Documenso" +NEXT_PRIVATE_SMTP_FROM_NAME="Crove Sign" # REQUIRED: Defines the email address to use as the from address. -NEXT_PRIVATE_SMTP_FROM_ADDRESS="noreply@documenso.com" +NEXT_PRIVATE_SMTP_FROM_ADDRESS="noreply@sign.crove.com" +# OPTIONAL: Support contact shown in transactional emails (password reset "contact us"). +NEXT_PUBLIC_SUPPORT_EMAIL="support@dos.ai" # OPTIONAL: Defines the service for nodemailer NEXT_PRIVATE_SMTP_SERVICE= # OPTIONAL: The API key to use for Resend.com diff --git a/apps/remix/app/components/general/settings-upsell/branding-upsell.tsx b/apps/remix/app/components/general/settings-upsell/branding-upsell.tsx index 966460fcfe..8db54e02ce 100644 --- a/apps/remix/app/components/general/settings-upsell/branding-upsell.tsx +++ b/apps/remix/app/components/general/settings-upsell/branding-upsell.tsx @@ -9,7 +9,7 @@ import { useTimedCycle } from './use-timed-cycle'; const DEMO_BRANDS = [ { name: 'Crove Sign', - letter: 'D', + letter: 'C', domain: 'noreply@sign.crove.com', accent: '#A2E771', ink: '#162C07', @@ -18,7 +18,7 @@ const DEMO_BRANDS = [ }, { name: 'Crove Sign', - letter: 'D', + letter: 'C', domain: 'noreply@sign.crove.com', accent: '#387BC7', ink: '#ffffff', @@ -27,7 +27,7 @@ const DEMO_BRANDS = [ }, { name: 'Crove Sign', - letter: 'D', + letter: 'C', domain: 'noreply@sign.crove.com', accent: '#9747F5', ink: '#ffffff', diff --git a/apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx b/apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx index ed1126036e..44135e1f93 100644 --- a/apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx +++ b/apps/remix/app/components/general/settings-upsell/email-domains-upsell.tsx @@ -147,7 +147,7 @@ export const EmailDomainsUpsell = () => { transition={{ duration: 0.28, ease: EASE }} className="flex min-w-0 items-center gap-1.5" > - {isBranded ? brandedSender.name : 'Documenso'} + {isBranded ? brandedSender.name : 'Crove Sign'} {/* Inside the keyed row so it exits with the name and pops back in on every cycle step. */} {isBranded && ( diff --git a/apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx b/apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx index 75a9883036..050f62444a 100644 --- a/apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx +++ b/apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx @@ -194,7 +194,7 @@ export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
  • If you are using staging, ensure that you have set the host prop on the embedding component to the - staging domain configured on your embedding component + your staging domain
  • diff --git a/packages/lib/server-only/auth/send-reset-password.ts b/packages/lib/server-only/auth/send-reset-password.ts index 01ef26d9ac..4d044ba4aa 100644 --- a/packages/lib/server-only/auth/send-reset-password.ts +++ b/packages/lib/server-only/auth/send-reset-password.ts @@ -50,7 +50,7 @@ export const sendResetPassword = async ({ userId, source }: SendResetPasswordOpt name: user.name || '', }, from: { - name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Documenso', + name: env('NEXT_PRIVATE_SMTP_FROM_NAME') || 'Crove Sign', address: env('NEXT_PRIVATE_SMTP_FROM_ADDRESS') || 'noreply@sign.crove.com', }, subject, diff --git a/packages/lib/utils/authenticator.ts b/packages/lib/utils/authenticator.ts index 5984603a97..7a44931023 100644 --- a/packages/lib/utils/authenticator.ts +++ b/packages/lib/utils/authenticator.ts @@ -9,7 +9,7 @@ export const getAuthenticatorOptions = () => { const rpId = webAppBaseUrl.hostname; return { - rpName: 'Documenso', + rpName: 'Crove Sign', rpId, origin: NEXT_PUBLIC_WEBAPP_URL(), timeout: PASSKEY_TIMEOUT,