Skip to content

remove react email components #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/core/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"imports": {
"@google-cloud/storage": "npm:@google-cloud/storage@^7.16.0",
"@oak/oak": "jsr:@oak/oak@^17.1.4",
"@react-email/components": "npm:@react-email/components@^0.1.0",
"@sentry/deno": "npm:@sentry/deno@^9.28.1",
"@std/assert": "jsr:@std/assert@1",
"@std/expect": "jsr:@std/expect@^1.0.16",
Expand Down
158 changes: 120 additions & 38 deletions packages/core/src/email/templates/DowngradeEmail.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Heading, Section, Text } from "@react-email/components";
import { baseTemplate } from "./base.tsx";
import { headingStyle } from "./styles.tsx";
import { sharedStyles } from "./sharedStyles.ts";
import type {
StripeBillingCycle,
StripeProduct,
Expand All @@ -20,47 +19,130 @@ const DowngradeEmail = (props: {
newSubscriptionDate: string;
}) => {
const previewText = "Confirmation of your subscription downgrade | NanoAPI";

return baseTemplate(
previewText,
<>
<Section>
<Heading as="h2" style={headingStyle}>
We are sorry to see you go
</Heading>
<Text>
Your subscription for workspace {props.workspaceName}{" "}
has been scheduled for downgrade.
</Text>
</Section>
<Section>
<Text
style={{ textAlign: "center", fontSize: "20px", fontWeight: "bold" }}
>
Previous subscription: {props.oldSubscription.product}{" "}
({props.oldSubscription.billingCycle ?? "Custom billing cycle"})
</Text>
<Text
style={{ textAlign: "center", fontSize: "20px", fontWeight: "bold" }}
{/* Header */}
<div style={{ ...sharedStyles.centerText, ...sharedStyles.section }}>
<div style={{ ...sharedStyles.iconCircle, backgroundColor: "#6b7280" }}>
📋
</div>
<h1 style={sharedStyles.heading}>Subscription Change Confirmed</h1>
<p style={sharedStyles.body}>
Your subscription for <strong>"{props.workspaceName}"</strong>{" "}
has been updated
</p>
</div>

{/* Plan Comparison */}
<div style={{ ...sharedStyles.section, ...sharedStyles.contentSpacing }}>
<h3 style={{ ...sharedStyles.subheading, ...sharedStyles.centerText }}>
Your Plan Changes
</h3>

<div style={sharedStyles.card}>
<div style={{ marginBottom: "16px" }}>
<div
style={{
...sharedStyles.small,
textTransform: "uppercase",
letterSpacing: "1px",
}}
>
Current Plan
</div>
<div
style={{ fontSize: "20px", fontWeight: "700", color: "#166534" }}
>
{props.oldSubscription.product}
</div>
<div style={sharedStyles.small}>
{props.oldSubscription.billingCycle ?? "Custom billing cycle"}
</div>
</div>

<div
style={{
textAlign: "center",
margin: "16px 0",
fontSize: "20px",
color: "#6b7280",
}}
>
⬇️
</div>

<div>
<div
style={{
...sharedStyles.small,
textTransform: "uppercase",
letterSpacing: "1px",
}}
>
New Plan
</div>
<div
style={{ fontSize: "20px", fontWeight: "700", color: "#991b1b" }}
>
{props.newSubscription.product}
</div>
<div style={sharedStyles.small}>
{props.newSubscription.billingCycle ?? "Custom billing cycle"}
</div>
</div>
</div>
</div>

{/* Effective Date */}
<div
style={{ ...sharedStyles.warningBox, ...sharedStyles.contentSpacing }}
>
<h3
style={{
...sharedStyles.subheading,
fontSize: "16px",
margin: "0 0 8px 0",
color: "#92400e",
}}
>
New subscription: {props.newSubscription.product}{" "}
({props.newSubscription.billingCycle ?? "Custom billing cycle"})
</Text>
<Text style={{ textAlign: "center", fontWeight: "bold" }}>
Effective date: {props.newSubscriptionDate}
</Text>
</Section>
<Section>
<Text>
Effective Date
</h3>
<p style={{ ...sharedStyles.small, color: "#92400e", margin: 0 }}>
Your current subscription will remain active until the end of your
billing period, and the new subscription will take effect on{" "}
{props.newSubscriptionDate}.
</Text>
<Text>
If you have any questions, please don't hesitate to contact our
support team.
</Text>
<Text>Best regards - Team Nano</Text>
</Section>
billing period. The new subscription will take effect on{" "}
<strong>{props.newSubscriptionDate}</strong>.
</p>
</div>

{/* Support */}
<div
style={{
...sharedStyles.card,
...sharedStyles.centerText,
...sharedStyles.contentSpacing,
}}
>
<p style={{ ...sharedStyles.small, margin: 0 }}>
Have questions about your subscription change? Our{" "}
<a href="mailto:[email protected]" style={sharedStyles.link}>
support team
</a>{" "}
is here to help you.
</p>
</div>

{/* Footer */}
<div style={{ ...sharedStyles.divider, ...sharedStyles.centerText }}>
<p style={{ ...sharedStyles.body, margin: "0 0 8px 0" }}>
Thank you for being part of our community! 🙏
</p>
<p style={sharedStyles.small}>
Best regards,<br />
The NanoAPI Team
</p>
</div>
</>,
);
};
Expand Down
114 changes: 80 additions & 34 deletions packages/core/src/email/templates/InvitationEmail.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,98 @@
import { Button, Heading, Section, Text } from "@react-email/components";
import { baseTemplate } from "./base.tsx";
import { headingStyle } from "./styles.tsx";
import { sharedStyles } from "./sharedStyles.ts";

const InvitationEmail = (props: {
workspaceName: string;
invitationLink: string;
}) => {
const previewText = `Invitation to join "${props.workspaceName}" on NanoAPI`;

return baseTemplate(
previewText,
<>
<Section>
<Heading as="h2" style={headingStyle}>
You have been invited to join "{props.workspaceName}"
</Heading>
<Text>
We're excited to have you as part of our team. To get started, simply
click the link below to accept your invitation and set up your
account:
</Text>
</Section>
<Section
style={{ display: "flex", justifyContent: "center", padding: 20 }}
{/* Header */}
<div style={{ ...sharedStyles.centerText, ...sharedStyles.section }}>
<div style={{ ...sharedStyles.iconCircle, backgroundColor: "#4f46e5" }}>
👥
</div>
<h1 style={sharedStyles.heading}>You're Invited!</h1>
<p style={sharedStyles.body}>
Join <strong>"{props.workspaceName}"</strong> on NanoAPI
</p>
</div>

{/* Invitation Details */}
<div
style={{
...sharedStyles.card,
...sharedStyles.centerText,
...sharedStyles.contentSpacing,
}}
>
<p style={sharedStyles.body}>
We're excited to have you as part of our team! To get started, simply
click the button below to accept your invitation and set up your
account.
</p>
<a href={props.invitationLink} style={sharedStyles.primaryButton}>
Accept Invitation
</a>
</div>

{/* What you'll get */}
<div style={{ ...sharedStyles.section, ...sharedStyles.contentSpacing }}>
<h3 style={{ ...sharedStyles.subheading, ...sharedStyles.centerText }}>
What you'll get access to:
</h3>
<div style={sharedStyles.card}>
<ul style={{ margin: 0, paddingLeft: "20px" }}>
<li style={sharedStyles.body}>
Collaborate on software architecture projects
</li>
<li style={sharedStyles.body}>
Access to shared workspaces and resources
</li>
<li style={sharedStyles.body}>
Use powerful development tools and CLI
</li>
<li style={sharedStyles.body}>
Team documentation and knowledge sharing
</li>
</ul>
</div>
</div>

{/* Security Notice */}
<div
style={{ ...sharedStyles.warningBox, ...sharedStyles.contentSpacing }}
>
<Button
href={props.invitationLink}
<h3
style={{
boxSizing: "border-box",
padding: 12,
fontWeight: 600,
borderRadius: 8,
textAlign: "center",
backgroundColor: "rgb(79,70,229)",
color: "rgb(255,255,255)",
...sharedStyles.subheading,
fontSize: "16px",
margin: "0 0 8px 0",
color: "#92400e",
}}
>
Accept Invitation
</Button>
</Section>
<Section>
<Text>
Secure Invitation
</h3>
<p style={{ ...sharedStyles.small, color: "#92400e", margin: 0 }}>
This invitation link is unique to you and will expire after a period
for security reasons. If you have any questions or need assistance,
please don't hesitate to reach out to your team administrator.
</Text>
<Text>We look forward to collaborating with you!</Text>
<Text>Best regards - Team Nano</Text>
</Section>
for security reasons. If you have any questions, please contact your
team administrator.
</p>
</div>

{/* Footer */}
<div style={{ ...sharedStyles.divider, ...sharedStyles.centerText }}>
<p style={{ ...sharedStyles.body, margin: "0 0 8px 0" }}>
We look forward to collaborating with you! 🚀
</p>
<p style={sharedStyles.small}>
Best regards,<br />
The NanoAPI Team
</p>
</div>
</>,
);
};
Expand Down
Loading