# pt-br.react.dev: the React documentation in Brazilian Portuguese

> pt-br.react.dev is the Brazilian Portuguese React documentation site, built as a Next.js application whose markdown content is watched from a remote source rather than only from the local checkout. The repository carries its own ESLint rule package, a heading id linter, a dead link checker and a glossary, all aimed at keeping a large translation in step with the English original.

**reactjs/pt-br.react.dev** — 🇧🇷 React documentation website in Portuguese (Brazil)

- Repository: https://github.com/reactjs/pt-br.react.dev
- Website: https://pt-br.react.dev
- Stars: 539 · Forks: 327
- Language: JavaScript
- License: CC-BY-4.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/reactjs-pt-br-react-dev

## A translation repository that runs like the upstream site

pt-br.react.dev is the Brazilian Portuguese version of the React documentation site, and the repository holds the source code and documentation that power it. The description says as much, and the site is at pt-br.react.dev.

The interesting part is that this is not a static dump of translated markdown. It is a full Next.js application with its own components, its own plugin set and its own build pipeline, and the translation sits inside it as content.

The local setup is the standard one for a site of this kind. You move into the project root, run yarn to install the website's npm dependencies, then run yarn dev to start the development server, which is powered by Next.js, and open the site in a browser.

```bash
1. `cd pt-br.react.dev` to go into the project root
2. `yarn` to install the website's npm dependencies
1. `yarn dev` to start the development server (powered by [Next.js](https://nextjs.org/))
1. `open http://localhost:3000` to open the site in a browser
```

The prerequisites are stated as a list: Git, Node at any version starting from v16.8.0 or greater, Yarn, a fork of the repo for contributions, and a clone of the repository on your local machine. The fork is the standard GitHub contribution flow rather than anything specific to this project.

The licence has two layers and they are worth separating. Content submitted to pt-br.react.dev is CC-BY-4.0 licensed, as found in the LICENSE-DOCS.md file. The package manifest sets the licence field to CC, and there is a LICENSE-DOCS.md at the top level next to a GLOSSARY.md, a CODE_OF_CONDUCT.md and a CONTRIBUTING.md.

The glossary is the piece that is specific to a translation project. Translating a technical documentation set means deciding what to call a hook, a component or a prop in Portuguese, and doing that consistently across hundreds of pages. A glossary file is where that decision gets recorded.

The last push was on 2026-10-19, there are no GitHub releases, and the primary language recorded for the repository is JavaScript.

## The dev script watches remote content, which is why it is not just next dev

The dev script in the package manifest is not the one you would expect, and it is the single most revealing line in the file:

```json
  "scripts": {
    "analyze": "ANALYZE=true next build",
    "dev": "next-remote-watch ./src/content",
    "prebuild:rsc": "node scripts/buildRscWorker.mjs",
    "build": "node scripts/buildRscWorker.mjs && next build && node --experimental-modules ./scripts/downloadFonts.mjs",
    "prettier": "yarn format:source",
    "prettier:diff": "yarn nit:source",
    "lint-heading-ids": "node scripts/headingIdLinter.js",
    "fix-headings": "node scripts/headingIdLinter.js --fix",
    "ci-check": "npm-run-all prettier:diff --parallel lint tsc lint-heading-ids rss deadlinks",
    "tsc": "tsc --noEmit",
    "start": "next start",
    "postinstall": "yarn --cwd eslint-local-rules install && is-ci || husky install .husky",
    "check-all": "npm-run-all prettier lint:fix tsc rss",
    "rss": "node scripts/generateRss.js",
    "deadlinks": "node scripts/deadLinkChecker.js",
    "copyright": "node scripts/copyright.js",
    "test:eslint-local-rules": "yarn --cwd eslint-local-rules test"
  },
```

The dev script runs next-remote-watch against the ./src/content directory rather than plain next dev. The build script is similarly layered: it runs a script to build an RSC worker, then next build, then a script to download fonts. The prebuild step for the RSC worker exists precisely because the build needs it.

The remote watch is what makes a translation workflow practical. The React documentation is maintained upstream in English and the Portuguese version follows it, so the Portuguese content does not live only in this repository. A watcher on the content directory means the site picks up content from the upstream remote as it changes, rather than requiring a copy to be vendored in and refreshed by hand.

The rest of the scripts show the same pattern of a project with several things to check. The lint script runs next lint and then ESLint over the markdown in the content directory, so prose is linted as well as code. Formatting has a pair, format:source to write and nit:source to list differences, both scoped to the plugins and source directories and both using the .prettierrc config. The check-all script, which is what contributors are told to run, chains prettier, the lint fix, the TypeScript check and the RSS generation.

There are three checks that are worth calling out because they are specific to a documentation site rather than to an application. The heading id linter runs a script that validates heading identifiers and can fix them, which matters because the anchors are links and a broken one is a broken link for anyone who bookmarked it. The dead link checker is another script, and the RSS generator a third, since a documentation site publishes a feed.

The continuous integration check runs prettier in diff mode in parallel with the lint, the TypeScript check, the heading id lint, the RSS generation and the dead link check. Running them in parallel is a small efficiency decision, and the ordering of the list in the check-all script, prettier then lint:fix then tsc then rss, is different, which tells you the local and CI flows are not identical.

## Local rules with their own package, and husky on install

Two entries in the top level directory listing are unusual for a documentation site, and together they describe a specific approach to code quality.

There is an eslint-local-rules/ directory, and the postinstall script installs it as its own package with yarn --cwd eslint-local-rules install. That means the custom lint rules live in a separate package with its own dependency tree, and the main project consumes them as a local plugin rather than defining them inline.

And there is a .husky/ directory, with the postinstall script running husky install on it, but only when not in a CI environment, which is what the is-ci check is for. So the git hooks are installed on a developer's machine and skipped on the build server.

The reason to put the rules in their own package is worth naming. Local ESLint rules are the kind of thing that needs its own tests, its own TypeScript configuration and its own release process if it is shared between repositories, and the scripts list a dedicated test command for them, yarn --cwd eslint-local-rules test. A documentation site is a reasonable place to accumulate such rules, since the constraints on a docs codebase, such as how a code example must be formatted or how a heading must be written, are not expressible with the off-the-shelf rules.

The other quality infrastructure follows the same pattern of being explicit. There is a .prettierrc and a .prettierignore, a .eslintrc and a .eslintignore, a tsconfig.json, a next.config.js, a postcss.config.js and a tailwind.config.js. The colors.js file at the root is a shared palette that both the styles and the components can reference, which is a small thing that matters when a site has a dark mode and a light mode and the two have to agree.

There is also a .env.development and a .env.production, a vercel.json for the deployment configuration, and a next-env.d.ts generated by the framework. The .claude/ directory and CLAUDE.md at the root are the agent-facing instructions, the same pattern the OpenData repository used, and their presence in a documentation site suggests the project expects contributors to work with automated tooling.

## Content, plugins and a public directory, in one repository

The top level listing shows three directories that carry the site itself: src/, plugins/ and public/.

The src/ directory is where the React components and the site logic live, and it also holds the content directory, which is the one the dev script watches and the one the markdown lint runs against. The content being inside src rather than at the root is a consequence of the Next.js routing, where the markdown files are the route data rather than static assets.

The plugins/ directory is the interesting one for a translation project. The formatting script covers both plugins and source, and the hot reload note says that if you are working with plugins you may need to remove the .cache directory and restart the server. That tells you plugins are compiled into the site rather than loaded at request time, and that the build cache does not always notice a change to them.

The public/ directory holds the static assets, and the font download step in the build script suggests that fonts are fetched into it at build time rather than committed, which keeps the repository small and the build reproducible.

The scripts/ directory holds the Node scripts that the package scripts invoke, and their names describe what the site does beyond rendering pages: buildRscWorker, downloadFonts, headingIdLinter, generateRss, deadLinkChecker and copyright. The copyright one is the odd name out and it suggests the site renders a copyright notice somewhere, which for a documentation project is the sort of thing that lives in a page footer.

The dependency list gives a picture of what a modern documentation site needs. Sandpack from Codesandbox renders the live code examples, DocSearch from Algolia provides the search, Headless UI and Radix UI provide the context menu, body-scroll-lock handles the modal scroll behaviour, classnames handles conditional classes, debounce for search input, and github-slugger for generating heading anchors. Next is pinned to 15.4.8 and the next-remote-watch package is the one that handles the remote content.

## The contribution flow, and where the translation work is tracked

The contribution instructions are detailed enough to be worth reading as a description of how a documentation translation is actually run.

The branch step is three commands. You check out main from any folder in your local repository, you pull origin main to ensure you have the latest main code, and you create a branch with a suitable name.



Then you make the change, following the running locally instructions, save the files and check in the browser. The hot reload behaviour is stated per content type: changes to React components in src will hot-reload, and changes to markdown files in content will hot-reload. If you are working with plugins you may need to remove the .cache directory and restart the server.

Testing the change has two parts. If possible, test any visual changes in all the latest versions of common browsers, on both desktop and mobile. And run yarn check-all, which runs Prettier, ESLint and validates types.

Then pushing, with the staging and commit in one command and a commit message describing the change, followed by pushing to the fork and opening the pull request. The visual changes instruction is specific: include screenshots if possible, and a preview build is triggered after your changes are pushed to GitHub.

That preview build is the part that makes the translation work practical. A translated page can differ from the English original in line wrapping, in table widths and in how a code block fits, and the only reliable way to check that is to look at the rendered page. The deployment configuration is vercel.json, which is consistent with a preview being generated per pull request.

The translation work itself is tracked in an issue on the repository, linked from the translation section of the documentation. The guidelines section points contributors at a contributing document with a section on guidelines for text, and the note that the documentation is divided into several sections with a different tone and purpose, which is the reminder that a translation is not a mechanical substitution of strings. The tone of a tutorial and the tone of a reference page are different, and the guidelines for text address that per section.

## Conclusion

pt-br.react.dev suits a Portuguese speaking developer who wants the React documentation in their own language and is close to the upstream English version, and for translators it shows what a large documentation translation actually requires in tooling terms. It does not suit you if you want an offline copy of the documentation, because the content is watched from a remote source and the site is served as an application. Before you contribute, read the guidelines for text in the contributing document, since the sections have different tones and a translation is not a string substitution, and use the preview build that is triggered by your pull request to check the rendered page, because line wrapping and code block widths differ from the English original.

## FAQ

### How do I run the pt-br.react.dev site locally?

Move into the project root with cd pt-br.react.dev, run yarn to install the website's npm dependencies, then run yarn dev to start the Next.js development server and open http://localhost:3000. The prerequisites are Git, Node at v16.8.0 or greater, and Yarn.

### What does the dev script do that next dev does not?

The dev script runs next-remote-watch against the ./src/content directory, so the site picks up content from a remote source as it changes rather than only from the local checkout. The build script similarly runs an RSC worker build step before next build and a font download step after it.

### Why does the repository have its own eslint-local-rules package?

The custom lint rules live in a separate package with its own dependency tree, installed by the postinstall script with yarn --cwd eslint-local-rules install, and the scripts include a dedicated test command for them. That lets rules specific to a documentation codebase be written and tested separately from the site itself.

### What does yarn check-all verify?

It chains four steps, namely prettier, the lint fix, the TypeScript check and the RSS generation. The continuous integration check is broader and runs prettier in diff mode in parallel with the lint, the TypeScript check, a heading id linter, the RSS generation and a dead link checker.

### Under what licence is the content on pt-br.react.dev?

Content submitted to the site is CC-BY-4.0 licensed, as set out in the LICENSE-DOCS.md file. The package metadata records the licence as CC.

## Sources

- [Issues](https://github.com/reactjs/pt-br.react.dev/issues)
- [License: CC-BY-4.0](https://github.com/reactjs/pt-br.react.dev/blob/main/LICENSE)
- [Project website](https://pt-br.react.dev)
- [reactjs/pt-br.react.dev on GitHub](https://github.com/reactjs/pt-br.react.dev)
- [README](https://github.com/reactjs/pt-br.react.dev/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/reactjs-pt-br-react-dev
