├── .env.example ├── .gitignore ├── .prettierignore ├── README.md ├── components.json ├── eslint.config.mjs ├── next.config.ts ├── package.json ├── pnpm-lock.yaml ├── postcss.config.mjs ├── src ├── app │ ├── apple │ │ ├── icon.svg │ │ └── page.tsx │ ├── docs │ │ └── component │ │ │ ├── button │ │ │ └── page.tsx │ │ │ ├── confirm-account │ │ │ └── page.tsx │ │ │ ├── grid │ │ │ └── page.tsx │ │ │ └── header │ │ │ └── page.tsx │ ├── dub │ │ ├── icon.svg │ │ └── page.tsx │ ├── framer │ │ ├── icon.svg │ │ └── page.tsx │ ├── globals.css │ ├── icon.svg │ ├── layout.tsx │ ├── myna-ui │ │ ├── icon.svg │ │ ├── layout.tsx │ │ └── page.tsx │ ├── notion │ │ ├── icon.svg │ │ └── page.tsx │ ├── opengraph-image.jpg │ ├── page.tsx │ ├── peerlist │ │ ├── icon.svg │ │ └── page.tsx │ ├── softgen │ │ ├── icon.svg │ │ └── page.tsx │ ├── substack │ │ ├── icon.svg │ │ └── page.tsx │ ├── supabase │ │ ├── icon.svg │ │ └── page.tsx │ └── twitter-image.jpg ├── components │ └── ui │ │ ├── accordion.tsx │ │ ├── alert-dialog.tsx │ │ ├── avatar.tsx │ │ ├── badge.tsx │ │ ├── breadcrumb.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── checkbox-tree.tsx │ │ ├── checkbox.tsx │ │ ├── collapsible.tsx │ │ ├── command.tsx │ │ ├── dialog.tsx │ │ ├── drawer.tsx │ │ ├── dropdown-menu.tsx │ │ ├── form.tsx │ │ ├── hover-card.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── loading.tsx │ │ ├── multiselect.tsx │ │ ├── pagination.tsx │ │ ├── popover.tsx │ │ ├── radio-group.tsx │ │ ├── read-component-source.ts │ │ ├── scroll-area.tsx │ │ ├── select-native.tsx │ │ ├── select.tsx │ │ ├── separator.tsx │ │ ├── skeleton.tsx │ │ ├── slider.tsx │ │ ├── sonner.tsx │ │ ├── switch.tsx │ │ ├── tabs.tsx │ │ ├── textarea.tsx │ │ ├── toast.tsx │ │ ├── toaster.tsx │ │ ├── toggle-group.tsx │ │ ├── toggle.tsx │ │ └── tooltip.tsx ├── email │ ├── apple │ │ └── welcome.tsx │ ├── components │ │ ├── button │ │ │ ├── button-with-border.tsx │ │ │ ├── button-with-icon.tsx │ │ │ ├── single-width-full.tsx │ │ │ ├── single.tsx │ │ │ └── two-button.tsx │ │ ├── confirm-account │ │ │ └── one.tsx │ │ ├── grid │ │ │ └── content-grid.tsx │ │ └── header │ │ │ ├── one.tsx │ │ │ ├── spline.tsx │ │ │ └── two.tsx │ ├── dub │ │ ├── product-update-email.tsx │ │ └── welcome-email.tsx │ ├── framer │ │ ├── 1+4--welcome-to-framer.tsx │ │ ├── 3+4--enhance-your-framer-experience.tsx │ │ └── invitation-email.tsx │ ├── myna-ui │ │ ├── 1-welcome-email.tsx │ │ ├── 2-verify-email.tsx │ │ ├── 3-account-verified.tsx │ │ ├── 4-login-alert.tsx │ │ ├── 5-account-locked.tsx │ │ ├── 6-password-updated.tsx │ │ └── 7-product-updates.tsx │ ├── notion │ │ └── notion-newsletter.tsx │ ├── peerlist │ │ ├── inbox-message.tsx │ │ ├── job-application.tsx │ │ └── welcome.tsx │ ├── softgen │ │ ├── 1-welcome-email.tsx │ │ ├── 2-payment-email.tsx │ │ ├── 3-payment-package-email.tsx │ │ ├── 4-purchase-token-email.tsx │ │ └── 5-team-invitation-email.tsx │ ├── substack │ │ ├── newsletter-recommendation.tsx │ │ └── unread-post.tsx │ └── supabase │ │ ├── supabase-verification-email.tsx │ │ └── welcome.tsx └── features │ ├── analytics │ └── posthog-page-view.tsx │ ├── email │ └── send │ │ ├── email-popover.tsx │ │ ├── email-trigger.ts │ │ └── index.tsx │ ├── global │ ├── cli-commands.tsx │ ├── code-block-wrapper.tsx │ ├── code-block.tsx │ ├── code-format-selector.tsx │ ├── component-source.tsx │ ├── copy-button.tsx │ ├── cta.tsx │ ├── footer.tsx │ ├── github-button.tsx │ ├── header.tsx │ ├── illustration.tsx │ ├── image.tsx │ ├── page-header.tsx │ ├── read-brand-source.ts │ ├── tag-scroll.tsx │ ├── template-layout.tsx │ ├── theme-provider.tsx │ ├── theme-toggle.tsx │ └── toast.tsx │ ├── hooks │ ├── use-character-limit.ts │ ├── use-colors.ts │ ├── use-config.ts │ ├── use-copy-to-clipboard.ts │ ├── use-copy.ts │ ├── use-image-upload.ts │ ├── use-mounted.ts │ ├── use-pagination.ts │ ├── use-slider-with-input.ts │ └── use-toast.ts │ ├── lib │ ├── color.ts │ ├── component.ts │ ├── email-to-html.tsx │ ├── regisry-color.ts │ ├── template-list.tsx │ └── utils.ts │ └── providers │ ├── ph-provider.tsx │ └── query-provider.tsx ├── tailwind.config.ts └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | PLUNK_PUBLIC_KEY="" 2 | NEXT_PUBLIC_PLUNK_SECRET_KEY="" 3 | 4 | NEXT_PUBLIC_POSTHOG_KEY="" 5 | NEXT_PUBLIC_POSTHOG_HOST="" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .next 3 | pnpm-lock.yaml 4 | public/r 5 | 6 | # Build output 7 | .next 8 | build 9 | dist 10 | 11 | # Cache 12 | .cache 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # reactui email 2 | 3 | **A [react.email](https://react.email) based template library with full Tailwind CSS support** 4 | 5 | ## Overview 6 | 7 | ReactUI Email is a simple collection of email templates built on top of [react.email](https://react.email) and fully styled with [tailwindcss](https://tailwindcss.com). The goal is to provide an easy-to-use and customizable solution for creating email templates in React. The project are still a work in progress. 8 | 9 | ## Features 10 | 11 | - **Tailwind CSS**: Fully integrated for easy customization. 12 | - **React-based**: Built on [react.email](https://react.email) for easy integration. 13 | - **Responsive**: Optimized for mobile and desktop email clients. 14 | 15 | ## Roadmap 16 | 17 | - Add more templates. 18 | - Improve template responsiveness. 19 | - Add documentation for easy integration with other tools. 20 | 21 | ## Contributing 22 | 23 | Feel free to contribute to this project by submitting pull requests or opening issues. Since this is a template in progress, your feedback and suggestions are appreciated. 24 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "src/app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "lib": "@/lib", 17 | "ui": "@/components/ui", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } 22 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { FlatCompat } from "@eslint/eslintrc"; 2 | import { dirname } from "path"; 3 | import { fileURLToPath } from "url"; 4 | 5 | const __filename = fileURLToPath(import.meta.url); 6 | const __dirname = dirname(__filename); 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }); 11 | 12 | const eslintConfig = [...compat.extends("next/core-web-vitals", "next/typescript")]; 13 | 14 | export default eslintConfig; 15 | -------------------------------------------------------------------------------- /next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from "next"; 2 | 3 | const nextConfig: NextConfig = { 4 | images: { 5 | remotePatterns: [ 6 | { 7 | protocol: "https", 8 | hostname: "cdn.brandfetch.io", 9 | port: "", 10 | pathname: "/**", 11 | }, 12 | { 13 | protocol: "https", 14 | hostname: "res.cloudinary.com", 15 | port: "", 16 | pathname: "/**", 17 | }, 18 | ], 19 | }, 20 | }; 21 | 22 | export default nextConfig; 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reactui-email", 3 | "version": "0.1.0", 4 | "private": true, 5 | "prettier": { 6 | "semi": true, 7 | "singleQuote": false, 8 | "printWidth": 100, 9 | "plugins": [ 10 | "prettier-plugin-organize-imports", 11 | "prettier-plugin-tailwindcss" 12 | ], 13 | "overrides": [ 14 | { 15 | "files": [ 16 | "tsconfig.json" 17 | ], 18 | "options": { 19 | "parser": "jsonc" 20 | } 21 | } 22 | ] 23 | }, 24 | "scripts": { 25 | "dev": "next dev --turbopack", 26 | "build": "next build", 27 | "start": "next start", 28 | "lint": "next lint", 29 | "format": "prettier --write . && pnpm run lint" 30 | }, 31 | "dependencies": { 32 | "@hookform/resolvers": "^3.10.0", 33 | "@mynaui/icons-react": "^0.3.3", 34 | "@plunk/node": "^3.0.3", 35 | "@radix-ui/react-accordion": "^1.2.2", 36 | "@radix-ui/react-alert-dialog": "^1.1.4", 37 | "@radix-ui/react-avatar": "^1.1.2", 38 | "@radix-ui/react-checkbox": "^1.1.3", 39 | "@radix-ui/react-collapsible": "^1.1.2", 40 | "@radix-ui/react-dialog": "^1.1.4", 41 | "@radix-ui/react-dropdown-menu": "^2.1.4", 42 | "@radix-ui/react-hover-card": "^1.1.4", 43 | "@radix-ui/react-icons": "^1.3.2", 44 | "@radix-ui/react-label": "^2.1.1", 45 | "@radix-ui/react-popover": "^1.1.4", 46 | "@radix-ui/react-radio-group": "^1.2.2", 47 | "@radix-ui/react-scroll-area": "^1.2.2", 48 | "@radix-ui/react-select": "^2.1.4", 49 | "@radix-ui/react-separator": "^1.1.1", 50 | "@radix-ui/react-slider": "^1.2.2", 51 | "@radix-ui/react-slot": "^1.1.1", 52 | "@radix-ui/react-switch": "^1.1.2", 53 | "@radix-ui/react-tabs": "^1.1.2", 54 | "@radix-ui/react-toast": "^1.2.4", 55 | "@radix-ui/react-toggle": "^1.1.1", 56 | "@radix-ui/react-toggle-group": "^1.1.1", 57 | "@radix-ui/react-tooltip": "^1.1.6", 58 | "@react-email/components": "^0.0.32", 59 | "@react-email/render": "1.0.4", 60 | "@remixicon/react": "^4.6.0", 61 | "@tanstack/react-query": "^5.64.2", 62 | "class-variance-authority": "^0.7.1", 63 | "clsx": "^2.1.1", 64 | "cmdk": "^1.0.4", 65 | "lucide-react": "^0.471.0", 66 | "next": "15.2.1", 67 | "next-themes": "^0.4.4", 68 | "posthog-js": "^1.215.4", 69 | "react": "^19.0.0", 70 | "react-dom": "^19.0.0", 71 | "react-hook-form": "^7.54.2", 72 | "react-icons": "^5.4.0", 73 | "react-resizable-panels": "^2.1.7", 74 | "shiki": "^1.26.1", 75 | "sonner": "^1.7.1", 76 | "tailwind-merge": "^2.6.0", 77 | "tailwindcss-animate": "^1.0.7", 78 | "vaul": "^1.1.2", 79 | "zod": "^3.24.1", 80 | "zustand": "^5.0.3" 81 | }, 82 | "devDependencies": { 83 | "@eslint/eslintrc": "^3", 84 | "@types/node": "^20", 85 | "@types/react": "^19", 86 | "@types/react-dom": "^19", 87 | "eslint": "^9", 88 | "eslint-config-next": "15.1.4", 89 | "postcss": "^8", 90 | "prettier": "^3.4.2", 91 | "prettier-plugin-organize-imports": "^4.1.0", 92 | "prettier-plugin-tailwindcss": "^0.6.9", 93 | "tailwindcss": "^3.4.1", 94 | "typescript": "^5" 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /src/app/apple/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/app/apple/page.tsx: -------------------------------------------------------------------------------- 1 | import PageHeader from "@/features/global/page-header"; 2 | import { readBrandSources } from "@/features/global/read-brand-source"; 3 | import { TemplateLayout } from "@/features/global/template-layout"; 4 | import { render } from "@/features/lib/email-to-html"; 5 | import { t } from "@/features/lib/utils"; 6 | import { Metadata } from "next"; 7 | import Link from "next/link"; 8 | import path from "path"; 9 | 10 | export const revalidate = 3600; 11 | 12 | export const metadata: Metadata = { 13 | title: "Apple Email Templates | ReactUI Email", 14 | description: 15 | "Collection of Apple-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 16 | keywords: [ 17 | "ReactUI Email", 18 | "Apple Email Templates", 19 | "TailwindCSS Email", 20 | "Next.js Email Templates", 21 | "Responsive Email Design", 22 | "Email Template Code", 23 | "React Email Components", 24 | "Apple Email Design", 25 | "Email Development", 26 | "Email Marketing Templates", 27 | ], 28 | openGraph: { 29 | title: "Apple Email Templates | ReactUI Email", 30 | description: 31 | "Collection of Apple-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 32 | url: "https://reactui.email/apple", 33 | images: [ 34 | { 35 | url: "https://reactui.email/opengraph-image.jpg", 36 | alt: "Apple Email Templates Preview", 37 | width: 1200, 38 | height: 630, 39 | }, 40 | ], 41 | }, 42 | twitter: { 43 | card: "summary_large_image", 44 | title: "Apple Email Templates | ReactUI Email", 45 | description: 46 | "Collection of Apple-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 47 | images: ["https://reactui.email/opengraph-image.jpg"], 48 | }, 49 | alternates: { 50 | canonical: "https://reactui.email/apple", 51 | }, 52 | robots: { 53 | index: true, 54 | follow: true, 55 | }, 56 | }; 57 | 58 | const Page = async () => { 59 | const brand = "apple"; 60 | 61 | const emailSource = await readBrandSources(brand); 62 | 63 | const emailPreviews = await Promise.all( 64 | emailSource.map(async (source) => { 65 | const emailModule = await import( 66 | `@/email/${brand}/${path.basename(source.filePath, ".tsx")}` 67 | ); 68 | const EmailComponent = emailModule.default; 69 | 70 | const emailHtml = await render(); 71 | 72 | const fileName = path 73 | .basename(source.filePath, ".tsx") 74 | .split("-") 75 | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 76 | .join(" "); 77 | 78 | return { 79 | fileName, 80 | content: source.content, 81 | emailHtml, 82 | }; 83 | }), 84 | ); 85 | 86 | return ( 87 |
88 |
89 |
90 | 91 | 92 | 93 | Apple 94 | {" "} 95 | 96 | is a global technology company that designs, develops, and sells consumer electronics, 97 | software, and services. 98 | 99 | 100 | {emailPreviews.map((preview) => ( 101 | 109 | ))} 110 |
111 |
112 |
113 | ); 114 | }; 115 | 116 | export default Page; 117 | -------------------------------------------------------------------------------- /src/app/docs/component/button/page.tsx: -------------------------------------------------------------------------------- 1 | import PageHeader from "@/features/global/page-header"; 2 | import { readBrandSources } from "@/features/global/read-brand-source"; 3 | import { TemplateLayout } from "@/features/global/template-layout"; 4 | import { render } from "@/features/lib/email-to-html"; 5 | import { Metadata } from "next"; 6 | import Link from "next/link"; 7 | import path from "path"; 8 | 9 | export const revalidate = 3600; 10 | 11 | export const metadata: Metadata = { 12 | title: "Button | ReactUI Email", 13 | description: 14 | "Preview and code for the React Email Button component, built with Next.js and TailwindCSS for ReactUI Email.", 15 | keywords: [ 16 | "ReactUI Email", 17 | "React Email Button", 18 | "TailwindCSS Email Components", 19 | "Next.js Email Templates", 20 | "Responsive Email Button", 21 | "Email Template Code", 22 | "React Email Components", 23 | ], 24 | openGraph: { 25 | title: "Button | ReactUI Email", 26 | description: 27 | "Explore the React Email Button component, featuring a clean, responsive design and code preview, built with ReactUI Email.", 28 | url: "https://reactui.email/button", 29 | images: [ 30 | { 31 | url: "https://reactui.email/opengraph-button.jpg", 32 | alt: "React Email Button Component Preview", 33 | width: 1200, 34 | height: 630, 35 | }, 36 | ], 37 | }, 38 | twitter: { 39 | card: "summary_large_image", 40 | title: "Button | ReactUI Email", 41 | description: 42 | "Check out the React Email Button component with preview and code, built with Next.js and TailwindCSS for ReactUI Email.", 43 | images: ["https://reactui.email/opengraph-image.jpg"], 44 | }, 45 | alternates: { 46 | canonical: "https://reactui.email/button", 47 | }, 48 | robots: { 49 | index: true, 50 | follow: true, 51 | }, 52 | }; 53 | 54 | const Button = async () => { 55 | const component = "button"; 56 | 57 | const componentSource = await readBrandSources(component, ["src", "email", "components"]); 58 | 59 | const componentPreview = await Promise.all( 60 | componentSource.map(async (source) => { 61 | const emailModule = await import( 62 | `@/email/components/${component}/${path.basename(source.filePath, ".tsx")}` 63 | ); 64 | const EmailComponent = emailModule.default; 65 | 66 | const emailHtml = await render(); 67 | 68 | const fileName = path 69 | .basename(source.filePath, ".tsx") 70 | .split("-") 71 | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 72 | .join(" "); 73 | 74 | return { 75 | fileName, 76 | content: source.content, 77 | emailHtml, 78 | }; 79 | }), 80 | ); 81 | 82 | return ( 83 |
84 |
85 |
86 | 87 | A simple button component with{" "} 88 | 89 | React Email 90 | {" "} 91 | &&{" "} 92 | 93 | Tailwind CSS 94 | 95 | 96 | 97 | {componentPreview.map((preview) => ( 98 | 106 | ))} 107 |
108 |
109 |
110 | ); 111 | }; 112 | 113 | export default Button; 114 | -------------------------------------------------------------------------------- /src/app/docs/component/confirm-account/page.tsx: -------------------------------------------------------------------------------- 1 | import PageHeader from "@/features/global/page-header"; 2 | import { readBrandSources } from "@/features/global/read-brand-source"; 3 | import { TemplateLayout } from "@/features/global/template-layout"; 4 | import { render } from "@/features/lib/email-to-html"; 5 | import { Metadata } from "next"; 6 | import Link from "next/link"; 7 | import path from "path"; 8 | 9 | export const revalidate = 3600; 10 | 11 | export const metadata: Metadata = { 12 | title: "Confirm Account | ReactUI Email", 13 | description: 14 | "Preview and code for the React Email Confirm Account component, built with Next.js and TailwindCSS for ReactUI Email.", 15 | keywords: [ 16 | "ReactUI Email", 17 | "React Email Confirm Account", 18 | "TailwindCSS Email Components", 19 | "Next.js Email Templates", 20 | "Responsive Email Confirm Account", 21 | "Email Template Code", 22 | "React Email Components", 23 | ], 24 | openGraph: { 25 | title: "Confirm Account | ReactUI Email", 26 | description: 27 | "Explore the React Email Card component, featuring a clean, responsive design and code preview, built with ReactUI Email.", 28 | url: "https://reactui.email/confirm-account", 29 | images: [ 30 | { 31 | url: "https://reactui.email/opengraph-confirm-account.jpg", 32 | alt: "React Email Confirm Account Component Preview", 33 | width: 1200, 34 | height: 630, 35 | }, 36 | ], 37 | }, 38 | twitter: { 39 | card: "summary_large_image", 40 | title: "Confirm Account | ReactUI Email", 41 | description: 42 | "Check out the React Email Confirm Account component with preview and code, built with Next.js and TailwindCSS for ReactUI Email.", 43 | images: ["https://reactui.email/opengraph-image.jpg"], 44 | }, 45 | alternates: { 46 | canonical: "https://reactui.email/confirm-account", 47 | }, 48 | robots: { 49 | index: true, 50 | follow: true, 51 | }, 52 | }; 53 | 54 | const ConfirmAccount = async () => { 55 | const component = "confirm-account"; 56 | 57 | const componentSource = await readBrandSources(component, ["src", "email", "components"]); 58 | 59 | const componentPreview = await Promise.all( 60 | componentSource.map(async (source) => { 61 | const emailModule = await import( 62 | `@/email/components/${component}/${path.basename(source.filePath, ".tsx")}` 63 | ); 64 | const EmailComponent = emailModule.default; 65 | 66 | const emailHtml = await render(); 67 | 68 | const fileName = path 69 | .basename(source.filePath, ".tsx") 70 | .split("-") 71 | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 72 | .join(" "); 73 | 74 | return { 75 | fileName, 76 | content: source.content, 77 | emailHtml, 78 | }; 79 | }), 80 | ); 81 | 82 | return ( 83 |
84 |
85 |
86 | 87 | A simple confirm account component with{" "} 88 | 89 | React Email 90 | {" "} 91 | &&{" "} 92 | 93 | Tailwind CSS 94 | 95 | 96 | 97 | {componentPreview.map((preview) => ( 98 | 106 | ))} 107 |
108 |
109 |
110 | ); 111 | }; 112 | 113 | export default ConfirmAccount; 114 | -------------------------------------------------------------------------------- /src/app/docs/component/grid/page.tsx: -------------------------------------------------------------------------------- 1 | import PageHeader from "@/features/global/page-header"; 2 | import { readBrandSources } from "@/features/global/read-brand-source"; 3 | import { TemplateLayout } from "@/features/global/template-layout"; 4 | import { render } from "@/features/lib/email-to-html"; 5 | import { Metadata } from "next"; 6 | import Link from "next/link"; 7 | import path from "path"; 8 | 9 | export const revalidate = 3600; 10 | 11 | export const metadata: Metadata = { 12 | title: "Grid | ReactUI Email", 13 | description: 14 | "Preview and code for the React Email Grid component, built with Next.js and TailwindCSS for ReactUI Email.", 15 | keywords: [ 16 | "ReactUI Email", 17 | "React Email Grid", 18 | "TailwindCSS Email Components", 19 | "Next.js Email Templates", 20 | "Responsive Email Grid", 21 | "Email Template Code", 22 | "React Email Components", 23 | ], 24 | openGraph: { 25 | title: "Grid | ReactUI Email", 26 | description: 27 | "Explore the React Email Grid component, featuring a clean, responsive design and code preview, built with ReactUI Email.", 28 | url: "https://reactui.email/grid", 29 | images: [ 30 | { 31 | url: "https://reactui.email/opengraph-image.jpg", 32 | alt: "React Email Grid Component Preview", 33 | width: 1200, 34 | height: 630, 35 | }, 36 | ], 37 | }, 38 | twitter: { 39 | card: "summary_large_image", 40 | title: "Grid | ReactUI Email", 41 | description: 42 | "Check out the React Email Grid component with preview and code, built with Next.js and TailwindCSS for ReactUI Email.", 43 | images: ["https://reactui.email/opengraph-image.jpg"], 44 | }, 45 | alternates: { 46 | canonical: "https://reactui.email/grid", 47 | }, 48 | robots: { 49 | index: true, 50 | follow: true, 51 | }, 52 | }; 53 | 54 | const Header = async () => { 55 | const component = "grid"; 56 | 57 | const componentSource = await readBrandSources(component, ["src", "email", "components"]); 58 | 59 | const componentPreview = await Promise.all( 60 | componentSource.map(async (source) => { 61 | const emailModule = await import( 62 | `@/email/components/${component}/${path.basename(source.filePath, ".tsx")}` 63 | ); 64 | const EmailComponent = emailModule.default; 65 | 66 | const emailHtml = await render(); 67 | 68 | const fileName = path 69 | .basename(source.filePath, ".tsx") 70 | .split("-") 71 | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 72 | .join(" "); 73 | 74 | return { 75 | fileName, 76 | content: source.content, 77 | emailHtml, 78 | }; 79 | }), 80 | ); 81 | 82 | return ( 83 |
84 |
85 |
86 | 87 | A simple header component with{" "} 88 | 89 | React Email 90 | {" "} 91 | &&{" "} 92 | 93 | Tailwind CSS 94 | 95 | 96 | 97 | {componentPreview.map((preview) => ( 98 | 107 | ))} 108 |
109 |
110 |
111 | ); 112 | }; 113 | 114 | export default Header; 115 | -------------------------------------------------------------------------------- /src/app/docs/component/header/page.tsx: -------------------------------------------------------------------------------- 1 | import PageHeader from "@/features/global/page-header"; 2 | import { readBrandSources } from "@/features/global/read-brand-source"; 3 | import { TemplateLayout } from "@/features/global/template-layout"; 4 | import { render } from "@/features/lib/email-to-html"; 5 | import { Metadata } from "next"; 6 | import Link from "next/link"; 7 | import path from "path"; 8 | 9 | export const revalidate = 3600; 10 | 11 | export const metadata: Metadata = { 12 | title: "Header | ReactUI Email", 13 | description: 14 | "Preview and code for the React Email Header component, built with Next.js and TailwindCSS for ReactUI Email.", 15 | keywords: [ 16 | "ReactUI Email", 17 | "React Email Header", 18 | "TailwindCSS Email Components", 19 | "Next.js Email Templates", 20 | "Responsive Email Header", 21 | "Email Template Code", 22 | "React Email Components", 23 | ], 24 | openGraph: { 25 | title: "Header | ReactUI Email", 26 | description: 27 | "Explore the React Email Header component, featuring a clean, responsive design and code preview, built with ReactUI Email.", 28 | url: "https://reactui.email/header", 29 | images: [ 30 | { 31 | url: "https://reactui.email/opengraph-header.jpg", 32 | alt: "React Email Header Component Preview", 33 | width: 1200, 34 | height: 630, 35 | }, 36 | ], 37 | }, 38 | twitter: { 39 | card: "summary_large_image", 40 | title: "Header | ReactUI Email", 41 | description: 42 | "Check out the React Email Header component with preview and code, built with Next.js and TailwindCSS for ReactUI Email.", 43 | images: ["https://reactui.email/opengraph-image.jpg"], 44 | }, 45 | alternates: { 46 | canonical: "https://reactui.email/header", 47 | }, 48 | robots: { 49 | index: true, 50 | follow: true, 51 | }, 52 | }; 53 | 54 | const Header = async () => { 55 | const component = "header"; 56 | 57 | const componentSource = await readBrandSources(component, ["src", "email", "components"]); 58 | 59 | const componentPreview = await Promise.all( 60 | componentSource.map(async (source) => { 61 | const emailModule = await import( 62 | `@/email/components/${component}/${path.basename(source.filePath, ".tsx")}` 63 | ); 64 | const EmailComponent = emailModule.default; 65 | 66 | const emailHtml = await render(); 67 | 68 | const fileName = path 69 | .basename(source.filePath, ".tsx") 70 | .split("-") 71 | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 72 | .join(" "); 73 | 74 | return { 75 | fileName, 76 | content: source.content, 77 | emailHtml, 78 | }; 79 | }), 80 | ); 81 | 82 | return ( 83 |
84 |
85 |
86 | 87 | A simple header component with{" "} 88 | 89 | React Email 90 | {" "} 91 | &&{" "} 92 | 93 | Tailwind CSS 94 | 95 | 96 | 97 | {componentPreview.map((preview) => ( 98 | 106 | ))} 107 |
108 |
109 |
110 | ); 111 | }; 112 | 113 | export default Header; 114 | -------------------------------------------------------------------------------- /src/app/dub/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/app/dub/page.tsx: -------------------------------------------------------------------------------- 1 | import PageHeader from "@/features/global/page-header"; 2 | import { readBrandSources } from "@/features/global/read-brand-source"; 3 | import { TemplateLayout } from "@/features/global/template-layout"; 4 | import { render } from "@/features/lib/email-to-html"; 5 | import { t } from "@/features/lib/utils"; 6 | import { Metadata } from "next"; 7 | import Link from "next/link"; 8 | import path from "path"; 9 | 10 | export const revalidate = 3600; 11 | 12 | export const metadata: Metadata = { 13 | title: "Dub | ReactUI Email", 14 | description: 15 | "Preview and code for the Dub Welcome Email template, built with Next.js and TailwindCSS for ReactUI Email.", 16 | keywords: [ 17 | "ReactUI Email", 18 | "Dub Email Template", 19 | "TailwindCSS Email", 20 | "Next.js Email Templates", 21 | "Responsive Email Design", 22 | "Email Template Code", 23 | "React Email Components", 24 | "Dub Welcome Email", 25 | "Dub React Components", 26 | ], 27 | openGraph: { 28 | title: "Dub | ReactUI Email", 29 | description: 30 | "Explore the Dub Welcome Email template, featuring a clean, responsive design and code preview, built with ReactUI Email.", 31 | url: "https://reactui.email", 32 | images: [ 33 | { 34 | url: "https://reactui.email/opengraph-image.jpg", 35 | alt: "Dub Welcome Email Template Preview", 36 | width: 1200, 37 | height: 630, 38 | }, 39 | ], 40 | }, 41 | twitter: { 42 | card: "summary_large_image", 43 | title: "Dub | ReactUI Email", 44 | description: 45 | "Check out the Dub Welcome Email template with preview and code, built with Next.js and TailwindCSS for ReactUI Email.", 46 | images: ["https://reactui.email/opengraph-image.jpg"], 47 | }, 48 | alternates: { 49 | canonical: "https://reactui.email/dub", 50 | }, 51 | robots: { 52 | index: true, 53 | follow: true, 54 | }, 55 | }; 56 | 57 | const Page = async () => { 58 | const brand = "dub"; 59 | 60 | const emailSource = await readBrandSources(brand); 61 | 62 | const emailPreviews = await Promise.all( 63 | emailSource.map(async (source) => { 64 | const emailModule = await import( 65 | `@/email/${brand}/${path.basename(source.filePath, ".tsx")}` 66 | ); 67 | const EmailComponent = emailModule.default; 68 | 69 | const emailHtml = await render(); 70 | 71 | const fileNameParts = path 72 | .basename(source.filePath, ".tsx") 73 | .split("--") 74 | .reverse() 75 | .map((part, index) => { 76 | if (index === 1) { 77 | return part.replace("+", " of "); 78 | } 79 | 80 | if (index === 0) { 81 | return part 82 | .split("-") 83 | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 84 | .join(" "); 85 | } 86 | 87 | return part; 88 | }); 89 | 90 | const shouldAddParentheses = /\d+\+\d+--/.test(path.basename(source.filePath)); 91 | 92 | const fileName = fileNameParts.join(" - (") + (shouldAddParentheses ? ")" : ""); 93 | 94 | return { 95 | fileName, 96 | content: source.content, 97 | emailHtml, 98 | }; 99 | }), 100 | ); 101 | 102 | return ( 103 |
104 |
105 |
106 | 107 | 108 | 109 | Dub.co 110 | {" "} 111 | 112 | is an open-source link management tool for modern marketing teams to create, share, and 113 | track short links. 114 | 115 | 116 | {emailPreviews.map((preview) => ( 117 | 125 | ))} 126 |
127 |
128 |
129 | ); 130 | }; 131 | 132 | export default Page; 133 | -------------------------------------------------------------------------------- /src/app/framer/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/app/icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Toaster as Sonner } from "@/components/ui/sonner"; 2 | import { Toaster } from "@/components/ui/toaster"; 3 | import Header from "@/features/global/header"; 4 | import Illustration from "@/features/global/illustration"; 5 | import { ThemeProvider } from "@/features/global/theme-provider"; 6 | import { cn } from "@/features/lib/utils"; 7 | import { PostHogProvider } from "@/features/providers/ph-provider"; 8 | import type { Metadata, Viewport } from "next"; 9 | import { Inter as FontSans } from "next/font/google"; 10 | import "./globals.css"; 11 | 12 | const fontSans = FontSans({ 13 | subsets: ["latin"], 14 | variable: "--font-sans", 15 | }); 16 | 17 | export const viewport: Viewport = { 18 | initialScale: 1, 19 | width: "device-width", 20 | maximumScale: 1, 21 | viewportFit: "cover", 22 | }; 23 | 24 | export const metadata: Metadata = { 25 | metadataBase: new URL("https://reactui.email"), 26 | title: "ReactUI Email - Email Templates for React", 27 | description: 28 | "A library of customizable React email components built with Tailwind CSS. Ready-to-use email templates, designed to be mobile-friendly and easily adaptable for your projects.", 29 | keywords: [ 30 | "React", 31 | "email templates", 32 | "email components", 33 | "Tailwind CSS", 34 | "open-source", 35 | "React UI components", 36 | "React UI email components", 37 | "React UI email templates", 38 | ], 39 | authors: [{ name: "Jay Suthar", url: "https://peerlist.io/sutharjay" }], 40 | }; 41 | 42 | export default function RootLayout({ 43 | children, 44 | }: Readonly<{ 45 | children: React.ReactNode; 46 | }>) { 47 | return ( 48 | 49 | 50 | 51 | 57 |
58 |
59 | 60 | {children} 61 |
62 | 63 | 64 |
65 |
66 | 67 | 68 | ); 69 | } 70 | -------------------------------------------------------------------------------- /src/app/myna-ui/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/app/myna-ui/layout.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useTheme } from "next-themes"; 4 | import React, { useEffect } from "react"; 5 | 6 | type Props = { 7 | children: React.ReactNode; 8 | }; 9 | 10 | const MynaUILayout = (props: Props) => { 11 | const { setTheme } = useTheme(); 12 | 13 | useEffect(() => { 14 | setTheme("light"); 15 | }, [setTheme]); 16 | 17 | return ( 18 | <> 19 |
{props.children}
20 | 21 | ); 22 | }; 23 | 24 | export default MynaUILayout; 25 | -------------------------------------------------------------------------------- /src/app/myna-ui/page.tsx: -------------------------------------------------------------------------------- 1 | import PageHeader from "@/features/global/page-header"; 2 | import { readBrandSources } from "@/features/global/read-brand-source"; 3 | import { TemplateLayout } from "@/features/global/template-layout"; 4 | import { render } from "@/features/lib/email-to-html"; 5 | import { Metadata } from "next"; 6 | import Link from "next/link"; 7 | import path from "path"; 8 | 9 | export const revalidate = 3600; 10 | 11 | export const metadata: Metadata = { 12 | title: "Myna UI | ReactUI Email", 13 | description: 14 | "Preview and code for the Myna UI Email templates, built with Next.js and TailwindCSS for ReactUI Email.", 15 | keywords: [ 16 | "ReactUI Email", 17 | "Myna UI Email Template", 18 | "TailwindCSS Email", 19 | "Next.js Email Templates", 20 | "Responsive Email Design", 21 | "Email Template Code", 22 | "React Email Components", 23 | "Myna UI Welcome Email", 24 | "Myna UI React Components", 25 | ], 26 | openGraph: { 27 | title: "Myna UI | ReactUI Email", 28 | description: 29 | "Explore the Myna UI Email templates, featuring a clean, responsive design and code preview, built with ReactUI Email.", 30 | url: "https://reactui.email", 31 | images: [ 32 | { 33 | url: "https://reactui.email/opengraph-image.jpg", 34 | alt: "Myna UI Email Template Preview", 35 | width: 1200, 36 | height: 630, 37 | }, 38 | ], 39 | }, 40 | twitter: { 41 | card: "summary_large_image", 42 | title: "Myna UI | ReactUI Email", 43 | description: 44 | "Check out the Myna UI Email templates with preview and code, built with Next.js and TailwindCSS for ReactUI Email.", 45 | images: ["https://reactui.email/opengraph-image.jpg"], 46 | }, 47 | alternates: { 48 | canonical: "https://reactui.email/myna-ui", 49 | }, 50 | robots: { 51 | index: true, 52 | follow: true, 53 | }, 54 | }; 55 | 56 | const Page = async () => { 57 | const brand = "myna-ui"; 58 | 59 | const emailSource = await readBrandSources(brand); 60 | 61 | const emailPreviews = await Promise.all( 62 | emailSource.map(async (source) => { 63 | const emailModule = await import( 64 | `@/email/${brand}/${path.basename(source.filePath, ".tsx")}` 65 | ); 66 | const EmailComponent = emailModule.default; 67 | 68 | const emailHtml = await render(); 69 | 70 | const fileName = path 71 | .basename(source.filePath, ".tsx") 72 | .replace(/^\d+-/, "") 73 | .split("-") 74 | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 75 | .join(" "); 76 | 77 | return { 78 | fileName, 79 | content: source.content, 80 | emailHtml, 81 | }; 82 | }), 83 | ); 84 | 85 | return ( 86 |
87 |
88 |
89 | 90 | 91 | 92 | Myna UI 93 | {" "} 94 | 95 | is a modern, accessible, and customizable UI library built with TailwindCSS. 96 | 97 | 98 | {emailPreviews.map((preview) => ( 99 | 107 | ))} 108 |
109 |
110 |
111 | ); 112 | }; 113 | 114 | export default Page; 115 | -------------------------------------------------------------------------------- /src/app/notion/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /src/app/notion/page.tsx: -------------------------------------------------------------------------------- 1 | import PageHeader from "@/features/global/page-header"; 2 | import { readBrandSources } from "@/features/global/read-brand-source"; 3 | import { TemplateLayout } from "@/features/global/template-layout"; 4 | import { render } from "@/features/lib/email-to-html"; 5 | import { t } from "@/features/lib/utils"; 6 | import { Metadata } from "next"; 7 | import Link from "next/link"; 8 | import path from "path"; 9 | 10 | export const revalidate = 3600; 11 | 12 | export const metadata: Metadata = { 13 | title: "Notion Email Templates | ReactUI Email", 14 | description: 15 | "Collection of Notion-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 16 | keywords: [ 17 | "ReactUI Email", 18 | "Notion Email Templates", 19 | "TailwindCSS Email", 20 | "Next.js Email Templates", 21 | "Responsive Email Design", 22 | "Email Template Code", 23 | "React Email Components", 24 | "Notion Email Design", 25 | "Email Development", 26 | "Email Marketing Templates", 27 | ], 28 | openGraph: { 29 | title: "Notion Email Templates | ReactUI Email", 30 | description: 31 | "Collection of Notion-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 32 | url: "https://reactui.email/notion", 33 | images: [ 34 | { 35 | url: "https://reactui.email/opengraph-image.jpg", 36 | alt: "Notion Email Templates Preview", 37 | width: 1200, 38 | height: 630, 39 | }, 40 | ], 41 | }, 42 | twitter: { 43 | card: "summary_large_image", 44 | title: "Notion Email Templates | ReactUI Email", 45 | description: 46 | "Collection of Notion-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 47 | images: ["https://reactui.email/opengraph-image.jpg"], 48 | }, 49 | alternates: { 50 | canonical: "https://reactui.email/notion", 51 | }, 52 | robots: { 53 | index: true, 54 | follow: true, 55 | }, 56 | }; 57 | 58 | const Page = async () => { 59 | const brand = "notion"; 60 | 61 | const emailSource = await readBrandSources(brand); 62 | 63 | const emailPreviews = await Promise.all( 64 | emailSource.map(async (source) => { 65 | const emailModule = await import( 66 | `@/email/${brand}/${path.basename(source.filePath, ".tsx")}` 67 | ); 68 | const EmailComponent = emailModule.default; 69 | 70 | const emailHtml = await render(); 71 | 72 | const fileName = path 73 | .basename(source.filePath, ".tsx") 74 | .split("-") 75 | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 76 | .join(" "); 77 | 78 | return { 79 | fileName, 80 | content: source.content, 81 | emailHtml, 82 | }; 83 | }), 84 | ); 85 | 86 | return ( 87 |
88 |
89 |
90 | 91 | 92 | 93 | Notion 94 | 95 | {" "} 96 | is an all-in-one workspace for notes, project management, documents, and collaboration. 97 | 98 | 99 | {emailPreviews.map((preview) => ( 100 | 108 | ))} 109 |
110 |
111 |
112 | ); 113 | }; 114 | 115 | export default Page; 116 | -------------------------------------------------------------------------------- /src/app/opengraph-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sutharjay1/reactui-email/5ed0acd7f68b910c848656b8c9fdb6570c436325/src/app/opengraph-image.jpg -------------------------------------------------------------------------------- /src/app/peerlist/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/app/peerlist/page.tsx: -------------------------------------------------------------------------------- 1 | import PageHeader from "@/features/global/page-header"; 2 | import { readBrandSources } from "@/features/global/read-brand-source"; 3 | import { TemplateLayout } from "@/features/global/template-layout"; 4 | import { render } from "@/features/lib/email-to-html"; 5 | import { t } from "@/features/lib/utils"; 6 | import { Metadata } from "next"; 7 | import Link from "next/link"; 8 | import path from "path"; 9 | 10 | export const revalidate = 3600; 11 | 12 | export const metadata: Metadata = { 13 | title: "Peerlist Email Templates | ReactUI Email", 14 | description: 15 | "Collection of Peerlist-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 16 | keywords: [ 17 | "ReactUI Email", 18 | "Peerlist Email Templates", 19 | "TailwindCSS Email", 20 | "Next.js Email Templates", 21 | "Responsive Email Design", 22 | "Email Template Code", 23 | "React Email Components", 24 | "Peerlist Email Design", 25 | "Email Development", 26 | "Email Marketing Templates", 27 | ], 28 | openGraph: { 29 | title: "Peerlist Email Templates | ReactUI Email", 30 | description: 31 | "Collection of Peerlist-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 32 | url: "https://reactui.email/peerlist", 33 | images: [ 34 | { 35 | url: "https://reactui.email/opengraph-image.jpg", 36 | alt: "Peerlist Email Templates Preview", 37 | width: 1200, 38 | height: 630, 39 | }, 40 | ], 41 | }, 42 | twitter: { 43 | card: "summary_large_image", 44 | title: "Peerlist Email Templates | ReactUI Email", 45 | description: 46 | "Collection of Peerlist-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 47 | images: ["https://reactui.email/opengraph-image.jpg"], 48 | }, 49 | alternates: { 50 | canonical: "https://reactui.email/peerlist", 51 | }, 52 | robots: { 53 | index: true, 54 | follow: true, 55 | }, 56 | }; 57 | 58 | const Page = async () => { 59 | const brand = "peerlist"; 60 | 61 | const emailSource = await readBrandSources(brand); 62 | 63 | const emailPreviews = await Promise.all( 64 | emailSource.map(async (source) => { 65 | const emailModule = await import( 66 | `@/email/${brand}/${path.basename(source.filePath, ".tsx")}` 67 | ); 68 | const EmailComponent = emailModule.default; 69 | 70 | const emailHtml = await render(); 71 | 72 | const fileName = path 73 | .basename(source.filePath, ".tsx") 74 | .split("-") 75 | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 76 | .join(" "); 77 | 78 | return { 79 | fileName, 80 | content: source.content, 81 | emailHtml, 82 | }; 83 | }), 84 | ); 85 | 86 | return ( 87 |
88 |
89 |
90 | 91 | 92 | 93 | Peerlist 94 | {" "} 95 | 96 | is a professional network for tech people to showcase their work, connect with peers, 97 | and find their next opportunity. 98 | 99 | 100 | {emailPreviews.map((preview) => ( 101 | 109 | ))} 110 |
111 |
112 |
113 | ); 114 | }; 115 | 116 | export default Page; 117 | -------------------------------------------------------------------------------- /src/app/softgen/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /src/app/softgen/page.tsx: -------------------------------------------------------------------------------- 1 | import PageHeader from "@/features/global/page-header"; 2 | import { readBrandSources } from "@/features/global/read-brand-source"; 3 | import { TemplateLayout } from "@/features/global/template-layout"; 4 | import { render } from "@/features/lib/email-to-html"; 5 | import { t } from "@/features/lib/utils"; 6 | import { Metadata } from "next"; 7 | import Link from "next/link"; 8 | import path from "path"; 9 | 10 | export const revalidate = 3600; 11 | 12 | export const metadata: Metadata = { 13 | title: "SoftGen | ReactUI Email", 14 | description: 15 | "Preview and code for the SoftGen Email templates, built with Next.js and TailwindCSS for ReactUI Email.", 16 | keywords: [ 17 | "ReactUI Email", 18 | "SoftGen Email Template", 19 | "TailwindCSS Email", 20 | "Next.js Email Templates", 21 | "Responsive Email Design", 22 | "Email Template Code", 23 | "React Email Components", 24 | "SoftGen Welcome Email", 25 | "SoftGen React Components", 26 | ], 27 | openGraph: { 28 | title: "SoftGen | ReactUI Email", 29 | description: 30 | "Explore the SoftGen Email templates, featuring a clean, responsive design and code preview, built with ReactUI Email.", 31 | url: "https://reactui.email", 32 | images: [ 33 | { 34 | url: "https://reactui.email/opengraph-image.jpg", 35 | alt: "SoftGen Email Template Preview", 36 | width: 1200, 37 | height: 630, 38 | }, 39 | ], 40 | }, 41 | twitter: { 42 | card: "summary_large_image", 43 | title: "SoftGen | ReactUI Email", 44 | description: 45 | "Check out the SoftGen Email templates with preview and code, built with Next.js and TailwindCSS for ReactUI Email.", 46 | images: ["https://reactui.email/opengraph-image.jpg"], 47 | }, 48 | alternates: { 49 | canonical: "https://reactui.email/softgen", 50 | }, 51 | robots: { 52 | index: true, 53 | follow: true, 54 | }, 55 | }; 56 | 57 | const Page = async () => { 58 | const brand = "softgen"; 59 | 60 | const emailSource = await readBrandSources(brand); 61 | 62 | const emailPreviews = await Promise.all( 63 | emailSource.map(async (source) => { 64 | const emailModule = await import( 65 | `@/email/${brand}/${path.basename(source.filePath, ".tsx")}` 66 | ); 67 | const EmailComponent = emailModule.default; 68 | 69 | const emailHtml = await render(); 70 | 71 | const fileName = path 72 | .basename(source.filePath, ".tsx") 73 | .replace(/^\d+-/, "") 74 | .split("-") 75 | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 76 | .join(" "); 77 | 78 | return { 79 | fileName, 80 | content: source.content, 81 | emailHtml, 82 | }; 83 | }), 84 | ); 85 | 86 | return ( 87 |
88 |
89 |
90 | 91 | 92 | 93 | Softgen 94 | {" "} 95 | 96 | is an AI-powered platform that builds full-stack web apps from your instructions. No 97 | coding needed. 98 | 99 | 100 | {emailPreviews.map((preview) => ( 101 | 109 | ))} 110 |
111 |
112 |
113 | ); 114 | }; 115 | 116 | export default Page; 117 | -------------------------------------------------------------------------------- /src/app/substack/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/app/substack/page.tsx: -------------------------------------------------------------------------------- 1 | import PageHeader from "@/features/global/page-header"; 2 | import { readBrandSources } from "@/features/global/read-brand-source"; 3 | import { TemplateLayout } from "@/features/global/template-layout"; 4 | import { render } from "@/features/lib/email-to-html"; 5 | import { t } from "@/features/lib/utils"; 6 | import { Metadata } from "next"; 7 | import Link from "next/link"; 8 | import path from "path"; 9 | 10 | export const revalidate = 3600; 11 | 12 | export const metadata: Metadata = { 13 | title: "Substack Email Templates | ReactUI Email", 14 | description: 15 | "Collection of Substack-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 16 | keywords: [ 17 | "ReactUI Email", 18 | "Substack Email Templates", 19 | "TailwindCSS Email", 20 | "Next.js Email Templates", 21 | "Responsive Email Design", 22 | "Email Template Code", 23 | "React Email Components", 24 | "Substack Email Design", 25 | "Email Development", 26 | "Email Marketing Templates", 27 | ], 28 | openGraph: { 29 | title: "Substack Email Templates | ReactUI Email", 30 | description: 31 | "Collection of Substack-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 32 | url: "https://reactui.email/substack", 33 | images: [ 34 | { 35 | url: "https://reactui.email/opengraph-image.jpg", 36 | alt: "Substack Email Templates Preview", 37 | width: 1200, 38 | height: 630, 39 | }, 40 | ], 41 | }, 42 | twitter: { 43 | card: "summary_large_image", 44 | title: "Substack Email Templates | ReactUI Email", 45 | description: 46 | "Collection of Substack-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 47 | images: ["https://reactui.email/opengraph-image.jpg"], 48 | }, 49 | alternates: { 50 | canonical: "https://reactui.email/substack", 51 | }, 52 | robots: { 53 | index: true, 54 | follow: true, 55 | }, 56 | }; 57 | 58 | const Page = async () => { 59 | const brand = "substack"; 60 | 61 | const emailSource = await readBrandSources(brand); 62 | 63 | const emailPreviews = await Promise.all( 64 | emailSource.map(async (source) => { 65 | const emailModule = await import( 66 | `@/email/${brand}/${path.basename(source.filePath, ".tsx")}` 67 | ); 68 | const EmailComponent = emailModule.default; 69 | 70 | const emailHtml = await render(); 71 | 72 | const fileName = path 73 | .basename(source.filePath, ".tsx") 74 | .split("-") 75 | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 76 | .join(" "); 77 | 78 | return { 79 | fileName, 80 | content: source.content, 81 | emailHtml, 82 | }; 83 | }), 84 | ); 85 | 86 | return ( 87 |
88 |
89 |
90 | 91 | 92 | 93 | Substack 94 | {" "} 95 | 96 | is a platform for writers and creators to publish newsletters, podcasts and build media 97 | businesses. 98 | 99 | 100 | {emailPreviews.map((preview) => ( 101 | 109 | ))} 110 |
111 |
112 |
113 | ); 114 | }; 115 | 116 | export default Page; 117 | -------------------------------------------------------------------------------- /src/app/supabase/icon.svg: -------------------------------------------------------------------------------- 1 | 3 | 6 | 9 | 12 | 13 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/app/supabase/page.tsx: -------------------------------------------------------------------------------- 1 | import PageHeader from "@/features/global/page-header"; 2 | import { readBrandSources } from "@/features/global/read-brand-source"; 3 | import { TemplateLayout } from "@/features/global/template-layout"; 4 | import { render } from "@/features/lib/email-to-html"; 5 | import { t } from "@/features/lib/utils"; 6 | import { Metadata } from "next"; 7 | import Link from "next/link"; 8 | import path from "path"; 9 | 10 | export const revalidate = 3600; 11 | 12 | export const metadata: Metadata = { 13 | title: "Supabase Email Templates | ReactUI Email", 14 | description: 15 | "Collection of Supabase-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 16 | keywords: [ 17 | "ReactUI Email", 18 | "Supabase Email Templates", 19 | "TailwindCSS Email", 20 | "Next.js Email Templates", 21 | "Responsive Email Design", 22 | "Email Template Code", 23 | "React Email Components", 24 | "Supabase Email Design", 25 | "Email Development", 26 | "Email Marketing Templates", 27 | ], 28 | openGraph: { 29 | title: "Supabase Email Templates | ReactUI Email", 30 | description: 31 | "Collection of Supabase-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 32 | url: "https://reactui.email/supabase", 33 | images: [ 34 | { 35 | url: "https://reactui.email/opengraph-image.jpg", 36 | alt: "Supabase Email Templates Preview", 37 | width: 1200, 38 | height: 630, 39 | }, 40 | ], 41 | }, 42 | twitter: { 43 | card: "summary_large_image", 44 | title: "Supabase Email Templates | ReactUI Email", 45 | description: 46 | "Collection of Supabase-style email templates built with React, Next.js and TailwindCSS. View previews and get the code for responsive, customizable email designs.", 47 | images: ["https://reactui.email/opengraph-image.jpg"], 48 | }, 49 | alternates: { 50 | canonical: "https://reactui.email/supabase", 51 | }, 52 | robots: { 53 | index: true, 54 | follow: true, 55 | }, 56 | }; 57 | 58 | const Page = async () => { 59 | const brand = "supabase"; 60 | 61 | const emailSource = await readBrandSources(brand); 62 | 63 | const emailPreviews = await Promise.all( 64 | emailSource.map(async (source) => { 65 | const emailModule = await import( 66 | `@/email/${brand}/${path.basename(source.filePath, ".tsx")}` 67 | ); 68 | const EmailComponent = emailModule.default; 69 | 70 | const emailHtml = await render(); 71 | 72 | const fileName = path 73 | .basename(source.filePath, ".tsx") 74 | .split("-") 75 | .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) 76 | .join(" "); 77 | 78 | return { 79 | fileName, 80 | content: source.content, 81 | emailHtml, 82 | }; 83 | }), 84 | ); 85 | 86 | return ( 87 |
88 |
89 |
90 | 91 | 92 | 93 | Supabase 94 | {" "} 95 | 96 | is an open source Firebase alternative providing all the backend features you need to 97 | build a product. 98 | 99 | 100 | {emailPreviews.map((preview) => ( 101 | 109 | ))} 110 |
111 |
112 |
113 | ); 114 | }; 115 | 116 | export default Page; 117 | -------------------------------------------------------------------------------- /src/app/twitter-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sutharjay1/reactui-email/5ed0acd7f68b910c848656b8c9fdb6570c436325/src/app/twitter-image.jpg -------------------------------------------------------------------------------- /src/components/ui/accordion.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as AccordionPrimitive from "@radix-ui/react-accordion"; 4 | import { ChevronDown } from "lucide-react"; 5 | import * as React from "react"; 6 | 7 | import { cn } from "@/features/lib/utils"; 8 | 9 | const Accordion = AccordionPrimitive.Root; 10 | 11 | const AccordionItem = React.forwardRef< 12 | React.ElementRef, 13 | React.ComponentPropsWithoutRef 14 | >(({ className, ...props }, ref) => ( 15 | 20 | )); 21 | AccordionItem.displayName = "AccordionItem"; 22 | 23 | const AccordionTrigger = React.forwardRef< 24 | React.ElementRef, 25 | React.ComponentPropsWithoutRef 26 | >(({ className, children, ...props }, ref) => ( 27 | 28 | svg]:rotate-180", 32 | className, 33 | )} 34 | {...props} 35 | > 36 | {children} 37 | 44 | 45 | )); 46 | AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName; 47 | 48 | const AccordionContent = React.forwardRef< 49 | React.ElementRef, 50 | React.ComponentPropsWithoutRef 51 | >(({ className, children, ...props }, ref) => ( 52 | 57 |
{children}
58 |
59 | )); 60 | 61 | AccordionContent.displayName = AccordionPrimitive.Content.displayName; 62 | 63 | export { Accordion, AccordionContent, AccordionItem, AccordionTrigger }; 64 | -------------------------------------------------------------------------------- /src/components/ui/avatar.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as AvatarPrimitive from "@radix-ui/react-avatar"; 4 | import * as React from "react"; 5 | 6 | import { cn } from "@/features/lib/utils"; 7 | 8 | const Avatar = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, ...props }, ref) => ( 12 | 17 | )); 18 | Avatar.displayName = AvatarPrimitive.Root.displayName; 19 | 20 | const AvatarImage = React.forwardRef< 21 | React.ElementRef, 22 | React.ComponentPropsWithoutRef 23 | >(({ className, ...props }, ref) => ( 24 | 29 | )); 30 | AvatarImage.displayName = AvatarPrimitive.Image.displayName; 31 | 32 | const AvatarFallback = React.forwardRef< 33 | React.ElementRef, 34 | React.ComponentPropsWithoutRef 35 | >(({ className, ...props }, ref) => ( 36 | 44 | )); 45 | AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName; 46 | 47 | export { Avatar, AvatarFallback, AvatarImage }; 48 | -------------------------------------------------------------------------------- /src/components/ui/badge.tsx: -------------------------------------------------------------------------------- 1 | import { cva, type VariantProps } from "class-variance-authority"; 2 | import * as React from "react"; 3 | 4 | import { cn } from "@/features/lib/utils"; 5 | 6 | const badgeVariants = cva( 7 | "inline-flex items-center justify-center rounded-full border px-1.5 text-xs font-medium leading-normal transition-colors outline-offset-2 focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring/70", 8 | { 9 | variants: { 10 | variant: { 11 | default: "border-transparent bg-primary text-primary-foreground", 12 | secondary: "border-transparent bg-secondary text-secondary-foreground", 13 | destructive: "border-transparent bg-destructive text-destructive-foreground", 14 | outline: "text-foreground", 15 | }, 16 | }, 17 | defaultVariants: { 18 | variant: "default", 19 | }, 20 | }, 21 | ); 22 | 23 | export interface BadgeProps 24 | extends React.HTMLAttributes, 25 | VariantProps {} 26 | 27 | function Badge({ className, variant, ...props }: BadgeProps) { 28 | return
; 29 | } 30 | 31 | export { Badge, badgeVariants }; 32 | -------------------------------------------------------------------------------- /src/components/ui/breadcrumb.tsx: -------------------------------------------------------------------------------- 1 | import { Slot } from "@radix-ui/react-slot"; 2 | import { ChevronRight, MoreHorizontal } from "lucide-react"; 3 | import * as React from "react"; 4 | 5 | import { cn } from "@/features/lib/utils"; 6 | 7 | const Breadcrumb = React.forwardRef< 8 | HTMLElement, 9 | React.ComponentPropsWithoutRef<"nav"> & { 10 | separator?: React.ReactNode; 11 | } 12 | >(({ ...props }, ref) =>