Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(docs): Improved contributing guide #1342

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
2f5410c
chore: Make the CONTRIBUTING.md point towards the docs contributing g…
gabrielmfern Feb 19, 2024
29435ac
chore(docs): Rename contributing page to "Old contributing" on the si…
gabrielmfern Feb 19, 2024
931a87b
feat(docs): Add new codebase overview (WIP) and opening issues page a…
gabrielmfern Feb 19, 2024
b53a36f
WIP: closer to finishing the write-up for the codebase overview
gabrielmfern Feb 19, 2024
efd7b14
feat(docs/contributing): linting, testing and a few other sections on…
gabrielmfern Feb 20, 2024
6d3aff4
feat(docs/contributing): Conclusion with "New issue" button
gabrielmfern Feb 20, 2024
a646478
chore(docs/contributing): Add icon to codebase-overview
gabrielmfern Feb 20, 2024
8ffea44
feat(docs/contributing): List all packages inside of a table
gabrielmfern Feb 20, 2024
99917f1
feat(docs/contributing): A grid of lists for all the packages
gabrielmfern Feb 20, 2024
7e09c02
feat(docs/contributing): Development workflow with 1. Setup done
gabrielmfern Feb 20, 2024
153405e
feat(docs/contributing): 2. Running tests
gabrielmfern Feb 20, 2024
be308b8
feat(docs/contributing): 3. Linting the project
gabrielmfern Feb 20, 2024
7b7c05f
feat(docs/contributing): 4. Building on the development workflow
gabrielmfern Feb 20, 2024
279cdad
feat(docs/contributing): Add ## building to the codebase-overview
gabrielmfern Feb 20, 2024
4aea026
fet(docs/contributing): Opening pull requests section
gabrielmfern Feb 20, 2024
1fe1d05
fix(docs): Invalid property "class" warning
gabrielmfern Mar 5, 2024
a35d13f
chore(docs/development-workflow): Small note on the `pnpm build` step
gabrielmfern Mar 5, 2024
e20c1e1
fix(docs): grammar on the "Opening issues" page
gabrielmfern Mar 5, 2024
0164c32
feat(docs): Section for writing a good description for pull requests
gabrielmfern Mar 5, 2024
a1c617a
fix(docs): Gramamr on the "building" in the development workflow
gabrielmfern Mar 5, 2024
acd433f
fix(docs): Grammar on the "Opening pull requests" page
gabrielmfern Mar 5, 2024
452ed59
chore(docs): Format
gabrielmfern Mar 5, 2024
6baa0ab
fix(root): broken link to the contributing guide on the docs
gabrielmfern Mar 5, 2024
5a59d05
feat(docs): Another argument for making a proper reproduction
gabrielmfern Mar 27, 2024
7b7cae5
fix(docs): Grammar based on the context
gabrielmfern Mar 27, 2024
52288f5
a few writing improvements on the opening issues section
gabrielmfern Jun 4, 2024
4c0015c
remove uneeded extra reason for why we build
gabrielmfern Jun 20, 2024
1f4b880
a few writing improvements on the linting for the development workflow
gabrielmfern Jun 20, 2024
681b166
improve writing in the running tests step
gabrielmfern Jun 20, 2024
d7f6568
add mention that issues that have been fixed under canary should stil…
gabrielmfern Jun 20, 2024
55e583a
add mention that docs pull requests should go onto main
gabrielmfern Jun 20, 2024
3cda0e9
add that the guidelines for PR descriptions are not required
gabrielmfern Jun 20, 2024
8fb5d74
add section for writing docs in the dev workflow
gabrielmfern Jun 20, 2024
e754ff3
remove old contribution navigation item
gabrielmfern Nov 15, 2024
42c8698
updat elinting and formatting section
gabrielmfern Feb 12, 2025
116039e
copy-edit review
cpenned Feb 13, 2025
3a629f8
Merge branch 'main' into feat/improved-contributing-guide
cpenned Feb 13, 2025
ba2feb2
add few writing adjustments
gabrielmfern Feb 17, 2025
ebfb4c0
copy over the introduction for contributing to the CONTRIBUTING.md
gabrielmfern Feb 17, 2025
8f20405
update writing docs step
gabrielmfern Feb 19, 2025
5a94d60
fix import on migrating to react email
gabrielmfern Feb 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 15 additions & 20 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
## Contributing
Thank you for considering contributing to React Email.

Wanna help? Awesome! There are many ways you can contribute.
We've created this guide to help you better understand how to contribute to the project, even if you've never contributed to an open source project before.

## Improving the docs
## How to report bugs

Documentation is extremely important and takes a fair deal of time and effort to write and keep updated. Everything is written in Markdown to facilitate the process of contributing.
To report a bug, please first read our guide on [opening issues](https://react.email/docs/contributing/opening-issues).

## Building new components
## How to contribute code

We’re open to expanding the catalog of components to cover as many use cases as possible. We suggest to open an issue for discussion first to make sure your idea is aligned with the project goals.
To open a pull request, please first read our guide on [opening pull requests](https://react.email/docs/contributing/opening-pull-requests), which outlines our process for RFCs and pull requests.

## Opening issues
### Codebase overview
If you need help getting familiar with our codebase, we recommend reading our [Codebase overview guide](https://react.email/docs/contributing/codebase-overview).

Open an issue to report bugs or to propose new features.
### Development workflow guide
We have also created a Development workflow guide to help you get familiar with the development workflow for React Email. It includes instructions for:
1. [Setting up your development environment](https://react.email/docs/contributing/development-workflow/1-setup)
2. [Running tests](https://react.email/docs/contributing/development-workflow/2-running-tests)
3. [Linting](https://react.email/docs/contributing/development-workflow/3-linting)
4. [Building](https://react.email/docs/contributing/development-workflow/4-building)
5. [Writing documentation](https://react.email/docs/contributing/development-workflow/5-writing-docs)

**- Reporting bugs:**
describe the bug as clearly as you can, including steps to reproduce, what happened and what you were expecting to happen. Also include browser version, OS and other related software’s (npm, Node.js, etc) versions when applicable.

**- Suggesting features:** explain the proposed feature, what it should do, why it is useful, how users should use it. Give us as much info as possible so it will be easier to discuss, access and implement the proposed feature. When you’re unsure about a certain aspect of the feature, feel free to leave it open for others to discuss and find an appropriate solution.

## Proposing pull requests

Pull requests are very welcome. Note that if you are going to propose drastic changes, be sure to open an issue for discussion first, to make sure that your PR will be accepted before you spend effort coding it.

**- Forking the repository:** clone it locally and create a branch for your proposed bug fix or new feature. Avoid working directly on the main branch.

**- Making changes:** implement your bug fix or feature, write tests to cover it and make sure all tests are passing. Then commit your changes, push your bug fix/feature branch to the origin (your forked repo) and open a pull request to the upstream (the repository you originally forked)‘s main branch.
2 changes: 1 addition & 1 deletion apps/docs/contributing.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'Contributing'
sidebarTitle: 'Contributing'
sidebarTitle: 'Old Contributing'
description: 'Wanna help? Awesome! There are many ways you can contribute.'
'og:image': 'https://react.email/static/covers/react-email.png'
icon: 'code-pull-request'
Expand Down
169 changes: 169 additions & 0 deletions apps/docs/contributing/codebase-overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
---
title: 'Codebase overview'
sidebarTitle: 'Codebase overview'
'og:image': 'https://react.email/static/covers/react-email.png'
description: 'An overview of the React Email codebase'
icon: 'folder-tree'
---

We've created this guide to help new contributors understand and navigate the React Email codebase.

## Top-level directories

After cloning the [React Email repository](https://github.com/resend/react-email) you will see a few root-level directories. Here's a brief overview of each:

<table>
<thead>
<tr>
<th>Directory</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
[apps](https://github.com/resend/react-email/tree/canary/apps)
</td>
<td>
Here you can find all of the apps related to our online presence, like:
- this documentation (under [apps/docs](https://github.com/resend/react-email/tree/canary/apps/docs)),
- the demo emails we have on [demo.react.email](https://demo.react.email/preview/vercel-invite-user.tsx)
(under [apps/demo](https://github.com/resend/react-email/tree/canary/apps/demo))
- the Next app we have for our landing page on [react.email](https://react.email) (under [apps/web](https://github.com/resend/react-email/tree/canary/apps/web))
</td>
</tr>
<tr>
<td>
[benchmarks](https://github.com/resend/react-email/tree/canary/benchmarks)
</td>
<td>
We make benchmarks from version-to-version to demonstrate data-observable performance gains with metrics like *p99 and p75*.

For example, see the [Improved Performance for Tailwind Emails](https://resend.com/blog/improved-performance-for-tailwind-emails) benchmark.
</td>
</tr>
<tr>
<td>
[packages](https://github.com/resend/react-email/tree/canary/packages)
</td>
<td>
Most contributions will be made to the packages in this directory.

This directory contains all our published [NPM](https://www.npmjs.com/) packages.
Each subdirectory is a single component published as its own package, with the exception of a few packages that serve as shared configuration.
</td>
</tr>
</tbody>
</table>

<Note>
Feel free to [open a discussion](https://github.com/resend/react-email/discussions/new?category=ideas) if you have suggestions on how to better structure these packages to make them more manageable and approachable.
</Note>

## Multiple packages

The react-email repository is a [pnpm monorepo](https://pnpm.io/next/workspaces), which means it contains
multiple packages.

Because we use pnpm, you will need to use [pnpm](https://pnpm.io/) to install and run each package. If you do not have pnpm installed, we recommend you install it using [corepack](https://github.com/nodejs/corepack):

```bash
corepack enable
corepack prepare pnpm@latest --activate
```

Currently, we have the following packages:

<div className="grid gap-2" style={{ gridTemplateColumns: '1fr 1fr 1fr' }}>
<div>
- [@react-email/body](https://github.com/resend/react-email/tree/canary/packages/body)
- [@react-email/button](https://github.com/resend/react-email/tree/canary/packages/button)
- [@react-email/code-block](https://github.com/resend/react-email/tree/canary/packages/code-block)
- [@react-email/code-inline](https://github.com/resend/react-email/tree/canary/packages/code-inline)
- [@react-email/column](https://github.com/resend/react-email/tree/canary/packages/column)
- [@react-email/components](https://github.com/resend/react-email/tree/canary/packages/components)
- [@react-email/container](https://github.com/resend/react-email/tree/canary/packages/container)
- [create-email](https://github.com/resend/react-email/tree/canary/packages/create-email)
- <span className="text-xs">Used for our [automatic setup](/getting-started/automatic-setup)</span>
</div>
<div>
- [@react-email/font](https://github.com/resend/react-email/tree/canary/packages/font)
- [@react-email/head](https://github.com/resend/react-email/tree/canary/packages/head)
- [@react-email/heading](https://github.com/resend/react-email/tree/canary/packages/heading)
- [@react-email/hr](https://github.com/resend/react-email/tree/canary/packages/hr)
- [@react-email/html](https://github.com/resend/react-email/tree/canary/packages/html)
- [@react-email/img](https://github.com/resend/react-email/tree/canary/packages/img)
- [@react-email/link](https://github.com/resend/react-email/tree/canary/packages/link)
- [@react-email/markdown](https://github.com/resend/react-email/tree/canary/packages/markdown)
- [@react-email/preview](https://github.com/resend/react-email/tree/canary/packages/preview)
</div>
<div>
- [react-email](https://github.com/resend/react-email/tree/canary/packages/react-email)
- <span className="text-xs">The package for our [email CLI](/cli)</span>
- [@react-email/render](https://github.com/resend/react-email/tree/canary/packages/render)
- [@react-email/row](https://github.com/resend/react-email/tree/canary/packages/row)
- [@react-email/section](https://github.com/resend/react-email/tree/canary/packages/section)
- [@react-email/tailwind](https://github.com/resend/react-email/tree/canary/packages/tailwind)
- [@react-email/text](https://github.com/resend/react-email/tree/canary/packages/text)
</div>
</div>

Most of these packages are very small and can be easily understood by reading the code, so feel free to explore.

### Turborepo

We encourage using [turborepo](https://turbo.build/repo) to manage the packages.

It's often helpful to [install Turborepo globally](https://turbo.build/repo/docs/installing) to make it easier to run commands in any of the repositories. With a global installation, running `turbo build` in any of the packages will build both the package
you are on as well as the dependent packages. The global installation handles [version mismatching as well](https://turbo.build/repo/docs/installing#install-per-repository).

### The React Email CLI

The CLI (i.e. `packages/react-email`) is key to the best development experience with react.email, but it is complex. Here is a brief overview of the CLI.

The CLI includes two components:
- A Next app for the `email dev` and `email build` commands
- A [commander.js](https://www.npmjs.com/package/commander) CLI

In the NextJS app, we include a `src/cli` directory that is not published but is compiled into a root `cli` directory. This structure provides a good developer experience as we can both share certain functions and communicate between the CLI components.

We trigger rebuilds of email templates after they have been saved using the
[chokidar](https://www.npmjs.com/package/chokidar) package
alongside the [socket.io](https://socket.io/) package to detect file changes and send
a message to the server to trigger a rebuild.

## Testing

For testing, we use [vitest](https://vitest.dev/). We prefer to define globals and run tests under the `happy-dom` environment.

We do not strictly enforce testing coverage, but encourage it.

For help testing, see our [Development workflow guide](/contributing/development-workflow/2-running-tests).

<Note>
The `@react-email/render` package's `renderAsync` does a fair bit of magic to simulate `edge` and other environments that are not supported by `happy-dom`. For this use case, we override the [environment on a per-file basis](https://vitest.dev/guide/environment#environments-for-specific-files) for its tests
</Note>

## Linting

We use [biomejs](https://biomejs.dev/) for linting and formatting. Both the linting and formatting are ensured by our GitHub CI so make sure you lint and format your code (`pnpm lint:fix`) before opening a PR or asking for a review on it.

For help linting and formatting, see our [Development workflow guide on linting](/contributing/development-workflow/3-linting).

## Building

We use [tsup](https://github.com/egoist/tsup) to build most packages. (The only exception for this is the `@react-email/tailwind` package which currently uses `vite` due to a few issues with `tsup` and `tailwindcss`'s bundling.) For help building packages, see our [Development workflow guide](/contributing/development-workflow/4-building).

<Note>
Building in each package will run `tsup` with a few settings, typically `src/index.ts --format esm,cjs --dts --external react`.
Tsup handles building both ESM and CJS versions along with the type definitions exported from the entry point, `src/index.ts`, without bundling `react`, which can cause issues.
</Note>

### Why build before publishing?

We build most of the packages before publishing for a few reasons:

1. All the exported types can be imported from the same place the JavaScript is imported
2. We have proper [CommonJS](https://nodejs.org/docs/latest/api/modules.html#modules-commonjs-modules)
and [ES Modules](https://nodejs.org/api/esm.html#modules-ecmascript-modules) support
3. Code that isn't exported is not published or downloaded
44 changes: 44 additions & 0 deletions apps/docs/contributing/development-workflow/1-setup.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
title: 'Setup'
sidebarTitle: '1. Setup'
'og:image': 'https://react.email/static/covers/react-email.png'
description: 'Things you will need to do beforehand to setup the project'
---

Before you can start developing, you will need to get the project setup.

<Info>
To contribute to the project, you must use **Node 18** or higher.
</Info>

<Steps>
<Step title="Clone the repository">
```bash
git clone https://github.com/resend/react-email
```
</Step>
<Step title={<>Enable <a href="https://pnpm.io/">pnpm</a> through <a href="https://github.com/nodejs/corepack">corepack</a></>}>
```bash inside of react-email
corepack enable
corepack prepare pnpm@latest --activate
```
</Step>
<Step title="Install all the dependencies">
```bash inside of react-email
pnpm install
```
</Step>
<Step title="Build all the packages">
```bash inside of react-email
pnpm build
```

<Note>
Building first is crucial because each package may depend on other packages, and pre-building them will ensure that you don't run into issues when developing.
</Note>
</Step>
</Steps>

If you plan to contribute to the docs, view our [Writing docs](/contributing/development-workflow/5-writing-docs) guide for additional setup.

If you have have any trouble, please [reach out on Discord](https://discord.com/invite/n2pWEjjNnD) or consider [opening up an issue on GitHub](https://github.com/resend/react-email/issues/new?assignees=&labels=Type%3A+Bug&projects=&template=1.bug_report.yml) after reading the [issue guidelines](/contributing/opening-issues).
26 changes: 26 additions & 0 deletions apps/docs/contributing/development-workflow/2-running-tests.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
title: 'Running tests'
sidebarTitle: '2. Running tests'
'og:image': 'https://react.email/static/covers/react-email.png'
description: 'Everything you need to know about our testing setup and strategy'
---

For testing, we use [vitest](https://vitest.dev/). We prefer to define globals and run tests under the `happy-dom` environment.

<Note>
The `@react-email/render` package's `renderAsync` does a fair bit of magic to simulate `edge` and other environments that are not supported by `happy-dom`. For this use case, we override the [environment on a per-file basis](https://vitest.dev/guide/environment#environments-for-specific-files) for its tests
</Note>

We do not strictly enforce testing coverage, but encourage it. A good rule of thumb is that if you need to simulate use
cases to check whether a specific portion of code works, you should split it into a function with a matching unit test.

After you have gone through the [setup](/contributing/development-workflow/1-setup) run
`pnpm test` inside any package. This will run the tests only once. We have two
scripts defined on our packages for testing:

- `pnpm test`: Runs all the tests once. If you run it on the root, it will run the
tests for all packages using
[turborepo](/contributing/codebase-overview#turborepo)
- `pnpm test:watch`: Runs all the tests and watches for changes. Vitest
automatically only runs the tests that are affected by the code you've
changed.
23 changes: 23 additions & 0 deletions apps/docs/contributing/development-workflow/3-linting.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: 'Linting'
sidebarTitle: '3. Linting'
'og:image': 'https://react.email/static/covers/react-email.png'
description: 'Everything you need to know about linting and formatting'
---

We use [biomejs](https://biomejs.dev/) for linting and formatting. Both linting and formatting are ensured by our GitHub CI, so before opening a PR or asking for a review, please lint and format your code.

## Check for linting issues
To check if there are any linting issues, run `pnpm lint` on the root of the workspace.

```bash
pnpm lint
```

To lint or format the entire project, run `pnpm lint:fix` on the root of the workspace.

```bash
pnpm lint:fix
```

Both the linting and formatting are ensured by our GitHub CI so make sure you lint and format your code before opening a PR or asking for a review on it.
27 changes: 27 additions & 0 deletions apps/docs/contributing/development-workflow/4-building.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: "Building"
sidebarTitle: "4. Building"
"og:image": "https://react.email/static/covers/react-email.png"
description: "How we build each package before publishing"
---

We use [tsup](https://github.com/egoist/tsup) to build most packages. (The only exception for this is the `@react-email/tailwind` package which currently uses `vite` due to a few issues with `tsup` and `tailwindcss`'s bundling.)

To build a package run:

```bash package/* (ex: package/render)
pnpm build
```

Building in each package will run `tsup` with a few settings, typically `src/index.ts --format esm,cjs --dts --external react`.
Tsup handles building both [ESM](https://nodejs.org/api/esm.html) and
[CJS](https://nodejs.org/docs/latest/api/modules.html) versions along with the type definitions exported from the entry point, `src/index.ts`, without bundling `react`, which can cause issues.

### Why build before publishing?

We build most of the packages before publishing for a few reasons:

1. All the exported types can be imported from the same place the JavaScript is imported
2. We have proper [CommonJS](https://nodejs.org/docs/latest/api/modules.html#modules-commonjs-modules)
and [ES Modules](https://nodejs.org/api/esm.html#modules-ecmascript-modules) support
3. Code that isn't exported is not published or downloaded
24 changes: 24 additions & 0 deletions apps/docs/contributing/development-workflow/5-writing-docs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: '5. Writing docs'
sidebarTitle: '5. Writing docs'
'og:image': 'https://react.email/static/covers/react-email.png'
---

We use [Mintlify](https://mintlify.com/) for our documentation.

To preview the docs, you just need to run:

```sh apps/docs
pnpm dev
```

Check out [Mintlify's development guide](https://mintlify.com/docs/development)
for a few more interesting development tools.

## Components

Mintlify uses `mdx` to allow us to write docs in a composable ways. Because of
`mdx`, we can build [our own
components](https://mintlify.com/docs/reusable-snippets#reusable-components)
but it's always best to use the components Mintlify already provides us. Before writing down a new component, check their [full list of components](https://mintlify.com/docs/content/components).

Loading
Loading