The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .changeset
    ├── README.md
    └── config.json
├── .github
    ├── CODEOWNERS
    ├── DISCUSSION_TEMPLATE
    │   ├── help.yml
    │   └── ideas.yml
    ├── ISSUE_TEMPLATE
    │   ├── 1.bug_report.yml
    │   └── config.yml
    ├── pull_request_template.md
    └── workflows
    │   ├── lint.yml
    │   ├── pin-dependencies-check.yml
    │   ├── preview-release.yml
    │   ├── pull-request-title-check.yml
    │   ├── release-canary.yml
    │   ├── release.yml
    │   └── tests.yml
├── .gitignore
├── .npmrc
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── SECURITY.md
├── apps
    ├── demo
    │   ├── .gitignore
    │   ├── emails
    │   │   ├── magic-links
    │   │   │   ├── aws-verify-email.tsx
    │   │   │   ├── linear-login-code.tsx
    │   │   │   ├── notion-magic-link.tsx
    │   │   │   ├── plaid-verify-identity.tsx
    │   │   │   ├── raycast-magic-link.tsx
    │   │   │   └── slack-confirm.tsx
    │   │   ├── newsletters
    │   │   │   ├── codepen-challengers.tsx
    │   │   │   ├── google-play-policy-update.tsx
    │   │   │   └── stack-overflow-tips.tsx
    │   │   ├── notifications
    │   │   │   ├── github-access-token.tsx
    │   │   │   ├── papermark-year-in-review.tsx
    │   │   │   ├── vercel-invite-user.tsx
    │   │   │   └── yelp-recent-login.tsx
    │   │   ├── receipts
    │   │   │   ├── apple-receipt.tsx
    │   │   │   └── nike-receipt.tsx
    │   │   ├── reset-password
    │   │   │   ├── dropbox-reset-password.tsx
    │   │   │   └── twitch-reset-password.tsx
    │   │   ├── reviews
    │   │   │   ├── airbnb-review.tsx
    │   │   │   └── amazon-review.tsx
    │   │   ├── static
    │   │   │   ├── airbnb-logo.png
    │   │   │   ├── airbnb-review-user.jpg
    │   │   │   ├── amazon-book.jpg
    │   │   │   ├── amazon-facebook.jpg
    │   │   │   ├── amazon-instagram.jpg
    │   │   │   ├── amazon-logo.png
    │   │   │   ├── amazon-prime-logo.png
    │   │   │   ├── amazon-rating.gif
    │   │   │   ├── amazon-twitter.jpg
    │   │   │   ├── apple-card-icon.png
    │   │   │   ├── apple-hbo-max-icon.jpeg
    │   │   │   ├── apple-logo.png
    │   │   │   ├── apple-wallet.png
    │   │   │   ├── aws-logo.png
    │   │   │   ├── codepen-challengers.png
    │   │   │   ├── codepen-cube.png
    │   │   │   ├── codepen-pro.png
    │   │   │   ├── dropbox-logo.png
    │   │   │   ├── github.png
    │   │   │   ├── google-play-academy.png
    │   │   │   ├── google-play-chat.png
    │   │   │   ├── google-play-footer.png
    │   │   │   ├── google-play-header.png
    │   │   │   ├── google-play-icon.png
    │   │   │   ├── google-play-logo.png
    │   │   │   ├── google-play-pl.png
    │   │   │   ├── google-play.png
    │   │   │   ├── koala-logo.png
    │   │   │   ├── linear-logo.png
    │   │   │   ├── netlify-logo.png
    │   │   │   ├── nike-logo.png
    │   │   │   ├── nike-phone.png
    │   │   │   ├── nike-product.png
    │   │   │   ├── nike-recomendation-1.png
    │   │   │   ├── nike-recomendation-2.png
    │   │   │   ├── nike-recomendation-3.png
    │   │   │   ├── nike-recomendation-4.png
    │   │   │   ├── notion-logo.png
    │   │   │   ├── plaid-logo.png
    │   │   │   ├── raycast-bg.png
    │   │   │   ├── raycast-logo.png
    │   │   │   ├── slack-facebook.png
    │   │   │   ├── slack-linkedin.png
    │   │   │   ├── slack-logo.png
    │   │   │   ├── slack-twitter.png
    │   │   │   ├── stack-overflow-header.png
    │   │   │   ├── stack-overflow-logo-sm.png
    │   │   │   ├── stack-overflow-logo.png
    │   │   │   ├── stripe-logo.png
    │   │   │   ├── twitch-icon-facebook.png
    │   │   │   ├── twitch-icon-twitter.png
    │   │   │   ├── twitch-logo.png
    │   │   │   ├── vercel-arrow.png
    │   │   │   ├── vercel-logo.png
    │   │   │   ├── vercel-team.png
    │   │   │   ├── vercel-user.png
    │   │   │   ├── yelp-footer.png
    │   │   │   ├── yelp-header.png
    │   │   │   └── yelp-logo.png
    │   │   └── welcome
    │   │   │   ├── koala-welcome.tsx
    │   │   │   ├── netlify-welcome.tsx
    │   │   │   └── stripe-welcome.tsx
    │   ├── license.md
    │   └── package.json
    ├── docs
    │   ├── changelog.mdx
    │   ├── cli.mdx
    │   ├── components
    │   │   ├── button.mdx
    │   │   ├── code-block.mdx
    │   │   ├── code-inline.mdx
    │   │   ├── column.mdx
    │   │   ├── container.mdx
    │   │   ├── font.mdx
    │   │   ├── head.mdx
    │   │   ├── heading.mdx
    │   │   ├── hr.mdx
    │   │   ├── html.mdx
    │   │   ├── image.mdx
    │   │   ├── link.mdx
    │   │   ├── markdown.mdx
    │   │   ├── preview.mdx
    │   │   ├── row.mdx
    │   │   ├── section.mdx
    │   │   ├── tailwind.mdx
    │   │   └── text.mdx
    │   ├── contributing.mdx
    │   ├── contributing
    │   │   ├── codebase-overview.mdx
    │   │   ├── development-workflow
    │   │   │   ├── 1-setup.mdx
    │   │   │   ├── 2-running-tests.mdx
    │   │   │   ├── 3-linting.mdx
    │   │   │   ├── 4-building.mdx
    │   │   │   └── 5-writing-docs.mdx
    │   │   ├── introduction.mdx
    │   │   ├── opening-issues.mdx
    │   │   └── opening-pull-requests.mdx
    │   ├── deployment.mdx
    │   ├── docs.json
    │   ├── favicon.png
    │   ├── getting-started
    │   │   ├── automatic-setup.mdx
    │   │   ├── manual-setup.mdx
    │   │   ├── migrating-to-react-email.mdx
    │   │   └── monorepo-setup
    │   │   │   ├── bun.mdx
    │   │   │   ├── choose-package-manager.mdx
    │   │   │   ├── npm.mdx
    │   │   │   ├── pnpm.mdx
    │   │   │   └── yarn.mdx
    │   ├── images
    │   │   ├── background.png
    │   │   ├── bg.png
    │   │   ├── local-dev.jpg
    │   │   └── preview-server-vercel-settings.png
    │   ├── integrations
    │   │   ├── aws-ses.mdx
    │   │   ├── mailersend.mdx
    │   │   ├── nodemailer.mdx
    │   │   ├── overview.mdx
    │   │   ├── plunk.mdx
    │   │   ├── postmark.mdx
    │   │   ├── resend.mdx
    │   │   ├── scaleway.mdx
    │   │   └── sendgrid.mdx
    │   ├── introduction.mdx
    │   ├── license.md
    │   ├── logo
    │   │   ├── dark.svg
    │   │   └── light.svg
    │   ├── package.json
    │   ├── roadmap.mdx
    │   ├── snippets
    │   │   ├── integrations.mdx
    │   │   ├── localdev.mdx
    │   │   ├── next-steps.mdx
    │   │   └── support.mdx
    │   └── utilities
    │   │   └── render.mdx
    └── web
    │   ├── .gitignore
    │   ├── .vscode
    │       └── settings.json
    │   ├── README.md
    │   ├── components
    │       ├── _components
    │       │   └── layout.tsx
    │       ├── article-with-image-as-background
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── article-with-image-on-right
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── article-with-image
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── article-with-multiple-authors
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── article-with-single-author
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── article-with-two-cards
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── bento-grid
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── checkout
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── code-block-with-custom-theme
    │       │   └── index.tsx
    │       ├── code-block-with-line-numbers
    │       │   └── index.tsx
    │       ├── code-block-with-predefined-theme
    │       │   └── index.tsx
    │       ├── code-block-without-theme
    │       │   └── index.tsx
    │       ├── code-inline-with-different-colors
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── customer-reviews
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── divider-between-rows-and-columns
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── download-buttons
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── ensure-matching-variants.spec.tsx
    │       ├── footer-with-one-column
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── footer-with-two-columns
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── four-images-in-a-grid
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── header-and-four-paragraphs-and-two-columns
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── header-and-four-paragraphs
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── header-and-list-items
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── header-and-numbered-list-items
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── header-and-three-centered-paragraphs
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── header-with-centered-menu
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── header-with-side-menu
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── header-with-social-icons
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── image-with-varying-sizes
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── images-on-horizontal-grid
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── images-on-vertical-grid
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── link-inline-with-text
    │       │   └── index.tsx
    │       ├── list-with-image-on-left
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── markdown-with-container-styles
    │       │   └── index.tsx
    │       ├── markdown-with-custom-styles
    │       │   └── index.tsx
    │       ├── multiple-headings
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── one-product-with-image-on-the-left
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── one-product
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── one-row-three-columns
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── one-row-two-columns
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── rounded-image
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── section-with-rows-and-columns
    │       │   └── index.tsx
    │       ├── simple-code-inline
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── simple-container
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── simple-divider
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── simple-heading
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── simple-image
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── simple-link
    │       │   └── index.tsx
    │       ├── simple-list
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── simple-markdown
    │       │   └── index.tsx
    │       ├── simple-pricing-table
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── simple-rating-survey
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── simple-section
    │       │   └── index.tsx
    │       ├── simple-text
    │       │   └── index.tsx
    │       ├── single-button
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── static
    │       │   ├── cube-icon.png
    │       │   ├── download-on-the-app-store.png
    │       │   ├── facebook-logo.png
    │       │   ├── get-it-on-google-play.png
    │       │   ├── heart-icon.png
    │       │   ├── in-icon.png
    │       │   ├── instagram-logo.png
    │       │   ├── logo-without-background.png
    │       │   ├── megaphone-icon.png
    │       │   ├── rocket-icon.png
    │       │   ├── steve-jobs.jpg
    │       │   ├── steve-wozniak.jpg
    │       │   ├── x-icon.png
    │       │   └── x-logo.png
    │       ├── structure.ts
    │       ├── survey-section
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── tailwind.config.ts
    │       ├── text-with-styling
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── three-columns-with-images
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── title-four-cards
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── title-three-cards-in-a-row
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       ├── tsconfig.json
    │       ├── two-buttons
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │       └── two-tiers-with-emphasized-tier
    │       │   ├── inline-styles.tsx
    │       │   └── tailwind.tsx
    │   ├── license.md
    │   ├── next-env.d.ts
    │   ├── next.config.js
    │   ├── package.json
    │   ├── postcss.config.js
    │   ├── public
    │       ├── brand
    │       │   ├── logo-without-background.png
    │       │   ├── logo.png
    │       │   └── resend.png
    │       ├── examples
    │       │   ├── airbnb-review.png
    │       │   ├── apple-receipt.png
    │       │   ├── authors
    │       │   │   ├── EmersonGarrido.png
    │       │   │   ├── Rychillie.png
    │       │   │   ├── abhinandanwadwa.png
    │       │   │   ├── bruno88cabral.png
    │       │   │   ├── bukinoshita.png
    │       │   │   ├── c0dr.png
    │       │   │   ├── camillegachido.png
    │       │   │   ├── joaom00.png
    │       │   │   ├── nettofarah.png
    │       │   │   ├── relferreira.png
    │       │   │   ├── ribeiroevandro.png
    │       │   │   ├── thecodeinfluencer.png
    │       │   │   └── zenorocha.png
    │       │   ├── aws-verify-email.png
    │       │   ├── dropbox-reset-password.png
    │       │   ├── github-access-token.png
    │       │   ├── google-play-policy-update.png
    │       │   ├── koala-welcome.png
    │       │   ├── linear-login-code.png
    │       │   ├── nike-receipt.png
    │       │   ├── notion-magic-link.png
    │       │   ├── plaid-verify-identity.png
    │       │   ├── raycast-magic-link.png
    │       │   ├── slack-confirm.png
    │       │   ├── stack-overflow-tips.png
    │       │   ├── stripe-welcome.png
    │       │   ├── twitch-reset-password.png
    │       │   ├── vercel-invite-user.png
    │       │   └── yelp-recent-login.png
    │       ├── fonts
    │       │   ├── commit-mono
    │       │   │   ├── commit-mono-italic.ttf
    │       │   │   └── commit-mono-regular.ttf
    │       │   ├── inter
    │       │   │   └── inter.ttf
    │       │   └── shantell-sans
    │       │   │   ├── shantell-sans-italic.ttf
    │       │   │   └── shantell-sans-regular.ttf
    │       ├── meta
    │       │   ├── apple-touch-icon.png
    │       │   ├── cover.png
    │       │   ├── favicon.ico
    │       │   └── favicon.svg
    │       └── static
    │       │   ├── atmos-vacuum-canister.jpg
    │       │   ├── bg.png
    │       │   ├── braun-analogue-clock.jpg
    │       │   ├── braun-classic-watch.jpg
    │       │   ├── braun-collection.jpg
    │       │   ├── braun-vintage.jpg
    │       │   ├── braun-wall-clock.jpg
    │       │   ├── braun-wireless-alarm.jpg
    │       │   ├── bundle-collection.jpg
    │       │   ├── clara-french-press.jpg
    │       │   ├── clyde-electric-kettle.jpg
    │       │   ├── coffee-bean-storage.jpg
    │       │   ├── covers
    │       │       ├── button.png
    │       │       ├── code-block.png
    │       │       ├── code-inline.png
    │       │       ├── column.png
    │       │       ├── components.png
    │       │       ├── container.png
    │       │       ├── create-email.png
    │       │       ├── font.png
    │       │       ├── head.png
    │       │       ├── heading.png
    │       │       ├── hr.png
    │       │       ├── html.png
    │       │       ├── img.png
    │       │       ├── link.png
    │       │       ├── markdown.png
    │       │       ├── patterns.png
    │       │       ├── preview.png
    │       │       ├── react-email.png
    │       │       ├── render.png
    │       │       ├── row.png
    │       │       ├── section.png
    │       │       ├── tailwind.png
    │       │       └── text.png
    │       │   ├── cube-icon.png
    │       │   ├── download-on-the-app-store.png
    │       │   ├── facebook-logo.png
    │       │   ├── get-it-on-google-play.png
    │       │   ├── grinder-collection.jpg
    │       │   ├── heart-icon.png
    │       │   ├── herman-miller-chair.jpg
    │       │   ├── icons
    │       │       ├── apple-mail.svg
    │       │       ├── gmail.svg
    │       │       ├── hey.svg
    │       │       ├── outlook.svg
    │       │       ├── superhuman.svg
    │       │       └── yahoo-mail.svg
    │       │   ├── in-icon.png
    │       │   ├── instagram-logo.png
    │       │   ├── logo-without-background.png
    │       │   ├── megaphone-icon.png
    │       │   ├── monty-art-cup-1.jpg
    │       │   ├── monty-art-cup-2.jpg
    │       │   ├── mugs-collection.jpg
    │       │   ├── ode-grinder.jpg
    │       │   ├── outdoor-living.jpg
    │       │   ├── rocket-icon.png
    │       │   ├── stagg-eletric-kettle.jpg
    │       │   ├── steve-jobs.jpg
    │       │   ├── steve-wozniak.jpg
    │       │   ├── vacuum-canister-clear-glass-bundle.jpg
    │       │   ├── versatile-comfort.jpg
    │       │   ├── x-icon.png
    │       │   └── x-logo.png
    │   ├── src
    │       ├── app
    │       │   ├── api
    │       │   │   ├── check-spam
    │       │   │   │   ├── __snapshots__
    │       │   │   │   │   └── check-spam.spec.tsx.snap
    │       │   │   │   ├── check-spam.spec.tsx
    │       │   │   │   ├── check-spam.ts
    │       │   │   │   ├── route.ts
    │       │   │   │   └── testing
    │       │   │   │   │   └── stripe-welcome-email.tsx
    │       │   │   └── send
    │       │   │   │   └── test
    │       │   │   │       └── route.ts
    │       │   ├── components
    │       │   │   ├── [slug]
    │       │   │   │   └── page.tsx
    │       │   │   ├── get-imported-components-for.tsx
    │       │   │   └── page.tsx
    │       │   ├── layout.tsx
    │       │   ├── not-found.tsx
    │       │   ├── page.tsx
    │       │   ├── robots.ts
    │       │   ├── sitemap.ts
    │       │   └── templates
    │       │   │   └── page.tsx
    │       ├── components
    │       │   ├── anchor.tsx
    │       │   ├── button.tsx
    │       │   ├── code-block.tsx
    │       │   ├── code.tsx
    │       │   ├── component-code-view.tsx
    │       │   ├── component-preview.tsx
    │       │   ├── component-view.tsx
    │       │   ├── components-view.tsx
    │       │   ├── footer.tsx
    │       │   ├── heading.tsx
    │       │   ├── icon-button.tsx
    │       │   ├── icons
    │       │   │   ├── icon-arrow-left.tsx
    │       │   │   ├── icon-base.tsx
    │       │   │   ├── icon-monitor.tsx
    │       │   │   ├── icon-phone.tsx
    │       │   │   └── icon-source.tsx
    │       │   ├── logo.tsx
    │       │   ├── menu.tsx
    │       │   ├── page-transition.tsx
    │       │   ├── spotlight.tsx
    │       │   ├── tab-trigger.tsx
    │       │   ├── template.tsx
    │       │   ├── text.tsx
    │       │   ├── tooltip-content.tsx
    │       │   ├── tooltip.tsx
    │       │   └── topbar.tsx
    │       ├── hooks
    │       │   └── use-stored-state.ts
    │       ├── illustrations
    │       │   ├── articles.tsx
    │       │   ├── buttons.tsx
    │       │   ├── code-block.tsx
    │       │   ├── code-inline.tsx
    │       │   ├── container.tsx
    │       │   ├── divider.tsx
    │       │   ├── ecommerce.tsx
    │       │   ├── features.tsx
    │       │   ├── feedback.tsx
    │       │   ├── footers.tsx
    │       │   ├── gallery.tsx
    │       │   ├── grid.tsx
    │       │   ├── headers.tsx
    │       │   ├── heading.tsx
    │       │   ├── image.tsx
    │       │   ├── link.tsx
    │       │   ├── list.tsx
    │       │   ├── markdown.tsx
    │       │   ├── marketing.tsx
    │       │   ├── pricing.tsx
    │       │   ├── section.tsx
    │       │   └── text.tsx
    │       ├── styles
    │       │   └── globals.css
    │       └── utils
    │       │   ├── as.ts
    │       │   ├── convert-uris-into-urls.spec.ts
    │       │   ├── convert-uris-into-urls.ts
    │       │   ├── slugify.ts
    │       │   ├── spam-assassin
    │       │       ├── __snapshots__
    │       │       │   └── parse-pointing-table-rows.spec.ts.snap
    │       │       ├── parse-pointing-table-rows.spec.ts
    │       │       ├── parse-pointing-table-rows.ts
    │       │       └── send-to-spamd.ts
    │       │   └── unreachable.ts
    │   ├── tailwind.config.js
    │   ├── tsconfig.json
    │   └── vitest.config.ts
├── benchmarks
    ├── preview-server
    │   ├── bench-results-30-iterations.json
    │   ├── package.json
    │   ├── src
    │   │   ├── local-vs-2.1.7-canary.2-on-startup.ts
    │   │   ├── local-vs-2.1.7-canary.2.ts
    │   │   └── utils
    │   │   │   ├── run-server-and-fetch-preview-page.ts
    │   │   │   └── run-server.ts
    │   └── startup-bench-results-30-iterations.json
    └── tailwind-component
    │   ├── .gitignore
    │   ├── README.md
    │   ├── bench-results-100-iterations.json
    │   ├── package.json
    │   ├── src
    │       ├── benchmark-0.0.12-vs-local-version.tsx
    │       ├── benchmark-0.0.17-vs-local-version.tsx
    │       ├── benchmark-with-vs-without.tsx
    │       ├── emails
    │       │   ├── with-tailwind.tsx
    │       │   └── without-tailwind.tsx
    │       └── tailwind-render.tsx
    │   ├── tailwind.config.js
    │   └── tsconfig.json
├── biome.json
├── examples
    ├── aws-ses
    │   ├── package.json
    │   ├── src
    │   │   ├── email.tsx
    │   │   └── index.tsx
    │   └── tsconfig.json
    ├── mailersend
    │   ├── package.json
    │   ├── src
    │   │   ├── email.tsx
    │   │   └── index.tsx
    │   └── tsconfig.json
    ├── nodemailer
    │   ├── package.json
    │   ├── src
    │   │   ├── email.tsx
    │   │   └── index.tsx
    │   └── tsconfig.json
    ├── plunk
    │   ├── package.json
    │   ├── src
    │   │   ├── email.tsx
    │   │   └── index.tsx
    │   └── tsconfig.json
    ├── postmark
    │   ├── package.json
    │   ├── src
    │   │   ├── email.tsx
    │   │   └── index.tsx
    │   └── tsconfig.json
    ├── resend
    │   ├── next-env.d.ts
    │   ├── package.json
    │   ├── src
    │   │   ├── lib
    │   │   │   └── resend.ts
    │   │   └── pages
    │   │   │   └── api
    │   │   │       └── send.ts
    │   ├── transactional
    │   │   └── emails
    │   │   │   └── waitlist.tsx
    │   └── tsconfig.json
    ├── scaleway
    │   ├── next
    │   │   ├── next-env.d.ts
    │   │   ├── package.json
    │   │   ├── src
    │   │   │   ├── lib
    │   │   │   │   └── scaleway.ts
    │   │   │   └── pages
    │   │   │   │   └── api
    │   │   │   │       └── send.tsx
    │   │   ├── transactional
    │   │   │   └── emails
    │   │   │   │   └── waitlist.tsx
    │   │   └── tsconfig.json
    │   └── node
    │   │   ├── package.json
    │   │   ├── src
    │   │       ├── email.tsx
    │   │       └── index.tsx
    │   │   └── tsconfig.json
    └── sendgrid
    │   ├── package.json
    │   ├── src
    │       ├── email.tsx
    │       └── index.tsx
    │   └── tsconfig.json
├── package.json
├── packages
    ├── body
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── body.spec.tsx.snap
    │   │   ├── body.spec.tsx
    │   │   ├── body.tsx
    │   │   └── index.ts
    │   └── tsconfig.json
    ├── button
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── button.spec.tsx.snap
    │   │   ├── button.spec.tsx
    │   │   ├── button.tsx
    │   │   ├── index.ts
    │   │   └── utils
    │   │   │   ├── parse-padding.ts
    │   │   │   ├── px-to-pt.ts
    │   │   │   └── utils.spec.ts
    │   └── tsconfig.json
    ├── code-block
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── code-block.tsx
    │   │   ├── index.ts
    │   │   ├── languages-available.ts
    │   │   ├── prism.ts
    │   │   └── themes.ts
    │   └── tsconfig.json
    ├── code-inline
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── code-inline.tsx
    │   │   └── index.ts
    │   └── tsconfig.json
    ├── column
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── column.spec.tsx.snap
    │   │   ├── column.spec.tsx
    │   │   ├── column.tsx
    │   │   └── index.ts
    │   └── tsconfig.json
    ├── components
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── heading.spec.tsx.snap
    │   │   └── index.ts
    │   └── tsconfig.json
    ├── container
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── container.spec.tsx.snap
    │   │   ├── container.spec.tsx
    │   │   ├── container.tsx
    │   │   └── index.ts
    │   └── tsconfig.json
    ├── create-email
    │   ├── .gitignore
    │   ├── .npmignore
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── index.js
    │   │   ├── index.spec.ts
    │   │   └── tree.js
    │   ├── template
    │   │   ├── .gitignore
    │   │   ├── CHANGELOG.md
    │   │   ├── emails
    │   │   │   ├── notion-magic-link.tsx
    │   │   │   ├── plaid-verify-identity.tsx
    │   │   │   ├── static
    │   │   │   │   ├── notion-logo.png
    │   │   │   │   ├── plaid-logo.png
    │   │   │   │   ├── plaid.png
    │   │   │   │   ├── stripe-logo.png
    │   │   │   │   ├── vercel-arrow.png
    │   │   │   │   ├── vercel-logo.png
    │   │   │   │   ├── vercel-team.png
    │   │   │   │   └── vercel-user.png
    │   │   │   ├── stripe-welcome.tsx
    │   │   │   └── vercel-invite-user.tsx
    │   │   ├── package.json
    │   │   ├── readme.md
    │   │   └── tsconfig.json
    │   ├── tsconfig.json
    │   └── vitest.config.ts
    ├── font
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── font.spec.tsx.snap
    │   │   ├── font.spec.tsx
    │   │   ├── font.tsx
    │   │   └── index.ts
    │   └── tsconfig.json
    ├── head
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── head.spec.tsx.snap
    │   │   ├── head.spec.tsx
    │   │   ├── head.tsx
    │   │   └── index.ts
    │   └── tsconfig.json
    ├── heading
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── heading.spec.tsx.snap
    │   │   ├── heading.spec.tsx
    │   │   ├── heading.tsx
    │   │   ├── index.ts
    │   │   └── utils
    │   │   │   ├── as.ts
    │   │   │   ├── spaces.ts
    │   │   │   └── utils.spec.ts
    │   └── tsconfig.json
    ├── hr
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── hr.spec.tsx.snap
    │   │   ├── hr.spec.tsx
    │   │   ├── hr.tsx
    │   │   └── index.ts
    │   └── tsconfig.json
    ├── html
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── html.spec.tsx.snap
    │   │   ├── html.spec.tsx
    │   │   ├── html.tsx
    │   │   └── index.ts
    │   └── tsconfig.json
    ├── img
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── img.spec.tsx.snap
    │   │   ├── img.spec.tsx
    │   │   ├── img.tsx
    │   │   └── index.ts
    │   └── tsconfig.json
    ├── link
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── link.spec.tsx.snap
    │   │   ├── index.ts
    │   │   ├── link.spec.tsx
    │   │   └── link.tsx
    │   └── tsconfig.json
    ├── markdown
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── markdown.spec.tsx.snap
    │   │   ├── index.ts
    │   │   ├── markdown.spec.tsx
    │   │   └── markdown.tsx
    │   └── tsconfig.json
    ├── preview-server
    │   ├── .gitignore
    │   ├── .npmignore
    │   ├── CHANGELOG.md
    │   ├── index.mjs
    │   ├── license.md
    │   ├── module-punycode.d.ts
    │   ├── next-env.d.ts
    │   ├── next.config.js
    │   ├── package.json
    │   ├── postcss.config.js
    │   ├── readme.md
    │   ├── scripts
    │   │   ├── build-preview-server.mts
    │   │   ├── dev.mts
    │   │   ├── fill-caniemail-data.mts
    │   │   ├── seed.mts
    │   │   └── utils
    │   │   │   └── default-seed
    │   │   │       ├── auth
    │   │   │           ├── account-confirmation.tsx
    │   │   │           └── forgot-password.tsx
    │   │   │       ├── communications
    │   │   │           ├── payment-overdue.tsx
    │   │   │           ├── team-invite.tsx
    │   │   │           └── webhooks-failed.tsx
    │   │   │       ├── feedback-request.tsx
    │   │   │       └── marketing
    │   │   │           └── changelog.tsx
    │   ├── src
    │   │   ├── actions
    │   │   │   ├── email-validation
    │   │   │   │   ├── __snapshots__
    │   │   │   │   │   └── check-images.spec.tsx.snap
    │   │   │   │   ├── caniemail-data.ts
    │   │   │   │   ├── check-compatibility.ts
    │   │   │   │   ├── check-images.spec.tsx
    │   │   │   │   ├── check-images.ts
    │   │   │   │   ├── check-links.spec.tsx
    │   │   │   │   ├── check-links.ts
    │   │   │   │   ├── get-code-location-from-ast-element.ts
    │   │   │   │   └── quick-fetch.ts
    │   │   │   ├── get-email-path-from-slug.ts
    │   │   │   ├── get-emails-directory-metadata-action.ts
    │   │   │   └── render-email-by-path.tsx
    │   │   ├── animated-icons-data
    │   │   │   ├── help.json
    │   │   │   ├── link.json
    │   │   │   ├── load.json
    │   │   │   └── mail.json
    │   │   ├── app
    │   │   │   ├── env.ts
    │   │   │   ├── favicon.ico
    │   │   │   ├── fonts.ts
    │   │   │   ├── fonts
    │   │   │   │   └── SFMono
    │   │   │   │   │   ├── SFMonoBold.otf
    │   │   │   │   │   ├── SFMonoBoldItalic.otf
    │   │   │   │   │   ├── SFMonoHeavy.otf
    │   │   │   │   │   ├── SFMonoHeavyItalic.otf
    │   │   │   │   │   ├── SFMonoLight.otf
    │   │   │   │   │   ├── SFMonoLightItalic.otf
    │   │   │   │   │   ├── SFMonoMedium.otf
    │   │   │   │   │   ├── SFMonoMediumItalic.otf
    │   │   │   │   │   ├── SFMonoRegular.otf
    │   │   │   │   │   ├── SFMonoRegularItalic.otf
    │   │   │   │   │   ├── SFMonoSemibold.otf
    │   │   │   │   │   └── SFMonoSemiboldItalic.otf
    │   │   │   ├── globals.css
    │   │   │   ├── layout.tsx
    │   │   │   ├── logo.png
    │   │   │   ├── page.tsx
    │   │   │   └── preview
    │   │   │   │   └── [...slug]
    │   │   │   │       ├── page.tsx
    │   │   │   │       ├── preview.tsx
    │   │   │   │       └── rendering-error.tsx
    │   │   ├── components
    │   │   │   ├── button.tsx
    │   │   │   ├── code-container.tsx
    │   │   │   ├── code-snippet.tsx
    │   │   │   ├── code.tsx
    │   │   │   ├── heading.tsx
    │   │   │   ├── icons
    │   │   │   │   ├── icon-arrow-down.tsx
    │   │   │   │   ├── icon-base.tsx
    │   │   │   │   ├── icon-bug.tsx
    │   │   │   │   ├── icon-button.tsx
    │   │   │   │   ├── icon-check.tsx
    │   │   │   │   ├── icon-clipboard.tsx
    │   │   │   │   ├── icon-download.tsx
    │   │   │   │   ├── icon-email.tsx
    │   │   │   │   ├── icon-file.tsx
    │   │   │   │   ├── icon-folder-open.tsx
    │   │   │   │   ├── icon-folder.tsx
    │   │   │   │   ├── icon-hide-sidebar.tsx
    │   │   │   │   ├── icon-image.tsx
    │   │   │   │   ├── icon-info.tsx
    │   │   │   │   ├── icon-link.tsx
    │   │   │   │   ├── icon-monitor.tsx
    │   │   │   │   ├── icon-phone.tsx
    │   │   │   │   ├── icon-reload.tsx
    │   │   │   │   ├── icon-source.tsx
    │   │   │   │   ├── icon-stamp.tsx
    │   │   │   │   └── icon-warning.tsx
    │   │   │   ├── index.ts
    │   │   │   ├── logo.tsx
    │   │   │   ├── resizable-wrapper.tsx
    │   │   │   ├── send.tsx
    │   │   │   ├── shell.tsx
    │   │   │   ├── sidebar
    │   │   │   │   ├── file-tree-directory-children.tsx
    │   │   │   │   ├── file-tree-directory.tsx
    │   │   │   │   ├── file-tree.tsx
    │   │   │   │   ├── index.ts
    │   │   │   │   └── sidebar.tsx
    │   │   │   ├── text.tsx
    │   │   │   ├── toolbar.tsx
    │   │   │   ├── toolbar
    │   │   │   │   ├── checking-results.tsx
    │   │   │   │   ├── code-preview-line-link.tsx
    │   │   │   │   ├── compatibility.tsx
    │   │   │   │   ├── linter.tsx
    │   │   │   │   ├── results-table.tsx
    │   │   │   │   ├── results.tsx
    │   │   │   │   ├── spam-assassin.tsx
    │   │   │   │   ├── toolbar-button.tsx
    │   │   │   │   └── use-cached-state.ts
    │   │   │   ├── tooltip-content.tsx
    │   │   │   ├── tooltip.tsx
    │   │   │   ├── topbar.tsx
    │   │   │   └── topbar
    │   │   │   │   ├── active-view-toggle-group.tsx
    │   │   │   │   └── view-size-controls.tsx
    │   │   ├── contexts
    │   │   │   ├── emails.tsx
    │   │   │   ├── fragment-identifier.tsx
    │   │   │   └── preview.tsx
    │   │   ├── hooks
    │   │   │   ├── use-clamped-state.ts
    │   │   │   ├── use-email-rendering-result.ts
    │   │   │   ├── use-fragment-identifier.ts
    │   │   │   ├── use-hot-reload.ts
    │   │   │   ├── use-icon-animation.ts
    │   │   │   └── use-rendering-metadata.ts
    │   │   └── utils
    │   │   │   ├── __snapshots__
    │   │   │       └── get-email-component.spec.ts.snap
    │   │   │   ├── caniemail
    │   │   │       ├── all-css-properties.ts
    │   │   │       ├── ast
    │   │   │       │   ├── __snapshots__
    │   │   │       │   │   ├── get-object-variables.spec.ts.snap
    │   │   │       │   │   └── get-used-style-properties.spec.ts.snap
    │   │   │       │   ├── get-object-variables.spec.ts
    │   │   │       │   ├── get-object-variables.ts
    │   │   │       │   ├── get-used-style-properties.spec.ts
    │   │   │       │   └── get-used-style-properties.ts
    │   │   │       ├── get-compatibility-stats-for-entry.ts
    │   │   │       ├── get-css-functions.ts
    │   │   │       ├── get-css-property-names.ts
    │   │   │       ├── get-css-property-with-value.ts
    │   │   │       ├── get-css-unit.ts
    │   │   │       ├── get-element-attributes.ts
    │   │   │       ├── get-element-names.ts
    │   │   │       └── tailwind
    │   │   │       │   ├── generate-tailwind-rules.ts
    │   │   │       │   ├── get-tailwind-config.ts
    │   │   │       │   ├── get-tailwind-metadata.spec.ts
    │   │   │       │   ├── get-tailwind-metadata.ts
    │   │   │       │   └── setup-tailwind-context.ts
    │   │   │   ├── cn.ts
    │   │   │   ├── constants.ts
    │   │   │   ├── contains-email-template.spec.ts
    │   │   │   ├── contains-email-template.ts
    │   │   │   ├── copy-text-to-clipboard.ts
    │   │   │   ├── esbuild
    │   │   │       ├── escape-string-for-regex.ts
    │   │   │       └── renderring-utilities-exporter.ts
    │   │   │   ├── get-email-component.spec.ts
    │   │   │   ├── get-email-component.ts
    │   │   │   ├── get-emails-directory-metadata.spec.ts
    │   │   │   ├── get-emails-directory-metadata.ts
    │   │   │   ├── get-line-and-column-from-offset.spec.ts
    │   │   │   ├── get-line-and-column-from-offset.ts
    │   │   │   ├── improve-error-with-sourcemap.ts
    │   │   │   ├── index.ts
    │   │   │   ├── js-email-detection.spec.ts
    │   │   │   ├── language-map.ts
    │   │   │   ├── linting.ts
    │   │   │   ├── load-stream.ts
    │   │   │   ├── register-spinner-autostopping.ts
    │   │   │   ├── result.ts
    │   │   │   ├── run-bundled-code.ts
    │   │   │   ├── sanitize.ts
    │   │   │   ├── static-node-modules-for-vm.ts
    │   │   │   ├── testing
    │   │   │       ├── js-email-export-default.js
    │   │   │       ├── js-email-test.js
    │   │   │       ├── mdx-email-test.js
    │   │   │       └── request-response-email.tsx
    │   │   │   ├── types
    │   │   │       ├── as.ts
    │   │   │       ├── email-template.ts
    │   │   │       ├── error-object.ts
    │   │   │       └── hot-reload-change.ts
    │   │   │   └── unreachable.ts
    │   ├── tailwind-internals.d.ts
    │   ├── tailwind.config.ts
    │   ├── tsconfig.json
    │   └── vitest.config.ts
    ├── preview
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── preview.spec.tsx.snap
    │   │   ├── index.ts
    │   │   ├── preview.spec.tsx
    │   │   └── preview.tsx
    │   └── tsconfig.json
    ├── react-email
    │   ├── .gitignore
    │   ├── .npmignore
    │   ├── CHANGELOG.md
    │   ├── dev
    │   │   ├── CHANGELOG.md
    │   │   ├── index.js
    │   │   └── package.json
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── actions
    │   │   │   └── email-validation
    │   │   │   │   └── __snapshots__
    │   │   │   │       └── check-images.spec.tsx.snap
    │   │   ├── commands
    │   │   │   ├── .npmignore
    │   │   │   ├── build.ts
    │   │   │   ├── dev.ts
    │   │   │   ├── export.ts
    │   │   │   ├── start.ts
    │   │   │   └── testing
    │   │   │   │   ├── .gitignore
    │   │   │   │   ├── __snapshots__
    │   │   │   │       └── export.spec.ts.snap
    │   │   │   │   └── export.spec.ts
    │   │   ├── index.ts
    │   │   └── utils
    │   │   │   ├── __snapshots__
    │   │   │       └── tree.spec.ts.snap
    │   │   │   ├── esbuild
    │   │   │       ├── escape-string-for-regex.ts
    │   │   │       └── renderring-utilities-exporter.ts
    │   │   │   ├── get-emails-directory-metadata.spec.ts
    │   │   │   ├── get-emails-directory-metadata.ts
    │   │   │   ├── get-preview-server-location.ts
    │   │   │   ├── index.ts
    │   │   │   ├── packageJson.ts
    │   │   │   ├── preview
    │   │   │       ├── get-env-variables-for-preview-app.ts
    │   │   │       ├── hot-reloading
    │   │   │       │   ├── create-dependency-graph.spec.ts
    │   │   │       │   ├── create-dependency-graph.ts
    │   │   │       │   ├── get-imported-modules.spec.ts
    │   │   │       │   ├── get-imported-modules.ts
    │   │   │       │   ├── resolve-path-aliases.spec.ts
    │   │   │       │   ├── resolve-path-aliases.ts
    │   │   │       │   ├── setup-hot-reloading.ts
    │   │   │       │   └── test
    │   │   │       │   │   ├── some-file.ts
    │   │   │       │   │   └── tsconfig.json
    │   │   │       ├── index.ts
    │   │   │       ├── serve-static-file.ts
    │   │   │       └── start-dev-server.ts
    │   │   │   ├── register-spinner-autostopping.ts
    │   │   │   ├── tree.spec.ts
    │   │   │   ├── tree.ts
    │   │   │   └── types
    │   │   │       ├── hot-reload-change.ts
    │   │   │       └── hot-reload-event.ts
    │   ├── tsconfig.json
    │   ├── tsup.config.ts
    │   └── vitest.config.ts
    ├── render
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── browser
    │   │   │   ├── __snapshots__
    │   │   │   │   └── render-web.spec.tsx.snap
    │   │   │   ├── index.ts
    │   │   │   ├── read-stream.ts
    │   │   │   ├── render-web.spec.tsx
    │   │   │   └── render.tsx
    │   │   ├── node
    │   │   │   ├── __snapshots__
    │   │   │   │   ├── render-async-edge.spec.tsx.snap
    │   │   │   │   ├── render-async-node.spec.tsx.snap
    │   │   │   │   ├── render-edge.spec.tsx.snap
    │   │   │   │   └── render-node.spec.tsx.snap
    │   │   │   ├── index.ts
    │   │   │   ├── read-stream.ts
    │   │   │   ├── render-edge.spec.tsx
    │   │   │   ├── render-node.spec.tsx
    │   │   │   └── render.tsx
    │   │   ├── react-internals.d.ts
    │   │   └── shared
    │   │   │   ├── options.ts
    │   │   │   ├── plain-text-selectors.ts
    │   │   │   └── utils
    │   │   │       ├── __snapshots__
    │   │   │           └── pretty.spec.ts.snap
    │   │   │       ├── pretty.spec.ts
    │   │   │       ├── pretty.ts
    │   │   │       ├── preview.tsx
    │   │   │       ├── stripe-email.html
    │   │   │       └── template.tsx
    │   ├── tsconfig.json
    │   └── tsup.config.ts
    ├── row
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── row.spec.tsx.snap
    │   │   ├── index.ts
    │   │   ├── row.spec.tsx
    │   │   └── row.tsx
    │   └── tsconfig.json
    ├── section
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── section.spec.tsx.snap
    │   │   ├── index.ts
    │   │   ├── section.spec.tsx
    │   │   └── section.tsx
    │   └── tsconfig.json
    ├── tailwind
    │   ├── CHANGELOG.md
    │   ├── copy-tailwind-types.mjs
    │   ├── integrations
    │   │   ├── integrations.spec.ts
    │   │   ├── nextjs
    │   │   │   ├── .gitignore
    │   │   │   ├── README.md
    │   │   │   ├── emails
    │   │   │   │   └── vercel-invite-user.tsx
    │   │   │   ├── next-env.d.ts
    │   │   │   ├── next.config.mjs
    │   │   │   ├── package.json
    │   │   │   ├── src
    │   │   │   │   └── app
    │   │   │   │   │   ├── favicon.ico
    │   │   │   │   │   ├── layout.tsx
    │   │   │   │   │   └── page.tsx
    │   │   │   └── tsconfig.json
    │   │   └── vite
    │   │   │   ├── .gitignore
    │   │   │   ├── README.md
    │   │   │   ├── emails
    │   │   │       └── vercel-invite-user.tsx
    │   │   │   ├── index.html
    │   │   │   ├── package.json
    │   │   │   ├── public
    │   │   │       └── vite.svg
    │   │   │   ├── src
    │   │   │       ├── App.tsx
    │   │   │       ├── main.tsx
    │   │   │       └── vite-env.d.ts
    │   │   │   ├── tsconfig.json
    │   │   │   ├── tsconfig.node.json
    │   │   │   └── vite.config.ts
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── tailwind.spec.tsx.snap
    │   │   ├── hooks
    │   │   │   ├── __snapshots__
    │   │   │   │   └── use-tailwind.spec.ts.snap
    │   │   │   └── use-suspensed-promise.ts
    │   │   ├── index.ts
    │   │   ├── tailwind.spec.tsx
    │   │   ├── tailwind.tsx
    │   │   └── utils
    │   │   │   ├── __snapshots__
    │   │   │       └── quick-safe-render-to-string.spec.tsx.snap
    │   │   │   ├── compatibility
    │   │   │       ├── convert-css-property-to-react-property.ts
    │   │   │       ├── escape-class-name.spec.ts
    │   │   │       ├── escape-class-name.ts
    │   │   │       ├── sanitize-class-name.spec.ts
    │   │   │       ├── sanitize-class-name.ts
    │   │   │       └── unescape-class.ts
    │   │   │   ├── css
    │   │   │       ├── make-inline-styles-for.spec.ts
    │   │   │       ├── make-inline-styles-for.ts
    │   │   │       ├── minify-css.ts
    │   │   │       ├── remove-if-empty-recursively.ts
    │   │   │       ├── remove-rule-duplicates-from-root.ts
    │   │   │       ├── resolve-all-css-variables.spec.ts
    │   │   │       ├── resolve-all-css-variables.ts
    │   │   │       ├── sanitize-declarations.ts
    │   │   │       ├── sanitize-non-inlinable-classes.spec.ts
    │   │   │       └── sanitize-non-inlinable-classes.ts
    │   │   │   ├── react
    │   │   │       ├── is-component.ts
    │   │   │       ├── map-react-tree.spec.tsx
    │   │   │       └── map-react-tree.ts
    │   │   │   ├── tailwindcss
    │   │   │       ├── __snapshots__
    │   │   │       │   └── setup-tailwind.spec.ts.snap
    │   │   │       ├── clone-element-with-inlined-styles.ts
    │   │   │       ├── setup-tailwind-context.ts
    │   │   │       ├── setup-tailwind.spec.ts
    │   │   │       ├── setup-tailwind.ts
    │   │   │       └── tailwind-internals.d.ts
    │   │   │   └── text
    │   │   │       └── from-dash-case-to-camel-case.ts
    │   ├── tsconfig.json
    │   ├── vite.config.ts
    │   └── vitest.config.ts
    ├── text
    │   ├── CHANGELOG.md
    │   ├── license.md
    │   ├── package.json
    │   ├── readme.md
    │   ├── src
    │   │   ├── __snapshots__
    │   │   │   └── text.spec.tsx.snap
    │   │   ├── index.ts
    │   │   ├── text.spec.tsx
    │   │   ├── text.tsx
    │   │   └── utils
    │   │   │   ├── compute-margins.spec.ts
    │   │   │   └── compute-margins.ts
    │   └── tsconfig.json
    └── tsconfig
    │   ├── base.json
    │   ├── nextjs.json
    │   ├── package.json
    │   └── react-library.json
├── playground
    ├── README.md
    ├── components.ts
    ├── emails
    │   ├── .gitignore
    │   └── example.tsx
    ├── package.json
    └── tsconfig.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── renovate.json
├── scripts
    ├── check-dependency-versions.ts
    └── pull-request-title-check.ts
├── tsconfig.json
├── turbo.json
└── vitest.config.ts


/.changeset/README.md:
--------------------------------------------------------------------------------
1 | # Changesets
2 | 
3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4 | with multi-package repos, or single-package repos to help you version and publish your code. You can
5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6 | 
7 | We have a quick list of common questions to get you started engaging with this project in
8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
9 | 


--------------------------------------------------------------------------------
/.changeset/config.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
 3 |   "access": "public",
 4 |   "baseBranch": "main",
 5 |   "changelog": "@changesets/cli/changelog",
 6 |   "commit": false,
 7 |   "fixed": [["react-email", "@react-email/preview-server"]],
 8 |   "ignore": [
 9 |     "@benchmarks/preview-server",
10 |     "@benchmarks/tailwind-component",
11 |     "demo",
12 |     "email-dev",
13 |     "web"
14 |   ],
15 |   "updateInternalDependencies": "patch"
16 | }
17 | 


--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | *                     @resend/engineering
2 | 


--------------------------------------------------------------------------------
/.github/DISCUSSION_TEMPLATE/help.yml:
--------------------------------------------------------------------------------
 1 | body:
 2 |   - type: textarea
 3 |     attributes:
 4 |       label: Summary
 5 |       description: What do you need help with?
 6 |     validations:
 7 |       required: true
 8 |   - type: textarea
 9 |     attributes:
10 |       label: Additional information
11 |       description: Any code snippets, error messages, or dependency details that may be related?
12 |       render: js
13 |     validations:
14 |       required: false
15 |   - type: input
16 |     attributes:
17 |       label: Example
18 |       description: A link to a minimal reproduction is helpful for collaborative debugging!
19 |     validations:
20 |       required: false
21 | 


--------------------------------------------------------------------------------
/.github/DISCUSSION_TEMPLATE/ideas.yml:
--------------------------------------------------------------------------------
 1 | body:
 2 |   - type: textarea
 3 |     attributes:
 4 |       label: Goals
 5 |       description: Short list of what the feature request aims to address?
 6 |       value: |
 7 |         1.
 8 |         2.
 9 |         3.
10 |     validations:
11 |       required: true
12 |   - type: textarea
13 |     attributes:
14 |       label: Background
15 |       description: Discuss prior art, why do you think this feature is needed? Are there current alternatives?
16 |     validations:
17 |       required: true
18 |   - type: textarea
19 |     attributes:
20 |       label: Proposal
21 |       description: How should this feature be implemented? Are you interested in contributing?
22 |     validations:
23 |       required: true
24 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 |   - name: Ask a question
4 |     url: https://github.com/resend/react-email/discussions
5 |     about: Ask questions and discuss with other community members
6 |   - name: Feature request
7 |     url: https://github.com/resend/react-email/discussions/new?category=ideas
8 |     about: Feature requests should be opened as discussions
9 | 


--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
 1 | <!-- Thanks for opening a PR! Your contribution is much appreciated.
 2 | To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below.
 3 | Choose the right checklist for the change(s) that you're making:
 4 | 
 5 | The PR name should follow `<type>(<scope>): <Message>`
 6 | 
 7 | Examples:
 8 | - New feature: `feat(button): Add new thing`
 9 | - Fix: `fix(react-email): Dev command
10 | - Misc/Chore: `chore(root): Update `readme.md`
11 | -->
12 | 


--------------------------------------------------------------------------------
/.github/workflows/pin-dependencies-check.yml:
--------------------------------------------------------------------------------
 1 | name: Pin Dependencies Check
 2 | on:
 3 |   push:
 4 |     branches:
 5 |       - main
 6 |       - canary
 7 |   pull_request:
 8 | permissions: 
 9 |   contents: read
10 |   pull-requests: read
11 | jobs:
12 |   pin-dependencies-check:
13 |     runs-on: buildjet-4vcpu-ubuntu-2204
14 |     container:
15 |       image: node:22
16 |     steps:
17 |       - name: Checkout
18 |         uses: actions/checkout@v4
19 |       - name: Check for pinned dependencies
20 |         run: npx tsx ./scripts/check-dependency-versions.ts
21 | 


--------------------------------------------------------------------------------
/.github/workflows/pull-request-title-check.yml:
--------------------------------------------------------------------------------
 1 | name: Pull Request Title Check
 2 | on:
 3 |   pull_request:
 4 |     types: [opened, edited, synchronize]
 5 | permissions: 
 6 |   pull-requests: read
 7 | jobs:
 8 |   pull-request-title-check:
 9 |     runs-on: buildjet-4vcpu-ubuntu-2204
10 |     container:
11 |       image: node:22
12 |     steps:
13 |       - name: Checkout code
14 |         uses: actions/checkout@v4
15 |       - name: Check pull request title
16 |         run: |
17 |           npx tsx ./scripts/pull-request-title-check.ts
18 | 


--------------------------------------------------------------------------------
/.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.js
 7 | 
 8 | # testing
 9 | coverage
10 | **/*/package-lock.json
11 | **/*/yalc.lock
12 | 
13 | # next.js
14 | .next/
15 | out/
16 | build
17 | dist
18 | .vercel
19 | 
20 | # misc
21 | .DS_Store
22 | *.pem
23 | .react-email
24 | 
25 | # debug
26 | npm-debug.log*
27 | yarn-debug.log*
28 | yarn-error.log*
29 | .pnpm-debug.log*
30 | 
31 | # local env files
32 | .env
33 | .env.local
34 | .env.development.local
35 | .env.test.local
36 | .env.production.local
37 | 
38 | # turbo
39 | .turbo
40 | 


--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | auto-install-peers = true
2 | 


--------------------------------------------------------------------------------
/apps/demo/.gitignore:
--------------------------------------------------------------------------------
1 | .react-email
2 | .vercel
3 | 


--------------------------------------------------------------------------------
/apps/demo/emails/static/airbnb-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/airbnb-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/airbnb-review-user.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/airbnb-review-user.jpg


--------------------------------------------------------------------------------
/apps/demo/emails/static/amazon-book.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/amazon-book.jpg


--------------------------------------------------------------------------------
/apps/demo/emails/static/amazon-facebook.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/amazon-facebook.jpg


--------------------------------------------------------------------------------
/apps/demo/emails/static/amazon-instagram.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/amazon-instagram.jpg


--------------------------------------------------------------------------------
/apps/demo/emails/static/amazon-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/amazon-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/amazon-prime-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/amazon-prime-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/amazon-rating.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/amazon-rating.gif


--------------------------------------------------------------------------------
/apps/demo/emails/static/amazon-twitter.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/amazon-twitter.jpg


--------------------------------------------------------------------------------
/apps/demo/emails/static/apple-card-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/apple-card-icon.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/apple-hbo-max-icon.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/apple-hbo-max-icon.jpeg


--------------------------------------------------------------------------------
/apps/demo/emails/static/apple-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/apple-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/apple-wallet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/apple-wallet.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/aws-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/aws-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/codepen-challengers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/codepen-challengers.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/codepen-cube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/codepen-cube.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/codepen-pro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/codepen-pro.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/dropbox-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/dropbox-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/github.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/google-play-academy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/google-play-academy.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/google-play-chat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/google-play-chat.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/google-play-footer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/google-play-footer.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/google-play-header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/google-play-header.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/google-play-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/google-play-icon.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/google-play-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/google-play-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/google-play-pl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/google-play-pl.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/google-play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/google-play.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/koala-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/koala-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/linear-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/linear-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/netlify-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/netlify-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/nike-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/nike-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/nike-phone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/nike-phone.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/nike-product.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/nike-product.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/nike-recomendation-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/nike-recomendation-1.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/nike-recomendation-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/nike-recomendation-2.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/nike-recomendation-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/nike-recomendation-3.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/nike-recomendation-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/nike-recomendation-4.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/notion-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/notion-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/plaid-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/plaid-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/raycast-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/raycast-bg.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/raycast-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/raycast-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/slack-facebook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/slack-facebook.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/slack-linkedin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/slack-linkedin.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/slack-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/slack-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/slack-twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/slack-twitter.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/stack-overflow-header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/stack-overflow-header.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/stack-overflow-logo-sm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/stack-overflow-logo-sm.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/stack-overflow-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/stack-overflow-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/stripe-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/stripe-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/twitch-icon-facebook.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/twitch-icon-facebook.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/twitch-icon-twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/twitch-icon-twitter.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/twitch-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/twitch-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/vercel-arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/vercel-arrow.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/vercel-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/vercel-logo.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/vercel-team.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/vercel-team.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/vercel-user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/vercel-user.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/yelp-footer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/yelp-footer.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/yelp-header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/yelp-header.png


--------------------------------------------------------------------------------
/apps/demo/emails/static/yelp-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/demo/emails/static/yelp-logo.png


--------------------------------------------------------------------------------
/apps/demo/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "demo",
 3 |   "version": "0.0.0",
 4 |   "private": true,
 5 |   "scripts": {
 6 |     "build": "email-dev build",
 7 |     "dev": "email-dev dev",
 8 |     "start": "email-dev start",
 9 |     "export": "email-dev export"
10 |   },
11 |   "dependencies": {
12 |     "@react-email/components": "workspace:*",
13 |     "react": "^19",
14 |     "react-dom": "^19",
15 |     "email-dev": "workspace:*"
16 |   },
17 |   "devDependencies": {
18 |     "@react-email/preview-server": "workspace:*",
19 |     "next": "^15.3.2",
20 |     "@types/react": "^19",
21 |     "@types/react-dom": "^19"
22 |   }
23 | }
24 | 


--------------------------------------------------------------------------------
/apps/docs/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/docs/favicon.png


--------------------------------------------------------------------------------
/apps/docs/images/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/docs/images/background.png


--------------------------------------------------------------------------------
/apps/docs/images/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/docs/images/bg.png


--------------------------------------------------------------------------------
/apps/docs/images/local-dev.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/docs/images/local-dev.jpg


--------------------------------------------------------------------------------
/apps/docs/images/preview-server-vercel-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/docs/images/preview-server-vercel-settings.png


--------------------------------------------------------------------------------
/apps/docs/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "docs",
 3 |   "version": "0.0.0",
 4 |   "private": true,
 5 |   "scripts": {
 6 |     "dev": "mintlify dev"
 7 |   },
 8 |   "dependencies": {
 9 |     "mintlify": "4.1.96",
10 |     "zod": "3.24.3"
11 |   }
12 | }
13 | 


--------------------------------------------------------------------------------
/apps/docs/snippets/localdev.mdx:
--------------------------------------------------------------------------------
 1 | 1. Clone the repository:
 2 | 
 3 | ```sh
 4 | git clone https://github.com/resend/react-email.git
 5 | ```
 6 | 
 7 | 2. Install all dependencies:
 8 | 
 9 | ```sh
10 | pnpm install
11 | ```
12 | 
13 | 3. Run local servers and watch for changes:
14 | 
15 | ```sh
16 | pnpm dev
17 | ```
18 | 


--------------------------------------------------------------------------------
/apps/docs/snippets/next-steps.mdx:
--------------------------------------------------------------------------------
 1 | Try adding these other components to your email.
 2 | 
 3 | <CardGroup>
 4 |   <Card title="Image" icon='image' href="/components/image">
 5 |     Display an image in your email.
 6 |   </Card>
 7 |   <Card title="Link" icon='link' href="/components/link">
 8 |     A hyperlink to web pages or anything else a URL can address.
 9 |   </Card>
10 |   <Card title="Divider" icon='horizontal-rule' href="/components/hr">
11 |     Display a divider that separates content areas in your email.
12 |   </Card>
13 |   <Card
14 |     title="Preview"
15 |     icon='magnifying-glass'
16 |     href="/components/preview"
17 |   >
18 |     A preview text that will be displayed in the inbox of the recipient.
19 |   </Card>
20 | </CardGroup>
21 | 
22 | 


--------------------------------------------------------------------------------
/apps/web/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 |   "files.associations": {
3 |     "*.css": "tailwindcss"
4 |   }
5 | }
6 | 


--------------------------------------------------------------------------------
/apps/web/components/code-inline-with-different-colors/inline-styles.tsx:
--------------------------------------------------------------------------------
 1 | import { CodeInline, Text } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Text style={{ textAlign: 'center' }}>
 6 |     Install the{' '}
 7 |     <CodeInline
 8 |       style={{
 9 |         backgroundColor: 'rgb(134,239,172)',
10 |         borderRadius: 6,
11 |         paddingLeft: 4,
12 |         paddingRight: 4,
13 |         paddingTop: 2,
14 |         paddingBottom: 2,
15 |       }}
16 |     >
17 |       @react-email/components
18 |     </CodeInline>{' '}
19 |     package
20 |   </Text>
21 | );
22 | 
23 | export default () => {
24 |   return <Layout>{component}</Layout>;
25 | };
26 | 


--------------------------------------------------------------------------------
/apps/web/components/code-inline-with-different-colors/tailwind.tsx:
--------------------------------------------------------------------------------
 1 | import { CodeInline, Text } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Text className="text-center">
 6 |     Install the{' '}
 7 |     <CodeInline className="rounded-[6px] bg-green-300 px-[4px] py-[2px]">
 8 |       @react-email/components
 9 |     </CodeInline>{' '}
10 |     package
11 |   </Text>
12 | );
13 | 
14 | export default () => {
15 |   return <Layout>{component}</Layout>;
16 | };
17 | 


--------------------------------------------------------------------------------
/apps/web/components/divider-between-rows-and-columns/inline-styles.tsx:
--------------------------------------------------------------------------------
 1 | import { Column, Hr, Row } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <>
 6 |     <Row>
 7 |       <Column>First column</Column>
 8 |       <Column>Second column</Column>
 9 |     </Row>
10 |     <Hr
11 |       style={{
12 |         marginTop: 16,
13 |         borderColor: 'rgb(209,213,219)',
14 |         marginBottom: 16,
15 |       }}
16 |     />
17 |     <Row>
18 |       <Column>First column</Column>
19 |       <Column>Second column</Column>
20 |     </Row>
21 |   </>
22 | );
23 | 
24 | export default () => {
25 |   return <Layout>{component}</Layout>;
26 | };
27 | 


--------------------------------------------------------------------------------
/apps/web/components/divider-between-rows-and-columns/tailwind.tsx:
--------------------------------------------------------------------------------
 1 | import { Column, Hr, Row } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <>
 6 |     <Row>
 7 |       <Column>First column</Column>
 8 |       <Column>Second column</Column>
 9 |     </Row>
10 |     <Hr className="my-[16px] border-gray-300" />
11 |     <Row>
12 |       <Column>First column</Column>
13 |       <Column>Second column</Column>
14 |     </Row>
15 |   </>
16 | );
17 | 
18 | export default () => {
19 |   return <Layout>{component}</Layout>;
20 | };
21 | 


--------------------------------------------------------------------------------
/apps/web/components/link-inline-with-text/index.tsx:
--------------------------------------------------------------------------------
 1 | import { Link, Text } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Text>
 6 |     This is <Link href="https://react.email">React Email</Link>
 7 |   </Text>
 8 | );
 9 | 
10 | export default () => {
11 |   return <Layout>{component}</Layout>;
12 | };
13 | 


--------------------------------------------------------------------------------
/apps/web/components/markdown-with-container-styles/index.tsx:
--------------------------------------------------------------------------------
 1 | import { Markdown } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Markdown
 6 |     markdownContainerStyles={{
 7 |       marginBlock: 30,
 8 |     }}
 9 |   >
10 |     {`## Hello, this is my email template
11 | 
12 | This is meant to be rendered as a paragraph. There is no way around it.
13 | 
14 | ### Another heading that I wrote
15 |         `}
16 |   </Markdown>
17 | );
18 | 
19 | export default () => {
20 |   return <Layout>{component}</Layout>;
21 | };
22 | 


--------------------------------------------------------------------------------
/apps/web/components/markdown-with-custom-styles/index.tsx:
--------------------------------------------------------------------------------
 1 | import { Markdown } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Markdown
 6 |     markdownCustomStyles={{
 7 |       h1: { color: 'red' },
 8 |       h2: { color: 'blue' },
 9 |       codeInline: { background: 'grey' },
10 |     }}
11 |   >
12 |     {`## Hello, this is my email template
13 | 
14 | This is meant to be rendered as a paragraph. There is no way around it.
15 | 
16 | ### Another heading that I wrote
17 |         `}
18 |   </Markdown>
19 | );
20 | 
21 | export default () => {
22 |   return <Layout>{component}</Layout>;
23 | };
24 | 


--------------------------------------------------------------------------------
/apps/web/components/one-row-three-columns/tailwind.tsx:
--------------------------------------------------------------------------------
 1 | import { Column, Row } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Row>
 6 |     <Column align="center" className="h-[40px] w-1/3 bg-orange-400/60">
 7 |       1/3
 8 |     </Column>
 9 |     <Column align="center" className="h-[40px] w-1/3 bg-emerald-400/60">
10 |       1/3
11 |     </Column>
12 |     <Column align="center" className="h-[40px] w-1/3 bg-cyan-400/60">
13 |       1/3
14 |     </Column>
15 |   </Row>
16 | );
17 | 
18 | export default () => {
19 |   return <Layout>{component}</Layout>;
20 | };
21 | 


--------------------------------------------------------------------------------
/apps/web/components/rounded-image/inline-styles.tsx:
--------------------------------------------------------------------------------
 1 | import { Img } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Img
 6 |     alt="Stagg Electric Kettle"
 7 |     height={250}
 8 |     src="/static/stagg-eletric-kettle.jpg"
 9 |     style={{ borderRadius: 12, margin: '0 auto' }}
10 |   />
11 | );
12 | 
13 | export default () => {
14 |   return <Layout>{component}</Layout>;
15 | };
16 | 


--------------------------------------------------------------------------------
/apps/web/components/rounded-image/tailwind.tsx:
--------------------------------------------------------------------------------
 1 | import { Img } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Img
 6 |     alt="Stagg Electric Kettle"
 7 |     className="rounded-[12px] [margin:0_auto]"
 8 |     height={250}
 9 |     src="/static/stagg-eletric-kettle.jpg"
10 |   />
11 | );
12 | 
13 | export default () => {
14 |   return <Layout>{component}</Layout>;
15 | };
16 | 


--------------------------------------------------------------------------------
/apps/web/components/section-with-rows-and-columns/index.tsx:
--------------------------------------------------------------------------------
 1 | import { Column, Row, Section } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Section>
 6 |     <Row>
 7 |       <Column>Column 1, Row 1</Column>
 8 |       <Column>Column 2, Row 1</Column>
 9 |     </Row>
10 |     <Row>
11 |       <Column>Column 1, Row 2</Column>
12 |       <Column>Column 2, Row 2</Column>
13 |     </Row>
14 |   </Section>
15 | );
16 | 
17 | export default () => {
18 |   return <Layout>{component}</Layout>;
19 | };
20 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-code-inline/inline-styles.tsx:
--------------------------------------------------------------------------------
 1 | import { CodeInline, Text } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Text style={{ textAlign: 'center' }}>
 6 |     Install the{' '}
 7 |     <CodeInline
 8 |       style={{
 9 |         backgroundColor: 'rgb(209,213,219)',
10 |         borderRadius: 6,
11 |         paddingLeft: 4,
12 |         paddingRight: 4,
13 |         paddingTop: 2,
14 |         paddingBottom: 2,
15 |       }}
16 |     >
17 |       @react-email/components
18 |     </CodeInline>{' '}
19 |     package
20 |   </Text>
21 | );
22 | 
23 | export default () => {
24 |   return <Layout>{component}</Layout>;
25 | };
26 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-code-inline/tailwind.tsx:
--------------------------------------------------------------------------------
 1 | import { CodeInline, Text } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Text className="text-center">
 6 |     Install the{' '}
 7 |     <CodeInline className="rounded-[6px] bg-gray-300 px-[4px] py-[2px]">
 8 |       @react-email/components
 9 |     </CodeInline>{' '}
10 |     package
11 |   </Text>
12 | );
13 | 
14 | export default () => {
15 |   return <Layout>{component}</Layout>;
16 | };
17 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-container/inline-styles.tsx:
--------------------------------------------------------------------------------
 1 | import { Container, Text } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Container style={{ backgroundColor: 'rgb(156,163,175)' }}>
 6 |     <Text
 7 |       style={{ color: 'rgb(255,255,255)', paddingLeft: 12, paddingRight: 12 }}
 8 |     >
 9 |       Hello, I am a container. I keep content centered and maintain it to a
10 |       maximum width while still taking up as much space as possible!
11 |     </Text>
12 |   </Container>
13 | );
14 | 
15 | export default () => {
16 |   return <Layout>{component}</Layout>;
17 | };
18 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-container/tailwind.tsx:
--------------------------------------------------------------------------------
 1 | import { Container, Text } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Container className="bg-gray-400">
 6 |     <Text className="px-[12px] text-white">
 7 |       Hello, I am a container. I keep content centered and maintain it to a
 8 |       maximum width while still taking up as much space as possible!
 9 |     </Text>
10 |   </Container>
11 | );
12 | 
13 | export default () => {
14 |   return <Layout>{component}</Layout>;
15 | };
16 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-divider/inline-styles.tsx:
--------------------------------------------------------------------------------
 1 | import { Hr, Text } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <>
 6 |     <Text>Before divider</Text>
 7 |     <Hr
 8 |       style={{
 9 |         marginTop: 16,
10 |         borderColor: 'rgb(209,213,219)',
11 |         marginBottom: 16,
12 |         borderTopWidth: 2,
13 |       }}
14 |     />
15 |     <Text>After divider</Text>
16 |   </>
17 | );
18 | 
19 | export default () => {
20 |   return <Layout>{component}</Layout>;
21 | };
22 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-divider/tailwind.tsx:
--------------------------------------------------------------------------------
 1 | import { Hr, Text } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <>
 6 |     <Text>Before divider</Text>
 7 |     <Hr className="my-[16px] border-gray-300 border-t-2" />
 8 |     <Text>After divider</Text>
 9 |   </>
10 | );
11 | 
12 | export default () => {
13 |   return <Layout>{component}</Layout>;
14 | };
15 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-heading/inline-styles.tsx:
--------------------------------------------------------------------------------
 1 | import { Heading } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Heading style={{ textAlign: 'center' }}>Ray Tomlinson</Heading>
 6 | );
 7 | 
 8 | export default () => {
 9 |   return <Layout>{component}</Layout>;
10 | };
11 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-heading/tailwind.tsx:
--------------------------------------------------------------------------------
 1 | import { Heading } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Heading className="text-center">Ray Tomlinson</Heading>
 6 | );
 7 | 
 8 | export default () => {
 9 |   return <Layout>{component}</Layout>;
10 | };
11 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-image/inline-styles.tsx:
--------------------------------------------------------------------------------
 1 | import { Img } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Img
 6 |     alt="Ode Grinder"
 7 |     height={250}
 8 |     src="/static/ode-grinder.jpg"
 9 |     style={{ marginLeft: 'auto', marginRight: 'auto' }}
10 |   />
11 | );
12 | 
13 | export default () => {
14 |   return <Layout>{component}</Layout>;
15 | };
16 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-image/tailwind.tsx:
--------------------------------------------------------------------------------
 1 | import { Img } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Img
 6 |     alt="Ode Grinder"
 7 |     className="mx-auto"
 8 |     height={250}
 9 |     src="/static/ode-grinder.jpg"
10 |   />
11 | );
12 | 
13 | export default () => {
14 |   return <Layout>{component}</Layout>;
15 | };
16 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-link/index.tsx:
--------------------------------------------------------------------------------
1 | import { Link } from '@react-email/components';
2 | import { Layout } from '../_components/layout';
3 | 
4 | export const component = <Link href="https://react.email">React Email</Link>;
5 | 
6 | export default () => {
7 |   return <Layout>{component}</Layout>;
8 | };
9 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-markdown/index.tsx:
--------------------------------------------------------------------------------
 1 | import { Markdown } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Markdown>
 6 |     {`## Hello, this is my email template
 7 | 
 8 | This is meant to be rendered as a paragraph. There is no way around it.
 9 | 
10 | ### Another heading that I wrote
11 |         `}
12 |   </Markdown>
13 | );
14 | 
15 | export default () => {
16 |   return <Layout>{component}</Layout>;
17 | };
18 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-section/index.tsx:
--------------------------------------------------------------------------------
 1 | import { Section, Text } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Section>
 6 |     <Text>Hello my section!</Text>
 7 |   </Section>
 8 | );
 9 | 
10 | export default () => {
11 |   return <Layout>{component}</Layout>;
12 | };
13 | 


--------------------------------------------------------------------------------
/apps/web/components/simple-text/index.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from '@react-email/components';
2 | import { Layout } from '../_components/layout';
3 | 
4 | export const component = <Text>A simple paragraph</Text>;
5 | 
6 | export default () => {
7 |   return <Layout>{component}</Layout>;
8 | };
9 | 


--------------------------------------------------------------------------------
/apps/web/components/single-button/inline-styles.tsx:
--------------------------------------------------------------------------------
 1 | import { Button } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Button
 6 |     href="https://react.email"
 7 |     style={{
 8 |       width: '100%',
 9 |       boxSizing: 'border-box',
10 |       padding: 12,
11 |       fontWeight: 600,
12 |       borderRadius: 8,
13 |       textAlign: 'center',
14 |       backgroundColor: 'rgb(79,70,229)',
15 |       color: 'rgb(255,255,255)',
16 |     }}
17 |   >
18 |     Get started
19 |   </Button>
20 | );
21 | 
22 | export default () => {
23 |   return <Layout>{component}</Layout>;
24 | };
25 | 


--------------------------------------------------------------------------------
/apps/web/components/single-button/tailwind.tsx:
--------------------------------------------------------------------------------
 1 | import { Button } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <Button
 6 |     className="box-border w-full rounded-[8px] bg-indigo-600 px-[12px] py-[12px] text-center font-semibold text-white"
 7 |     href="https://react.email"
 8 |   >
 9 |     Get started
10 |   </Button>
11 | );
12 | 
13 | export default () => {
14 |   return <Layout>{component}</Layout>;
15 | };
16 | 


--------------------------------------------------------------------------------
/apps/web/components/static/cube-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/cube-icon.png


--------------------------------------------------------------------------------
/apps/web/components/static/download-on-the-app-store.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/download-on-the-app-store.png


--------------------------------------------------------------------------------
/apps/web/components/static/facebook-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/facebook-logo.png


--------------------------------------------------------------------------------
/apps/web/components/static/get-it-on-google-play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/get-it-on-google-play.png


--------------------------------------------------------------------------------
/apps/web/components/static/heart-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/heart-icon.png


--------------------------------------------------------------------------------
/apps/web/components/static/in-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/in-icon.png


--------------------------------------------------------------------------------
/apps/web/components/static/instagram-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/instagram-logo.png


--------------------------------------------------------------------------------
/apps/web/components/static/logo-without-background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/logo-without-background.png


--------------------------------------------------------------------------------
/apps/web/components/static/megaphone-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/megaphone-icon.png


--------------------------------------------------------------------------------
/apps/web/components/static/rocket-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/rocket-icon.png


--------------------------------------------------------------------------------
/apps/web/components/static/steve-jobs.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/steve-jobs.jpg


--------------------------------------------------------------------------------
/apps/web/components/static/steve-wozniak.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/steve-wozniak.jpg


--------------------------------------------------------------------------------
/apps/web/components/static/x-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/x-icon.png


--------------------------------------------------------------------------------
/apps/web/components/static/x-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/components/static/x-logo.png


--------------------------------------------------------------------------------
/apps/web/components/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | export default {};
2 | 


--------------------------------------------------------------------------------
/apps/web/components/text-with-styling/inline-styles.tsx:
--------------------------------------------------------------------------------
 1 | import { Text } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <>
 6 |     <Text
 7 |       style={{
 8 |         color: 'rgb(129,140,248)',
 9 |         fontSize: 24,
10 |         lineHeight: '32px',
11 |         fontWeight: 600,
12 |       }}
13 |     >
14 |       Amazing content
15 |     </Text>
16 |     <Text>
17 |       This is the actual content that the accented text above refers to.
18 |     </Text>
19 |   </>
20 | );
21 | 
22 | export default () => {
23 |   return <Layout>{component}</Layout>;
24 | };
25 | 


--------------------------------------------------------------------------------
/apps/web/components/text-with-styling/tailwind.tsx:
--------------------------------------------------------------------------------
 1 | import { Text } from '@react-email/components';
 2 | import { Layout } from '../_components/layout';
 3 | 
 4 | export const component = (
 5 |   <>
 6 |     <Text className="font-semibold text-[24px] text-indigo-400 leading-[32px]">
 7 |       Amazing content
 8 |     </Text>
 9 |     <Text>
10 |       This is the actual content that the accented text above refers to.
11 |     </Text>
12 |   </>
13 | );
14 | 
15 | export default () => {
16 |   return <Layout>{component}</Layout>;
17 | };
18 | 


--------------------------------------------------------------------------------
/apps/web/components/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "compilerOptions": {
3 |     "jsx": "react-jsx"
4 |   }
5 | }
6 | 


--------------------------------------------------------------------------------
/apps/web/next-env.d.ts:
--------------------------------------------------------------------------------
1 | /// <reference types="next" />
2 | /// <reference types="next/image-types/global" />
3 | 
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
6 | 


--------------------------------------------------------------------------------
/apps/web/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 |   plugins: {
3 |     tailwindcss: {},
4 |     autoprefixer: {},
5 |   },
6 | };
7 | 


--------------------------------------------------------------------------------
/apps/web/public/brand/logo-without-background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/brand/logo-without-background.png


--------------------------------------------------------------------------------
/apps/web/public/brand/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/brand/logo.png


--------------------------------------------------------------------------------
/apps/web/public/brand/resend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/brand/resend.png


--------------------------------------------------------------------------------
/apps/web/public/examples/airbnb-review.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/airbnb-review.png


--------------------------------------------------------------------------------
/apps/web/public/examples/apple-receipt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/apple-receipt.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/EmersonGarrido.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/EmersonGarrido.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/Rychillie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/Rychillie.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/abhinandanwadwa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/abhinandanwadwa.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/bruno88cabral.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/bruno88cabral.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/bukinoshita.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/bukinoshita.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/c0dr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/c0dr.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/camillegachido.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/camillegachido.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/joaom00.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/joaom00.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/nettofarah.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/nettofarah.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/relferreira.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/relferreira.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/ribeiroevandro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/ribeiroevandro.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/thecodeinfluencer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/thecodeinfluencer.png


--------------------------------------------------------------------------------
/apps/web/public/examples/authors/zenorocha.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/authors/zenorocha.png


--------------------------------------------------------------------------------
/apps/web/public/examples/aws-verify-email.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/aws-verify-email.png


--------------------------------------------------------------------------------
/apps/web/public/examples/dropbox-reset-password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/dropbox-reset-password.png


--------------------------------------------------------------------------------
/apps/web/public/examples/github-access-token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/github-access-token.png


--------------------------------------------------------------------------------
/apps/web/public/examples/google-play-policy-update.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/google-play-policy-update.png


--------------------------------------------------------------------------------
/apps/web/public/examples/koala-welcome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/koala-welcome.png


--------------------------------------------------------------------------------
/apps/web/public/examples/linear-login-code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/linear-login-code.png


--------------------------------------------------------------------------------
/apps/web/public/examples/nike-receipt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/nike-receipt.png


--------------------------------------------------------------------------------
/apps/web/public/examples/notion-magic-link.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/notion-magic-link.png


--------------------------------------------------------------------------------
/apps/web/public/examples/plaid-verify-identity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/plaid-verify-identity.png


--------------------------------------------------------------------------------
/apps/web/public/examples/raycast-magic-link.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/raycast-magic-link.png


--------------------------------------------------------------------------------
/apps/web/public/examples/slack-confirm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/slack-confirm.png


--------------------------------------------------------------------------------
/apps/web/public/examples/stack-overflow-tips.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/stack-overflow-tips.png


--------------------------------------------------------------------------------
/apps/web/public/examples/stripe-welcome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/stripe-welcome.png


--------------------------------------------------------------------------------
/apps/web/public/examples/twitch-reset-password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/twitch-reset-password.png


--------------------------------------------------------------------------------
/apps/web/public/examples/vercel-invite-user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/vercel-invite-user.png


--------------------------------------------------------------------------------
/apps/web/public/examples/yelp-recent-login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/examples/yelp-recent-login.png


--------------------------------------------------------------------------------
/apps/web/public/fonts/commit-mono/commit-mono-italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/fonts/commit-mono/commit-mono-italic.ttf


--------------------------------------------------------------------------------
/apps/web/public/fonts/commit-mono/commit-mono-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/fonts/commit-mono/commit-mono-regular.ttf


--------------------------------------------------------------------------------
/apps/web/public/fonts/inter/inter.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/fonts/inter/inter.ttf


--------------------------------------------------------------------------------
/apps/web/public/fonts/shantell-sans/shantell-sans-italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/fonts/shantell-sans/shantell-sans-italic.ttf


--------------------------------------------------------------------------------
/apps/web/public/fonts/shantell-sans/shantell-sans-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/fonts/shantell-sans/shantell-sans-regular.ttf


--------------------------------------------------------------------------------
/apps/web/public/meta/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/meta/apple-touch-icon.png


--------------------------------------------------------------------------------
/apps/web/public/meta/cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/meta/cover.png


--------------------------------------------------------------------------------
/apps/web/public/meta/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/meta/favicon.ico


--------------------------------------------------------------------------------
/apps/web/public/static/atmos-vacuum-canister.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/atmos-vacuum-canister.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/bg.png


--------------------------------------------------------------------------------
/apps/web/public/static/braun-analogue-clock.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/braun-analogue-clock.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/braun-classic-watch.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/braun-classic-watch.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/braun-collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/braun-collection.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/braun-vintage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/braun-vintage.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/braun-wall-clock.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/braun-wall-clock.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/braun-wireless-alarm.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/braun-wireless-alarm.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/bundle-collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/bundle-collection.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/clara-french-press.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/clara-french-press.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/clyde-electric-kettle.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/clyde-electric-kettle.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/coffee-bean-storage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/coffee-bean-storage.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/covers/button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/button.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/code-block.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/code-block.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/code-inline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/code-inline.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/column.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/column.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/components.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/components.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/container.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/container.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/create-email.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/create-email.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/font.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/font.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/head.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/head.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/heading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/heading.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/hr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/hr.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/html.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/html.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/img.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/link.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/link.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/markdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/markdown.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/patterns.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/patterns.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/preview.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/react-email.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/react-email.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/render.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/render.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/row.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/row.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/section.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/section.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/tailwind.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/tailwind.png


--------------------------------------------------------------------------------
/apps/web/public/static/covers/text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/covers/text.png


--------------------------------------------------------------------------------
/apps/web/public/static/cube-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/cube-icon.png


--------------------------------------------------------------------------------
/apps/web/public/static/download-on-the-app-store.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/download-on-the-app-store.png


--------------------------------------------------------------------------------
/apps/web/public/static/facebook-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/facebook-logo.png


--------------------------------------------------------------------------------
/apps/web/public/static/get-it-on-google-play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/get-it-on-google-play.png


--------------------------------------------------------------------------------
/apps/web/public/static/grinder-collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/grinder-collection.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/heart-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/heart-icon.png


--------------------------------------------------------------------------------
/apps/web/public/static/herman-miller-chair.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/herman-miller-chair.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/in-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/in-icon.png


--------------------------------------------------------------------------------
/apps/web/public/static/instagram-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/instagram-logo.png


--------------------------------------------------------------------------------
/apps/web/public/static/logo-without-background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/logo-without-background.png


--------------------------------------------------------------------------------
/apps/web/public/static/megaphone-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/megaphone-icon.png


--------------------------------------------------------------------------------
/apps/web/public/static/monty-art-cup-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/monty-art-cup-1.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/monty-art-cup-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/monty-art-cup-2.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/mugs-collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/mugs-collection.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/ode-grinder.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/ode-grinder.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/outdoor-living.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/outdoor-living.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/rocket-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/rocket-icon.png


--------------------------------------------------------------------------------
/apps/web/public/static/stagg-eletric-kettle.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/stagg-eletric-kettle.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/steve-jobs.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/steve-jobs.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/steve-wozniak.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/steve-wozniak.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/vacuum-canister-clear-glass-bundle.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/vacuum-canister-clear-glass-bundle.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/versatile-comfort.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/versatile-comfort.jpg


--------------------------------------------------------------------------------
/apps/web/public/static/x-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/x-icon.png


--------------------------------------------------------------------------------
/apps/web/public/static/x-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/apps/web/public/static/x-logo.png


--------------------------------------------------------------------------------
/apps/web/src/app/robots.ts:
--------------------------------------------------------------------------------
 1 | const Robots = () => {
 2 |   return {
 3 |     rules: [
 4 |       {
 5 |         userAgent: '*',
 6 |         allow: '/',
 7 |       },
 8 |     ],
 9 |     sitemap: 'https://react.email/sitemap.xml',
10 |     host: 'https://react.email',
11 |   };
12 | };
13 | 
14 | export default Robots;
15 | 


--------------------------------------------------------------------------------
/apps/web/src/app/sitemap.ts:
--------------------------------------------------------------------------------
 1 | const Sitemap = async () => {
 2 |   const routes = ['', '/components', '/examples'].map((route) => ({
 3 |     url: `https://react.email${route}`,
 4 |     lastModified: new Date().toISOString().split('T')[0],
 5 |   }));
 6 | 
 7 |   return [...routes];
 8 | };
 9 | 
10 | export default Sitemap;
11 | 


--------------------------------------------------------------------------------
/apps/web/src/components/anchor.tsx:
--------------------------------------------------------------------------------
 1 | import classNames from 'classnames';
 2 | import type * as React from 'react';
 3 | 
 4 | export const Anchor: React.FC<
 5 |   Readonly<React.ComponentPropsWithoutRef<'a'>>
 6 | > = ({ className, ...props }) => (
 7 |   <a
 8 |     className={classNames(
 9 |       'rounded-sm outline-none transition-transform duration-200 ease-in-out',
10 |       'hover:-translate-y-1',
11 |       'focus:ring-2 focus:ring-white/20 focus:ring-offset-4 focus:ring-offset-black',
12 |       'text-slate-12',
13 |       className,
14 |     )}
15 |     {...props}
16 |   >
17 |     {props.children}
18 |   </a>
19 | );
20 | 


--------------------------------------------------------------------------------
/apps/web/src/components/components-view.tsx:
--------------------------------------------------------------------------------
 1 | import type { ImportedComponent } from '../app/components/get-imported-components-for';
 2 | import { ComponentView } from './component-view';
 3 | 
 4 | interface ComponentsViewProps {
 5 |   components: ImportedComponent[];
 6 | }
 7 | 
 8 | export const ComponentsView: React.FC<ComponentsViewProps> = ({
 9 |   components,
10 | }) => {
11 |   return (
12 |     <>
13 |       {components.map((component, index) => (
14 |         <ComponentView
15 |           className={index !== 0 ? 'border-slate-4 border-t pt-4' : ''}
16 |           component={component}
17 |           key={component.slug}
18 |         />
19 |       ))}
20 |     </>
21 |   );
22 | };
23 | 


--------------------------------------------------------------------------------
/apps/web/src/components/icon-button.tsx:
--------------------------------------------------------------------------------
 1 | import classNames from 'classnames';
 2 | import type * as React from 'react';
 3 | 
 4 | type IconButtonProps = React.ComponentPropsWithoutRef<'button'>;
 5 | 
 6 | export const IconButton: React.FC<Readonly<IconButtonProps>> = ({
 7 |   children,
 8 |   className,
 9 |   ...props
10 | }) => (
11 |   <button
12 |     {...props}
13 |     className={classNames(
14 |       'rounded p-1 text-[#EEF7FE] transition duration-200 ease-in-out hover:text-white focus:text-white focus:outline-none focus:ring-2 focus:ring-slate-6',
15 |       className,
16 |     )}
17 |     type="button"
18 |   >
19 |     {children}
20 |   </button>
21 | );
22 | 


--------------------------------------------------------------------------------
/apps/web/src/components/icons/icon-base.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | 
 3 | export type IconElement = SVGSVGElement;
 4 | export interface IconProps extends React.ComponentPropsWithoutRef<'svg'> {
 5 |   size?: number;
 6 | }
 7 | 
 8 | export const IconBase = React.forwardRef<IconElement, Readonly<IconProps>>(
 9 |   ({ size = 20, ...props }, forwardedRef) => (
10 |     <svg
11 |       fill="none"
12 |       height={size}
13 |       ref={forwardedRef}
14 |       viewBox="0 0 24 24"
15 |       width={size}
16 |       xmlns="http://www.w3.org/2000/svg"
17 |       {...props}
18 |     />
19 |   ),
20 | );
21 | 
22 | IconBase.displayName = 'IconBase';
23 | 


--------------------------------------------------------------------------------
/apps/web/src/components/icons/icon-source.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | import type { IconElement, IconProps } from './icon-base';
 3 | import { IconBase } from './icon-base';
 4 | 
 5 | export const IconSource = React.forwardRef<IconElement, Readonly<IconProps>>(
 6 |   ({ ...props }, forwardedRef) => (
 7 |     <IconBase ref={forwardedRef} {...props}>
 8 |       <path
 9 |         d="M17.4 15L21 11.5L17.4 8M6.6 8L3 11.5L6.6 15M14.25 4.5L9.75 18.5"
10 |         stroke="currentColor"
11 |         strokeLinecap="round"
12 |         strokeLinejoin="round"
13 |         strokeWidth="1.5"
14 |       />
15 |     </IconBase>
16 |   ),
17 | );
18 | 
19 | IconSource.displayName = 'IconSource';
20 | 


--------------------------------------------------------------------------------
/apps/web/src/components/tooltip.tsx:
--------------------------------------------------------------------------------
 1 | import * as TooltipPrimitive from '@radix-ui/react-tooltip';
 2 | import type * as React from 'react';
 3 | import { TooltipContent } from './tooltip-content';
 4 | 
 5 | type RootProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>;
 6 | 
 7 | export type TooltipProps = RootProps;
 8 | 
 9 | export const TooltipRoot: React.FC<Readonly<TooltipProps>> = ({
10 |   children,
11 |   ...props
12 | }) => <TooltipPrimitive.Root {...props}>{children}</TooltipPrimitive.Root>;
13 | 
14 | export const Tooltip = Object.assign(TooltipRoot, {
15 |   Arrow: TooltipPrimitive.TooltipArrow,
16 |   Provider: TooltipPrimitive.TooltipProvider,
17 |   Content: TooltipContent,
18 |   Trigger: TooltipPrimitive.TooltipTrigger,
19 | });
20 | 


--------------------------------------------------------------------------------
/apps/web/src/components/topbar.tsx:
--------------------------------------------------------------------------------
 1 | import classNames from 'classnames';
 2 | import Link from 'next/link';
 3 | import type * as React from 'react';
 4 | import { Logo } from './logo';
 5 | import { Menu } from './menu';
 6 | 
 7 | export const Topbar: React.FC<
 8 |   Readonly<React.ComponentPropsWithoutRef<'header'>>
 9 | > = ({ className, ...props }) => (
10 |   <header
11 |     className={classNames(
12 |       'z-[3] flex items-center justify-between px-6 py-8',
13 |       className,
14 |     )}
15 |     {...props}
16 |   >
17 |     <Link
18 |       className="-ml-[.375rem] flex scroll-m-2 rounded-md pr-[.375rem] transition-colors focus:outline-none focus:ring focus:ring-slate-4"
19 |       href="/"
20 |     >
21 |       <Logo />
22 |     </Link>
23 |     <Menu />
24 |   </header>
25 | );
26 | 


--------------------------------------------------------------------------------
/apps/web/src/hooks/use-stored-state.ts:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | 
 3 | export const useStoredState = <T extends string | undefined>(
 4 |   key: string,
 5 |   defaultValue: T,
 6 | ): [state: T, setState: (newValue: T) => void] => {
 7 |   const [state, setState] = React.useState<T>(defaultValue);
 8 |   React.useEffect(() => {
 9 |     const storedValue = localStorage.getItem(key);
10 |     if (storedValue) {
11 |       setState(storedValue as T);
12 |     }
13 |   }, [key]);
14 | 
15 |   return [
16 |     state,
17 |     (newValue) => {
18 |       if (newValue) {
19 |         localStorage.setItem(key, newValue);
20 |       }
21 |       setState(newValue);
22 |     },
23 |   ];
24 | };
25 | 


--------------------------------------------------------------------------------
/apps/web/src/illustrations/articles.tsx:
--------------------------------------------------------------------------------
 1 | const IllustrationArticles: React.FC = () => (
 2 |   <div className="relative flex aspect-square w-[45%] translate-y-3 flex-col items-center gap-1.5 rounded-md bg-[#0F0F10] bg-gradient-to-b from-transparent via-black/20 to-black/10 px-3 pt-2 pb-5 shadow-sm transition-transform duration-150 ease-[cubic-bezier(.42,0,.58,1.8)] group-hover:skew-x-2">
 3 |     <div className="aspect-video w-full rounded-sm bg-slate-4" />
 4 |     <div className="h-3 w-[66%] rounded-sm bg-slate-5" />
 5 |     <div className="h-3 w-[66%] rounded-sm bg-slate-5" />
 6 |     <div className="mt-1 h-3 w-[24%] rounded-sm border border-[#2EBDC9] bg-[#25AEBA] shadow-[0px_0px_15px_5px_rgba(37,174,186,0.30)]" />
 7 |   </div>
 8 | );
 9 | 
10 | export default IllustrationArticles;
11 | 


--------------------------------------------------------------------------------
/apps/web/src/illustrations/buttons.tsx:
--------------------------------------------------------------------------------
 1 | import { MousePointer2Icon } from 'lucide-react';
 2 | 
 3 | const IllustrationButtons: React.FC = () => (
 4 |   <div className="relative flex h-6 w-[24%] items-center justify-center rounded-md border border-[#2EBDC9] bg-[#25AEBA] p-1 shadow-sm transition-transform duration-150 ease-[cubic-bezier(.42,0,.58,1.8)] group-hover:rotate-3">
 5 |     <div className="h-2 w-[80%] rounded-sm bg-black/30" />
 6 |     <MousePointer2Icon
 7 |       className="-bottom-4 group-hover:-rotate-12 absolute left-[80%] transition-transform duration-150 ease-[cubic-bezier(.42,0,.58,1.8)]"
 8 |       fill="currentColor"
 9 |       stroke="currentColor"
10 |     />
11 |   </div>
12 | );
13 | 
14 | export default IllustrationButtons;
15 | 


--------------------------------------------------------------------------------
/apps/web/src/illustrations/code-inline.tsx:
--------------------------------------------------------------------------------
 1 | import { ChevronRightIcon } from 'lucide-react';
 2 | 
 3 | const IllustrationCodeInline: React.FC = () => (
 4 |   <div className="relative flex w-[40%] items-center gap-2 rounded-full bg-[#0F0F10] bg-gradient-to-b from-transparent via-black/20 to-black/20 p-3 shadow-sm transition-transform duration-150 ease-[cubic-bezier(.42,0,.58,1.8)] group-hover:skew-x-2">
 5 |     <ChevronRightIcon size={14} strokeWidth={4} />
 6 |     <div className="h-1 w-[24%] rounded-sm border border-[#2EBDC9] bg-[#25AEBA] shadow-[0px_0px_9px_4px_rgba(37,174,186,0.10)] transition-colors ease-in-out" />
 7 |     <div className="h-1 shrink grow basis-0 rounded-sm bg-slate-5" />
 8 |   </div>
 9 | );
10 | 
11 | export default IllustrationCodeInline;
12 | 


--------------------------------------------------------------------------------
/apps/web/src/illustrations/divider.tsx:
--------------------------------------------------------------------------------
 1 | const IllustrationDivider: React.FC = () => (
 2 |   <div className="relative flex w-[40%] flex-col items-center gap-4 rounded-sm bg-[#0F0F10] bg-gradient-to-b from-transparent via-black/20 to-black/20 p-3 shadow-sm transition-transform duration-150 ease-[cubic-bezier(.42,0,.58,1.8)] group-hover:skew-x-3">
 3 |     <div className="h-3 w-[66%] rounded-sm bg-slate-5" />
 4 |     <div className="mr-1 flex h-0.5 w-full items-center justify-center gap-1 rounded-sm border border-[#2EBDC9] bg-[#25AEBA] shadow-[0px_0px_9px_4px_rgba(37,174,186,0.10)] transition-all group-hover:scale-x-105" />
 5 |     <div className="h-3 w-[66%] rounded-sm bg-slate-5" />
 6 |   </div>
 7 | );
 8 | 
 9 | export default IllustrationDivider;
10 | 


--------------------------------------------------------------------------------
/apps/web/src/illustrations/heading.tsx:
--------------------------------------------------------------------------------
 1 | const IllustrationHeading: React.FC = () => (
 2 |   <div className="relative flex w-[40%] flex-col items-center gap-2 rounded-md bg-[#0F0F10] bg-gradient-to-b from-transparent via-black/20 to-black/20 px-2 pt-2 pb-4 shadow-sm">
 3 |     <div className="h-2 w-[84%] rounded-sm bg-slate-6 transition-transform group-hover:scale-x-105" />
 4 |     <div className="h-2 w-[72%] rounded-sm bg-slate-5 transition-transform group-hover:scale-x-105" />
 5 |     <div className="h-2 w-[60%] rounded-sm bg-slate-4 transition-transform group-hover:scale-x-105" />
 6 |     <div className="h-2 w-[42%] rounded-sm bg-slate-3 transition-transform group-hover:scale-x-105" />
 7 |   </div>
 8 | );
 9 | 
10 | export default IllustrationHeading;
11 | 


--------------------------------------------------------------------------------
/apps/web/src/illustrations/image.tsx:
--------------------------------------------------------------------------------
 1 | import { ImageIcon } from 'lucide-react';
 2 | 
 3 | const IllustrationImage: React.FC = () => (
 4 |   <div className="flex aspect-square w-[30%] items-center justify-center rounded-md bg-slate-4 transition-colors group-hover:bg-slate-5">
 5 |     <ImageIcon className="opacity-5 transition-opacity group-hover:opacity-20" />
 6 |   </div>
 7 | );
 8 | 
 9 | export default IllustrationImage;
10 | 


--------------------------------------------------------------------------------
/apps/web/src/illustrations/section.tsx:
--------------------------------------------------------------------------------
1 | const IllustrationSection: React.FC = () => (
2 |   <div className="relative flex aspect-video w-[40%] flex-col items-center gap-2 rounded-md border-[.1875rem] border-slate-4 border-dashed bg-[#0F0F10] bg-gradient-to-b from-transparent via-black/20 to-black/20 px-2 pt-2 pb-4 shadow-sm transition-transform duration-150 ease-[cubic-bezier(.42,0,.58,1.8)] group-hover:skew-x-2" />
3 | );
4 | 
5 | export default IllustrationSection;
6 | 


--------------------------------------------------------------------------------
/apps/web/src/illustrations/text.tsx:
--------------------------------------------------------------------------------
 1 | const IllustrationText: React.FC = () => (
 2 |   <div className="group-hover:-skew-x-6 relative flex w-[40%] translate-y-3 flex-col gap-2 rounded-md bg-[#0F0F10] bg-gradient-to-b from-transparent via-black/20 to-black/20 p-2 shadow-sm transition-transform duration-150 ease-[cubic-bezier(.42,0,.58,1.8)]">
 3 |     <div className="h-1 w-[84%] rounded-sm bg-slate-5" />
 4 |     <div className="flex w-full gap-1">
 5 |       <div className="h-1 shrink grow basis-0 rounded-sm bg-slate-5" />
 6 |       <div className="h-1 shrink grow basis-0 rounded-sm bg-slate-8" />
 7 |     </div>
 8 |   </div>
 9 | );
10 | 
11 | export default IllustrationText;
12 | 


--------------------------------------------------------------------------------
/apps/web/src/styles/globals.css:
--------------------------------------------------------------------------------
 1 | @tailwind base;
 2 | @tailwind components;
 3 | @tailwind utilities;
 4 | 
 5 | @media (prefers-reduced-motion: no-preference) {
 6 |   * {
 7 |     scroll-behavior: smooth;
 8 |   }
 9 | }
10 | 
11 | #root,
12 | #__next {
13 |   isolation: isolate;
14 | }
15 | 


--------------------------------------------------------------------------------
/apps/web/src/utils/as.ts:
--------------------------------------------------------------------------------
 1 | export type As<
 2 |   DefaultTag extends React.ElementType,
 3 |   T1 extends React.ElementType,
 4 |   T2 extends React.ElementType = T1,
 5 |   T3 extends React.ElementType = T1,
 6 |   T4 extends React.ElementType = T1,
 7 |   T5 extends React.ElementType = T1,
 8 | > =
 9 |   | (React.ComponentPropsWithRef<DefaultTag> & {
10 |       as?: DefaultTag;
11 |     })
12 |   | (React.ComponentPropsWithRef<T1> & {
13 |       as: T1;
14 |     })
15 |   | (React.ComponentPropsWithRef<T2> & {
16 |       as: T2;
17 |     })
18 |   | (React.ComponentPropsWithRef<T3> & {
19 |       as: T3;
20 |     })
21 |   | (React.ComponentPropsWithRef<T4> & {
22 |       as: T4;
23 |     })
24 |   | (React.ComponentPropsWithRef<T5> & {
25 |       as: T5;
26 |     });
27 | 


--------------------------------------------------------------------------------
/apps/web/src/utils/slugify.ts:
--------------------------------------------------------------------------------
1 | export const slugify = (text: string): string =>
2 |   text
3 |     .toLowerCase()
4 |     .trim()
5 |     .replace(/\s+/g, '-')
6 |     .replace(/[^\w-]+/g, '')
7 |     .replace(/--+/g, '-');
8 | 


--------------------------------------------------------------------------------
/apps/web/src/utils/unreachable.ts:
--------------------------------------------------------------------------------
1 | export const unreachable = (
2 |   condition: never,
3 |   message = `Entered unreachable code. Received '${
4 |     typeof condition === 'string' ? condition : JSON.stringify(condition)
5 |   }'.`,
6 | ): never => {
7 |   throw new TypeError(message);
8 | };
9 | 


--------------------------------------------------------------------------------
/apps/web/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "extends": "tsconfig/nextjs.json",
 3 |   "compilerOptions": {
 4 |     "target": "ES2018",
 5 |     "plugins": [{ "name": "next" }],
 6 |     "paths": { "@/*": ["./src/*"] },
 7 |     "types": ["vitest/globals"]
 8 |   },
 9 |   "include": [
10 |     "next-env.d.ts",
11 |     "**/*.ts",
12 |     "**/*.tsx",
13 |     ".next/types/**/*.ts",
14 |     "next.config.js"
15 |   ],
16 |   "exclude": ["node_modules"]
17 | }
18 | 


--------------------------------------------------------------------------------
/apps/web/vitest.config.ts:
--------------------------------------------------------------------------------
 1 | import path from 'node:path';
 2 | import { loadEnvConfig } from '@next/env';
 3 | import { defineConfig } from 'vitest/config';
 4 | 
 5 | loadEnvConfig(__dirname, true);
 6 | 
 7 | export default defineConfig({
 8 |   test: {
 9 |     globals: true,
10 |     environment: 'jsdom',
11 |   },
12 |   esbuild: {
13 |     tsconfigRaw: {
14 |       compilerOptions: {
15 |         jsx: 'react-jsx',
16 |       },
17 |     },
18 |   },
19 |   resolve: {
20 |     alias: {
21 |       '@': path.resolve(__dirname, './src'),
22 |     },
23 |   },
24 | });
25 | 


--------------------------------------------------------------------------------
/benchmarks/tailwind-component/.gitignore:
--------------------------------------------------------------------------------
1 | isolate-*.log
2 | flamegraph.html
3 | .preview
4 | .vscpreview
5 | 


--------------------------------------------------------------------------------
/benchmarks/tailwind-component/src/tailwind-render.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@react-email/render';
2 | import { Tailwind as CurrentTailwind } from '@react-email/tailwind';
3 | import EmailWithTailwind from './emails/with-tailwind.js';
4 | 
5 | await render(<EmailWithTailwind Tailwind={CurrentTailwind} />);
6 | 


--------------------------------------------------------------------------------
/benchmarks/tailwind-component/tailwind.config.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/benchmarks/tailwind-component/tailwind.config.js


--------------------------------------------------------------------------------
/benchmarks/tailwind-component/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "$schema": "https://json.schemastore.org/tsconfig",
 3 |   "extends": "tsconfig/react-library.json",
 4 |   "include": ["src"],
 5 |   "exclude": ["dist", "build", "node_modules"],
 6 |   "compilerOptions": {
 7 |     "target": "esnext",
 8 |     "noUncheckedIndexedAccess": true,
 9 |     "resolveJsonModule": true,
10 |     "moduleResolution": "Node",
11 |     "declarationMap": false,
12 |     "declaration": false,
13 |     "outDir": "dist"
14 |   }
15 | }
16 | 


--------------------------------------------------------------------------------
/examples/aws-ses/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "react-email-with-aws-ses",
 3 |   "license": "MIT",
 4 |   "private": true,
 5 |   "sideEffects": false,
 6 |   "type": "module",
 7 |   "main": "./dist/index.js",
 8 |   "files": [
 9 |     "dist/**"
10 |   ],
11 |   "scripts": {
12 |     "build": "tsup-node src/index.tsx --format esm --target node20",
13 |     "dev": "tsup-node src/index.tsx --format esm --target node20 --watch",
14 |     "clean": "rm -rf dist"
15 |   },
16 |   "dependencies": {
17 |     "@aws-sdk/client-ses": "^3",
18 |     "@react-email/components": "^0.0.36",
19 |     "react": "^19",
20 |     "react-dom": "^19"
21 |   },
22 |   "devDependencies": {
23 |     "tsup": "^8.0.0",
24 |     "typescript": "^4"
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/examples/aws-ses/src/email.tsx:
--------------------------------------------------------------------------------
 1 | import { Button, Html } from '@react-email/components';
 2 | import type * as React from 'react';
 3 | 
 4 | interface EmailProps {
 5 |   url: string;
 6 | }
 7 | 
 8 | export const Email: React.FC<Readonly<EmailProps>> = ({ url }) => {
 9 |   return (
10 |     <Html lang="en">
11 |       <Button href={url}>Click me</Button>
12 |     </Html>
13 |   );
14 | };
15 | 


--------------------------------------------------------------------------------
/examples/mailersend/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "react-email-with-mailersend",
 3 |   "license": "MIT",
 4 |   "private": true,
 5 |   "sideEffects": false,
 6 |   "type": "module",
 7 |   "main": "./dist/index.js",
 8 |   "files": [
 9 |     "dist/**"
10 |   ],
11 |   "scripts": {
12 |     "build": "tsup-node src/index.tsx --format esm --target node20",
13 |     "dev": "tsup-node src/index.tsx --format esm --target node20 --watch",
14 |     "clean": "rm -rf dist"
15 |   },
16 |   "dependencies": {
17 |     "@react-email/components": "^0.0.36",
18 |     "mailersend": "^2",
19 |     "react": "^19",
20 |     "react-dom": "^19"
21 |   },
22 |   "devDependencies": {
23 |     "tsup": "^8.0.0",
24 |     "typescript": "^4"
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/examples/mailersend/src/email.tsx:
--------------------------------------------------------------------------------
 1 | import { Button, Html } from '@react-email/components';
 2 | 
 3 | interface EmailProps {
 4 |   url: string;
 5 | }
 6 | 
 7 | export const Email: React.FC<Readonly<EmailProps>> = ({ url }) => {
 8 |   return (
 9 |     <Html lang="en">
10 |       <Button href={url}>Click me</Button>
11 |     </Html>
12 |   );
13 | };
14 | 


--------------------------------------------------------------------------------
/examples/mailersend/src/index.tsx:
--------------------------------------------------------------------------------
 1 | import { render } from '@react-email/components';
 2 | import { EmailParams, MailerSend, Recipient, Sender } from 'mailersend';
 3 | import { Email } from './email';
 4 | 
 5 | const mailerSend = new MailerSend({
 6 |   apiKey: process.env.MAILERSEND_API_KEY || '',
 7 | });
 8 | 
 9 | const emailHtml = await render(<Email url="https://example.com" />);
10 | 
11 | const sentFrom = new Sender('you@yourdomain.com', 'Your name');
12 | const recipients = [new Recipient('your@client.com', 'Your Client')];
13 | 
14 | const emailParams = new EmailParams()
15 |   .setFrom(sentFrom)
16 |   .setTo(recipients)
17 |   .setSubject('This is a Subject')
18 |   .setHtml(emailHtml);
19 | 
20 | await mailerSend.email.send(emailParams);
21 | 


--------------------------------------------------------------------------------
/examples/nodemailer/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "react-email-with-nodemailer",
 3 |   "license": "MIT",
 4 |   "private": true,
 5 |   "sideEffects": false,
 6 |   "type": "module",
 7 |   "main": "./dist/index.js",
 8 |   "files": [
 9 |     "dist/**"
10 |   ],
11 |   "scripts": {
12 |     "build": "tsup-node src/index.tsx --format esm --target node20",
13 |     "dev": "tsup-node src/index.tsx --format esm --target node20 --watch",
14 |     "clean": "rm -rf dist"
15 |   },
16 |   "dependencies": {
17 |     "@react-email/components": "^0.0.36",
18 |     "nodemailer": "^6",
19 |     "react": "^19",
20 |     "react-dom": "^19"
21 |   },
22 |   "devDependencies": {
23 |     "@types/nodemailer": "^6",
24 |     "tsup": "^8.0.0",
25 |     "typescript": "^4"
26 |   }
27 | }
28 | 


--------------------------------------------------------------------------------
/examples/nodemailer/src/email.tsx:
--------------------------------------------------------------------------------
 1 | import { Button, Html } from '@react-email/components';
 2 | 
 3 | interface EmailProps {
 4 |   url: string;
 5 | }
 6 | 
 7 | export const Email: React.FC<Readonly<EmailProps>> = ({ url }) => {
 8 |   return (
 9 |     <Html lang="en">
10 |       <Button href={url}>Click me</Button>
11 |     </Html>
12 |   );
13 | };
14 | 


--------------------------------------------------------------------------------
/examples/nodemailer/src/index.tsx:
--------------------------------------------------------------------------------
 1 | import { render } from '@react-email/components';
 2 | import nodemailer from 'nodemailer';
 3 | import { Email } from './email';
 4 | 
 5 | const transporter = nodemailer.createTransport({
 6 |   host: 'smtp.forwardemail.net',
 7 |   port: 465,
 8 |   secure: true,
 9 |   auth: {
10 |     user: 'my_user',
11 |     pass: 'my_password',
12 |   },
13 | });
14 | 
15 | const emailHtml = await render(<Email url="https://example.com" />);
16 | 
17 | const options = {
18 |   from: 'you@example.com',
19 |   to: 'user@gmail.com',
20 |   subject: 'hello world',
21 |   html: emailHtml,
22 | };
23 | 
24 | await transporter.sendMail(options);
25 | 


--------------------------------------------------------------------------------
/examples/plunk/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "react-email-with-plunk",
 3 |   "license": "MIT",
 4 |   "private": true,
 5 |   "sideEffects": false,
 6 |   "type": "module",
 7 |   "main": "./dist/index.js",
 8 |   "files": [
 9 |     "dist/**"
10 |   ],
11 |   "scripts": {
12 |     "build": "tsup-node src/index.tsx --format esm --target node20",
13 |     "dev": "tsup-node src/index.tsx --format esm --target node20 --watch",
14 |     "clean": "rm -rf dist"
15 |   },
16 |   "dependencies": {
17 |     "@plunk/node": "^3",
18 |     "@react-email/components": "^0.0.36",
19 |     "react": "^19",
20 |     "react-dom": "^19"
21 |   },
22 |   "devDependencies": {
23 |     "tsup": "^8.0.0",
24 |     "typescript": "^4"
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/examples/plunk/src/email.tsx:
--------------------------------------------------------------------------------
 1 | import { Button, Html } from '@react-email/components';
 2 | 
 3 | interface EmailProps {
 4 |   url: string;
 5 | }
 6 | 
 7 | export const Email: React.FC<Readonly<EmailProps>> = ({ url }) => {
 8 |   return (
 9 |     <Html lang="en">
10 |       <Button href={url}>Click me</Button>
11 |     </Html>
12 |   );
13 | };
14 | 


--------------------------------------------------------------------------------
/examples/plunk/src/index.tsx:
--------------------------------------------------------------------------------
 1 | import plunkImport from '@plunk/node';
 2 | import { render } from '@react-email/components';
 3 | import { Email } from './email';
 4 | 
 5 | const Plunk = (
 6 |   plunkImport as unknown as {
 7 |     default: typeof plunkImport;
 8 |   }
 9 | ).default;
10 | 
11 | // See https://github.com/useplunk/node/issues/2 for why Plunk.default
12 | const plunk = new Plunk(process.env.PLUNK_API_KEY || '');
13 | 
14 | const emailHtml = await render(<Email url="https://example.com" />);
15 | 
16 | await plunk.emails.send({
17 |   to: 'hello@useplunk.com',
18 |   subject: 'Hello world',
19 |   body: emailHtml,
20 | });
21 | 


--------------------------------------------------------------------------------
/examples/postmark/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "react-email-with-postmark",
 3 |   "license": "MIT",
 4 |   "private": true,
 5 |   "type": "module",
 6 |   "sideEffects": false,
 7 |   "main": "./dist/index.js",
 8 |   "files": [
 9 |     "dist/**"
10 |   ],
11 |   "scripts": {
12 |     "build": "tsup-node src/index.tsx --format esm --target node20",
13 |     "dev": "tsup-node src/index.tsx --format esm --target node20 --watch",
14 |     "clean": "rm -rf dist"
15 |   },
16 |   "dependencies": {
17 |     "postmark": "^3",
18 |     "@react-email/components": "^0.0.36",
19 |     "react": "^19",
20 |     "react-dom": "^19"
21 |   },
22 |   "devDependencies": {
23 |     "tsup": "^8.0.0",
24 |     "typescript": "^4"
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/examples/postmark/src/email.tsx:
--------------------------------------------------------------------------------
 1 | import { Button, Html } from '@react-email/components';
 2 | 
 3 | interface EmailProps {
 4 |   url: string;
 5 | }
 6 | 
 7 | export const Email: React.FC<Readonly<EmailProps>> = ({ url }) => {
 8 |   return (
 9 |     <Html lang="en">
10 |       <Button href={url}>Click me</Button>
11 |     </Html>
12 |   );
13 | };
14 | 


--------------------------------------------------------------------------------
/examples/postmark/src/index.tsx:
--------------------------------------------------------------------------------
 1 | import { render } from '@react-email/components';
 2 | import postmark from 'postmark';
 3 | import { Email } from './email';
 4 | 
 5 | const client = new postmark.ServerClient(process.env.POSTMARK_API_KEY || '');
 6 | 
 7 | const emailHtml = await render(<Email url="https://example.com" />);
 8 | 
 9 | const options = {
10 |   From: 'you@example.com',
11 |   To: 'user@gmail.com',
12 |   Subject: 'hello world',
13 |   HtmlBody: emailHtml,
14 | };
15 | 
16 | await client.sendEmail(options);
17 | 


--------------------------------------------------------------------------------
/examples/resend/next-env.d.ts:
--------------------------------------------------------------------------------
1 | /// <reference types="next" />
2 | /// <reference types="next/image-types/global" />
3 | 
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
6 | 


--------------------------------------------------------------------------------
/examples/resend/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "react-email-with-resend",
 3 |   "license": "MIT",
 4 |   "private": true,
 5 |   "sideEffects": false,
 6 |   "scripts": {
 7 |     "build": "next build",
 8 |     "dev": "next dev",
 9 |     "start": "next start"
10 |   },
11 |   "dependencies": {
12 |     "next": "^15",
13 |     "@react-email/components": "^0.0.36",
14 |     "react": "^19",
15 |     "react-dom": "^19",
16 |     "resend": "^4"
17 |   },
18 |   "devDependencies": {
19 |     "@types/node": "^22.0.0",
20 |     "@types/react": "^19",
21 |     "@types/react-dom": "^19",
22 |     "typescript": "^5"
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/examples/resend/src/lib/resend.ts:
--------------------------------------------------------------------------------
1 | import { Resend } from 'resend';
2 | 
3 | export const resend = new Resend(process.env.RESEND_API_KEY);
4 | 


--------------------------------------------------------------------------------
/examples/resend/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "compilerOptions": {
 3 |     "lib": ["dom", "dom.iterable", "esnext"],
 4 |     "allowJs": true,
 5 |     "skipLibCheck": true,
 6 |     "strict": false,
 7 |     "forceConsistentCasingInFileNames": true,
 8 |     "strictNullChecks": true,
 9 |     "noEmit": true,
10 |     "incremental": true,
11 |     "esModuleInterop": true,
12 |     "module": "esnext",
13 |     "moduleResolution": "node",
14 |     "resolveJsonModule": true,
15 |     "isolatedModules": true,
16 |     "jsx": "preserve",
17 |     "target": "ES2017"
18 |   },
19 |   "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
20 |   "exclude": ["node_modules"]
21 | }
22 | 


--------------------------------------------------------------------------------
/examples/scaleway/next/next-env.d.ts:
--------------------------------------------------------------------------------
1 | /// <reference types="next" />
2 | /// <reference types="next/image-types/global" />
3 | 
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
6 | 


--------------------------------------------------------------------------------
/examples/scaleway/next/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "react-email-with-next-scaleway",
 3 |   "license": "MIT",
 4 |   "private": true,
 5 |   "sideEffects": false,
 6 |   "scripts": {
 7 |     "build": "next build",
 8 |     "dev": "next dev",
 9 |     "start": "next start"
10 |   },
11 |   "dependencies": {
12 |     "@scaleway/sdk": "^1",
13 |     "next": "^15",
14 |     "@react-email/components": "^0.0.36",
15 |     "react": "^19",
16 |     "react-dom": "^19"
17 |   },
18 |   "devDependencies": {
19 |     "@types/node": "^22.0.0",
20 |     "@types/react": "^19",
21 |     "@types/react-dom": "^19",
22 |     "typescript": "^4"
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/examples/scaleway/next/src/lib/scaleway.ts:
--------------------------------------------------------------------------------
 1 | import { createClient, TransactionalEmail } from '@scaleway/sdk';
 2 | 
 3 | const client = createClient({
 4 |   accessKey: process.env.ACCESS_KEY,
 5 |   secretKey: process.env.SECRET_KEY,
 6 |   defaultProjectId: process.env.PROJECT_ID,
 7 |   defaultRegion: 'fr-par',
 8 |   defaultZone: 'fr-par-1',
 9 | });
10 | 
11 | export const scalewayTEM = new TransactionalEmail.v1alpha1.API(client);
12 | 


--------------------------------------------------------------------------------
/examples/scaleway/next/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "compilerOptions": {
 3 |     "lib": ["dom", "dom.iterable", "esnext"],
 4 |     "allowJs": true,
 5 |     "skipLibCheck": true,
 6 |     "strict": false,
 7 |     "forceConsistentCasingInFileNames": true,
 8 |     "noEmit": true,
 9 |     "incremental": true,
10 |     "strictNullChecks": true,
11 |     "esModuleInterop": true,
12 |     "module": "esnext",
13 |     "moduleResolution": "node",
14 |     "resolveJsonModule": true,
15 |     "isolatedModules": true,
16 |     "jsx": "preserve",
17 |     "target": "ES2017"
18 |   },
19 |   "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
20 |   "exclude": ["node_modules"]
21 | }
22 | 


--------------------------------------------------------------------------------
/examples/scaleway/node/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "react-email-with-node-scaleway",
 3 |   "license": "MIT",
 4 |   "private": true,
 5 |   "sideEffects": false,
 6 |   "main": "./dist/index.js",
 7 |   "type": "module",
 8 |   "files": [
 9 |     "dist/**"
10 |   ],
11 |   "scripts": {
12 |     "build": "tsup-node src/index.tsx --format esm --target node20",
13 |     "dev": "tsup-node src/index.tsx --format esm --target node20 --watch"
14 |   },
15 |   "dependencies": {
16 |     "@scaleway/sdk": "^1",
17 |     "@react-email/components": "^0.0.36",
18 |     "react": "^19",
19 |     "react-dom": "^19"
20 |   },
21 |   "devDependencies": {
22 |     "tsup": "^8.0.0",
23 |     "typescript": "^4"
24 |   }
25 | }
26 | 


--------------------------------------------------------------------------------
/examples/sendgrid/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "react-email-with-sendgrid",
 3 |   "license": "MIT",
 4 |   "private": true,
 5 |   "sideEffects": false,
 6 |   "type": "module",
 7 |   "main": "./dist/index.js",
 8 |   "files": [
 9 |     "dist/**"
10 |   ],
11 |   "scripts": {
12 |     "build": "tsup-node src/index.tsx --format esm --target node20",
13 |     "dev": "tsup-node src/index.tsx --format esm --target node20 --watch",
14 |     "clean": "rm -rf dist"
15 |   },
16 |   "dependencies": {
17 |     "@sendgrid/mail": "^7",
18 |     "@react-email/components": "^0.0.36",
19 |     "react": "^19",
20 |     "react-dom": "^19"
21 |   },
22 |   "devDependencies": {
23 |     "tsup": "^8.0.0",
24 |     "typescript": "^4"
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/examples/sendgrid/src/email.tsx:
--------------------------------------------------------------------------------
 1 | import { Button, Html } from '@react-email/components';
 2 | 
 3 | interface EmailProps {
 4 |   url: string;
 5 | }
 6 | 
 7 | export const Email: React.FC<Readonly<EmailProps>> = ({ url }) => {
 8 |   return (
 9 |     <Html lang="en">
10 |       <Button href={url}>Click me</Button>
11 |     </Html>
12 |   );
13 | };
14 | 


--------------------------------------------------------------------------------
/examples/sendgrid/src/index.tsx:
--------------------------------------------------------------------------------
 1 | import { render } from '@react-email/components';
 2 | import sendgrid from '@sendgrid/mail';
 3 | import { Email } from './email';
 4 | 
 5 | sendgrid.setApiKey(process.env.SENDGRID_API_KEY || '');
 6 | 
 7 | const emailHtml = await render(<Email url="https://example.com" />);
 8 | 
 9 | const options = {
10 |   from: 'you@example.com',
11 |   to: 'user@gmail.com',
12 |   subject: 'hello world',
13 |   html: emailHtml,
14 | };
15 | 
16 | await sendgrid.send(options);
17 | 


--------------------------------------------------------------------------------
/packages/body/src/__snapshots__/body.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 | 
3 | exports[`<Body> component > renders correctly 1`] = `"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><body>Lorem ipsum<!--/$--></body>"`;
4 | 


--------------------------------------------------------------------------------
/packages/body/src/body.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | 
 3 | export type BodyProps = Readonly<React.HtmlHTMLAttributes<HTMLBodyElement>>;
 4 | 
 5 | export const Body = React.forwardRef<HTMLBodyElement, BodyProps>(
 6 |   ({ children, style, ...props }, ref) => {
 7 |     return (
 8 |       <body {...props} ref={ref} style={style}>
 9 |         {children}
10 |       </body>
11 |     );
12 |   },
13 | );
14 | 
15 | Body.displayName = 'Body';
16 | 


--------------------------------------------------------------------------------
/packages/body/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './body';
2 | 


--------------------------------------------------------------------------------
/packages/body/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/button/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 | 


--------------------------------------------------------------------------------
/packages/button/src/utils/px-to-pt.ts:
--------------------------------------------------------------------------------
1 | export const pxToPt = (px: number | undefined): number | undefined =>
2 |   typeof px === 'number' && !Number.isNaN(Number(px))
3 |     ? (px * 3) / 4
4 |     : undefined;
5 | 


--------------------------------------------------------------------------------
/packages/button/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/code-block/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './code-block';
2 | export * from './languages-available';
3 | export * from './themes';
4 | 


--------------------------------------------------------------------------------
/packages/code-block/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/code-inline/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './code-inline';
2 | 


--------------------------------------------------------------------------------
/packages/code-inline/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/column/src/__snapshots__/column.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 | 
3 | exports[`<Column> component > renders correctly 1`] = `"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><td data-id="__react-email-column">Lorem ipsum</td><!--/$-->"`;
4 | 


--------------------------------------------------------------------------------
/packages/column/src/column.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | 
 3 | export type ColumnProps = Readonly<React.ComponentPropsWithoutRef<'td'>>;
 4 | 
 5 | export const Column = React.forwardRef<HTMLTableCellElement, ColumnProps>(
 6 |   ({ children, style, ...props }, ref) => {
 7 |     return (
 8 |       <td {...props} data-id="__react-email-column" ref={ref} style={style}>
 9 |         {children}
10 |       </td>
11 |     );
12 |   },
13 | );
14 | 
15 | Column.displayName = 'Column';
16 | 


--------------------------------------------------------------------------------
/packages/column/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './column';
2 | 


--------------------------------------------------------------------------------
/packages/column/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/components/src/__snapshots__/heading.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 | 
3 | exports[`render renders the <Heading> component 1`] = `"<!DOCTYPE html PUBLIC \\"-//W3C//DTD XHTML 1.0 Transitional//EN\\" \\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\"><h2 style=\\"margin-left:4px;margin-right:4px\\">Lorem ipsum</h2>"`;
4 | 


--------------------------------------------------------------------------------
/packages/components/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/container/src/__snapshots__/container.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 | 
3 | exports[`<Container> component > renders correctly 1`] = `"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation" style="max-width:300px"><tbody><tr style="width:100%"><td><button type="button">Hi</button></td></tr></tbody></table><!--/$-->"`;
4 | 


--------------------------------------------------------------------------------
/packages/container/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './container';
2 | 


--------------------------------------------------------------------------------
/packages/container/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/create-email/.gitignore:
--------------------------------------------------------------------------------
1 | .test
2 | 


--------------------------------------------------------------------------------
/packages/create-email/.npmignore:
--------------------------------------------------------------------------------
1 | .test
2 | template/node_modules
3 | template/CHANGELOG.md
4 | template/.turbo
5 | template/.react-email
6 | 


--------------------------------------------------------------------------------
/packages/create-email/template/.gitignore:
--------------------------------------------------------------------------------
1 | .react-email


--------------------------------------------------------------------------------
/packages/create-email/template/emails/static/notion-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/create-email/template/emails/static/notion-logo.png


--------------------------------------------------------------------------------
/packages/create-email/template/emails/static/plaid-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/create-email/template/emails/static/plaid-logo.png


--------------------------------------------------------------------------------
/packages/create-email/template/emails/static/plaid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/create-email/template/emails/static/plaid.png


--------------------------------------------------------------------------------
/packages/create-email/template/emails/static/stripe-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/create-email/template/emails/static/stripe-logo.png


--------------------------------------------------------------------------------
/packages/create-email/template/emails/static/vercel-arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/create-email/template/emails/static/vercel-arrow.png


--------------------------------------------------------------------------------
/packages/create-email/template/emails/static/vercel-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/create-email/template/emails/static/vercel-logo.png


--------------------------------------------------------------------------------
/packages/create-email/template/emails/static/vercel-team.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/create-email/template/emails/static/vercel-team.png


--------------------------------------------------------------------------------
/packages/create-email/template/emails/static/vercel-user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/create-email/template/emails/static/vercel-user.png


--------------------------------------------------------------------------------
/packages/create-email/template/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "react-email-starter",
 3 |   "version": "1.1.0",
 4 |   "private": true,
 5 |   "scripts": {
 6 |     "build": "email build",
 7 |     "dev": "email dev",
 8 |     "export": "email export"
 9 |   },
10 |   "dependencies": {
11 |     "@react-email/components": "INSERT_COMPONENTS_VERSION",
12 |     "react-dom": "^19.0.0",
13 |     "react": "^19.0.0"
14 |   },
15 |   "devDependencies": {
16 |     "@react-email/preview-server": "INSERT_REACT_EMAIL_VERSION",
17 |     "@types/react": "^19.0.1",
18 |     "@types/react-dom": "^19.0.1",
19 |     "react-email": "INSERT_REACT_EMAIL_VERSION"
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/packages/create-email/template/readme.md:
--------------------------------------------------------------------------------
 1 | # React Email Starter
 2 | 
 3 | A live preview right in your browser so you don't need to keep sending real emails during development.
 4 | 
 5 | ## Getting Started
 6 | 
 7 | First, install the dependencies:
 8 | 
 9 | ```sh
10 | npm install
11 | # or
12 | yarn
13 | ```
14 | 
15 | Then, run the development server:
16 | 
17 | ```sh
18 | npm run dev
19 | # or
20 | yarn dev
21 | ```
22 | 
23 | Open [localhost:3000](http://localhost:3000) with your browser to see the result.
24 | 
25 | ## License
26 | 
27 | MIT License
28 | 


--------------------------------------------------------------------------------
/packages/create-email/template/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "compilerOptions": {
 3 |     "composite": false,
 4 |     "jsx": "react-jsx",
 5 |     "skipLibCheck": true,
 6 |     "strict": true,
 7 |     "noEmit": true,
 8 |     "strictNullChecks": true
 9 |   },
10 |   "include": ["**/*.ts", "**/*.tsx"],
11 |   "exclude": ["node_modules", ".react-email"]
12 | }
13 | 


--------------------------------------------------------------------------------
/packages/create-email/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "extends": "tsconfig/base.json",
 3 |   "include": ["**/*.ts", "**/*.tsx"],
 4 |   "exclude": ["dist", "build", "node_modules", ".test"],
 5 |   "compilerOptions": {
 6 |     "noEmit": true,
 7 |     "types": ["vitest/globals"]
 8 |   }
 9 | }
10 | 


--------------------------------------------------------------------------------
/packages/create-email/vitest.config.ts:
--------------------------------------------------------------------------------
 1 | import { defineConfig } from 'vitest/config';
 2 | 
 3 | export default defineConfig({
 4 |   test: {
 5 |     globals: true,
 6 |     environment: 'happy-dom',
 7 |     exclude: ['.test/**/*', 'template/**/*', '**/node_modules'],
 8 |   },
 9 | });
10 | 


--------------------------------------------------------------------------------
/packages/font/src/__snapshots__/font.spec.tsx.snap:
--------------------------------------------------------------------------------
 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 2 | 
 3 | exports[`<Font> component > renders correctly 1`] = `
 4 | "<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><style>
 5 |     @font-face {
 6 |       font-family: 'Roboto';
 7 |       font-style: normal;
 8 |       font-weight: 400;
 9 |       mso-font-alt: 'Verdana';
10 |       
11 |     }
12 | 
13 |     * {
14 |       font-family: 'Roboto', Verdana;
15 |     }
16 |   </style><!--/$-->"
17 | `;
18 | 


--------------------------------------------------------------------------------
/packages/font/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './font';
2 | 


--------------------------------------------------------------------------------
/packages/font/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/head/src/head.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | 
 3 | export type HeadProps = Readonly<React.ComponentPropsWithoutRef<'head'>>;
 4 | 
 5 | export const Head = React.forwardRef<HTMLHeadElement, HeadProps>(
 6 |   ({ children, ...props }, ref) => (
 7 |     <head {...props} ref={ref}>
 8 |       <meta content="text/html; charset=UTF-8" httpEquiv="Content-Type" />
 9 |       <meta name="x-apple-disable-message-reformatting" />
10 |       {children}
11 |     </head>
12 |   ),
13 | );
14 | 
15 | Head.displayName = 'Head';
16 | 


--------------------------------------------------------------------------------
/packages/head/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './head';
2 | 


--------------------------------------------------------------------------------
/packages/head/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/heading/src/__snapshots__/heading.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 | 
3 | exports[`render > renders the <Heading> component 1`] = `"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><h2 style="margin-left:4px;margin-right:4px">Lorem ipsum</h2><!--/$-->"`;
4 | 


--------------------------------------------------------------------------------
/packages/heading/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './heading';
2 | 


--------------------------------------------------------------------------------
/packages/heading/src/utils/as.ts:
--------------------------------------------------------------------------------
 1 | export type As<
 2 |   DefaultTag extends React.ElementType,
 3 |   T1 extends React.ElementType,
 4 |   T2 extends React.ElementType = T1,
 5 |   T3 extends React.ElementType = T1,
 6 |   T4 extends React.ElementType = T1,
 7 |   T5 extends React.ElementType = T1,
 8 | > =
 9 |   | (React.ComponentPropsWithRef<DefaultTag> & {
10 |       as?: DefaultTag;
11 |     })
12 |   | (React.ComponentPropsWithRef<T1> & {
13 |       as: T1;
14 |     })
15 |   | (React.ComponentPropsWithRef<T2> & {
16 |       as: T2;
17 |     })
18 |   | (React.ComponentPropsWithRef<T3> & {
19 |       as: T3;
20 |     })
21 |   | (React.ComponentPropsWithRef<T4> & {
22 |       as: T4;
23 |     })
24 |   | (React.ComponentPropsWithRef<T5> & {
25 |       as: T5;
26 |     });
27 | 


--------------------------------------------------------------------------------
/packages/heading/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/hr/src/__snapshots__/hr.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 | 
3 | exports[`<Hr> component > renders correctly 1`] = `"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><hr style="width:100%;border:none;border-top:1px solid #eaeaea"/><!--/$-->"`;
4 | 


--------------------------------------------------------------------------------
/packages/hr/src/hr.spec.tsx:
--------------------------------------------------------------------------------
 1 | import { render } from '@react-email/render';
 2 | import { Hr } from './index';
 3 | 
 4 | describe('<Hr> component', () => {
 5 |   it('passes styles and other props correctly', async () => {
 6 |     const style = {
 7 |       width: '50%',
 8 |       borderColor: 'black',
 9 |     };
10 |     const html = await render(<Hr data-testid="hr-test" style={style} />);
11 |     expect(html).toContain('width:50%');
12 |     expect(html).toContain('border-color:black');
13 |     expect(html).toContain('data-testid="hr-test"');
14 |   });
15 | 
16 |   it('renders correctly', async () => {
17 |     const actualOutput = await render(<Hr />);
18 |     expect(actualOutput).toMatchSnapshot();
19 |   });
20 | });
21 | 


--------------------------------------------------------------------------------
/packages/hr/src/hr.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | 
 3 | export type HrProps = Readonly<React.ComponentPropsWithoutRef<'hr'>>;
 4 | 
 5 | export const Hr = React.forwardRef<HTMLHRElement, HrProps>(
 6 |   ({ style, ...props }, ref) => (
 7 |     <hr
 8 |       {...props}
 9 |       ref={ref}
10 |       style={{
11 |         width: '100%',
12 |         border: 'none',
13 |         borderTop: '1px solid #eaeaea',
14 |         ...style,
15 |       }}
16 |     />
17 |   ),
18 | );
19 | 
20 | Hr.displayName = 'Hr';
21 | 


--------------------------------------------------------------------------------
/packages/hr/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './hr';
2 | 


--------------------------------------------------------------------------------
/packages/hr/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/html/src/__snapshots__/html.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 | 
3 | exports[`<Html> component > renders correctly 1`] = `"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html dir="ltr" lang="en"><head></head><!--$--><!--/$--></html>"`;
4 | 


--------------------------------------------------------------------------------
/packages/html/src/html.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | 
 3 | export type HtmlProps = Readonly<React.ComponentPropsWithoutRef<'html'>>;
 4 | 
 5 | export const Html = React.forwardRef<HTMLHtmlElement, HtmlProps>(
 6 |   ({ children, lang = 'en', dir = 'ltr', ...props }, ref) => (
 7 |     <html {...props} dir={dir} lang={lang} ref={ref}>
 8 |       {children}
 9 |     </html>
10 |   ),
11 | );
12 | 
13 | Html.displayName = 'Html';
14 | 


--------------------------------------------------------------------------------
/packages/html/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './html';
2 | 


--------------------------------------------------------------------------------
/packages/html/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/img/src/__snapshots__/img.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 | 
3 | exports[`<Img> component > renders correctly 1`] = `"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><link rel="preload" as="image" href="cat.jpg"/><!--$--><img alt="Cat" height="300" src="cat.jpg" style="display:block;outline:none;border:none;text-decoration:none" width="300"/><!--/$-->"`;
4 | 


--------------------------------------------------------------------------------
/packages/img/src/img.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | 
 3 | export type ImgProps = Readonly<React.ComponentPropsWithoutRef<'img'>>;
 4 | 
 5 | export const Img = React.forwardRef<HTMLImageElement, ImgProps>(
 6 |   ({ alt, src, width, height, style, ...props }, ref) => (
 7 |     <img
 8 |       {...props}
 9 |       alt={alt}
10 |       height={height}
11 |       ref={ref}
12 |       src={src}
13 |       style={{
14 |         display: 'block',
15 |         outline: 'none',
16 |         border: 'none',
17 |         textDecoration: 'none',
18 |         ...style,
19 |       }}
20 |       width={width}
21 |     />
22 |   ),
23 | );
24 | 
25 | Img.displayName = 'Img';
26 | 


--------------------------------------------------------------------------------
/packages/img/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './img';
2 | 


--------------------------------------------------------------------------------
/packages/img/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/link/src/__snapshots__/link.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 | 
3 | exports[`<Link> component > renders correctly 1`] = `"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><a href="https://example.com" style="color:#067df7;text-decoration-line:none" target="_blank">Example</a><!--/$-->"`;
4 | 


--------------------------------------------------------------------------------
/packages/link/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './link';
2 | 


--------------------------------------------------------------------------------
/packages/link/src/link.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | 
 3 | export type LinkProps = Readonly<React.ComponentPropsWithoutRef<'a'>>;
 4 | 
 5 | export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
 6 |   ({ target = '_blank', style, ...props }, ref) => (
 7 |     <a
 8 |       {...props}
 9 |       ref={ref}
10 |       style={{
11 |         color: '#067df7',
12 |         textDecorationLine: 'none',
13 |         ...style,
14 |       }}
15 |       target={target}
16 |     >
17 |       {props.children}
18 |     </a>
19 |   ),
20 | );
21 | 
22 | Link.displayName = 'Link';
23 | 


--------------------------------------------------------------------------------
/packages/link/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/markdown/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './markdown';
2 | 


--------------------------------------------------------------------------------
/packages/markdown/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/preview-server/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .next
3 | 
4 | # for testing
5 | static
6 | emails
7 | .env*
8 | 


--------------------------------------------------------------------------------
/packages/preview-server/.npmignore:
--------------------------------------------------------------------------------
1 | .react-email
2 | ./emails
3 | ./emails/static
4 | node_modules
5 | .turbo
6 | 


--------------------------------------------------------------------------------
/packages/preview-server/index.mjs:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * this file is required so that import.meta.resolve and require.resolve can properly can find the module for this package
 3 |  */
 4 | import fs from 'node:fs/promises';
 5 | import path from 'node:path';
 6 | import url from 'node:url';
 7 | 
 8 | const filename = url.fileURLToPath(import.meta.url);
 9 | const dirname = path.dirname(filename);
10 | const packageJson = JSON.parse(
11 |   await fs.readFile(path.join(dirname, 'package.json'), 'utf-8'),
12 | );
13 | 
14 | /**
15 |  * @type {string}
16 |  */
17 | export const version = packageJson.version;
18 | 


--------------------------------------------------------------------------------
/packages/preview-server/module-punycode.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'module-punycode' {
2 |   export * from 'node:punycode';
3 | }
4 | 


--------------------------------------------------------------------------------
/packages/preview-server/next-env.d.ts:
--------------------------------------------------------------------------------
1 | /// <reference types="next" />
2 | /// <reference types="next/image-types/global" />
3 | 
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
6 | 


--------------------------------------------------------------------------------
/packages/preview-server/postcss.config.js:
--------------------------------------------------------------------------------
1 | const path = require('node:path');
2 | 
3 | module.exports = {
4 |   plugins: {
5 |     tailwindcss: { config: path.resolve(__dirname, 'tailwind.config.ts') },
6 |     autoprefixer: {},
7 |   },
8 | };
9 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/actions/email-validation/get-code-location-from-ast-element.ts:
--------------------------------------------------------------------------------
 1 | import type { HTMLElement } from 'node-html-parser';
 2 | import { getLineAndColumnFromOffset } from '../../utils/get-line-and-column-from-offset';
 3 | 
 4 | export interface CodeLocation {
 5 |   line: number;
 6 |   column: number;
 7 | }
 8 | 
 9 | export const getCodeLocationFromAstElement = (
10 |   ast: HTMLElement,
11 |   html: string,
12 | ): CodeLocation => {
13 |   const [line, column] = getLineAndColumnFromOffset(ast.range[0], html);
14 |   return {
15 |     line,
16 |     column,
17 |   };
18 | };
19 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/actions/email-validation/quick-fetch.ts:
--------------------------------------------------------------------------------
 1 | import type { IncomingMessage } from 'node:http';
 2 | import http from 'node:http';
 3 | import https from 'node:https';
 4 | 
 5 | export const quickFetch = (url: URL) => {
 6 |   return new Promise<IncomingMessage>((resolve, reject) => {
 7 |     const caller = url.protocol === 'https:' ? https : http;
 8 |     caller
 9 |       .get(url, (res) => {
10 |         resolve(res);
11 |       })
12 |       .on('error', (error) => reject(error));
13 |   });
14 | };
15 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/actions/get-emails-directory-metadata-action.ts:
--------------------------------------------------------------------------------
 1 | 'use server';
 2 | 
 3 | import type { EmailsDirectory } from '../utils/get-emails-directory-metadata';
 4 | import { getEmailsDirectoryMetadata } from '../utils/get-emails-directory-metadata';
 5 | 
 6 | export const getEmailsDirectoryMetadataAction = async (
 7 |   absolutePathToEmailsDirectory: string,
 8 |   keepFileExtensions = false,
 9 |   isSubDirectory = false,
10 | 
11 |   baseDirectoryPath = absolutePathToEmailsDirectory,
12 | ): Promise<EmailsDirectory | undefined> => {
13 |   return getEmailsDirectoryMetadata(
14 |     absolutePathToEmailsDirectory,
15 |     keepFileExtensions,
16 |     isSubDirectory,
17 |     baseDirectoryPath,
18 |   );
19 | };
20 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/app/env.ts:
--------------------------------------------------------------------------------
 1 | /* eslint-disable @typescript-eslint/no-non-null-assertion */
 2 | /** ONLY ACCESSIBLE ON THE SERVER */
 3 | export const emailsDirRelativePath = process.env.EMAILS_DIR_RELATIVE_PATH!;
 4 | 
 5 | /** ONLY ACCESSIBLE ON THE SERVER */
 6 | export const userProjectLocation = process.env.USER_PROJECT_LOCATION!;
 7 | 
 8 | /** ONLY ACCESSIBLE ON THE SERVER */
 9 | export const emailsDirectoryAbsolutePath =
10 |   process.env.EMAILS_DIR_ABSOLUTE_PATH!;
11 | 
12 | export const isBuilding = process.env.NEXT_PUBLIC_IS_BUILDING === 'true';
13 | 
14 | export const isPreviewDevelopment =
15 |   process.env.NEXT_PUBLIC_IS_PREVIEW_DEVELOPMENT === 'true';
16 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/favicon.ico


--------------------------------------------------------------------------------
/packages/preview-server/src/app/fonts/SFMono/SFMonoBold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/fonts/SFMono/SFMonoBold.otf


--------------------------------------------------------------------------------
/packages/preview-server/src/app/fonts/SFMono/SFMonoBoldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/fonts/SFMono/SFMonoBoldItalic.otf


--------------------------------------------------------------------------------
/packages/preview-server/src/app/fonts/SFMono/SFMonoHeavy.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/fonts/SFMono/SFMonoHeavy.otf


--------------------------------------------------------------------------------
/packages/preview-server/src/app/fonts/SFMono/SFMonoHeavyItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/fonts/SFMono/SFMonoHeavyItalic.otf


--------------------------------------------------------------------------------
/packages/preview-server/src/app/fonts/SFMono/SFMonoLight.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/fonts/SFMono/SFMonoLight.otf


--------------------------------------------------------------------------------
/packages/preview-server/src/app/fonts/SFMono/SFMonoLightItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/fonts/SFMono/SFMonoLightItalic.otf


--------------------------------------------------------------------------------
/packages/preview-server/src/app/fonts/SFMono/SFMonoMedium.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/fonts/SFMono/SFMonoMedium.otf


--------------------------------------------------------------------------------
/packages/preview-server/src/app/fonts/SFMono/SFMonoMediumItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/fonts/SFMono/SFMonoMediumItalic.otf


--------------------------------------------------------------------------------
/packages/preview-server/src/app/fonts/SFMono/SFMonoRegular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/fonts/SFMono/SFMonoRegular.otf


--------------------------------------------------------------------------------
/packages/preview-server/src/app/fonts/SFMono/SFMonoRegularItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/fonts/SFMono/SFMonoRegularItalic.otf


--------------------------------------------------------------------------------
/packages/preview-server/src/app/fonts/SFMono/SFMonoSemibold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/fonts/SFMono/SFMonoSemibold.otf


--------------------------------------------------------------------------------
/packages/preview-server/src/app/fonts/SFMono/SFMonoSemiboldItalic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/fonts/SFMono/SFMonoSemiboldItalic.otf


--------------------------------------------------------------------------------
/packages/preview-server/src/app/globals.css:
--------------------------------------------------------------------------------
 1 | @tailwind base;
 2 | @tailwind components;
 3 | @tailwind utilities;
 4 | 
 5 | html {
 6 |   color-scheme: dark;
 7 | }
 8 | 
 9 | .popup-open iframe {
10 |   pointer-events: none;
11 | }
12 | 
13 | nav > div > div > .line {
14 |   display: none;
15 | }
16 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/app/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/app/logo.png


--------------------------------------------------------------------------------
/packages/preview-server/src/components/code-snippet.tsx:
--------------------------------------------------------------------------------
 1 | const CodeSnippet = ({ children }) => {
 2 |   return (
 3 |     <code className="m-0.5 inline-block rounded-md bg-white/10 p-1 font-mono leading-none text-slate-12">
 4 |       {children}
 5 |     </code>
 6 |   );
 7 | };
 8 | 
 9 | export default CodeSnippet;
10 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/components/icons/icon-arrow-down.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | import type { IconElement, IconProps } from './icon-base';
 3 | import { IconBase } from './icon-base';
 4 | 
 5 | export const IconArrowDown = React.forwardRef<IconElement, Readonly<IconProps>>(
 6 |   ({ ...props }, forwardedRef) => (
 7 |     <IconBase ref={forwardedRef} {...props}>
 8 |       <path
 9 |         d="M12 16L6 9.85966L6.84 9L12 14.2808L17.16 9L18 9.85966L12 16Z"
10 |         fill="currentColor"
11 |       />
12 |     </IconBase>
13 |   ),
14 | );
15 | 
16 | IconArrowDown.displayName = 'IconArrowDown';
17 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/components/icons/icon-base.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | 
 3 | export type IconElement = React.ElementRef<'svg'>;
 4 | export type RootProps = React.ComponentPropsWithoutRef<'svg'>;
 5 | 
 6 | export interface IconProps extends RootProps {
 7 |   size?: number;
 8 | }
 9 | 
10 | export const IconBase = React.forwardRef<IconElement, Readonly<IconProps>>(
11 |   ({ size = 20, children, ...props }, forwardedRef) => (
12 |     <svg
13 |       fill="none"
14 |       height={size}
15 |       ref={forwardedRef}
16 |       viewBox="0 0 24 24"
17 |       width={size}
18 |       xmlns="http://www.w3.org/2000/svg"
19 |       {...props}
20 |     >
21 |       {children}
22 |     </svg>
23 |   ),
24 | );
25 | 
26 | IconBase.displayName = 'IconBase';
27 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/components/icons/icon-button.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | import { cn } from '../../utils';
 3 | 
 4 | export type IconButtonProps = React.ComponentPropsWithoutRef<'button'>;
 5 | 
 6 | export const IconButton = React.forwardRef<
 7 |   HTMLButtonElement,
 8 |   Readonly<IconButtonProps>
 9 | >(({ children, className, ...props }, forwardedRef) => (
10 |   <button
11 |     type="button"
12 |     {...props}
13 |     className={cn(
14 |       'focus:ring-gray-8 rounded text-slate-11 transition duration-200 ease-in-out hover:text-slate-12 focus:text-slate-12 focus:outline-none focus:ring-2',
15 |       className,
16 |     )}
17 |     ref={forwardedRef}
18 |   >
19 |     {children}
20 |   </button>
21 | ));
22 | 
23 | IconButton.displayName = 'IconButton';
24 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/components/icons/icon-check.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | import type { IconElement, IconProps } from './icon-base';
 3 | import { IconBase } from './icon-base';
 4 | 
 5 | export const IconCheck = React.forwardRef<IconElement, Readonly<IconProps>>(
 6 |   ({ ...props }, forwardedRef) => (
 7 |     <IconBase ref={forwardedRef} {...props}>
 8 |       <path
 9 |         d="M16.25 8.75L10.406 15.25L7.75 12.75"
10 |         stroke="currentColor"
11 |         strokeLinecap="round"
12 |         strokeLinejoin="round"
13 |         strokeWidth="1.5"
14 |       />
15 |     </IconBase>
16 |   ),
17 | );
18 | 
19 | IconCheck.displayName = 'IconCheck';
20 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/components/icons/icon-download.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | import type { IconElement, IconProps } from './icon-base';
 3 | import { IconBase } from './icon-base';
 4 | 
 5 | export const IconDownload = React.forwardRef<IconElement, Readonly<IconProps>>(
 6 |   ({ ...props }, forwardedRef) => (
 7 |     <IconBase ref={forwardedRef} {...props}>
 8 |       <path
 9 |         d="M4.75 14.75v1.5a3 3 0 0 0 3 3h8.5a3 3 0 0 0 3-3v-1.5M12 14.25v-9.5M8.75 10.75l3.25 3.5 3.25-3.5"
10 |         stroke="currentColor"
11 |         strokeLinecap="round"
12 |         strokeLinejoin="round"
13 |         strokeWidth={1.5}
14 |       />
15 |     </IconBase>
16 |   ),
17 | );
18 | 
19 | IconDownload.displayName = 'IconDownload';
20 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/components/icons/icon-email.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | import type { IconElement, IconProps } from './icon-base';
 3 | import { IconBase } from './icon-base';
 4 | 
 5 | export const IconEmail = React.forwardRef<IconElement, Readonly<IconProps>>(
 6 |   (props, forwardedRef) => {
 7 |     return (
 8 |       <IconBase {...props} ref={forwardedRef}>
 9 |         <path
10 |           d="M20 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2m0 4.7l-8 5.334L4 8.7V6.297l8 5.333l8-5.333z"
11 |           fill="currentColor"
12 |         />
13 |       </IconBase>
14 |     );
15 |   },
16 | );
17 | 
18 | IconEmail.displayName = 'IconEmail';
19 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/components/icons/icon-image.tsx:
--------------------------------------------------------------------------------
 1 | import { forwardRef } from 'react';
 2 | import type { IconElement, IconProps } from './icon-base';
 3 | import { IconBase } from './icon-base';
 4 | 
 5 | export const IconImage = forwardRef<IconElement, IconProps>((props, ref) => (
 6 |   <IconBase {...props} ref={ref}>
 7 |     <g
 8 |       fill="none"
 9 |       stroke="currentColor"
10 |       strokeLinecap="round"
11 |       strokeLinejoin="round"
12 |       strokeWidth="2"
13 |     >
14 |       <rect width="18" height="18" x="3" y="3" rx="2" ry="2" />
15 |       <circle cx="9" cy="9" r="2" />
16 |       <path d="m21 15l-3.086-3.086a2 2 0 0 0-2.828 0L6 21" />
17 |     </g>
18 |   </IconBase>
19 | ));
20 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/components/icons/icon-source.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | import type { IconElement, IconProps } from './icon-base';
 3 | import { IconBase } from './icon-base';
 4 | 
 5 | export const IconSource = React.forwardRef<IconElement, Readonly<IconProps>>(
 6 |   ({ ...props }, forwardedRef) => (
 7 |     <IconBase ref={forwardedRef} {...props}>
 8 |       <path
 9 |         d="M17.4 15L21 11.5L17.4 8M6.6 8L3 11.5L6.6 15M14.25 4.5L9.75 18.5"
10 |         stroke="currentColor"
11 |         strokeLinecap="round"
12 |         strokeLinejoin="round"
13 |         strokeWidth="1.5"
14 |       />
15 |     </IconBase>
16 |   ),
17 | );
18 | 
19 | IconSource.displayName = 'IconSource';
20 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export * from './button';
2 | export * from './code';
3 | export * from './heading';
4 | export * from './logo';
5 | export * from './sidebar';
6 | export * from './text';
7 | export * from './topbar';
8 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/components/sidebar/index.ts:
--------------------------------------------------------------------------------
1 | export * from './sidebar';
2 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/components/toolbar/results-table.tsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/preview-server/src/components/toolbar/results-table.tsx


--------------------------------------------------------------------------------
/packages/preview-server/src/components/tooltip.tsx:
--------------------------------------------------------------------------------
 1 | import * as TooltipPrimitive from '@radix-ui/react-tooltip';
 2 | import type * as React from 'react';
 3 | import { TooltipContent } from './tooltip-content';
 4 | 
 5 | type RootProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>;
 6 | 
 7 | export type TooltipProps = RootProps;
 8 | 
 9 | export const TooltipRoot: React.FC<Readonly<TooltipProps>> = ({
10 |   children,
11 |   ...props
12 | }) => <TooltipPrimitive.Root {...props}>{children}</TooltipPrimitive.Root>;
13 | 
14 | export const Tooltip = Object.assign(TooltipRoot, {
15 |   Arrow: TooltipPrimitive.TooltipArrow,
16 |   Provider: TooltipPrimitive.TooltipProvider,
17 |   Content: TooltipContent,
18 |   Trigger: TooltipPrimitive.TooltipTrigger,
19 | });
20 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/hooks/use-fragment-identifier.ts:
--------------------------------------------------------------------------------
 1 | import { usePathname, useSearchParams } from 'next/navigation';
 2 | import { useEffect, useState } from 'react';
 3 | 
 4 | export const useFragmentIdentifier = () => {
 5 |   const pathname = usePathname();
 6 |   const searchParams = useSearchParams();
 7 |   const [fragmentIdentifier, setFragmentIdentifier] = useState<string>();
 8 | 
 9 |   useEffect(() => {
10 |     setFragmentIdentifier(global.location?.hash);
11 |   }, [pathname, searchParams]);
12 | 
13 |   return fragmentIdentifier;
14 | };
15 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/caniemail/ast/__snapshots__/get-used-style-properties.spec.ts.snap:
--------------------------------------------------------------------------------
 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 2 | 
 3 | exports[`getUsedStyleProperties() 1`] = `
 4 | [
 5 |   {
 6 |     "location": SourceLocation {
 7 |       "end": Position {
 8 |         "column": 21,
 9 |         "index": 91,
10 |         "line": 5,
11 |       },
12 |       "filename": undefined,
13 |       "identifierName": undefined,
14 |       "start": Position {
15 |         "column": 2,
16 |         "index": 72,
17 |         "line": 5,
18 |       },
19 |     },
20 |     "name": "borderRadius",
21 |     "value": "5px",
22 |   },
23 | ]
24 | `;
25 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/caniemail/ast/get-object-variables.spec.ts:
--------------------------------------------------------------------------------
 1 | import { parse } from '@babel/parser';
 2 | import { getObjectVariables } from './get-object-variables';
 3 | 
 4 | test('getObjectVariables()', () => {
 5 |   const reactCode = `
 6 | <Button style={buttonStyle}>Click me</Button>
 7 | 
 8 | const buttonStyle = {
 9 |   borderRadius: '5px',
10 | };
11 | `;
12 |   const ast = parse(reactCode, {
13 |     strictMode: false,
14 |     errorRecovery: true,
15 |     sourceType: 'unambiguous',
16 |     plugins: ['jsx', 'typescript', 'decorators'],
17 |   });
18 |   expect(getObjectVariables(ast)).toMatchSnapshot();
19 | });
20 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/caniemail/get-css-property-with-value.ts:
--------------------------------------------------------------------------------
 1 | const propertyRegex =
 2 |   /(?<propertyName>[a-z-]+)\s*:\s*(?<propertyValue>[a-zA-Z\-0-9()+*/_ ]+)/;
 3 | 
 4 | export const getCssPropertyWithValue = (title: string) => {
 5 |   const match = propertyRegex.exec(title.trim());
 6 |   if (match) {
 7 |     const [_full, propertyName, propertyValue] = match;
 8 |     return {
 9 |       name: propertyName!,
10 |       value: propertyValue!,
11 |     };
12 |   }
13 |   return undefined;
14 | };
15 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/caniemail/get-css-unit.ts:
--------------------------------------------------------------------------------
1 | export const getCssUnit = (title: string) => {
2 |   return title.endsWith(' unit') ? title.replace(' unit', '') : undefined;
3 | };
4 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/caniemail/get-element-attributes.ts:
--------------------------------------------------------------------------------
1 | export function getElementAttributes(title: string) {
2 |   if (title.endsWith(' attribute')) {
3 |     return [title.replace(' attribute', '')];
4 |   }
5 | 
6 |   return [];
7 | }
8 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/caniemail/get-element-names.ts:
--------------------------------------------------------------------------------
 1 | export const getElementNames = (title: string, keywords: string | null) => {
 2 |   const match = /<(?<elementName>[^>]*)> element/.exec(title);
 3 |   if (match) {
 4 |     const [_full, elementName] = match;
 5 | 
 6 |     if (elementName) {
 7 |       return [elementName.toLowerCase()];
 8 |     }
 9 |   }
10 | 
11 |   if (keywords !== null && keywords.length > 0) {
12 |     return keywords
13 |       .toLowerCase()
14 |       .split(/\s*,\s*/)
15 |       .map((piece) => piece.trim());
16 |   }
17 | 
18 |   if (title.split(',').length > 1) {
19 |     return title
20 |       .toLowerCase()
21 |       .split(/\s*,\s*/)
22 |       .map((piece) => piece.trim());
23 |   }
24 | 
25 |   return [];
26 | };
27 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/caniemail/tailwind/setup-tailwind-context.ts:
--------------------------------------------------------------------------------
 1 | import { createContext } from 'tailwindcss/lib/lib/setupContextUtils';
 2 | import resolveConfig from 'tailwindcss/resolveConfig';
 3 | import type { TailwindConfig } from './get-tailwind-config';
 4 | 
 5 | export const setupTailwindContext = (config: TailwindConfig) => {
 6 |   return createContext(
 7 |     resolveConfig({
 8 |       ...config,
 9 |       content: [],
10 |       corePlugins: {
11 |         preflight: false,
12 |       },
13 |     }),
14 |   );
15 | };
16 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/cn.ts:
--------------------------------------------------------------------------------
1 | import { type ClassValue, clsx } from 'clsx';
2 | import { twMerge } from 'tailwind-merge';
3 | 
4 | export const cn = (...inputs: ClassValue[]) => {
5 |   return twMerge(clsx(inputs));
6 | };
7 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/constants.ts:
--------------------------------------------------------------------------------
1 | export const tabTransition = {
2 |   type: 'spring',
3 |   stiffness: 2000,
4 |   damping: 80,
5 |   mass: 1,
6 | };
7 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/copy-text-to-clipboard.ts:
--------------------------------------------------------------------------------
1 | export const copyTextToClipboard = async (text: string) => {
2 |   try {
3 |     await navigator.clipboard.writeText(text);
4 |   } catch {
5 |     throw new Error('Not able to copy');
6 |   }
7 | };
8 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/esbuild/escape-string-for-regex.ts:
--------------------------------------------------------------------------------
1 | export function escapeStringForRegex(string: string) {
2 |   return string.replace(/[|\\{}()[\]^$+*?.]/g, '\\
amp;').replace(/-/g, '\\x2d');
3 | }
4 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/get-line-and-column-from-offset.spec.ts:
--------------------------------------------------------------------------------
 1 | import { getLineAndColumnFromOffset } from './get-line-and-column-from-offset';
 2 | 
 3 | test('getLineAndColumnFromOffset()', () => {
 4 |   const content = `export default function MyEmail() {
 5 |   return <div className="testing classes to make sure this is not removed" id="my-div" aria-label="my beautiful div">
 6 |     inside the div, should also stay unchanged
 7 |   </div>;
 8 | }`;
 9 |   const offset = content.indexOf('className');
10 |   expect(getLineAndColumnFromOffset(offset, content)).toEqual([2, 15]);
11 | });
12 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/get-line-and-column-from-offset.ts:
--------------------------------------------------------------------------------
 1 | export const getLineAndColumnFromOffset = (
 2 |   offset: number,
 3 |   content: string,
 4 | ): [line: number, column: number] => {
 5 |   const lineBreaks = [...content.slice(0, offset).matchAll(/\n|\r|\r\n/g)];
 6 | 
 7 |   const line = lineBreaks.length + 1;
 8 |   const column = offset - (lineBreaks[lineBreaks.length - 1]?.index ?? 0);
 9 | 
10 |   return [line, column];
11 | };
12 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './cn';
2 | export * from './copy-text-to-clipboard';
3 | export * from './language-map';
4 | export * from './sanitize';
5 | export * from './types/as';
6 | export * from './unreachable';
7 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/language-map.ts:
--------------------------------------------------------------------------------
1 | const languageMap = {
2 |   jsx: 'React',
3 |   markup: 'HTML',
4 |   markdown: 'Plain Text',
5 | };
6 | 
7 | export default languageMap;
8 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/load-stream.ts:
--------------------------------------------------------------------------------
 1 | export async function* loadStream<T>(stream: ReadableStream<T>) {
 2 |   const reader = stream.getReader();
 3 |   try {
 4 |     while (true) {
 5 |       const { value, done } = await reader.read();
 6 |       if (done) {
 7 |         break;
 8 |       }
 9 | 
10 |       yield value;
11 |     }
12 |   } finally {
13 |     reader.releaseLock();
14 |   }
15 | }
16 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/register-spinner-autostopping.ts:
--------------------------------------------------------------------------------
 1 | import logSymbols from 'log-symbols';
 2 | import type { Ora } from 'ora';
 3 | 
 4 | const spinners = new Set<Ora>();
 5 | 
 6 | process.on('SIGINT', () => {
 7 |   spinners.forEach((spinner) => {
 8 |     if (spinner.isSpinning) {
 9 |       spinner.stop();
10 |     }
11 |   });
12 | });
13 | 
14 | process.on('exit', (code) => {
15 |   if (code !== 0) {
16 |     spinners.forEach((spinner) => {
17 |       if (spinner.isSpinning) {
18 |         spinner.stopAndPersist({
19 |           symbol: logSymbols.error,
20 |         });
21 |       }
22 |     });
23 |   }
24 | });
25 | 
26 | export const registerSpinnerAutostopping = (spinner: Ora) => {
27 |   spinners.add(spinner);
28 | };
29 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/sanitize.ts:
--------------------------------------------------------------------------------
1 | /**
2 |  * Sanitizes text by replacing underscores and hyphens with spaces
3 |  */
4 | export const sanitize = (text: string): string => {
5 |   return text.replace(/[_-]/g, ' ');
6 | };
7 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/testing/js-email-export-default.js:
--------------------------------------------------------------------------------
 1 | // A JavaScript email component with ES6 export default
 2 | import { Button, Html } from '@react-email/components';
 3 | 
 4 | function Email() {
 5 |   return (
 6 |     <Html>
 7 |       <Button
 8 |         href="https://example.com"
 9 |         style={{ background: '#000', color: '#fff', padding: '12px 20px' }}
10 |       >
11 |         Click me
12 |       </Button>
13 |     </Html>
14 |   );
15 | }
16 | 
17 | export default Email;
18 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/testing/js-email-test.js:
--------------------------------------------------------------------------------
 1 | // A simple JavaScript email component
 2 | const _React = require('react');
 3 | const { Html, Button } = require('@react-email/components');
 4 | 
 5 | function Email() {
 6 |   return (
 7 |     <Html>
 8 |       <Button
 9 |         href="https://example.com"
10 |         style={{ background: '#000', color: '#fff', padding: '12px 20px' }}
11 |       >
12 |         Click me
13 |       </Button>
14 |     </Html>
15 |   );
16 | }
17 | 
18 | module.exports = Email;
19 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/testing/request-response-email.tsx:
--------------------------------------------------------------------------------
 1 | /* eslint-disable @typescript-eslint/no-unused-vars */
 2 | const _req = new Request('https://react.email');
 3 | const _res = new Response('{}');
 4 | 
 5 | const Email = () => {
 6 |   return <div />;
 7 | };
 8 | 
 9 | export default Email;
10 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/types/as.ts:
--------------------------------------------------------------------------------
 1 | export type As<
 2 |   DefaultTag extends React.ElementType,
 3 |   T1 extends React.ElementType,
 4 |   T2 extends React.ElementType = T1,
 5 |   T3 extends React.ElementType = T1,
 6 |   T4 extends React.ElementType = T1,
 7 |   T5 extends React.ElementType = T1,
 8 | > =
 9 |   | (React.ComponentPropsWithRef<DefaultTag> & {
10 |       as?: DefaultTag;
11 |     })
12 |   | (React.ComponentPropsWithRef<T1> & {
13 |       as: T1;
14 |     })
15 |   | (React.ComponentPropsWithRef<T2> & {
16 |       as: T2;
17 |     })
18 |   | (React.ComponentPropsWithRef<T3> & {
19 |       as: T3;
20 |     })
21 |   | (React.ComponentPropsWithRef<T4> & {
22 |       as: T4;
23 |     })
24 |   | (React.ComponentPropsWithRef<T5> & {
25 |       as: T5;
26 |     });
27 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/types/email-template.ts:
--------------------------------------------------------------------------------
1 | export interface EmailTemplate {
2 |   (props: Record<string, unknown> | Record<string, never>): React.ReactNode;
3 |   PreviewProps?: Record<string, unknown>;
4 | }
5 | 
6 | export const isEmailTemplate = (val: unknown): val is EmailTemplate => {
7 |   return typeof val === 'function';
8 | };
9 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/types/error-object.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * An object that mimics the structure of the Error class,
 3 |  * we just can't use the Error class here because server actions can't
 4 |  * return classes
 5 |  */
 6 | export interface ErrorObject {
 7 |   name: string;
 8 |   stack: string | undefined;
 9 |   cause?: unknown;
10 |   message: string;
11 | }
12 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/types/hot-reload-change.ts:
--------------------------------------------------------------------------------
 1 | export interface HotReloadChange {
 2 |   filename: string;
 3 |   event:
 4 |     | 'all'
 5 |     | 'ready'
 6 |     | 'add'
 7 |     | 'change'
 8 |     | 'addDir'
 9 |     | 'unlink'
10 |     | 'unlinkDir'
11 |     | 'raw'
12 |     | 'error';
13 | }
14 | 


--------------------------------------------------------------------------------
/packages/preview-server/src/utils/unreachable.ts:
--------------------------------------------------------------------------------
1 | export const unreachable = (
2 |   condition: string | Record<string, unknown>,
3 |   message = `Entered unreachable code. Received '${
4 |     typeof condition === 'string' ? condition : JSON.stringify(condition)
5 |   }'.`,
6 | ): never => {
7 |   throw new TypeError(message);
8 | };
9 | 


--------------------------------------------------------------------------------
/packages/preview-server/vitest.config.ts:
--------------------------------------------------------------------------------
 1 | import { defineConfig } from 'vitest/config';
 2 | 
 3 | export default defineConfig({
 4 |   test: {
 5 |     globals: true,
 6 |     environment: 'happy-dom',
 7 |   },
 8 |   esbuild: {
 9 |     tsconfigRaw: {
10 |       compilerOptions: {
11 |         jsx: 'react-jsx',
12 |       },
13 |     },
14 |   },
15 | });
16 | 


--------------------------------------------------------------------------------
/packages/preview/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './preview';
2 | 


--------------------------------------------------------------------------------
/packages/preview/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/react-email/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .next
3 | cli
4 | !src/cli
5 | 
6 | # for testing
7 | .for-dependency-graph.ts
8 | static
9 | 


--------------------------------------------------------------------------------
/packages/react-email/.npmignore:
--------------------------------------------------------------------------------
1 | .react-email
2 | ./emails
3 | ./emails/static
4 | node_modules
5 | .turbo
6 | src/cli
7 | tsup.config.ts
8 | 


--------------------------------------------------------------------------------
/packages/react-email/dev/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # email-dev
2 | 
3 | ## 0.0.1
4 | 


--------------------------------------------------------------------------------
/packages/react-email/dev/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "email-dev",
 3 |   "version": "0.0.1",
 4 |   "bin": "index.js",
 5 |   "private": true,
 6 |   "type": "module",
 7 |   "scripts": {
 8 |     "start": "node ."
 9 |   }
10 | }
11 | 


--------------------------------------------------------------------------------
/packages/react-email/src/commands/.npmignore:
--------------------------------------------------------------------------------
1 | testing
2 | 


--------------------------------------------------------------------------------
/packages/react-email/src/commands/testing/.gitignore:
--------------------------------------------------------------------------------
1 | # for the `email export` command
2 | out
3 | 


--------------------------------------------------------------------------------
/packages/react-email/src/utils/esbuild/escape-string-for-regex.ts:
--------------------------------------------------------------------------------
1 | export function escapeStringForRegex(string: string) {
2 |   return string.replace(/[|\\{}()[\]^$+*?.]/g, '\\
amp;').replace(/-/g, '\\x2d');
3 | }
4 | 


--------------------------------------------------------------------------------
/packages/react-email/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './preview/index.js';
2 | export * from './tree.js';
3 | 


--------------------------------------------------------------------------------
/packages/react-email/src/utils/packageJson.ts:
--------------------------------------------------------------------------------
1 | // @ts-expect-error Typescript doesn't want to allow this, but it's fine since we're using tsup
2 | import packageJson from '../../package.json';
3 | 
4 | export { packageJson };
5 | 


--------------------------------------------------------------------------------
/packages/react-email/src/utils/preview/get-env-variables-for-preview-app.ts:
--------------------------------------------------------------------------------
 1 | import path from 'node:path';
 2 | 
 3 | export const getEnvVariablesForPreviewApp = (
 4 |   relativePathToEmailsDirectory: string,
 5 |   cwd: string,
 6 | ) => {
 7 |   return {
 8 |     EMAILS_DIR_RELATIVE_PATH: relativePathToEmailsDirectory,
 9 |     EMAILS_DIR_ABSOLUTE_PATH: path.resolve(cwd, relativePathToEmailsDirectory),
10 |     USER_PROJECT_LOCATION: cwd,
11 |   } as const;
12 | };
13 | 


--------------------------------------------------------------------------------
/packages/react-email/src/utils/preview/hot-reloading/resolve-path-aliases.spec.ts:
--------------------------------------------------------------------------------
 1 | import path from 'node:path';
 2 | import { resolvePathAliases } from './resolve-path-aliases.js';
 3 | 
 4 | test('resolveImports()', async () => {
 5 |   expect(
 6 |     resolvePathAliases(
 7 |       ['@/some-file'],
 8 |       path.resolve(import.meta.dirname, './test'),
 9 |     ),
10 |   ).toEqual(['./some-file']);
11 | });
12 | 


--------------------------------------------------------------------------------
/packages/react-email/src/utils/preview/hot-reloading/test/some-file.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/react-email/src/utils/preview/hot-reloading/test/some-file.ts


--------------------------------------------------------------------------------
/packages/react-email/src/utils/preview/hot-reloading/test/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "compilerOptions": {
3 |     "paths": {
4 |       "@/*": ["./*"]
5 |     }
6 |   },
7 |   "include": ["**/*.ts", "**/*.tsx"]
8 | }
9 | 


--------------------------------------------------------------------------------
/packages/react-email/src/utils/preview/index.ts:
--------------------------------------------------------------------------------
1 | export * from './hot-reloading/setup-hot-reloading.js';
2 | export * from './start-dev-server.js';
3 | 


--------------------------------------------------------------------------------
/packages/react-email/src/utils/register-spinner-autostopping.ts:
--------------------------------------------------------------------------------
 1 | import logSymbols from 'log-symbols';
 2 | import type { Ora } from 'ora';
 3 | 
 4 | const spinners = new Set<Ora>();
 5 | 
 6 | process.on('SIGINT', () => {
 7 |   spinners.forEach((spinner) => {
 8 |     if (spinner.isSpinning) {
 9 |       spinner.stop();
10 |     }
11 |   });
12 | });
13 | 
14 | process.on('exit', (code) => {
15 |   if (code !== 0) {
16 |     spinners.forEach((spinner) => {
17 |       if (spinner.isSpinning) {
18 |         spinner.stopAndPersist({
19 |           symbol: logSymbols.error,
20 |         });
21 |       }
22 |     });
23 |   }
24 | });
25 | 
26 | export const registerSpinnerAutostopping = (spinner: Ora) => {
27 |   spinners.add(spinner);
28 | };
29 | 


--------------------------------------------------------------------------------
/packages/react-email/src/utils/tree.spec.ts:
--------------------------------------------------------------------------------
1 | import { tree } from './tree.js';
2 | 
3 | test('tree(__dirname, 2)', async () => {
4 |   expect(await tree(__dirname, 2)).toMatchSnapshot();
5 | });
6 | 


--------------------------------------------------------------------------------
/packages/react-email/src/utils/types/hot-reload-change.ts:
--------------------------------------------------------------------------------
1 | import type { HotReloadEvent } from './hot-reload-event.js';
2 | 
3 | export interface HotReloadChange {
4 |   filename: string;
5 |   event: HotReloadEvent;
6 | }
7 | 


--------------------------------------------------------------------------------
/packages/react-email/src/utils/types/hot-reload-event.ts:
--------------------------------------------------------------------------------
1 | import type { EventName } from 'chokidar/handler.js';
2 | 
3 | export type HotReloadEvent = EventName;
4 | 


--------------------------------------------------------------------------------
/packages/react-email/tsup.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'tsup';
2 | 
3 | export default defineConfig({
4 |   dts: false,
5 |   entry: ['./src/index.ts'],
6 |   format: ['esm'],
7 |   outDir: 'dist',
8 | });
9 | 


--------------------------------------------------------------------------------
/packages/react-email/vitest.config.ts:
--------------------------------------------------------------------------------
 1 | import { defineConfig } from 'vitest/config';
 2 | 
 3 | export default defineConfig({
 4 |   test: {
 5 |     globals: true,
 6 |     environment: 'happy-dom',
 7 |   },
 8 |   esbuild: {
 9 |     tsconfigRaw: {
10 |       compilerOptions: {
11 |         jsx: 'react-jsx',
12 |       },
13 |     },
14 |   },
15 | });
16 | 


--------------------------------------------------------------------------------
/packages/render/src/browser/index.ts:
--------------------------------------------------------------------------------
 1 | import type { Options } from '../shared/options';
 2 | import { render } from './render';
 3 | 
 4 | /**
 5 |  * @deprecated use {@link render}
 6 |  */
 7 | export const renderAsync = (element: React.ReactElement, options?: Options) => {
 8 |   return render(element, options);
 9 | };
10 | 
11 | export * from '../shared/options';
12 | export * from '../shared/plain-text-selectors';
13 | export * from '../shared/utils/pretty';
14 | export * from './render';
15 | 


--------------------------------------------------------------------------------
/packages/render/src/node/index.ts:
--------------------------------------------------------------------------------
 1 | import type { Options } from '../shared/options';
 2 | import { render } from './render';
 3 | 
 4 | /**
 5 |  * @deprecated use {@link render}
 6 |  */
 7 | export const renderAsync = (element: React.ReactElement, options?: Options) => {
 8 |   return render(element, options);
 9 | };
10 | 
11 | export * from '../shared/options';
12 | export * from '../shared/plain-text-selectors';
13 | export * from '../shared/utils/pretty';
14 | export * from './render';
15 | 


--------------------------------------------------------------------------------
/packages/render/src/react-internals.d.ts:
--------------------------------------------------------------------------------
1 | declare module "react-dom/server.browser" {
2 |   export * from "react-dom/server";
3 | }
4 | 


--------------------------------------------------------------------------------
/packages/render/src/shared/options.ts:
--------------------------------------------------------------------------------
 1 | import type { HtmlToTextOptions } from 'html-to-text';
 2 | import type { pretty } from './utils/pretty';
 3 | 
 4 | export type Options = {
 5 |   /**
 6 |    * @deprecated use {@link pretty} instead
 7 |    */
 8 |   pretty?: boolean;
 9 | } & (
10 |   | {
11 |       plainText?: false;
12 |     }
13 |   | {
14 |       plainText?: true;
15 |       /**
16 |        * These are options you can pass down directly to the library we use for
17 |        * converting the rendered email's HTML into plain text.
18 |        *
19 |        * @see https://github.com/html-to-text/node-html-to-text
20 |        */
21 |       htmlToTextOptions?: HtmlToTextOptions;
22 |     }
23 | );
24 | 


--------------------------------------------------------------------------------
/packages/render/src/shared/plain-text-selectors.ts:
--------------------------------------------------------------------------------
 1 | import type { SelectorDefinition } from 'html-to-text';
 2 | 
 3 | export const plainTextSelectors: SelectorDefinition[] = [
 4 |   { selector: 'img', format: 'skip' },
 5 |   { selector: '[data-skip-in-text=true]', format: 'skip' },
 6 |   {
 7 |     selector: 'a',
 8 |     options: { linkBrackets: false },
 9 |   },
10 | ];
11 | 


--------------------------------------------------------------------------------
/packages/render/src/shared/utils/preview.tsx:
--------------------------------------------------------------------------------
1 | export const Preview: React.FC = () => (
2 |   <>
3 |     <div data-skip-in-text={true}>This should be hidden from plain text</div>
4 |     <h1>This should be rendered in plain text</h1>
5 |   </>
6 | );
7 | 


--------------------------------------------------------------------------------
/packages/render/src/shared/utils/template.tsx:
--------------------------------------------------------------------------------
 1 | import type * as React from 'react';
 2 | 
 3 | interface TemplateProps {
 4 |   firstName: string;
 5 | }
 6 | 
 7 | export const Template: React.FC<Readonly<TemplateProps>> = ({ firstName }) => (
 8 |   <>
 9 |     <h1>Welcome, {firstName}!</h1>
10 |     <img alt="test" src="img/test.png" />
11 |     <p>Thanks for trying our product. We're thrilled to have you on board!</p>
12 |   </>
13 | );
14 | 


--------------------------------------------------------------------------------
/packages/render/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/render/tsup.config.ts:
--------------------------------------------------------------------------------
 1 | import { defineConfig } from 'tsup';
 2 | 
 3 | export default defineConfig([
 4 |   {
 5 |     dts: true,
 6 |     entry: ['./src/node/index.ts'],
 7 |     outDir: './dist/node',
 8 |     format: ['cjs', 'esm'],
 9 |   },
10 |   {
11 |     dts: true,
12 |     entry: ['./src/browser/index.ts'],
13 |     outDir: './dist/browser',
14 |     format: ['cjs', 'esm'],
15 |   },
16 | ]);
17 | 


--------------------------------------------------------------------------------
/packages/row/src/__snapshots__/row.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 | 
3 | exports[`<Row> component > renders correctly 1`] = `"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation"><tbody style="width:100%"><tr style="width:100%"></tr></tbody></table><!--/$-->"`;
4 | 


--------------------------------------------------------------------------------
/packages/row/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './row';
2 | 


--------------------------------------------------------------------------------
/packages/row/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/section/src/__snapshots__/section.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 | 
3 | exports[`<Section> component > renders correctly 1`] = `"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><!--$--><table align="center" width="100%" border="0" cellPadding="0" cellSpacing="0" role="presentation"><tbody><tr><td>Lorem ipsum</td></tr></tbody></table><!--/$-->"`;
4 | 


--------------------------------------------------------------------------------
/packages/section/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './section';
2 | 


--------------------------------------------------------------------------------
/packages/section/src/section.tsx:
--------------------------------------------------------------------------------
 1 | import * as React from 'react';
 2 | 
 3 | export type SectionProps = Readonly<React.ComponentPropsWithoutRef<'table'>>;
 4 | 
 5 | export const Section = React.forwardRef<HTMLTableElement, SectionProps>(
 6 |   ({ children, style, ...props }, ref) => {
 7 |     return (
 8 |       <table
 9 |         align="center"
10 |         width="100%"
11 |         border={0}
12 |         cellPadding="0"
13 |         cellSpacing="0"
14 |         role="presentation"
15 |         {...props}
16 |         ref={ref}
17 |         style={style}
18 |       >
19 |         <tbody>
20 |           <tr>
21 |             <td>{children}</td>
22 |           </tr>
23 |         </tbody>
24 |       </table>
25 |     );
26 |   },
27 | );
28 | 
29 | Section.displayName = 'Section';
30 | 


--------------------------------------------------------------------------------
/packages/section/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/tailwind/copy-tailwind-types.mjs:
--------------------------------------------------------------------------------
 1 | import { promises as fs } from 'node:fs';
 2 | import path from 'node:path';
 3 | import url from 'node:url';
 4 | 
 5 | const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
 6 | 
 7 | await fs.cp(
 8 |   path.resolve(__dirname, './node_modules/tailwindcss/types'),
 9 |   path.resolve(__dirname, './dist/tailwindcss'),
10 |   {
11 |     recursive: true,
12 |   },
13 | );
14 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/nextjs/.gitignore:
--------------------------------------------------------------------------------
 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
 2 | 
 3 | # dependencies
 4 | /node_modules
 5 | /.pnp
 6 | .yalc
 7 | yalc.lock
 8 | .pnp.js
 9 | yalc.lock
10 | .yarn/install-state.gz
11 | 
12 | # testing
13 | /coverage
14 | 
15 | # next.js
16 | /.next/
17 | /out/
18 | 
19 | # production
20 | /build
21 | 
22 | # misc
23 | .DS_Store
24 | *.pem
25 | 
26 | # debug
27 | npm-debug.log*
28 | yarn-debug.log*
29 | yarn-error.log*
30 | 
31 | # local env files
32 | .env*.local
33 | 
34 | # vercel
35 | .vercel
36 | 
37 | # typescript
38 | *.tsbuildinfo
39 | next-env.d.ts
40 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/nextjs/README.md:
--------------------------------------------------------------------------------
 1 | This is a NextJS project bootstrapped with `create-next-app@latest` that contains a Tailwind
 2 | email using most of the features we provide that will be auto-built on testing to
 3 | make sure this new release works properly with the latest version of NextJS when being built.
 4 | 
 5 | We do this testing so that things are more reliable and this couldn't be done using pnpm
 6 | workspaces as they link code instead of actually copying the content into node_modules.
 7 | The solution we use to copy the code in a way that mimics the actual `npm install @react-email/tailwind` is `yalc`.
 8 | 
 9 | Se [the test file](../_tests/nextjs.spec.ts) for more info.
10 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/nextjs/next-env.d.ts:
--------------------------------------------------------------------------------
1 | /// <reference types="next" />
2 | /// <reference types="next/image-types/global" />
3 | 
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
6 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/nextjs/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 |   compress: false,
4 |   swcMinify: false,
5 | };
6 | 
7 | export default nextConfig;
8 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/nextjs/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "nextjs-with-tailwind",
 3 |   "version": "0.1.0",
 4 |   "private": true,
 5 |   "scripts": {
 6 |     "dev": "next dev",
 7 |     "build": "next build",
 8 |     "start": "next start",
 9 |     "preinstall": "yalc add @react-email/tailwind"
10 |   },
11 |   "dependencies": {
12 |     "@react-email/components": "0.0.36",
13 |     "@react-email/tailwind": "file:.yalc/@react-email/tailwind",
14 |     "next": "^15",
15 |     "react": "^19",
16 |     "react-dom": "^19"
17 |   },
18 |   "devDependencies": {
19 |     "@types/node": "^22.0.0",
20 |     "@types/react": "^19",
21 |     "@types/react-dom": "^19",
22 |     "typescript": "^5",
23 |     "yalc": "1.0.0-pre.53"
24 |   }
25 | }
26 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/nextjs/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/resend/react-email/b2407a1156d0251cfe466a159306c47d3bcfcfae/packages/tailwind/integrations/nextjs/src/app/favicon.ico


--------------------------------------------------------------------------------
/packages/tailwind/integrations/nextjs/src/app/layout.tsx:
--------------------------------------------------------------------------------
 1 | import type { Metadata } from 'next';
 2 | import { Inter } from 'next/font/google';
 3 | 
 4 | const inter = Inter({ subsets: ['latin'] });
 5 | 
 6 | export const metadata: Metadata = {
 7 |   title: 'Create Next App',
 8 |   description: 'Generated by create next app',
 9 | };
10 | 
11 | const RootLayout = ({
12 |   children,
13 | }: Readonly<{
14 |   children: React.ReactNode;
15 | }>) => {
16 |   return (
17 |     <html lang="en">
18 |       <body className={inter.className}>{children}</body>
19 |     </html>
20 |   );
21 | };
22 | 
23 | export default RootLayout;
24 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/nextjs/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@react-email/components';
2 | import { VercelInviteUserEmail } from '../../emails/vercel-invite-user';
3 | 
4 | export default async function Home() {
5 |   const emailHtml = await render(<VercelInviteUserEmail />);
6 |   return <div dangerouslySetInnerHTML={{ __html: emailHtml }} />;
7 | }
8 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/nextjs/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "compilerOptions": {
 3 |     "lib": ["dom", "dom.iterable", "esnext"],
 4 |     "allowJs": true,
 5 |     "skipLibCheck": true,
 6 |     "strict": true,
 7 |     "noEmit": true,
 8 |     "esModuleInterop": true,
 9 |     "module": "esnext",
10 |     "moduleResolution": "bundler",
11 |     "resolveJsonModule": true,
12 |     "isolatedModules": true,
13 |     "jsx": "preserve",
14 |     "incremental": true,
15 |     "plugins": [
16 |       {
17 |         "name": "next"
18 |       }
19 |     ],
20 |     "paths": {
21 |       "@/*": ["./src/*"]
22 |     },
23 |     "target": "ES2017"
24 |   },
25 |   "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26 |   "exclude": ["node_modules"]
27 | }
28 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/vite/.gitignore:
--------------------------------------------------------------------------------
 1 | # Logs
 2 | logs
 3 | *.log
 4 | npm-debug.log*
 5 | yarn-debug.log*
 6 | yarn-error.log*
 7 | pnpm-debug.log*
 8 | lerna-debug.log*
 9 | 
10 | node_modules
11 | dist
12 | .yalc
13 | yalc.lock
14 | dist-ssr
15 | *.local
16 | 
17 | # Editor directories and files
18 | .vscode/*
19 | !.vscode/extensions.json
20 | .idea
21 | .DS_Store
22 | *.suo
23 | *.ntvs*
24 | *.njsproj
25 | *.sln
26 | *.sw?
27 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/vite/README.md:
--------------------------------------------------------------------------------
 1 | This is a Vite React project bootstrapped with `npm create vite@latest` that contains a Tailwind
 2 | email using most of the features we provide that will be auto-built on testing to
 3 | make sure this new release works properly with the latest version of Vite when being built.
 4 | 
 5 | We do this testing so that things are more reliable before we get to publishing. This
 6 | couldn't be done using pnpm workspaces as they link code instead of actually copying the content into node_modules.
 7 | The solution we use to copy the code, in a way that mimics the actual `npm install @react-email/tailwind`, is `yalc`.
 8 | 
 9 | Se [the test file](../_tests/vite.spec.ts) for more info.
10 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/vite/index.html:
--------------------------------------------------------------------------------
 1 | <!doctype html>
 2 | <html lang="en">
 3 |   <head>
 4 |     <meta charset="UTF-8" />
 5 |     <link rel="icon" type="image/svg+xml" href="/vite.svg" />
 6 |     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 7 |     <title>Vite + React + TS</title>
 8 |   </head>
 9 |   <body>
10 |     <div id="root"></div>
11 |     <script type="module" src="/src/main.tsx"></script>
12 |   </body>
13 | </html>
14 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/vite/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "vite-with-tailwind",
 3 |   "private": true,
 4 |   "version": "0.0.0",
 5 |   "type": "module",
 6 |   "scripts": {
 7 |     "dev": "vite",
 8 |     "build": "vite build",
 9 |     "preinstall": "yalc add @react-email/tailwind",
10 |     "preview": "vite preview"
11 |   },
12 |   "dependencies": {
13 |     "@react-email/components": "0.0.36",
14 |     "@react-email/tailwind": "file:.yalc/@react-email/tailwind",
15 |     "react": "^19",
16 |     "react-dom": "^19"
17 |   },
18 |   "devDependencies": {
19 |     "@types/react": "^19",
20 |     "@types/react-dom": "^19",
21 |     "@vitejs/plugin-react": "^4.2.1",
22 |     "typescript": "^5.2.2",
23 |     "vite": "^6.3.2",
24 |     "yalc": "1.0.0-pre.53"
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/vite/src/App.tsx:
--------------------------------------------------------------------------------
 1 | import { render } from '@react-email/components';
 2 | import { VercelInviteUserEmail } from '../emails/vercel-invite-user';
 3 | 
 4 | function App() {
 5 |   const emailHtml = render(<VercelInviteUserEmail />);
 6 | 
 7 |   return <div dangerouslySetInnerHTML={{ __html: emailHtml }} />;
 8 | }
 9 | 
10 | export default App;
11 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/vite/src/main.tsx:
--------------------------------------------------------------------------------
 1 | import React from 'react';
 2 | import ReactDOM from 'react-dom/client';
 3 | import App from './App.tsx';
 4 | 
 5 | ReactDOM.createRoot(document.getElementById('root')!).render(
 6 |   <React.StrictMode>
 7 |     <App />
 8 |   </React.StrictMode>,
 9 | );
10 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/vite/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | /// <reference types="vite/client" />
2 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/vite/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2020",
 4 |     "useDefineForClassFields": true,
 5 |     "lib": ["ES2020", "DOM", "DOM.Iterable"],
 6 |     "module": "ESNext",
 7 |     "skipLibCheck": true,
 8 | 
 9 |     /* Bundler mode */
10 |     "moduleResolution": "bundler",
11 |     "allowImportingTsExtensions": true,
12 |     "resolveJsonModule": true,
13 |     "isolatedModules": true,
14 |     "noEmit": true,
15 |     "jsx": "react-jsx",
16 | 
17 |     /* Linting */
18 |     "strict": true,
19 |     "noUnusedLocals": true,
20 |     "noUnusedParameters": true,
21 |     "noFallthroughCasesInSwitch": true
22 |   },
23 |   "include": ["src"],
24 |   "references": [{ "path": "./tsconfig.node.json" }]
25 | }
26 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/vite/tsconfig.node.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "compilerOptions": {
 3 |     "composite": true,
 4 |     "skipLibCheck": true,
 5 |     "module": "ESNext",
 6 |     "moduleResolution": "bundler",
 7 |     "allowSyntheticDefaultImports": true,
 8 |     "strict": true
 9 |   },
10 |   "include": ["vite.config.ts"]
11 | }
12 | 


--------------------------------------------------------------------------------
/packages/tailwind/integrations/vite/vite.config.ts:
--------------------------------------------------------------------------------
1 | import react from '@vitejs/plugin-react';
2 | import { defineConfig } from 'vite';
3 | 
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 |   plugins: [react()],
7 | });
8 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/hooks/__snapshots__/use-tailwind.spec.ts.snap:
--------------------------------------------------------------------------------
 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 2 | 
 3 | exports[`useTailwind() 1`] = `
 4 | ".text-red-500 {
 5 |     color: rgb(239 68 68 / 1)
 6 | }
 7 |   @media (min-width: 640px) {
 8 |     .sm\\:bg-blue-300 {
 9 |         background-color: rgb(147 197 253 / 1)
10 |     }
11 | }
12 |   .bg-slate-900 {
13 |     background-color: rgb(15 23 42 / 1)
14 | }
15 | "
16 | `;
17 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './tailwind';
2 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/__snapshots__/quick-safe-render-to-string.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 | 
3 | exports[`quick safe render to string 1`] = `"<div className="bg-red-500 text-gray-200"><h1><Component><div className="user-name flex text-2xl"></div></Component></h1><span className="dark:bg-green-500 hover:bg-green-800 transition-colors"></span></div><span className="dark:bg-green-500 hover:bg-green-800 transition-colors"></span>"`;
4 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/compatibility/convert-css-property-to-react-property.ts:
--------------------------------------------------------------------------------
 1 | import { fromDashCaseToCamelCase } from '../text/from-dash-case-to-camel-case';
 2 | 
 3 | export const convertCssPropertyToReactProperty = (prop: string) => {
 4 |   const modifiedProp = prop.toLowerCase();
 5 | 
 6 |   if (modifiedProp.startsWith('--')) {
 7 |     return modifiedProp;
 8 |   }
 9 | 
10 |   if (modifiedProp.startsWith('-ms-')) {
11 |     return fromDashCaseToCamelCase(modifiedProp.slice(1));
12 |   }
13 | 
14 |   return fromDashCaseToCamelCase(modifiedProp);
15 | };
16 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/compatibility/escape-class-name.spec.ts:
--------------------------------------------------------------------------------
 1 | import { escapeClassName } from './escape-class-name';
 2 | 
 3 | describe('escapeClassName function', () => {
 4 |   it('should escape the first character properly', () => {
 5 |     expect(escapeClassName('[min-height-')).toBe('\\[min-height-');
 6 |   });
 7 | 
 8 |   it('should not escape an already escaped first-character', () => {
 9 |     expect(escapeClassName('\\[min-height-')).toBe('\\[min-height-');
10 |   });
11 | 
12 |   it('should escape `min-height-[calc(25px+100%-20%*2/4)]` correctly', () => {
13 |     expect(escapeClassName('min-height-[calc(25px+100%-20%*2/4)]')).toBe(
14 |       'min-height-\\[calc\\(25px\\+100\\%-20\\%\\*2\\/4\\)\\]',
15 |     );
16 |   });
17 | });
18 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/compatibility/escape-class-name.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Escapes all characters that may not be accepted on
 3 |  * CSS selectors by using the regex "[^a-zA-Z0-9\-_]".
 4 |  *
 5 |  * Also does a bit more trickery to avoid escaping already
 6 |  * escaped characters.
 7 |  */
 8 | export const escapeClassName = (className: string) => {
 9 |   return className.replace(
10 |     /*      we need this look ahead capturing group to avoid using negative look behinds */
11 |     /([^\\]|^)(?=([^a-zA-Z0-9\-_]))/g,
12 |     (match, prefixCharacter: string, characterToEscape: string) => {
13 |       if (prefixCharacter === '' && characterToEscape === '\\') return match;
14 | 
15 |       return `${prefixCharacter}\\`;
16 |     },
17 |   );
18 | };
19 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/compatibility/sanitize-class-name.spec.ts:
--------------------------------------------------------------------------------
1 | import { sanitizeClassName } from './sanitize-class-name';
2 | 
3 | test('sanitizeClassName', () => {
4 |   expect(sanitizeClassName('min-height-[calc(25px+100%-20%*2/4)]')).toBe(
5 |     'min-height-calc25pxplus100pc-20pc_2_4',
6 |   );
7 | });
8 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/compatibility/unescape-class.ts:
--------------------------------------------------------------------------------
1 | export function unescapeClass(singleClass: string) {
2 |   return singleClass.replaceAll(/\\[0-9]|\\/g, '');
3 | }
4 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/css/make-inline-styles-for.spec.ts:
--------------------------------------------------------------------------------
 1 | import { setupTailwind } from '../tailwindcss/setup-tailwind';
 2 | import { makeInlineStylesFor } from './make-inline-styles-for';
 3 | 
 4 | test('makeInlineStylesFor()', () => {
 5 |   const tailwind = setupTailwind({});
 6 | 
 7 |   const className =
 8 |     'bg-red-500 sm:bg-blue-300 w-full md:max-w-[400px] my-custom-class';
 9 |   const tailwindStyles = tailwind.generateRootForClasses(className.split(' '));
10 | 
11 |   expect(makeInlineStylesFor(className, tailwindStyles)).toEqual({
12 |     styles: { backgroundColor: 'rgb(239 68 68 / 1)', width: '100%' },
13 |     residualClassName: 'sm:bg-blue-300 md:max-w-[400px] my-custom-class',
14 |   });
15 | });
16 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/css/remove-if-empty-recursively.ts:
--------------------------------------------------------------------------------
 1 | import type { Container, Document } from 'postcss';
 2 | 
 3 | export const removeIfEmptyRecursively = (node: Container | Document) => {
 4 |   if (node.first === undefined) {
 5 |     const parent = node.parent;
 6 |     if (parent) {
 7 |       node.remove();
 8 |       removeIfEmptyRecursively(parent);
 9 |     }
10 |   }
11 | };
12 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/css/remove-rule-duplicates-from-root.ts:
--------------------------------------------------------------------------------
 1 | import type { Root } from 'postcss';
 2 | import { removeIfEmptyRecursively } from './remove-if-empty-recursively';
 3 | 
 4 | export const removeRuleDuplicatesFromRoot = (root: Root) => {
 5 |   root.walkRules((rule) => {
 6 |     root.walkRules(rule.selector, (duplicateRule) => {
 7 |       if (duplicateRule === rule) return;
 8 | 
 9 |       const parent = duplicateRule.parent;
10 |       duplicateRule.remove();
11 |       if (parent) {
12 |         removeIfEmptyRecursively(parent);
13 |       }
14 |     });
15 |   });
16 | };
17 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/react/is-component.ts:
--------------------------------------------------------------------------------
 1 | export const isComponent = (
 2 |   element: React.ReactElement,
 3 | ): element is React.ReactElement<unknown, React.FC<unknown>> => {
 4 |   return (
 5 |     typeof element.type === 'function' ||
 6 |     // @ts-expect-error - we know this is a component that may have a render function
 7 |     element.type.render !== undefined
 8 |   );
 9 | };
10 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/tailwindcss/__snapshots__/setup-tailwind.spec.ts.snap:
--------------------------------------------------------------------------------
 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 2 | 
 3 | exports[`tailwind's generateRootForClasses() 1`] = `
 4 | ".text-red-500 {
 5 |     color: rgb(239 68 68 / 1)
 6 | }
 7 |   @media (min-width: 640px) {
 8 |     .sm\\:bg-blue-300 {
 9 |         background-color: rgb(147 197 253 / 1)
10 |     }
11 | }
12 |   .bg-slate-900 {
13 |     background-color: rgb(15 23 42 / 1)
14 | }
15 | "
16 | `;
17 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/tailwindcss/setup-tailwind-context.ts:
--------------------------------------------------------------------------------
 1 | import { createContext } from 'tailwindcss/lib/lib/setupContextUtils';
 2 | import resolveConfig from 'tailwindcss/resolveConfig';
 3 | import type { TailwindConfig } from '../../tailwind';
 4 | 
 5 | export const setupTailwindContext = (config: TailwindConfig) => {
 6 |   return createContext(
 7 |     resolveConfig({
 8 |       ...config,
 9 |       content: [],
10 |       corePlugins: {
11 |         preflight: false,
12 |       },
13 |     }),
14 |   );
15 | };
16 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/tailwindcss/setup-tailwind.spec.ts:
--------------------------------------------------------------------------------
 1 | import { setupTailwind } from './setup-tailwind';
 2 | 
 3 | test("tailwind's generateRootForClasses()", () => {
 4 |   const tailwind = setupTailwind({});
 5 | 
 6 |   expect(
 7 |     tailwind
 8 |       .generateRootForClasses([
 9 |         'text-red-500',
10 |         'sm:bg-blue-300',
11 |         'bg-slate-900',
12 |       ])
13 |       .toString(),
14 |   ).toMatchSnapshot();
15 | });
16 | 


--------------------------------------------------------------------------------
/packages/tailwind/src/utils/text/from-dash-case-to-camel-case.ts:
--------------------------------------------------------------------------------
1 | export const fromDashCaseToCamelCase = (text: string) => {
2 |   return text.replace(/-(\w|$)/g, (_, p1: string) => p1.toUpperCase());
3 | };
4 | 


--------------------------------------------------------------------------------
/packages/tailwind/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "$schema": "https://json.schemastore.org/tsconfig",
 3 |   "extends": "tsconfig/react-library.json",
 4 |   "include": ["."],
 5 |   "exclude": [
 6 |     "dist",
 7 |     "build",
 8 |     "node_modules",
 9 |     "integrations/vite",
10 |     "integrations/nextjs"
11 |   ],
12 |   "compilerOptions": {
13 |     "strict": true,
14 |     "noEmit": true
15 |   }
16 | }
17 | 


--------------------------------------------------------------------------------
/packages/tailwind/vitest.config.ts:
--------------------------------------------------------------------------------
 1 | import path from 'node:path';
 2 | import { defineConfig } from 'vitest/config';
 3 | 
 4 | export default defineConfig({
 5 |   test: {
 6 |     globals: true,
 7 |     environment: 'happy-dom',
 8 |   },
 9 |   server: {
10 |     watch: {
11 |       ignored: [path.resolve(__dirname, './integrations/**/*')],
12 |     },
13 |   },
14 | });
15 | 


--------------------------------------------------------------------------------
/packages/text/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './text';
2 | 


--------------------------------------------------------------------------------
/packages/text/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/react-library.json",
3 |   "include": ["."],
4 |   "exclude": ["dist", "build", "node_modules"]
5 | }
6 | 


--------------------------------------------------------------------------------
/packages/tsconfig/base.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "$schema": "https://json.schemastore.org/tsconfig",
 3 |   "display": "Default",
 4 |   "compilerOptions": {
 5 |     "composite": false,
 6 |     "declaration": true,
 7 |     "declarationMap": true,
 8 |     "esModuleInterop": true,
 9 |     "forceConsistentCasingInFileNames": true,
10 |     "inlineSources": false,
11 |     "isolatedModules": true,
12 |     "moduleResolution": "node",
13 |     "noUnusedLocals": false,
14 |     "noUnusedParameters": false,
15 |     "preserveWatchOutput": true,
16 |     "skipLibCheck": true,
17 |     "strict": true,
18 |     "strictNullChecks": true
19 |   },
20 |   "exclude": ["node_modules"]
21 | }
22 | 


--------------------------------------------------------------------------------
/packages/tsconfig/nextjs.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "$schema": "https://json.schemastore.org/tsconfig",
 3 |   "display": "Next.js",
 4 |   "extends": "./base.json",
 5 |   "compilerOptions": {
 6 |     "plugins": [{ "name": "next" }],
 7 |     "allowJs": true,
 8 |     "declaration": false,
 9 |     "declarationMap": false,
10 |     "incremental": true,
11 |     "jsx": "preserve",
12 |     "lib": ["dom", "dom.iterable", "esnext"],
13 |     "module": "esnext",
14 |     "noEmit": true,
15 |     "resolveJsonModule": true,
16 |     "strict": false,
17 |     "target": "es5"
18 |   },
19 |   "include": ["src", "next-env.d.ts"],
20 |   "exclude": ["node_modules"]
21 | }
22 | 


--------------------------------------------------------------------------------
/packages/tsconfig/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "tsconfig",
 3 |   "version": "0.0.0",
 4 |   "private": true,
 5 |   "license": "MIT",
 6 |   "publishConfig": {
 7 |     "access": "public"
 8 |   }
 9 | }
10 | 


--------------------------------------------------------------------------------
/packages/tsconfig/react-library.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "$schema": "https://json.schemastore.org/tsconfig",
 3 |   "display": "React Library",
 4 |   "extends": "./base.json",
 5 |   "compilerOptions": {
 6 |     "jsx": "react-jsx",
 7 |     "lib": ["ESNext", "DOM", "DOM.Iterable"],
 8 |     "module": "ESNext",
 9 |     "target": "es6",
10 |     "types": ["vitest/globals"]
11 |   }
12 | }
13 | 


--------------------------------------------------------------------------------
/playground/emails/.gitignore:
--------------------------------------------------------------------------------
1 | **/*.tsx
2 | !example.tsx
3 | 


--------------------------------------------------------------------------------
/playground/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "playground",
 3 |   "version": "0.0.0",
 4 |   "private": true,
 5 |   "scripts": {
 6 |     "dev": "email dev",
 7 |     "export": "email export"
 8 |   },
 9 |   "dependencies": {
10 |     "@react-email/render": "workspace:*",
11 |     "react": "^19",
12 |     "react-dom": "^19"
13 |   },
14 |   "devDependencies": {
15 |     "@react-email/preview-server": "workspace:*",
16 |     "@types/react": "^19",
17 |     "@types/react-dom": "^19",
18 |     "react-email": "workspace:*",
19 |     "tsconfig": "workspace:*"
20 |   }
21 | }
22 | 


--------------------------------------------------------------------------------
/playground/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "extends": "tsconfig/react-library.json",
 3 |   "compilerOptions": {
 4 |     "paths": {
 5 |       "@react-email/components": ["./components.ts"]
 6 |     }
 7 |   },
 8 |   "include": ["."]
 9 | }
10 | 


--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 |   - "apps/*"
3 |   - "benchmarks/*"
4 |   - "packages/*"
5 |   - "packages/react-email/dev"
6 |   - "playground"
7 | 


--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 |   "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 |   "extends": ["config:recommended"],
4 |   "ignorePaths": ["benchmarks"],
5 |   "schedule": ["before 3am on the first day of the month"],
6 |   "updateNotScheduled": false,
7 |   "rebaseWhen": "conflicted"
8 | }
9 | 


--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "tsconfig/base.json",
3 |   "compilerOptions": {
4 |     "jsx": "react-jsx",
5 |     "types": ["vitest/globals"]
6 |   }
7 | }
8 | 


--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
 1 | /// <reference types="vitest" />
 2 | 
 3 | import { defineConfig } from 'vitest/config';
 4 | 
 5 | export default defineConfig({
 6 |   test: {
 7 |     globals: true,
 8 |     environment: 'happy-dom',
 9 |   },
10 | });
11 | 


--------------------------------------------------------------------------------