-
Dioxus is a portable, performant, and ergonomic framework for building cross-platform user interfaces in Rust.
@@ -70,6 +69,7 @@ Dioxus can be used to deliver webapps, desktop apps, static sites, mobile apps,
If you know React, then you already know Dioxus.
### Unique features:
+
- Desktop apps running natively (no Electron!) in less than 10 lines of code.
- Incredibly ergonomic and powerful state management.
- Comprehensive inline documentation - hover and guides for all HTML elements, listeners, and events.
@@ -89,14 +89,12 @@ If you know React, then you already know Dioxus.
-
## Example Projects:
| File Navigator (Desktop) | WiFi scanner (Desktop) | TodoMVC (All platforms) | E-commerce w/ Tailwind (SSR/LiveView) |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [![File Explorer](https://github.com/DioxusLabs/example-projects/raw/master/file-explorer/image.png)](https://github.com/DioxusLabs/example-projects/blob/master/file-explorer) | [![Wifi Scanner Demo](https://github.com/DioxusLabs/example-projects/raw/master/wifi-scanner/demo_small.png)](https://github.com/DioxusLabs/example-projects/blob/master/wifi-scanner) | [![TodoMVC example](https://github.com/DioxusLabs/example-projects/raw/master/todomvc/example.png)](https://github.com/DioxusLabs/example-projects/blob/master/todomvc) | [![E-commerce Example](https://github.com/DioxusLabs/example-projects/raw/master/ecommerce-site/demo.png)](https://github.com/DioxusLabs/example-projects/blob/master/ecommerce-site) |
-
See the [awesome-dioxus](https://github.com/DioxusLabs/awesome-dioxus) page for a curated list of content in the Dioxus Ecosystem.
## Why Dioxus and why Rust?
@@ -105,7 +103,7 @@ TypeScript is a fantastic addition to JavaScript, but it's still fundamentally J
By using Rust, we gain:
-- Static types for *every* library
+- Static types for _every_ library
- Immutability by default
- A simple and intuitive module system
- Integrated documentation (`go to source` _actually goes to source_)
@@ -127,6 +125,7 @@ Specifically, Dioxus provides us many other assurances:
And much more. Dioxus makes Rust apps just as fast to write as React apps, but affords more robustness, giving your frontend team greater confidence in making big changes in shorter time.
## Why NOT Dioxus?
+
You shouldn't use Dioxus if:
- You don't like the React Hooks approach to frontend
@@ -135,6 +134,7 @@ You shouldn't use Dioxus if:
- You need a Send+Sync UI solution (Dioxus is not currently thread-safe)
## Comparison with other Rust UI frameworks
+
Dioxus primarily emphasizes **developer experience** and **familiarity with React principles**.
- [Yew](https://github.com/yewstack/yew): prefers the elm pattern instead, no borrowed props, supports SSR (no hydration), no direct desktop/mobile support.
@@ -143,7 +143,6 @@ Dioxus primarily emphasizes **developer experience** and **familiarity with Reac
- [Dominator](https://github.com/Pauan/rust-dominator): Signal-based zero-cost alternative, less emphasis on community and docs.
- [Azul](https://azul.rs): Fully native HTML/CSS renderer for desktop applications, no support for web/ssr
-
## Parity with React & Roadmap
Dioxus is heavily inspired by React, but we want your transition to feel like an upgrade. Dioxus is _most_ of the way there, but missing a few key features. These include:
@@ -174,7 +173,7 @@ Want to jump in and help build the future of Rust frontend? There's plenty of pl
This project is licensed under the [MIT license].
-[MIT license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
+[mit license]: https://github.com/DioxusLabs/dioxus/blob/master/LICENSE-MIT
### Contribution
diff --git a/docs/.gitignore b/docs/guide/.gitignore
similarity index 100%
rename from docs/.gitignore
rename to docs/guide/.gitignore
diff --git a/docs/guide/book.toml b/docs/guide/book.toml
index f343e8dcf..b171d9698 100644
--- a/docs/guide/book.toml
+++ b/docs/guide/book.toml
@@ -7,6 +7,11 @@ language = "en"
[language.en]
name = "English"
+[language.pt-br]
+name = "Português Brasileiro"
+title = "Documentação do Dioxus"
+description = "Introdução ao Dioxus, um framework portátil, de alto desempenho e ergonômico para criar interfaces de usuário multiplataforma em Rust."
+
[rust]
edition = "2018"
diff --git a/docs/guide/src/en/SUMMARY.md b/docs/guide/src/en/SUMMARY.md
index 92836297b..28ecfe688 100644
--- a/docs/guide/src/en/SUMMARY.md
+++ b/docs/guide/src/en/SUMMARY.md
@@ -33,11 +33,11 @@
- [Desktop](publishing/desktop.md)
- [Web](publishing/web.md)
------------
+---
- [Custom Renderer](custom_renderer/index.md)
------------
+---
[Roadmap](roadmap.md)
[Contributing](contributing.md)
diff --git a/docs/guide/src/en/__unused/advanced-guides/rsx.md b/docs/guide/src/en/__unused/advanced-guides/rsx.md
new file mode 100644
index 000000000..062246490
--- /dev/null
+++ b/docs/guide/src/en/__unused/advanced-guides/rsx.md
@@ -0,0 +1,63 @@
+# VNodes with RSX, HTML, and NodeFactory
+
+Many modern frameworks provide a domain-specific-language for declaring user-interfaces. In the case of React, this language extension is called JSX and must be handled through additional dependencies and pre/post processors to transform your source code. With Rust, we can simply provide a procedural macro in the Dioxus dependency itself that mimics the JSX language.
+
+With Dioxus, we actually ship two different macros – a macro that mimics JSX (the `html!` macro) and a macro that mimics Rust's native nested-struct syntax (the `rsx!` macro). These macros simply transform their inputs into NodeFactory calls.
+
+For instance, this html! call:
+```rust
+html!(
"hello world"
)
+```
+becomes this NodeFactory call:
+```rust
+|f| f.element(
+ dioxus_elements::div, // tag
+ [], // listeners
+ [], // attributes
+ [f.static_text("hello world")], // children
+ None // key
+)
+```
+The NodeFactory API is fairly ergonomic, making it a viable option to use directly. The NodeFactory API is also compile-time correct and has incredible syntax highlighting support. We use what Rust calls a "unit type" – the `dioxus_elements::div` and associated methods to ensure that a `div` can only have attributes associated with `div`s. This lets us tack on relevant documentation, autocomplete support, and jump-to-definition for methods and attributes.
+
+![Compile time correct syntax](../images/compiletimecorrect.png)
+
+## html! macro
+
+The html! macro supports a limited subset of the html standard. Rust's macro parsing tools are somewhat limited, so all text between tags _must be quoted_.
+
+However, writing HTML by hand is a bit tedious – IDE tools for Rust don't support linting/autocomplete/syntax highlighting. We suggest using RSX – it's more natural for Rust programs and _does_ integrate well with Rust IDE tools.
+
+```rust
+let name = "jane";
+let pending = false;
+let count = 10;
+
+dioxus::ssr::render_lazy(html! {
+
+
"Hello, {name}!"
+
"Status: {pending}!"
+
"Count {count}!"
+
+});
+```
+
+## rsx! macro
+
+The rsx! macro is a VNode builder macro designed especially for Rust programs. Writing these should feel very natural, much like assembling a struct. VSCode also supports these with code folding, bracket-tabbing, bracket highlighting, section selecting, inline documentation, GOTO definition, and refactoring support.
+
+When helpful, the Dioxus VSCode extension provides a way of converting a selection of HTML directly to RSX, so you can import templates from the web directly into your existing app.
+
+It's also a bit easier on the eyes than HTML.
+
+```rust
+dioxus::ssr::render_lazy(rsx! {
+ div {
+ p {"Hello, {name}!"}
+ p {"Status: {pending}!"}
+ p {"Count {count}!"}
+ }
+});
+```
+
+In the next section, we'll cover the `rsx!` macro in more depth.
diff --git a/docs/guide/src/en/__unused/composing.md b/docs/guide/src/en/__unused/composing.md
new file mode 100644
index 000000000..5746d6477
--- /dev/null
+++ b/docs/guide/src/en/__unused/composing.md
@@ -0,0 +1,243 @@
+# Thinking in Reactively
+
+We've finally reached the point in our tutorial where we can talk about the theory of Reactivity. We've talked about defining a declarative view, but not about the aspects that make our code *reactive*.
+
+Understanding the theory of reactive programming is essential to making sense of Dioxus and writing effective, performant UIs.
+
+In this section, we'll talk about:
+
+- One-way data flow
+- Modifying data
+- Forcing renders
+- How renders propagate
+
+This section is a bit long, but worth the read. We recommend coffee, tea, and/or snacks.
+
+## Reactive Programming
+
+Dioxus is one of a handful of Rust libraries that provide a "Reactive Programming Model". The term "Reactive programming" is a classification of programming paradigm – much like functional or imperative programming. This is a very important distinction since it affects how we *think* about our code.
+
+Reactive programming is a programming model concerned with deriving computations from asynchronous data flow. Most reactive programs are comprised of datasources, intermediate computations, and a final result.
+
+We consider the rendered GUI to be the final result of our Dioxus apps. The datasources for our apps include local and global state.
+
+For example, the model presented in the figure below is comprised of two data sources: time and a constant. These values are passed through our computation graph to achieve a final result: `g`.
+
+![Reactive Model](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e9/Reactive_programming_glitches.svg/440px-Reactive_programming_glitches.svg.png)
+
+Whenever our `seconds` variable changes, we will then reevaluate the computation for `t`. Because `g` relies on `t`, we will also reevaluate its computation too. Notice that we would've reevaluated the computation for `g` even if `t` didn't change because `seconds` is used to calculate `g`.
+
+However, if we somehow changed our constant from `1` to `2`, then we need to reevaluate `t`. If, for whatever reason, this change did not affect the result of `t`, then we wouldn't try to reevaluate `g`.
+
+In Reactive Programming, we don't think about whether or not we should reevaluate `t` or `g`; instead, we simply provide functions of computation and let the framework figure out the rest for us.
+
+In Rust, our reactive app would look something like:
+
+```rust
+fn compute_g(t: i32, seconds: i32) -> bool {
+ t > seconds
+}
+
+fn compute_t(constant: i32, seconds: i32) -> i32 {
+ constant + seconds
+}
+
+fn compute_graph(constant: i32, seconds: i32) -> bool {
+ let t = compute_t(constant, seconds);
+ let g = compute_g(t, seconds);
+ g
+}
+```
+
+## How is Dioxus Reactive?
+
+The Dioxus VirtualDom provides us a framework for reactive programming. When we build apps with dioxus, we need to provide our own datasources. This can be either initial props or some values fetched from the network. We then pass this data through our app into components through properties.
+
+If we represented the reactive graph presented above in Dioxus, it would look very similar:
+
+```rust
+// Declare a component that holds our datasources and calculates `g`
+fn RenderGraph(cx: Scope) -> Element {
+ let seconds = use_datasource(SECONDS);
+ let constant = use_state(&cx, || 1);
+
+ cx.render(rsx!(
+ RenderG { seconds: seconds }
+ RenderT { seconds: seconds, constant: constant }
+ ))
+}
+
+// "calculate" g by rendering `t` and `seconds`
+#[inline_props]
+fn RenderG(cx: Scope, seconds: i32) -> Element {
+ cx.render(rsx!{ "There are {seconds} seconds remaining..." })
+}
+
+// calculate and render `t` in its own component
+#[inline_props]
+fn RenderT(cx: Scope, seconds: i32, constant: i32) -> Element {
+ let res = seconds + constant;
+ cx.render(rsx!{ "{res}" })
+}
+```
+
+With this app, we've defined three components. Our top-level component provides our datasources (the hooks), computation nodes (child components), and a final value (what's "rendered").
+
+Now, whenever the `constant` changes, our `RenderT` component will be re-rendered. However, if `seconds` doesn't change, then we don't need to re-render `RenderG` because the input is the same. If `seconds` *does* change, then both RenderG and RenderT will be reevaluated.
+
+Dioxus is "Reactive" because it provides this framework for us. All we need to do is write our own tiny units of computation and Dioxus figures out which components need to be reevaluated automatically.
+
+These extra checks and algorithms add some overhead, which is why you see projects like [Sycamore](http://sycamore-rs.netlify.app) and [SolidJS](http://solidjs.com) eliminating them altogether. Dioxus is *really* fast, so we're willing to exchange the added overhead for improved developer experience.
+
+## How do we update values in our dataflow graph?
+
+Dioxus will automatically figure out how to regenerate parts of our app when datasources change. But how exactly can we update our data sources?
+
+In Dioxus there are two datasources:
+
+1. Local state in `use_hook` and all other hooks
+2. Global state through `provide_context`.
+
+Technically, the root props of the VirtualDom are a third datasource, but since we cannot modify them, they are not worth talking about.
+
+### Local State
+
+For local state in hooks, Dioxus gives us the `use_hook` method which returns an `&mut T` without any requirements. This means raw hook values are not tracked by Dioxus. In fact, we could write a component that modifies a hook value directly:
+
+```rust
+fn app(cx: Scope) -> Element {
+ let mut count = cx.use_hook(|_| 0);
+ cx.render(rsx!{
+ button {
+ onclick: move |_| *count += 1,
+ "Count: {count}"
+ }
+ })
+}
+```
+
+However, when this value is written to, the component does not know to be reevaluated. We must explicitly tell Dioxus that this component is "dirty" and needs to be re-rendered. This is done through the `cx.needs_update` method:
+
+```rust
+button {
+ onclick: move |_| {
+ *count += 1;
+ cx.needs_update();
+ },
+ "Count: {count}"
+}
+```
+
+Now, whenever we click the button, the value will change and the component will be re-rendered.
+
+> Re-rendering is when Dioxus calls your function component *again*. Component functions will be called over and over throughout their lifetime, so they should be mostly side-effect free.
+
+### Understand this!
+
+Your component functions will be called ("rendered" in our lingo) for as long as the component is present in the tree.
+
+A single component will be called multiple times, modifying its own internal state or rendering new nodes with new values from its properties.
+
+### App-Global State
+
+With the `provide_context` and `consume_context` methods on `Scope`, we can share values to descendants without having to pass values through component props. This has the side-effect of making our datasources less obvious from a high-level perspective, but it makes our components more modular within the same codebase.
+
+To make app-global state easier to reason about, Dioxus makes all values provided through `provide_context` immutable. This means any library built on top of `provide_context` needs to use interior mutability to modify shared global state.
+
+In these cases, App-Global state needs to manually track which components need to be re-generated.
+
+To regenerate *any* component in your app, you can get a handle to the Dioxus' internal scheduler through `schedule_update_any`:
+
+```rust
+let force_render = cx.schedule_update_any();
+
+// force a render of the root component
+force_render(ScopeId(0));
+```
+
+## What does it mean for a component to "re-render"?
+
+In our guides, we frequently use the phrase "re-render" to describe updates to our app. You'll often hear this paired with "preventing unnecessary re-renders." But what exactly does this mean?
+
+When we call `dioxus::desktop::launch`, Dioxus will create a new `Scope` object and call the component we gave it. Our `rsx!` calls will create new nodes which we return back to the VirtualDom. Dioxus will then look through these nodes for child components, call their functions, and so on until every component has been "rendered." We consider these nodes "rendered" because they were created because of our explicit actions.
+
+The tree of UI that dioxus creates will roughly look like the tree of components presented earlier:
+
+![Tree of UI](../images/component_tree.png)
+
+But what happens when we call `needs_update` after modifying some important state? Well, if Dioxus called our component's function again, then we would produce new, different nodes. In fact, this is exactly what Dioxus does!
+
+At this point, we have some old nodes and some new nodes. Again, we call this "rendering" because Dioxus had to create new nodes because of our explicit actions. Any time new nodes get created, our VirtualDom is being "rendered."
+
+These nodes are stored in an extremely efficient memory allocator called a "bump arena." For example, a div with a handler and attribute would be stored in memory in two locations: the "old" tree and the "new" tree.
+
+![Bump Arenas](../images/oldnew.png)
+
+From here, Dioxus computes the difference between these trees and updates the Real DOM to make it look like the new version of what we've declared.
+
+![Diffing](../images/diffing.png)
+
+## Suppressing Renders
+
+So, we know how to make Dioxus render, but how do we *stop* it? What if we *know* that our state didn't change and we shouldn't render and diff new nodes because they'll be exactly the same as the last time?
+
+In these cases, you want to reach for *memoization*. In Dioxus, memoization involves preventing a component from rendering again if its props didn't change since the last time it attempted to render.
+
+Visually, you can tell that a component will only re-render if the new value is sufficiently different than the old one.
+
+| props.val | re-render |
+| --------- | --------- |
+| 10 | true |
+| 20 | true |
+| 20 | false |
+| 20 | false |
+| 10 | true |
+| 30 | false |
+
+This is why when you `derive(Props)`, you must also implement the `PartialEq` trait. To override the memoization strategy for a component, you can simply implement your own PartialEq.
+
+```rust
+struct CustomProps {
+ val: i32,
+}
+
+impl PartialEq for CustomProps {
+ fn partial_eq(&self, other: &Self) -> bool {
+ // we don't render components that have a val less than 5
+ if other.val > 5 && self.val > 5{
+ self.val == other.val
+ }
+ }
+}
+```
+
+However, for components that borrow data, it doesn't make sense to implement PartialEq since the actual references in memory might be different.
+
+You can technically override this behavior by implementing the `Props` trait manually, though it's unsafe and easy to mess up:
+
+```rust
+unsafe impl Properties for CustomProps {
+ fn memoize(&self, other &Self) -> bool {
+ self != other
+ }
+}
+```
+
+TLDR:
+- Dioxus checks if props changed between renders
+- If props changed according to PartialEq, Dioxus re-renders the component
+- Props that have a lifetime (ie `<'a>`) will always be re-rendered
+
+## Wrapping Up
+
+Wow, that was a lot of material!
+
+Let's see if we can recap what was presented:
+
+- Reactive programming calculates a final value from datasources and computation
+- Dioxus is "reactive" since it figures out which computations to check
+- `schedule_update` must be called to mark a component as dirty
+- dirty components will be re-rendered (called multiple times) to produce a new UI
+- Renders can be suppressed with memoization
+
+This theory is crucial to understand how to compose components and how to control renders in your app.
diff --git a/docs/guide/src/en/__unused/event_javascript.rs b/docs/guide/src/en/__unused/event_javascript.rs
new file mode 100644
index 000000000..2b0a60340
--- /dev/null
+++ b/docs/guide/src/en/__unused/event_javascript.rs
@@ -0,0 +1,26 @@
+
+## JavaScript Handlers
+
+Instead of passing a closure, you can also pass a string to event handlers – this lets you use JavaScript (if your renderer can execute JavaScript):
+
+```rust
+{{#include ../../examples/event_javascript.rs:rsx}}
+```
+
+
+#![allow(non_snake_case)]
+use dioxus::prelude::*;
+
+fn main() {
+ dioxus::desktop::launch(App);
+}
+
+fn App(cx: Scope) -> Element {
+ cx.render(rsx! {
+ // ANCHOR: rsx
+ div {
+ onclick: "alert('hello world')",
+ }
+ // ANCHOR_END: rsx
+ })
+}
diff --git a/docs/guide/src/en/__unused/index.md b/docs/guide/src/en/__unused/index.md
new file mode 100644
index 000000000..1732afdae
--- /dev/null
+++ b/docs/guide/src/en/__unused/index.md
@@ -0,0 +1,38 @@
+# Managing State
+
+Every app you'll build with Dioxus will have some sort of state that needs to be maintained and updated as your users interact with it. However, managing state can be particularly challenging at times, and is frequently the source of bugs in many GUI frameworks.
+
+In this chapter, we'll cover the various ways to manage state, the appropriate terminology, various patterns, and some problems you might run into.
+
+
+## The Problem
+
+Why do people say state management is so difficult? What does it mean?
+
+Generally, state management is the code you need to write to ensure that your app renders the *correct* content. If the user inputs a name, then you need to display the appropriate response – like alerts, validation, and disable/enable various elements on the page. Things can quickly become tricky if you need loading screens and cancellable tasks.
+
+For the simplest of apps, all of your state can enter the app from the root props. This is common in server-side rendering – we can collect all of the required state *before* rendering the content.
+
+```rust
+let all_content = get_all_content().await;
+
+let output = dioxus::ssr::render_lazy(rsx!{
+ div {
+ RenderContent { content: all_content }
+ }
+});
+```
+
+With this incredibly simple setup, it is highly unlikely that you'll have rendering bugs. There simply is barely any state to manage.
+
+However, most of your apps will store state inside of the Dioxus VirtualDom – either through local state or global state.
+
+
+## Your options
+
+To deal with complexity, you have a couple of options:
+
+- Refactor state out of shared state and into reusable components and hooks.
+- Lift state upwards to be spread across multiple components (fan out).
+- Use the Context API to share state globally.
+- Use a dedicated state management solution like Fermi.
diff --git a/docs/guide/src/en/getting_started/mobile.md b/docs/guide/src/en/getting_started/mobile.md
index 25a276db5..ad49817ec 100644
--- a/docs/guide/src/en/getting_started/mobile.md
+++ b/docs/guide/src/en/getting_started/mobile.md
@@ -71,4 +71,4 @@ fn app(cx: Scope) -> Element {
}
})
}
-```
+```
\ No newline at end of file
diff --git a/docs/guide/src/en/getting_started/ssr.md b/docs/guide/src/en/getting_started/ssr.md
index 0e17c2c70..e4f825f0e 100644
--- a/docs/guide/src/en/getting_started/ssr.md
+++ b/docs/guide/src/en/getting_started/ssr.md
@@ -106,4 +106,4 @@ async fn app_endpoint() -> Html {
And that's it!
-> You might notice that you cannot hold the VirtualDom across an await point. Dioxus is currently not ThreadSafe, so it _must_ remain on the thread it started. We are working on loosening this requirement.
+> You might notice that you cannot hold the VirtualDom across an await point. Dioxus is currently not ThreadSafe, so it _must_ remain on the thread it started. We are working on loosening this requirement.
\ No newline at end of file
diff --git a/docs/guide/src/en/roadmap.md b/docs/guide/src/en/roadmap.md
index 3f0dac800..281520b73 100644
--- a/docs/guide/src/en/roadmap.md
+++ b/docs/guide/src/en/roadmap.md
@@ -129,4 +129,4 @@ We are currently working on our own build tool called [Dioxus CLI](https://githu
The internal architecture of Dioxus was designed from day one to support the `LiveView` use-case, where a web server hosts a running app for each connected user. As of today, there is no first-class LiveView support – you'll need to wire this up yourself.
-While not currently fully implemented, the expectation is that LiveView apps can be a hybrid between Wasm and server-rendered where only portions of a page are "live" and the rest of the page is either server-rendered, statically generated, or handled by the host SPA.
+While not currently fully implemented, the expectation is that LiveView apps can be a hybrid between Wasm and server-rendered where only portions of a page are "live" and the rest of the page is either server-rendered, statically generated, or handled by the host SPA.
\ No newline at end of file
diff --git a/docs/guide/src/pt-br/SUMMARY.md b/docs/guide/src/pt-br/SUMMARY.md
new file mode 100644
index 000000000..45cc4912f
--- /dev/null
+++ b/docs/guide/src/pt-br/SUMMARY.md
@@ -0,0 +1,43 @@
+# Sumário
+
+[Introdução](index.md)
+
+- [Introdução Rápida as Plataformas](getting_started/index.md)
+ - [Desktop](getting_started/desktop.md)
+ - [Web](getting_started/web.md)
+ - [Hot Reload](getting_started/hot_reload.md)
+ - [Renderização por Servidor](getting_started/ssr.md)
+ - [Interface do Terminal](getting_started/tui.md)
+ - [Móvel](getting_started/mobile.md)
+- [Descrevendo a Interface do Usuário](describing_ui/index.md)
+ - [Atributos Especiais](describing_ui/special_attributes.md)
+ - [Componentes](describing_ui/components.md)
+ - [Props](describing_ui/component_props.md)
+ - [Componente Filho](describing_ui/component_children.md)
+- [Interatividade](interactivity/index.md)
+ - [Manipuladores de Eventos](interactivity/event_handlers.md)
+ - [Hooks & Estado de Componentes](interactivity/hooks.md)
+ - [Entradas do Usuário](interactivity/user_input.md)
+ - [Estado Compartilhado](interactivity/sharing_state.md)
+ - [Hooks Personalizados](interactivity/custom_hooks.md)
+ - [Renderização Dinâmica](interactivity/dynamic_rendering.md)
+ - [Roteamento](interactivity/roteador.md)
+- [Assincronia](async/index.md)
+ - [UseFuture](async/use_future.md)
+ - [UseCoroutine](async/use_coroutine.md)
+ - [Gerando Futures](async/spawn.md)
+- [Práticas Recomendadas](best_practices/index.md)
+ - [Tratamento de erros](best_practices/error_handling.md)
+ - [Antipadrões](best_practices/antipatterns.md)
+- [Publicação](publishing/index.md)
+ - [Desktop](publishing/desktop.md)
+ - [Web](publishing/web.md)
+
+---
+
+- [Renderizador Personalizado](custom_renderer/index.md)
+
+---
+
+[Roteiro](roadmap.md)
+[Contribuindo](contributing.md)
diff --git a/docs/guide/src/pt-br/async/index.md b/docs/guide/src/pt-br/async/index.md
new file mode 100644
index 000000000..ea3cae827
--- /dev/null
+++ b/docs/guide/src/pt-br/async/index.md
@@ -0,0 +1,9 @@
+# Trabalhando em Assincronia
+
+Muitas vezes, os aplicativos precisam interagir com sistemas de arquivos, interfaces de rede, hardware ou temporizadores. Este capítulo fornece uma visão geral do uso de código assíncrono no Dioxus.
+
+## O Tempo de Execução (runtime)
+
+Por padrão, o Dioxus-Desktop vem com o runtime `Tokio` e configura tudo automaticamente para você. No momento, isso não é configurável, embora seja fácil escrever uma integração para o desktop Dioxus que use um tempo de execução assíncrono diferente.
+
+Dioxus atualmente não é `thread-safe`, então qualquer código assíncrono que você escreve _não_ precisa ser `Send/Sync`. Isso significa que você pode usar estruturas não `thread-safe` como `Cell`, `Rc` e `RefCell`.
diff --git a/docs/guide/src/pt-br/async/spawn.md b/docs/guide/src/pt-br/async/spawn.md
new file mode 100644
index 000000000..92c6a1615
--- /dev/null
+++ b/docs/guide/src/pt-br/async/spawn.md
@@ -0,0 +1,29 @@
+# Gerando Futures
+
+Os **"hooks"** `use_future` e `use_coroutine` são úteis se você quiser gerar incondicionalmente o `Future`. Às vezes, porém, você desejará apenas gerar um `Future` em resposta a um evento, como um clique do mouse. Por exemplo, suponha que você precise enviar uma solicitação quando o usuário clicar em um botão "log in". Para isso, você pode usar `cx.spawn`:
+
+```rust
+{{#include ../../examples/spawn.rs:spawn}}
+```
+
+> Nota: `spawn` sempre gerará um _novo_ `Future`. Você provavelmente não quer chamá-lo em cada renderização.
+
+O `Future` deve ser `'static` – então quaisquer valores capturados pela tarefa não podem carregar nenhuma referência a `cx`, como um `UseState`.
+
+No entanto, como você normalmente precisa de uma maneira de atualizar o valor de um gancho, você pode usar `to_owned` para criar um clone do _handle_ do _hook_. Você pode então usar esse clone no encerramento assíncrono.
+
+Para tornar isso um pouco menos detalhado, o Dioxus exporta a macro `to_owned!` que criará uma ligação como mostrado acima, o que pode ser bastante útil ao lidar com muitos valores.
+
+```rust
+{{#include ../../examples/spawn.rs:to_owned_macro}}
+```
+
+Calling `spawn` will give you a `JoinHandle` which lets you cancel or pause the future.
+
+## Gerando Tarefas do Tokio
+
+Às vezes, você pode querer gerar uma tarefa em segundo plano que precise de vários _threads_ ou conversar com o hardware que pode bloquear o código do seu aplicativo. Nesses casos, podemos gerar diretamente uma tarefa Tokio do nosso `Future`. Para Dioxus-Desktop, sua tarefa será gerada no tempo de execução Multi-Tarefado do Tokio:
+
+```rust
+{{#include ../../examples/spawn.rs:tokio}}
+```
diff --git a/docs/guide/src/pt-br/async/use_coroutine.md b/docs/guide/src/pt-br/async/use_coroutine.md
new file mode 100644
index 000000000..c27878fd8
--- /dev/null
+++ b/docs/guide/src/pt-br/async/use_coroutine.md
@@ -0,0 +1,181 @@
+# Corrotinas
+
+Outra boa ferramenta para manter em sua caixa de ferramentas assíncrona são as corrotinas. Corrotinas são `Futures` que podem ser interrompidos, iniciados, pausados e retomados manualmente.
+
+Assim como os `Futures` regulares, o código em uma corrotina Dioxus será executado até o próximo ponto `await` antes do _render_. Esse controle de baixo nível sobre tarefas assíncronas é bastante poderoso, permitindo tarefas em _loop_ infinito, como pesquisa de WebSocket, temporizadores em segundo plano e outras ações periódicas.
+
+## `use_coroutine`
+
+A configuração básica para corrotinas é o _hook_ `use_coroutine`. A maioria das corrotinas que escrevemos serão _loops_ de pesquisa usando `async`/`await`.
+
+```rust
+fn app(cx: Scope) -> Element {
+ let ws: &UseCoroutine<()> = use_coroutine(&cx, |rx| async move {
+ // Connect to some sort of service
+ let mut conn = connect_to_ws_server().await;
+
+ // Wait for data on the service
+ while let Some(msg) = conn.next().await {
+ // handle messages
+ }
+ });
+}
+```
+
+Para muitos serviços, um _loop_ assíncrono simples lidará com a maioria dos casos de uso.
+
+No entanto, se quisermos desabilitar temporariamente a corrotina, podemos "pausá-la" usando o método `pause` e "retomá-la" usando o método `resume`:
+
+```rust
+let sync: &UseCoroutine<()> = use_coroutine(&cx, |rx| async move {
+ // code for syncing
+});
+
+if sync.is_running() {
+ cx.render(rsx!{
+ button {
+ onclick: move |_| sync.pause(),
+ "Disable syncing"
+ }
+ })
+} else {
+ cx.render(rsx!{
+ button {
+ onclick: move |_| sync.resume(),
+ "Enable syncing"
+ }
+ })
+}
+```
+
+Esse padrão é onde as corrotinas são extremamente úteis – em vez de escrever toda a lógica complicada para pausar nossas tarefas assíncronas como faríamos com `Promises` de JavaScript, o modelo do Rust nos permite simplesmente não pesquisar nosso `Future`.
+
+## Enviando valores
+
+Você deve ter notado que o encerramento `use_coroutine` recebe um argumento chamado `rx`. O que é aquilo? Bem, um padrão comum em aplicativos complexos é lidar com vários códigos assíncronos de uma só vez. Com bibliotecas como o Redux Toolkit, gerenciar várias promessas ao mesmo tempo pode ser um desafio e uma fonte comum de _bugs_.
+
+Usando corrotinas, temos a oportunidade de centralizar nossa lógica assíncrona. O parâmetro `rx` é um canal ilimitado para código externo à corrotina para enviar dados _para_ a corrotina. Em vez de fazer um _loop_ em um serviço externo, podemos fazer um _loop_ no próprio canal, processando mensagens de dentro de nosso aplicativo sem precisar gerar um novo `Future`. Para enviar dados para a corrotina, chamaríamos "send" no _handle_.
+
+```rust
+enum ProfileUpdate {
+ SetUsername(String),
+ SetAge(i32)
+}
+
+let profile = use_coroutine(&cx, |mut rx: UnboundedReciver| async move {
+ let mut server = connect_to_server().await;
+
+ while let Ok(msg) = rx.next().await {
+ match msg {
+ ProfileUpdate::SetUsername(name) => server.update_username(name).await,
+ ProfileUpdate::SetAge(age) => server.update_age(age).await,
+ }
+ }
+});
+
+
+cx.render(rsx!{
+ button {
+ onclick: move |_| profile.send(ProfileUpdate::SetUsername("Bob".to_string())),
+ "Update username"
+ }
+})
+```
+
+Para aplicativos suficientemente complexos, poderíamos criar vários "serviços" úteis diferentes que fazem um _loop_ nos canais para atualizar o aplicativo.
+
+```rust
+let profile = use_coroutine(&cx, profile_service);
+let editor = use_coroutine(&cx, editor_service);
+let sync = use_coroutine(&cx, sync_service);
+
+async fn profile_service(rx: UnboundedReceiver) {
+ // do stuff
+}
+
+async fn sync_service(rx: UnboundedReceiver) {
+ // do stuff
+}
+
+async fn editor_service(rx: UnboundedReceiver) {
+ // do stuff
+}
+```
+
+Podemos combinar corrotinas com `Fermi` para emular o sistema `Thunk` do **Redux Toolkit** com muito menos dor de cabeça. Isso nos permite armazenar todo o estado do nosso aplicativo _dentro_ de uma tarefa e, em seguida, simplesmente atualizar os valores de "visualização" armazenados em `Atoms`. Não pode ser subestimado o quão poderosa é essa técnica: temos todas as vantagens das tarefas nativas do Rust com as otimizações e ergonomia do estado global. Isso significa que seu estado _real_ não precisa estar vinculado a um sistema como `Fermi` ou `Redux` – os únicos `Atoms` que precisam existir são aqueles que são usados para controlar a interface.
+
+```rust
+static USERNAME: Atom = |_| "default".to_string();
+
+fn app(cx: Scope) -> Element {
+ let atoms = use_atom_root(&cx);
+
+ use_coroutine(&cx, |rx| sync_service(rx, atoms.clone()));
+
+ cx.render(rsx!{
+ Banner {}
+ })
+}
+
+fn Banner(cx: Scope) -> Element {
+ let username = use_read(&cx, USERNAME);
+
+ cx.render(rsx!{
+ h1 { "Welcome back, {username}" }
+ })
+}
+```
+
+Agora, em nosso serviço de sincronização, podemos estruturar nosso estado como quisermos. Só precisamos atualizar os valores da _view_ quando estiver pronto.
+
+```rust
+enum SyncAction {
+ SetUsername(String),
+}
+
+async fn sync_service(mut rx: UnboundedReceiver, atoms: AtomRoot) {
+ let username = atoms.write(USERNAME);
+ let errors = atoms.write(ERRORS);
+
+ while let Ok(msg) = rx.next().await {
+ match msg {
+ SyncAction::SetUsername(name) => {
+ if set_name_on_server(&name).await.is_ok() {
+ username.set(name);
+ } else {
+ errors.make_mut().push("SetUsernameFailed");
+ }
+ }
+ }
+ }
+}
+```
+
+## Valores de Rendimento
+
+Para obter valores de uma corrotina, basta usar um identificador `UseState` e definir o valor sempre que sua corrotina concluir seu trabalho.
+
+```rust
+let sync_status = use_state(&cx, || Status::Launching);
+let sync_task = use_coroutine(&cx, |rx: UnboundedReceiver| {
+ to_owned![sync_status];
+ async move {
+ loop {
+ delay_ms(1000).await;
+ sync_status.set(Status::Working);
+ }
+ }
+})
+```
+
+## Injeção Automática na API de Contexto
+
+Os identificadores de corrotina são injetados automaticamente por meio da API de contexto. `use_coroutine_handle` com o tipo de mensagem como genérico pode ser usado para buscar um _handle_.
+
+```rust
+fn Child(cx: Scope) -> Element {
+ let sync_task = use_coroutine_handle::(&cx);
+
+ sync_task.send(SyncAction::SetUsername);
+}
+```
diff --git a/docs/guide/src/pt-br/async/use_future.md b/docs/guide/src/pt-br/async/use_future.md
new file mode 100644
index 000000000..d57d926a9
--- /dev/null
+++ b/docs/guide/src/pt-br/async/use_future.md
@@ -0,0 +1,31 @@
+# `UseFuture`
+
+[`use_future`](https://docs.rs/dioxus-hooks/latest/dioxus_hooks/fn.use_future.html) permite executar um encerramento assíncrono e fornece seu resultado.
+
+Por exemplo, podemos fazer uma solicitação de API dentro de `use_future`:
+
+```rust
+{{#include ../../examples/use_future.rs:use_future}}
+```
+
+O código dentro de `use_future` será enviado ao agendador do Dioxus assim que o componente for renderizado.
+
+Podemos usar `.value()` para obter o resultado do `Future`. Na primeira execução, como não há dados prontos quando o componente é carregado, seu valor será `None`. No entanto, uma vez finalizado o `Future`, o componente será renderizado novamente e o valor agora será `Some(...)`, contendo o valor de retorno do encerramento.
+
+Podemos então renderizar esse resultado:
+
+```rust
+{{#include ../../examples/use_future.rs:render}}
+```
+
+## Reiniciando o `Future`
+
+O identificador `UseFuture` fornece um método `restart`. Ele pode ser usado para executar o `Future` novamente, produzindo um novo valor.
+
+## Dependências
+
+Muitas vezes, você precisará executar o `Future` novamente toda vez que algum valor (por exemplo, uma prop) mudar. Ao invés de `.restart` manualmente, você pode fornecer uma tupla de "dependências" para o gancho. Ele executará automaticamente o `Future` quando qualquer uma dessas dependências for alterada. Exemplo:
+
+```rust
+{{#include ../../examples/use_future.rs:dependency}}
+```
diff --git a/docs/guide/src/pt-br/best_practices/antipatterns.md b/docs/guide/src/pt-br/best_practices/antipatterns.md
new file mode 100644
index 000000000..49bb44be6
--- /dev/null
+++ b/docs/guide/src/pt-br/best_practices/antipatterns.md
@@ -0,0 +1,33 @@
+# Antipadrões
+
+Este exemplo mostra o que não fazer e fornece uma razão pela qual um determinado padrão é considerado um "AntiPattern". A maioria dos antipadrões são considerados errados por motivos de desempenho ou por prejudicar a reutilização do código.
+
+## Fragmentos Aninhados Desnecessariamente
+
+Os fragmentos não montam um elemento físico no DOM imediatamente, então o Dioxus deve recorrer a seus filhos para encontrar um nó DOM físico. Este processo é chamado de "normalização". Isso significa que fragmentos profundamente aninhados fazem o Dioxus realizar um trabalho desnecessário. Prefira um ou dois níveis de fragmentos/componentes aninhados até apresentar um elemento DOM verdadeiro.
+
+Apenas os nós Componente e Fragmento são suscetíveis a esse problema. O Dioxus atenua isso com componentes fornecendo uma API para registrar o estado compartilhado sem o padrão _Context Provider_.
+
+```rust
+{{#include ../../examples/anti_patterns.rs:nested_fragments}}
+```
+
+## Chaves do Iterador Incorretas
+
+Conforme descrito no capítulo de renderização condicional, os itens da lista devem ter _keys_ exclusivas associadas aos mesmos itens nas renderizações. Isso ajuda o Dioxus a associar o estado aos componentes contidos e garante um bom desempenho de diferenciação. Não omita as _keys_, a menos que você saiba que a lista é estática e nunca será alterada.
+
+```rust
+{{#include ../../examples/anti_patterns.rs:iter_keys}}
+```
+
+## Evite Mutabilidade Interior em `Props`
+
+Embora seja tecnicamente aceitável ter um `Mutex` ou um `RwLock` nos _props_, eles serão difíceis de usar.
+
+Suponha que você tenha um _struct_ `User` contendo o campo `username: String`. Se você passar uma _prop_ `Mutex` para um componente `UserComponent`, esse componente pode querer passar o nome de usuário como uma _prop_ `&str` para um componente filho. No entanto, ele não pode passar esse campo emprestado, pois ele só viveria enquanto o bloqueio do `Mutex`, que pertence à função `UserComponent`. Portanto, o componente será forçado a clonar o campo `username`.
+
+## Evite Atualizar o Estado Durante a Renderização
+
+Toda vez que você atualiza o estado, o Dioxus precisa renderizar novamente o componente – isso é ineficiente! Considere refatorar seu código para evitar isso.
+
+Além disso, se você atualizar incondicionalmente o estado durante a renderização, ele será renderizado novamente em um _loop_ infinito.
diff --git a/docs/guide/src/pt-br/best_practices/error_handling.md b/docs/guide/src/pt-br/best_practices/error_handling.md
new file mode 100644
index 000000000..52c560b6d
--- /dev/null
+++ b/docs/guide/src/pt-br/best_practices/error_handling.md
@@ -0,0 +1,153 @@
+# Manipulação de Erros
+
+Um ponto forte do Rust para desenvolvimento Web é a confiabilidade de sempre saber onde os erros podem ocorrer e ser forçado a lidar com eles
+
+No entanto, não falamos sobre tratamento de erros neste guia! Neste capítulo, abordaremos algumas estratégias para lidar com erros para garantir que seu aplicativo nunca falhe.
+
+## O mais simples – retornando None
+
+Observadores astutos podem ter notado que `Element` é na verdade um alias de tipo para `Option`. Você não precisa saber o que é um `VNode`, mas é importante reconhecer que não poderíamos retornar nada:
+
+```rust
+fn App(cx: Scope) -> Element {
+ None
+}
+```
+
+Isso nos permite adicionar um pouco de açúcar sintático para operações que achamos que _não devem_ falhar, mas ainda não estamos confiantes o suficiente para "desempacotar".
+
+> A natureza de `Option` pode mudar no futuro à medida que a característica `try` for atualizada.
+
+```rust
+fn App(cx: Scope) -> Element {
+ // immediately return "None"
+ let name = cx.use_hook(|_| Some("hi"))?;
+}
+```
+
+## Retorno Antecipado do Resultado
+
+Como o Rust não pode aceitar opções e resultados com a infraestrutura _try_ existente, você precisará manipular os resultados manualmente. Isso pode ser feito convertendo-os em `Option` ou manipulando-os explicitamente.
+
+```rust
+fn App(cx: Scope) -> Element {
+ // Convert Result to Option
+ let name = cx.use_hook(|_| "1.234").parse().ok()?;
+
+
+ // Early return
+ let count = cx.use_hook(|_| "1.234");
+ let val = match count.parse() {
+ Ok(val) => val
+ Err(err) => return cx.render(rsx!{ "Parsing failed" })
+ };
+}
+```
+
+Observe que enquanto os ganchos no Dioxus não gostam de ser chamados em condicionais ou loops, eles _estão_ bem com retornos antecipados. Retornar um estado de erro antecipadamente é uma maneira completamente válida de lidar com erros.
+
+## Resultados usando `match`
+
+A próxima "melhor" maneira de lidar com erros no Dioxus é combinar (`match`) o erro localmente. Essa é a maneira mais robusta de lidar com erros, embora não seja dimensionada para arquiteturas além de um único componente.
+
+Para fazer isso, simplesmente temos um estado de erro embutido em nosso componente:
+
+```rust
+let err = use_state(&cx, || None);
+```
+
+Sempre que realizarmos uma ação que gere um erro, definiremos esse estado de erro. Podemos então combinar o erro de várias maneiras (retorno antecipado, elemento de retorno etc.).
+
+```rust
+fn Commandline(cx: Scope) -> Element {
+ let error = use_state(&cx, || None);
+
+ cx.render(match *error {
+ Some(error) => rsx!(
+ h1 { "An error occured" }
+ )
+ None => rsx!(
+ input {
+ oninput: move |_| error.set(Some("bad thing happened!")),
+ }
+ )
+ })
+}
+```
+
+## Passando Estados de Erro Através de Componentes
+
+Se você estiver lidando com alguns componentes com um mínimo de aninhamento, basta passar o identificador de erro para componentes filhos.
+
+```rust
+fn Commandline(cx: Scope) -> Element {
+ let error = use_state(&cx, || None);
+
+ if let Some(error) = **error {
+ return cx.render(rsx!{ "An error occured" });
+ }
+
+ cx.render(rsx!{
+ Child { error: error.clone() }
+ Child { error: error.clone() }
+ Child { error: error.clone() }
+ Child { error: error.clone() }
+ })
+}
+```
+
+Assim como antes, nossos componentes filhos podem definir manualmente o erro durante suas próprias ações. A vantagem desse padrão é que podemos isolar facilmente os estados de erro para alguns componentes por vez, tornando nosso aplicativo mais previsível e robusto.
+
+## Tornando Global
+
+Uma estratégia para lidar com erros em cascata em aplicativos maiores é sinalizar um erro usando o estado global. Esse padrão específico envolve a criação de um contexto de "erro" e, em seguida, defini-lo sempre que relevante. Este método em particular não é tão "sofisticado" quanto o controle de erros do React, mas é mais adequado para Rust.
+
+Para começar, considere usar um _hook_ embutido como `use_context` e `use_context_provider` ou `Fermi`. Claro, é muito fácil criar seu próprio _hook_ também.
+
+No "topo" de nossa arquitetura, queremos declarar explicitamente um valor que pode ser um erro.
+
+```rust
+enum InputError {
+ None,
+ TooLong,
+ TooShort,
+}
+
+static INPUT_ERROR: Atom = |_| InputError::None;
+```
+
+Então, em nosso componente de nível superior, queremos tratar explicitamente o possível estado de erro para esta parte da árvore.
+
+```rust
+fn TopLevel(cx: Scope) -> Element {
+ let error = use_read(&cx, INPUT_ERROR);
+
+ match error {
+ TooLong => return cx.render(rsx!{ "FAILED: Too long!" }),
+ TooShort => return cx.render(rsx!{ "FAILED: Too Short!" }),
+ _ => {}
+ }
+}
+```
+
+Agora, sempre que um componente _downstream_ tiver um erro em suas ações, ele pode simplesmente definir seu próprio estado de erro:
+
+```rust
+fn Commandline(cx: Scope) -> Element {
+ let set_error = use_set(&cx, INPUT_ERROR);
+
+ cx.render(rsx!{
+ input {
+ oninput: move |evt| {
+ if evt.value.len() > 20 {
+ set_error(InputError::TooLong);
+ }
+ }
+ }
+ })
+}
+```
+
+Essa abordagem de tratamento de erros é melhor em aplicativos que têm estados de erro "bem definidos". Considere usar uma `crate` como `thiserror` ou `anyhow` para simplificar a geração dos tipos de erro.
+
+Esse padrão é amplamente popular em muitos contextos e é particularmente útil sempre que seu código gera um erro irrecuperável. Você pode capturar esses estados de erro "globais" resultar em `panic!` ou estragar o estado.
diff --git a/docs/guide/src/pt-br/best_practices/index.md b/docs/guide/src/pt-br/best_practices/index.md
new file mode 100644
index 000000000..3330c4327
--- /dev/null
+++ b/docs/guide/src/pt-br/best_practices/index.md
@@ -0,0 +1,30 @@
+# Práticas Recomendadas
+
+## Componentes Reutilizáveis
+
+Tanto quanto possível, divida seu código em pequenos componentes e _hooks_ reutilizáveis, em vez de implementar grandes partes da interface do usuário em um único componente. Isso ajudará você a manter o código sustentável – é muito mais fácil, por exemplo, adicionar, remover ou reordenar partes da interface do usuário se ela estiver organizada em componentes.
+
+Organize seus componentes em módulos para manter a base de código fácil de navegar!
+
+## Minimize as Dependências do Estado
+
+Embora seja possível compartilhar o estado entre os componentes, isso só deve ser feito quando necessário. Qualquer componente associado a um objeto de estado específico precisa ser renderizado novamente quando esse estado for alterado. Por esta razão:
+
+- Mantenha o estado local para um componente, se possível
+- Ao compartilhar o estado por meio de adereços, passe apenas os dados específicos necessários
+
+## Bibliotecas Reutilizáveis
+
+Ao publicar uma biblioteca projetada para funcionar com o Dioxus, é altamente recomendável usar apenas o recurso principal na `crate` `dioxus`. Isso faz com que sua `crate` seja compilada mais rapidamente, mais estável e evita a inclusão de bibliotecas incompatíveis que podem fazer com que ela não seja compilada em plataformas não suportadas.
+
+❌ Não inclua dependências desnecessárias nas bibliotecas:
+
+```toml
+dioxus = { version = "...", features = ["web", "desktop", "full"]}
+```
+
+✅ Adicione apenas os recursos que você precisa:
+
+```toml
+dioxus = { version = "...", features = "core"}
+```
diff --git a/docs/guide/src/pt-br/contributing.md b/docs/guide/src/pt-br/contributing.md
new file mode 100644
index 000000000..404a174db
--- /dev/null
+++ b/docs/guide/src/pt-br/contributing.md
@@ -0,0 +1,20 @@
+# Contribuindo
+
+O desenvolvimento acontece no [repositório do Dioxus no GitHub](https://github.com/DioxusLabs/dioxus). Se você encontrou um bug ou tem uma ideia para um recurso, envie um _issue_ (verifique se alguém ainda não o fez (https://github.com/DioxusLabs/dioxus/issues)).
+
+[Discussões do GitHub](https://github.com/DioxusLabs/dioxus/discussions) podem ser usadas como um lugar para pedir ajuda ou falar sobre recursos. Você também pode participar do [nosso canal Discord](https://discord.gg/XgGxMSkvUM) onde algumas discussões de desenvolvimento acontecem.
+
+## Como melhorar os documentos
+
+Se você quiser melhorar os documentos, os PRs são bem-vindos! Ambos os documentos do Rust ([source](https://github.com/DioxusLabs/dioxus/tree/master/packages)) e este guia ([source](https://github.com/DioxusLabs/dioxus/tree/master /docs/guide)) pode ser encontrado no repositório do GitHub.
+
+## Trabalhando no Ecossistema
+
+Parte do que torna o React ótimo é o rico ecossistema. Gostaríamos do mesmo para Dioxus! Portanto, se você tem uma biblioteca em mente que gostaria de escrever e da qual acha que muitas pessoas se beneficiariam, ela será apreciada. Você pode [navegar no npm.js](https://www.npmjs.com/search?q=keywords:react-component) para se inspirar.
+
+## Bugs e recursos
+
+Se você corrigiu [um problema aberto](https://github.com/DioxusLabs/dioxus/issues), sinta-se à vontade para enviar um PR! Você também pode dar uma olhada no [roteiro](./roadmap.md) e trabalhar em algo lá. Considere [entre em contato](https://discord.gg/XgGxMSkvUM) com a equipe primeiro para garantir que todos estejam na mesma página e que você não faça um trabalho inútil!
+
+Todas as solicitações de PR (incluindo aquelas feitas por um membro da equipe) devem ser aprovadas por pelo menos um outro membro da equipe.
+Decisões maiores e mais sutis sobre design, arquitetura, mudanças de última hora, trade-offs, etc. são feitas por consenso da equipe.
diff --git a/docs/guide/src/pt-br/custom_renderer/index.md b/docs/guide/src/pt-br/custom_renderer/index.md
new file mode 100644
index 000000000..68881382a
--- /dev/null
+++ b/docs/guide/src/pt-br/custom_renderer/index.md
@@ -0,0 +1,505 @@
+# Renderizador Personalizado
+
+Dioxus é uma estrutura incrivelmente portátil para desenvolvimento de interface do usuário. As lições, conhecimentos, _hooks_ e componentes que você adquire ao longo do tempo sempre podem ser usados para projetos futuros. No entanto, às vezes, esses projetos não podem aproveitar um renderizador compatível ou você precisa implementar seu próprio renderizador melhor.
+
+Ótimas notícias: o design do renderizador depende inteiramente de você! Nós fornecemos sugestões e inspiração com os renderizadores originais, mas só realmente precisamos processar `DomEdits` e enviar `UserEvents`.
+
+## Detalhes
+
+A implementação do renderizador é bastante simples. O renderizador precisa:
+
+1. Lidar com o fluxo de edições gerado por atualizações no DOM virtual
+2. Registrar ouvintes e passar eventos para o sistema de eventos do DOM virtual
+
+Essencialmente, seu renderizador precisa implementar a `trait` `RealDom` e gerar objetos `EventTrigger` para atualizar o `VirtualDOM`. A partir daí, você terá tudo o que precisa para renderizar o `VirtualDOM` na tela.
+
+Internamente, o Dioxus lida com o relacionamento da árvore, `diffing`, gerenciamento de memória e o sistema de eventos, deixando o mínimo necessário para que os renderizadores se implementem.
+
+Como referência, confira o interpretador `javascript` ou o renderizador `tui` como ponto de partida para seu renderizador personalizado.
+
+## DomEdit
+
+O tipo "DomEdit" é uma `enum` serializada que representa uma operação atômica que ocorre no `RealDom`. As variantes seguem aproximadamente este conjunto:
+
+```rust
+enum DomEdit {
+ PushRoot,
+ AppendChildren,
+ ReplaceWith,
+ InsertAfter,
+ InsertBefore,
+ Remove,
+ CreateTextNode,
+ CreateElement,
+ CreateElementNs,
+ CreatePlaceholder,
+ NewEventListener,
+ RemoveEventListener,
+ SetText,
+ SetAttribute,
+ RemoveAttribute,
+ PopRoot,
+}
+```
+
+O mecanismo de diferenciação Dioxus opera como uma [máquina de pilha] (https://en.wikipedia.org/wiki/Stack_machine) onde o método "push_root" empurra um novo nó DOM "real" para a pilha e "append_child" e "replace_with" " ambos removem nós da pilha.
+
+### Exemplo
+
+Para fins de compreensão, vamos considerar este exemplo – uma declaração de interface do usuário muito simples:
+
+```rust
+rsx!( h1 {"hello world"} )
+```
+
+Para começar, o Dioxus deve primeiro navegar até o contêiner dessa tag h1. Para "navegar" aqui, o algoritmo de diferenciação interna gera o `DomEdit` `PushRoot` onde o ID da raiz é o contêiner.
+
+Quando o renderizador recebe essa instrução, ele empurra o `Node` real para sua própria pilha. A pilha do renderizador real ficará assim:
+
+```rust
+instructions: [
+ PushRoot(Container)
+]
+stack: [
+ ContainerNode,
+]
+```
+
+Em seguida, o Dioxus encontrará o nó `h1`. O algoritmo `diff` decide que este nó precisa ser criado, então o Dioxus irá gerar o DomEdit `CreateElement`. Quando o renderizador receber esta instrução, ele criará um nó desmontado e o enviará para sua própria pilha (_stack_):
+
+```rust
+instructions: [
+ PushRoot(Container),
+ CreateElement(h1),
+]
+stack: [
+ ContainerNode,
+ h1,
+]
+```
+
+Em seguida, Dioxus vê o nó de texto e gera o DomEdit `CreateTextNode`:
+
+```rust
+instructions: [
+ PushRoot(Container),
+ CreateElement(h1),
+ CreateTextNode("hello world")
+]
+stack: [
+ ContainerNode,
+ h1,
+ "hello world"
+]
+```
+
+Lembre-se, o nó de texto não está anexado a nada (ele está desmontado), então o Dioxus precisa gerar um _Edit_ que conecte o nó de texto ao elemento `h1`. Depende da situação, mas neste caso usamos `AppendChildren`. Isso remove o nó de texto da _stack_, deixando o elemento `h1` como o próximo elemento na linha.
+
+```rust
+instructions: [
+ PushRoot(Container),
+ CreateElement(h1),
+ CreateTextNode("hello world"),
+ AppendChildren(1)
+]
+stack: [
+ ContainerNode,
+ h1
+]
+```
+
+Chamamos `AppendChildren` novamente, retirando o nó `h1` e anexando-o ao pai:
+
+```rust
+instructions: [
+ PushRoot(Container),
+ CreateElement(h1),
+ CreateTextNode("hello world"),
+ AppendChildren(1),
+ AppendChildren(1)
+]
+stack: [
+ ContainerNode,
+]
+```
+
+Finalmente, o contêiner é aberto, pois não precisamos mais dele.
+
+```rust
+instructions: [
+ PushRoot(Container),
+ CreateElement(h1),
+ CreateTextNode("hello world"),
+ AppendChildren(1),
+ AppendChildren(1),
+ PopRoot
+]
+stack: []
+```
+
+Com o tempo, nossa _stack_ ficou assim:
+
+```rust
+[]
+[Container]
+[Container, h1]
+[Container, h1, "hello world"]
+[Container, h1]
+[Container]
+[]
+```
+
+Observe como nossa _stack_ fica vazia depois que a interface do usuário é montada. Convenientemente, essa abordagem separa completamente o `VirtualDOM` e o `RealDOM`. Além disso, essas edições são serializáveis, o que significa que podemos até gerenciar UIs em uma conexão de rede. Esta pequena _stack_ e edições serializadas tornam o Dioxus independente das especificidades da plataforma.
+
+Dioxus também é muito rápido. Como o Dioxus divide a fase de `diff` e `patch`, ele é capaz de fazer todas as edições no `RealDOM` em um período de tempo muito curto (menos de um único quadro), tornando a renderização muito rápida. Ele também permite que o Dioxus cancele grandes operações de diferenciação se ocorrer um trabalho de prioridade mais alta durante a diferenciação.
+
+É importante notar que há uma camada de conexão entre o Dioxus e o renderizador. Dioxus salva e carrega elementos (a edição `PushRoot`) com um ID. Dentro do `VirtualDOM`, isso é rastreado apenas como um `u64`.
+
+Sempre que uma edição `CreateElement` é gerada durante a comparação, o Dioxus incrementa seu contador de nós e atribui a esse novo elemento seu `NodeCount` atual. O `RealDom` é responsável por lembrar este ID e enviar o nó correto quando `PushRoot(ID)` é gerado. Dioxus recupera IDs de elementos quando removidos. Para ficar em sincronia com Dioxus, você pode usar um `Sparce Vec` (`Vec