Skip to content

Commit

Permalink
Initial commit from Create Next App
Browse files Browse the repository at this point in the history
  • Loading branch information
scopsy committed Jun 11, 2024
0 parents commit 00d0931
Show file tree
Hide file tree
Showing 18 changed files with 9,391 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
4 changes: 4 additions & 0 deletions app/api/echo/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { serve } from "@novu/echo/next";
import { echo } from "../../echo/client";

export const { GET, POST, PUT } = serve({ client: echo });
64 changes: 64 additions & 0 deletions app/echo/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Echo } from "@novu/echo";
import { renderReactEmail } from "./emails/vercel";

export const echo = new Echo({
/**
* Enable this flag only during local development
*/
devModeBypassAuthentication: process.env.NODE_ENV === "development",
});

echo.workflow(
"hello-world",
async ({ step }) => {
await step.email(
"send-email",
async (inputs) => {
return {
subject: "This is an email subject",
body: renderReactEmail(inputs),
};
},
{
inputSchema: {
type: "object",

properties: {
showButton: { type: "boolean", default: true },
username: { type: "string", default: "alanturing" },
userImage: {
type: "string",
default:
"https://react-email-demo-bdj5iju9r-resend.vercel.app/static/vercel-user.png",
format: "uri",
},
invitedByUsername: { type: "string", default: "Alan" },
invitedByEmail: {
type: "string",
default: "[email protected]",
format: "email",
},
teamName: { type: "string", default: "Team Awesome" },
teamImage: {
type: "string",
default:
"https://react-email-demo-bdj5iju9r-resend.vercel.app/static/vercel-team.png",
format: "uri",
},
inviteLink: {
type: "string",
default: "https://vercel.com/teams/invite/foo",
format: "uri",
},
inviteFromIp: { type: "string", default: "204.13.186.218" },
inviteFromLocation: {
type: "string",
default: "São Paulo, Brazil",
},
},
},
},
);
},
{ payloadSchema: { type: "object", properties: {} } },
);
184 changes: 184 additions & 0 deletions app/echo/emails/vercel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import {
Body,
Button,
Container,
Column,
Head,
Heading,
Hr,
Html,
Img,
Link,
Preview,
Row,
Section,
Text,
render,
} from "@react-email/components";
import { Tailwind } from "@react-email/tailwind";
import * as React from "react";

interface VercelInviteUserEmailProps {
username?: string;
userImage?: string;
invitedByUsername?: string;
invitedByEmail?: string;
teamName?: string;
teamImage?: string;
inviteLink?: string;
inviteFromIp?: string;
inviteFromLocation?: string;
}

const baseUrl = process.env.VERCEL_URL
? `https://react-email-demo-bdj5iju9r-resend.vercel.app`
: "https://react-email-demo-bdj5iju9r-resend.vercel.app";

export const VercelInviteUserEmail = ({
username,
showButton,
userImage,
invitedByUsername,
invitedByEmail,
teamName,
teamImage,
inviteLink,
inviteFromIp,
inviteFromLocation,
listItems,
}: any) => {
const previewText = `Join ${invitedByUsername} on Vercel`;

return (
<Html>
<Head />
<Preview>{previewText}</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans px-2">
<Container className="border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] max-w-[465px]">
<Section className="mt-[32px]">
<Img
src={`${baseUrl}/static/vercel-logo.png`}
width="40"
height="37"
alt="Vercel"
className="my-0 mx-auto"
/>
</Section>
<Heading className="text-black text-[24px] font-normal text-center p-0 my-[30px] mx-0">
Joined <strong>{teamName}</strong> on <strong>Vercel</strong>
</Heading>
<Text className="text-black text-[14px] leading-[24px]">
Hello {username},
</Text>
<Text className="text-black text-[14px] leading-[24px]">
<strong>{invitedByUsername}</strong> (
<Link
href={`mailto:${invitedByEmail}`}
className="text-blue-600 no-underline"
>
{invitedByEmail}
</Link>
) has invited you to the <strong>{teamName}</strong> team on{" "}
<strong>Vercel</strong>.
</Text>
<Section>
<Row>
<Column align="right">
<Img
className="rounded-full"
src={userImage}
width="64"
height="64"
/>
</Column>
<Column align="center">
<Img
src={`${baseUrl}/static/vercel-arrow.png`}
width="12"
height="9"
alt="invited you to"
/>
</Column>
<Column align="left">
<Img
className="rounded-full"
src={teamImage}
width="64"
height="64"
/>
</Column>
</Row>
</Section>

{listItems?.map((item: string) => {
return (
<Row key={item}>
{item === "component1" ? (
<Column>
<Button
className="bg-[#000000] rounded text-white text-[12px] font-semibold no-underline text-center px-5 py-3"
href={inviteLink}
>
Test Button
</Button>
</Column>
) : null}
{item === "component2" ? (
<Column>
<Text className="text-[#666666] text-[12px] leading-[24px]">
{item}
</Text>
</Column>
) : null}
{item === "component3" ? (
<Column>
{" "}
<Hr className="border border-solid border-[#eaeaea] my-[26px] mx-0 w-full" />
</Column>
) : null}
{item === "component4" ? <Column> IMAGE</Column> : null}
</Row>
);
})}
{showButton && (
<Section className="text-center mt-[32px] mb-[32px]">
<Button
className="bg-[#000000] rounded text-white text-[12px] font-semibold no-underline text-center px-5 py-3"
href={inviteLink}
>
Join the team
</Button>
</Section>
)}

<Section></Section>
<Text className="text-black text-[14px] leading-[24px]">
or copy and paste this URL into your browser:{" "}
<Link href={inviteLink} className="text-blue-600 no-underline">
{inviteLink}
</Link>
</Text>
<Hr className="border border-solid border-[#eaeaea] my-[26px] mx-0 w-full" />
<Text className="text-[#666666] text-[12px] leading-[24px]">
This invitation was intended for{" "}
<span className="text-black">{username}</span>. This invite was
sent from <span className="text-black">{inviteFromIp}</span>{" "}
located in{" "}
<span className="text-black">{inviteFromLocation}</span>. If you
were not expecting this invitation, you can ignore this email. If
you are concerned about your account&apos;s safety, please reply
to this email to get in touch with us.
</Text>
</Container>
</Body>
</Tailwind>
</Html>
);
};

export default VercelInviteUserEmail;

export function renderReactEmail(inputs: any) {
return render(<VercelInviteUserEmail {...inputs} />);
}
Binary file added app/favicon.ico
Binary file not shown.
33 changes: 33 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}

@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
}
}

body {
color: rgb(var(--foreground-rgb));
background: linear-gradient(
to bottom,
transparent,
rgb(var(--background-end-rgb))
)
rgb(var(--background-start-rgb));
}

@layer utilities {
.text-balance {
text-wrap: balance;
}
}
22 changes: 22 additions & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
);
}
Loading

0 comments on commit 00d0931

Please sign in to comment.