diff --git a/apps/web/public/images/rallly-logo-mark.png b/apps/web/public/images/rallly-logo-mark.png
new file mode 100644
index 00000000000..13ef1b75104
Binary files /dev/null and b/apps/web/public/images/rallly-logo-mark.png differ
diff --git a/apps/web/src/env.ts b/apps/web/src/env.ts
index f621462eb2a..c26e2327946 100644
--- a/apps/web/src/env.ts
+++ b/apps/web/src/env.ts
@@ -49,6 +49,12 @@ export const env = createEnv({
* Example: "user@example.com, *@example.com, *@*.example.com"
*/
ALLOWED_EMAILS: z.string().optional(),
+ /**
+ * Email addresses for support and no-reply emails.
+ */
+ SUPPORT_EMAIL: z.string().email(),
+ NOREPLY_EMAIL: z.string().email().optional(),
+ NOREPLY_EMAIL_NAME: z.string().default("Rallly"),
},
/*
* Environment variables available on the client (and server).
@@ -90,6 +96,9 @@ export const env = createEnv({
NEXT_PUBLIC_POSTHOG_API_KEY: process.env.NEXT_PUBLIC_POSTHOG_API_KEY,
NEXT_PUBLIC_POSTHOG_API_HOST: process.env.NEXT_PUBLIC_POSTHOG_API_HOST,
NEXT_PUBLIC_SELF_HOSTED: process.env.NEXT_PUBLIC_SELF_HOSTED,
+ SUPPORT_EMAIL: process.env.SUPPORT_EMAIL,
+ NOREPLY_EMAIL: process.env.NOREPLY_EMAIL,
+ NOREPLY_EMAIL_NAME: process.env.NOREPLY_EMAIL_NAME,
},
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
});
diff --git a/apps/web/src/utils/emails.ts b/apps/web/src/utils/emails.ts
index 130c574712e..11e6376f371 100644
--- a/apps/web/src/utils/emails.ts
+++ b/apps/web/src/utils/emails.ts
@@ -1,25 +1,26 @@
import { EmailClient, SupportedEmailProviders } from "@rallly/emails";
+import { env } from "@/env";
import { absoluteUrl } from "@/utils/absolute-url";
-
-const env = process.env["NODE" + "_ENV"];
+import { isSelfHosted } from "@/utils/constants";
export const emailClient = new EmailClient({
- openPreviews: env === "development",
+ openPreviews: env.NODE_ENV === "development",
provider: {
name: (process.env.EMAIL_PROVIDER as SupportedEmailProviders) ?? "smtp",
},
mail: {
from: {
- name: (process.env.NOREPLY_EMAIL_NAME as string) || "Rallly",
- address:
- (process.env.NOREPLY_EMAIL as string) ||
- (process.env.SUPPORT_EMAIL as string),
+ name: env.NOREPLY_EMAIL_NAME,
+ address: env.NOREPLY_EMAIL || env.SUPPORT_EMAIL,
},
},
context: {
- logoUrl: absoluteUrl("/logo.png"),
+ logoUrl: isSelfHosted
+ ? absoluteUrl("/images/rallly-logo-mark.png")
+ : "https://rallly-public.s3.amazonaws.com/images/rallly-logo-mark.png",
baseUrl: absoluteUrl(""),
domain: absoluteUrl("").replace(/(^\w+:|^)\/\//, ""),
+ supportEmail: env.SUPPORT_EMAIL,
},
});
diff --git a/packages/emails/src/templates/_components/email-context.tsx b/packages/emails/src/templates/_components/email-context.tsx
index 34159783a05..966d5c46834 100644
--- a/packages/emails/src/templates/_components/email-context.tsx
+++ b/packages/emails/src/templates/_components/email-context.tsx
@@ -2,10 +2,12 @@ export type EmailContext = {
logoUrl: string;
baseUrl: string;
domain: string;
+ supportEmail: string;
};
export const defaultEmailContext = {
- logoUrl: "https://rallly.co/logo.png",
+ logoUrl: "https://rallly-public.s3.amazonaws.com/images/rallly-logo-mark.png",
baseUrl: "https://rallly.co",
domain: "rallly.co",
+ supportEmail: "support@rallly.co",
};
diff --git a/packages/emails/src/templates/_components/email-layout.tsx b/packages/emails/src/templates/_components/email-layout.tsx
index 4f7a652922f..e9cf91c211f 100644
--- a/packages/emails/src/templates/_components/email-layout.tsx
+++ b/packages/emails/src/templates/_components/email-layout.tsx
@@ -4,97 +4,56 @@ import {
Head,
Html,
Img,
- Link,
Preview,
+ Section,
} from "@react-email/components";
import { EmailContext } from "./email-context";
-import { fontFamily, Section, Text } from "./styled-components";
+import { darkTextColor, fontFamily, Link, Text } from "./styled-components";
export interface EmailLayoutProps {
preview: string;
- recipientName?: string;
- footNote?: React.ReactNode;
ctx: EmailContext;
}
const containerStyles = {
- maxWidth: "600px",
+ maxWidth: "480px",
margin: "0 auto",
background: "white",
fontFamily,
- padding: 16,
- border: "1px solid #E2E8F0",
- borderRadius: 5,
-};
-
-const sectionStyles = {
- marginTop: "16px",
- marginBottom: "16px",
-};
-
-const linkStyles = {
- color: "#64748B",
- marginRight: "8px",
+ padding: "32px 8px",
+ color: darkTextColor,
};
export const EmailLayout = ({
preview,
- recipientName,
children,
- footNote,
ctx,
}: React.PropsWithChildren) => {
- const { logoUrl, baseUrl } = ctx;
+ const { logoUrl } = ctx;
return (
{preview}
-
+
-
-
- {recipientName ? Hi {recipientName}, : null}
- {children}
- {footNote ? (
-
- {footNote}
-
- ) : null}
-
-
-
- Home
-
- •
-
- Twitter
-
- •
-
- Github
-
- •
-
- Contact
-
+
+ {children}
+
+
+ Powered by{" "}
+
+ rallly.co
+
+
diff --git a/packages/emails/src/templates/_components/notification-email.tsx b/packages/emails/src/templates/_components/notification-email.tsx
index ecb54450a62..60d8a0d33c4 100644
--- a/packages/emails/src/templates/_components/notification-email.tsx
+++ b/packages/emails/src/templates/_components/notification-email.tsx
@@ -1,3 +1,5 @@
+import { Section } from "@react-email/section";
+
import { EmailContext } from "./email-context";
import { EmailLayout } from "./email-layout";
import { Button, Link, Text } from "./styled-components";
@@ -15,7 +17,6 @@ export interface NotificationEmailProps extends NotificationBaseProps {
}
export const NotificationEmail = ({
- name,
pollUrl,
disableNotificationsUrl,
preview,
@@ -24,23 +25,17 @@ export const NotificationEmail = ({
}: React.PropsWithChildren) => {
const { domain } = ctx;
return (
-
- If you would like to stop receiving updates you can{" "}
-
- turn notifications off
-
- .
- >
- }
- preview={preview}
- >
+
{children}
-
+
+
+ If you would like to stop receiving updates you can{" "}
+
+ turn notifications off
+
+ .
);
diff --git a/packages/emails/src/templates/_components/styled-components.tsx b/packages/emails/src/templates/_components/styled-components.tsx
index d4c7cc8c314..eeaf2ccc435 100644
--- a/packages/emails/src/templates/_components/styled-components.tsx
+++ b/packages/emails/src/templates/_components/styled-components.tsx
@@ -11,6 +11,8 @@ import {
import { EmailContext } from "./email-context";
+export const lightTextColor = "#4B5563";
+export const darkTextColor = "#1F2937";
export const borderColor = "#E2E8F0";
export const Text = (
props: TextProps & { light?: boolean; small?: boolean },
@@ -23,7 +25,7 @@ export const Text = (
margin: "16px 0",
fontFamily,
fontSize: small ? "14px" : "16px",
- color: light ? "#64748B" : "#334155",
+ color: light ? lightTextColor : darkTextColor,
lineHeight: "1.5",
...props.style,
}}
@@ -46,6 +48,11 @@ export const Button = (props: React.ComponentProps) => {
borderRadius: "4px",
padding: "12px 14px",
fontFamily,
+ boxSizing: "border-box",
+ display: "block",
+ width: "100%",
+ maxWidth: "100%",
+ textAlign: "center",
fontSize: "16px",
color: "white",
}}
@@ -62,23 +69,24 @@ export const Link = (props: LinkProps) => {
);
};
+const fontSize = {
+ h1: "20px",
+ h2: "18px",
+ h3: "16px",
+ h4: "16px",
+ h5: "14px",
+ h6: "12px",
+};
+
export const Heading = (
props: React.ComponentProps,
) => {
- const { as = "h3" } = props;
- const fontSize = {
- h1: "32px",
- h2: "24px",
- h3: "20px",
- h4: "16px",
- h5: "14px",
- h6: "12px",
- };
+ const { as = "h1" } = props;
+
return (
{
return (
-
+
+ Final date booked!
{title} has been booked for:
@@ -73,9 +78,9 @@ export const FinalizeHostEmail = ({
We've notified participants and sent them calendar invites.
-
+
+
);
};
diff --git a/packages/emails/src/templates/finalized-participant.tsx b/packages/emails/src/templates/finalized-participant.tsx
index 6dfffa6d916..73fc37b844d 100644
--- a/packages/emails/src/templates/finalized-participant.tsx
+++ b/packages/emails/src/templates/finalized-participant.tsx
@@ -2,7 +2,12 @@ import { Column, Row, Section } from "@react-email/components";
import { defaultEmailContext, EmailContext } from "./_components/email-context";
import { EmailLayout } from "./_components/email-layout";
-import { borderColor, Button, Text } from "./_components/styled-components";
+import {
+ borderColor,
+ Button,
+ Heading,
+ Text,
+} from "./_components/styled-components";
export interface FinalizeParticipantEmailProps {
date: string;
@@ -19,7 +24,6 @@ export interface FinalizeParticipantEmailProps {
}
export const FinalizeParticipantEmail = ({
- name = "Guest",
title = "Untitled Poll",
hostName = "Host",
pollUrl = "https://rallly.co",
@@ -30,12 +34,13 @@ export const FinalizeParticipantEmail = ({
ctx = defaultEmailContext,
}: FinalizeParticipantEmailProps) => {
return (
-
+
+ Final date booked!
{hostName} has booked {title} for the
following date:
-
+
Please find attached a calendar invite for this event.
-
+
+
);
};
diff --git a/packages/emails/src/templates/login.tsx b/packages/emails/src/templates/login.tsx
index 972f0e389d3..32a993735f0 100644
--- a/packages/emails/src/templates/login.tsx
+++ b/packages/emails/src/templates/login.tsx
@@ -1,3 +1,5 @@
+import { Section } from "@react-email/components";
+
import { defaultEmailContext, EmailContext } from "./_components/email-context";
import { EmailLayout } from "./_components/email-layout";
import {
@@ -17,43 +19,40 @@ interface LoginEmailProps {
}
export const LoginEmail = ({
- name = "Guest",
code = "123456",
magicLink = "https://rallly.co",
ctx = defaultEmailContext,
}: LoginEmailProps) => {
return (
-
- You're receiving this email because a request was made to login
- to . If this wasn't you, let us know by
- replying to this email.
- >
- }
- recipientName={name}
- preview="Use this link to log in on this device."
- >
-
- To log in to your account, please choose one of the following options:
-
-
- Option 1: Magic Link
- Click this magic link to log in on this device.
+
+ Login
+ Enter this one-time 6-digit verification code:
+
+
+ {code}
+
+
+ This code is valid for 15 minutes
+
+
+
- This link will expire in 15 minutes.
-
-
- Option 2: Verification Code
- Enter this one-time 6-digit verification code.
-
- {code}
-
- This code will expire in 15 minutes.
-
+
+
+ You're receiving this email because a request was made to login to{" "}
+ . If this wasn't you contact{" "}
+ {ctx.supportEmail}.
+
);
};
diff --git a/packages/emails/src/templates/new-comment.tsx b/packages/emails/src/templates/new-comment.tsx
index a36cc7438c6..59aa15e6e9a 100644
--- a/packages/emails/src/templates/new-comment.tsx
+++ b/packages/emails/src/templates/new-comment.tsx
@@ -2,7 +2,7 @@ import { defaultEmailContext } from "./_components/email-context";
import NotificationEmail, {
NotificationBaseProps,
} from "./_components/notification-email";
-import { Text } from "./_components/styled-components";
+import { Heading, Text } from "./_components/styled-components";
export interface NewCommentEmailProps extends NotificationBaseProps {
authorName: string;
@@ -25,6 +25,7 @@ export const NewCommentEmail = ({
disableNotificationsUrl={disableNotificationsUrl}
preview="Go to your poll to see what they said."
>
+ New Comment
{authorName} has commented on {title}.
diff --git a/packages/emails/src/templates/new-participant-confirmation.tsx b/packages/emails/src/templates/new-participant-confirmation.tsx
index 0fc2f49e439..662117a2f36 100644
--- a/packages/emails/src/templates/new-participant-confirmation.tsx
+++ b/packages/emails/src/templates/new-participant-confirmation.tsx
@@ -1,6 +1,12 @@
import { defaultEmailContext, EmailContext } from "./_components/email-context";
import { EmailLayout } from "./_components/email-layout";
-import { Button, Domain, Section, Text } from "./_components/styled-components";
+import {
+ Button,
+ Domain,
+ Heading,
+ Section,
+ Text,
+} from "./_components/styled-components";
interface NewParticipantConfirmationEmailProps {
name: string;
@@ -10,24 +16,13 @@ interface NewParticipantConfirmationEmailProps {
}
export const NewParticipantConfirmationEmail = ({
title = "Untitled Poll",
- name = "John",
editSubmissionUrl = "https://rallly.co",
ctx = defaultEmailContext,
}: NewParticipantConfirmationEmailProps) => {
const { domain } = ctx;
return (
-
- You are receiving this email because a response was submitted on{" "}
- . If this wasn't you, please ignore this
- email.
- >
- }
- recipientName={name}
- preview="To edit your response use the link below"
- >
+
+ Poll Response Confirmation
Your response to {title} has been submitted.
@@ -35,11 +30,15 @@ export const NewParticipantConfirmationEmail = ({
While the poll is still open you can change your response using the link
below.
-
+
+
+ You are receiving this email because a response was submitted on{" "}
+ . If this wasn't you, please ignore this email.
+
);
};
diff --git a/packages/emails/src/templates/new-participant.tsx b/packages/emails/src/templates/new-participant.tsx
index 09b4cee2174..e053a0f0c7a 100644
--- a/packages/emails/src/templates/new-participant.tsx
+++ b/packages/emails/src/templates/new-participant.tsx
@@ -2,7 +2,7 @@ import { defaultEmailContext } from "./_components/email-context";
import NotificationEmail, {
NotificationBaseProps,
} from "./_components/notification-email";
-import { Text } from "./_components/styled-components";
+import { Heading, Text } from "./_components/styled-components";
export interface NewParticipantEmailProps extends NotificationBaseProps {
participantName: string;
@@ -25,10 +25,12 @@ export const NewParticipantEmail = ({
disableNotificationsUrl={disableNotificationsUrl}
preview="Go to your poll to see the new response."
>
+ New Response
{participantName} has responded to{" "}
{title}.
+ Go to your poll to see the new response.
);
};
diff --git a/packages/emails/src/templates/new-poll.tsx b/packages/emails/src/templates/new-poll.tsx
index 3133816a911..e1222c07fd6 100644
--- a/packages/emails/src/templates/new-poll.tsx
+++ b/packages/emails/src/templates/new-poll.tsx
@@ -1,6 +1,12 @@
import { defaultEmailContext, EmailContext } from "./_components/email-context";
import { EmailLayout } from "./_components/email-layout";
-import { Button, Card, Link, Text } from "./_components/styled-components";
+import {
+ Button,
+ Card,
+ Heading,
+ Link,
+ Text,
+} from "./_components/styled-components";
export interface NewPollEmailProps {
title: string;
@@ -10,82 +16,28 @@ export interface NewPollEmailProps {
ctx: EmailContext;
}
-const ShareLink = ({
- title,
- participantLink,
- name,
- children,
-}: React.PropsWithChildren<{
- name: string;
- title: string;
- participantLink: string;
-}>) => {
- return (
-
- {children}
-
- );
-};
-
export const NewPollEmail = ({
title = "Untitled Poll",
- name = "John",
adminLink = "https://rallly.co/admin/abcdefg123",
participantLink = "https://rallly.co/invite/wxyz9876",
ctx = defaultEmailContext,
}: NewPollEmailProps) => {
- const { baseUrl, domain } = ctx;
return (
- You are receiving this email because a new poll was created with this
- email address on {domain}. If this
- wasn't you, please ignore this email.
- >
- }
- recipientName={name}
preview="Share your participant link to start collecting responses."
>
+ New Poll Created
- Your poll has been successfully created! Here are the details:
+ Your meeting poll titled {`"${title}"`} is ready! Share
+ it using the link below:
-
-
- Title: {title}
-
- Invite Link:{" "}
+
+
{participantLink}
-
-
- Share via email
-
-
-
- To invite participants to your poll, simply share the{" "}
- Invite Link above with them. They'll be able to
- vote on their preferred meeting times and dates.
-
-
- If you need to make any changes to your poll, or if you want to see the
- results so far, just click on the button below:
-
-
-
-
+
);
};
diff --git a/packages/emails/src/templates/register.tsx b/packages/emails/src/templates/register.tsx
index 9a4c5bfb4d0..232d840a317 100644
--- a/packages/emails/src/templates/register.tsx
+++ b/packages/emails/src/templates/register.tsx
@@ -1,6 +1,9 @@
+import { Section } from "@react-email/section";
+
import { defaultEmailContext, EmailContext } from "./_components/email-context";
import { EmailLayout } from "./_components/email-layout";
import {
+ Card,
Domain,
Heading,
Text,
@@ -17,24 +20,34 @@ export const RegisterEmail = ({
ctx = defaultEmailContext,
}: RegisterEmailProps) => {
return (
-
- You're receiving this email because a request was made to
- register an account on . If this wasn't you,
- please ignore this email.
- >
- }
- preview={`Your 6-digit code is: ${code}`}
- >
+
+ Verify your email address
Please use the following 6-digit verification code to verify your email:
-
- {code}
-
- This code is valid for 15 minutes
+
+
+ {code}
+
+
+ This code is valid for 15 minutes
+
+
+
+
+ You're receiving this email because a request was made to
+ register an account on . If this wasn't you,
+ please ignore this email.
+
+
);
};