diff --git a/.gitbook.yaml b/.gitbook.yaml
new file mode 100644
index 00000000000..2a894db64e2
--- /dev/null
+++ b/.gitbook.yaml
@@ -0,0 +1 @@
+root: ./docs/src
diff --git a/.github/workflows/doctests.yml b/.github/workflows/doctests.yml
new file mode 100644
index 00000000000..4da9ec61096
--- /dev/null
+++ b/.github/workflows/doctests.yml
@@ -0,0 +1,27 @@
+name: Documentation tests
+on:
+ push:
+ paths:
+ - "docs/**/*"
+ pull_request:
+ paths:
+ - "docs/**/*"
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Setup Rust
+ uses: actions-rs/toolchain@v1
+ with:
+ toolchain: stable
+ target: wasm32-unknown-unknown
+ - name: Run tests
+ run: cd docs && cargo test
+ check-spelling:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Check spelling
+ run: bash ci/spellcheck.sh list
diff --git a/.gitignore b/.gitignore
index 3c6f327e589..061f0d74763 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ orig.*
/.idea
/.vscode
/cmake-build-debug
+/docs/target
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index b1d8ad6dc2a..ea5d0ee00b9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -57,3 +57,4 @@ members = [
"examples/two_apps",
"examples/webgl",
]
+exclude=["docs"]
\ No newline at end of file
diff --git a/README.md b/README.md
index bb5302471a0..1350a472f3c 100644
--- a/README.md
+++ b/README.md
@@ -97,4 +97,4 @@ Support this project with your organization. Your logo will show up here with a
-
+
\ No newline at end of file
diff --git a/ci/dictionary.txt b/ci/dictionary.txt
new file mode 100644
index 00000000000..d40d130f076
--- /dev/null
+++ b/ci/dictionary.txt
@@ -0,0 +1,17 @@
+personal_ws-1.1 en 0 utf-8
+APIs
+bindgen
+interoperable
+interoperability
+libs
+Libs
+minimising
+Optimisations
+roadmap
+README
+stdweb
+html
+Roadmap
+wasm
+Wasm
+WebAssembly
diff --git a/ci/spellcheck.sh b/ci/spellcheck.sh
new file mode 100755
index 00000000000..03d48d784b2
--- /dev/null
+++ b/ci/spellcheck.sh
@@ -0,0 +1,101 @@
+#!/bin/bash
+
+aspell --version
+
+# Taken from the Rust Book (https://github.com/rust-lang/book/)
+
+# Checks project Markdown files for spelling mistakes.
+
+# Notes:
+
+# This script needs dictionary file ($dict_filename) with project-specific
+# valid words. If this file is missing, first invocation of a script generates
+# a file of words considered typos at the moment. User should remove real typos
+# from this file and leave only valid words. When script generates false
+# positive after source modification, new valid word should be added
+# to dictionary file.
+
+# Default mode of this script is interactive. Each source file is scanned for
+# typos. aspell opens window, suggesting fixes for each found typo. Original
+# files with errors will be backed up to files with format "filename.md.bak".
+
+# When running in CI, this script should be run in "list" mode (pass "list"
+# as first argument). In this mode script scans all files and reports found
+# errors. Exit code in this case depends on scan result:
+# 1 if any errors found,
+# 0 if all is clear.
+
+# Script skips words with length less than or equal to 3. This helps to avoid
+# some false positives.
+
+# We can consider skipping source code in markdown files (```code```) to reduce
+# rate of false positives, but then we lose ability to detect typos in code
+# comments/strings etc.
+
+shopt -s nullglob
+
+dict_filename=./ci/dictionary.txt
+markdown_sources=(./docs/**/*.md)
+mode="check"
+
+# aspell repeatedly modifies the personal dictionary for some reason,
+# so we should use a copy of our dictionary.
+dict_path="/tmp/dictionary.txt"
+
+if [[ "$1" == "list" ]]; then
+ mode="list"
+fi
+
+# Error if running in list (CI) mode and there isn't a dictionary file;
+# creating one in CI won't do any good :(
+if [[ "$mode" == "list" && ! -f "$dict_filename" ]]; then
+ echo "No dictionary file found! A dictionary file is required in CI!"
+ exit 1
+fi
+
+if [[ ! -f "$dict_filename" ]]; then
+ # Pre-check mode: generates dictionary of words aspell consider typos.
+ # After user validates that this file contains only valid words, we can
+ # look for typos using this dictionary and some default aspell dictionary.
+ echo "Scanning files to generate dictionary file '$dict_filename'."
+ echo "Please check that it doesn't contain any misspellings."
+
+ echo "personal_ws-1.1 en 0 utf-8" > "$dict_filename"
+ cat "${markdown_sources[@]}" | aspell --ignore 3 list | sort -u >> "$dict_filename"
+elif [[ "$mode" == "list" ]]; then
+ # List (default) mode: scan all files, report errors.
+ declare -i retval=0
+
+ cp "$dict_filename" "$dict_path"
+
+ if [ ! -f $dict_path ]; then
+ retval=1
+ exit "$retval"
+ fi
+
+ for fname in "${markdown_sources[@]}"; do
+ command=$(aspell --ignore 3 --personal="$dict_path" "$mode" < "$fname")
+ if [[ -n "$command" ]]; then
+ for error in $command; do
+ # FIXME: find more correct way to get line number
+ # (ideally from aspell). Now it can make some false positives,
+ # because it is just a grep.
+ grep --with-filename --line-number --color=always "$error" "$fname"
+ done
+ retval=1
+ fi
+ done
+ exit "$retval"
+elif [[ "$mode" == "check" ]]; then
+ # Interactive mode: fix typos.
+ cp "$dict_filename" "$dict_path"
+
+ if [ ! -f $dict_path ]; then
+ retval=1
+ exit "$retval"
+ fi
+
+ for fname in "${markdown_sources[@]}"; do
+ aspell --ignore 3 --dont-backup --personal="$dict_path" "$mode" "$fname"
+ done
+fi
\ No newline at end of file
diff --git a/docs/Cargo.toml b/docs/Cargo.toml
new file mode 100644
index 00000000000..734671b1c6b
--- /dev/null
+++ b/docs/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "docs"
+version = "0.1.0"
+authors = ["Yew Maintainers "]
+edition = "2018"
+
+[dependencies]
+doc-comment = "0.3.3"
+wasm-bindgen = "0.2"
+wasm-bindgen-test = "0.3.0"
+wee_alloc = "0.4"
+yew = { version = "0.16.0", features = ["wasm_test"] }
\ No newline at end of file
diff --git a/docs/LICENSE b/docs/LICENSE
new file mode 100644
index 00000000000..0e259d42c99
--- /dev/null
+++ b/docs/LICENSE
@@ -0,0 +1,121 @@
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000000..7bc47dc622f
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,54 @@
+# Contributing to the documentation
+
+Firstly, thanks for considering contributing to Yew. We're a friendly community of humans who
+collaborate to build (hopefully) awesome software. We try to write software which is easy to use so
+we ask that you follow a few guidelines when contributing – these are laid out in this document.
+
+Note that this document is about *contributing documentation* not contributing code and only
+applies to the contents of the `docs` folder – not any other parts of the project.
+
+## Can I just submit a PR or do I need to create an issue first?
+
+PRs not attached to previously created issues are welcome *if* they're a small change. This could
+be something like fixing a small grammar mistake or a typo.
+
+If your PR is something bigger create an issue beforehand. This will save everyone time and effort:
+
+1. Multiple people don't end up submitting duplicate PRs doing the same thing.
+2. People have a chance to submit feedback on an idea *before* someone does a lot of work on it.
+3. It's easy to track progress on the development of the documentation.
+
+## Spelling and grammar
+
+We recognise that not everyone who contributes to Yew will have "perfect" grammar or be a native
+English speaker. We're all human; everyone makes mistakes and nobody will look down on you if you
+make typos or grammar mistakes (we'll just fix them, merge PRs and move on with life).
+
+To help catch spelling mistakes, we use a spellchecking script which originally came from the Rust
+Book. If it picks up a spelling "mistake" which isn't actually a mistake, then please add it to the
+list in `ci/dictionary.txt` (in alphabetically sorted order).
+
+If in doubt about spelling, grammar or style you might find it useful to consult the
+[Microsoft Style Guide](https://docs.microsoft.com/style-guide/) which we sometimes use as a handy
+reference.
+
+## Line wrap
+Having really long lines makes it hard to review code and see differences between versions. To
+solve this problem all lines should be wrapped at 100 characters.
+
+## Building the book locally
+
+Note that Yew uses Gitbook which renders differently from mdbook. However the latest Gitbook is
+not compatible with gitbook-cli :(
+
+### Install mdbook:
+
+```bash
+$ cargo install mdbook
+```
+
+### Render and view the book:
+
+```bash
+$ mdbook serve
+```
\ No newline at end of file
diff --git a/docs/build.rs b/docs/build.rs
new file mode 100644
index 00000000000..9cd8eb31d8f
--- /dev/null
+++ b/docs/build.rs
@@ -0,0 +1,21 @@
+use std::env;
+use std::error::Error;
+use std::fs;
+use std::path::Path;
+
+fn main() -> Result<(), Box> {
+ let out_dir = env::var_os("OUT_DIR").unwrap();
+ let src_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
+ let out_path = Path::new(&out_dir);
+
+ let original_path = src_path.join("getting-started/build-a-sample-app.md");
+ let original_str = fs::read_to_string(original_path)?.replace("fn main", "fn _main");
+ let sanitized_path = out_path.join("getting-started/build-a-sample-app.md");
+ let _ignore = fs::create_dir(&out_path.join("getting-started"));
+ fs::write(sanitized_path, original_str)?;
+
+ println!("cargo:rerun-if-changed=build.rs");
+ println!("cargo:rerun-if-changed=src/getting-started-build-a-simple-app.md");
+
+ Ok(())
+}
diff --git a/docs/src/.gitbook/assets/yew.svg b/docs/src/.gitbook/assets/yew.svg
new file mode 100644
index 00000000000..35a471408f5
--- /dev/null
+++ b/docs/src/.gitbook/assets/yew.svg
@@ -0,0 +1,7 @@
+
diff --git a/docs/src/README.md b/docs/src/README.md
new file mode 100644
index 00000000000..ca220093d55
--- /dev/null
+++ b/docs/src/README.md
@@ -0,0 +1,81 @@
+# Introduction
+
+## What is Yew?
+
+**Yew** is a modern [Rust](https://www.rust-lang.org/) framework for creating multi-threaded
+front-end web apps with [WebAssembly](https://webassembly.org/).
+
+* It features a **component-based** framework which makes it easy to create interactive UIs.
+Developers who have experience with frameworks like [React](https://reactjs.org/) and
+[Elm](https://elm-lang.org/) should feel quite at home when using Yew.
+* It has **great performance** by minimising DOM API calls and by helping developers easily offload
+processing to background web workers.
+* It supports **JavaScript interoperability**, allowing developers to leverage NPM packages and
+integrate with existing JavaScript applications.
+
+### Join Us 😊
+
+* You can report bugs and discuss features on the
+[GitHub issues page](https://github.com/yewstack/yew/issues)
+* We ❤️ pull requests. Check out
+[good first issues](https://github.com/yewstack/yew/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
+if you'd like to help out!
+* Our [Discord chat](https://discord.gg/VQck8X4) is very active and is a great place to ask
+questions.
+
+
+
+### Ready to dive in?
+
+Click the link below to learn how to build your first Yew app and learn from community example
+projects.
+
+{% page-ref page="getting-started/project-setup/" %}
+
+### **Still not convinced?**
+
+This project is built on cutting edge technology and is great for developers who like to develop the
+foundational projects of tomorrow. Here are some reasons why we believe that frameworks like Yew are
+the future of web development.
+
+#### **Wait, why WebAssembly?**
+
+WebAssembly _\(Wasm\)_ is a portable low-level language that Rust can compile into. It runs at
+native speeds in the browser and is interoperable with JavaScript and supported in all major
+browsers. For ideas on how to get the most out of WebAssembly for your app, check out this list of
+[Use Cases](https://webassembly.org/docs/use-cases/).
+
+It should be noted that using Wasm is not \(yet\) a silver bullet for improving the performance of
+a web app. As of right now, using DOM APIs from WebAssembly is still slower than calling them
+directly from JavaScript. This is a temporary issue which the [WebAssembly Interface Types](https://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/Explainer.md) proposal aims to
+resolve. If you would like to learn more, check out this
+[excellent article](https://hacks.mozilla.org/2019/08/webassembly-interface-types/) from Mozilla.
+
+#### Ok, but why Rust?
+
+Rust is blazing fast and reliable with its rich type system and ownership model. It has a tough
+learning curve but is well worth the effort. Rust has been voted the most loved programming
+language in Stack Overflow's Developer Survey five years in a row:
+[2016](https://insights.stackoverflow.com/survey/2016#technology-most-loved-dreaded-and-wanted),
+[2017](https://insights.stackoverflow.com/survey/2017#most-loved-dreaded-and-wanted),
+[2018](https://insights.stackoverflow.com/survey/2018#technology-_-most-loved-dreaded-and-wanted-languages),
+[2019](https://insights.stackoverflow.com/survey/2019#technology-_-most-loved-dreaded-and-wanted-languages)
+and [2020](https://insights.stackoverflow.com/survey/2020#most-loved-dreaded-and-wanted).
+
+Rust also helps developers write safer code with its rich type system and ownership model. Say
+goodbye to hard to track down race condition bugs in JavaScript! In fact, with Rust, most of your
+bugs will be caught by the compiler before your app even runs. And don't worry, when your app does
+run into an error, you can still get full stack-traces for your Rust code in the browser console.
+
+#### Alternatives?
+
+We love to share ideas with other projects and believe we can all help each other reach the full
+potential of this exciting new technology. If you're not into Yew, you may like the following
+projects:
+
+* [Percy](https://github.com/chinedufn/percy) - _"A modular toolkit for building isomorphic web
+apps with Rust + WebAssembly"_
+* [Seed](https://github.com/seed-rs/seed) - _"A Rust framework for creating web apps"_
+
+
+
diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md
new file mode 100644
index 00000000000..431b2cb2e76
--- /dev/null
+++ b/docs/src/SUMMARY.md
@@ -0,0 +1,44 @@
+# Table of contents
+
+* [Introduction](README.md)
+
+## Getting Started
+
+* [Project Setup](getting-started/project-setup/README.md)
+ * [Using wasm-pack](getting-started/project-setup/using-wasm-pack.md)
+ * [Using wasm-bindgen](getting-started/project-setup/using-wasm-bindgen.md)
+ * [Using cargo-web](getting-started/project-setup/using-cargo-web.md)
+* [Starter Templates](getting-started/starter-templates.md)
+* [Build a Sample App](getting-started/build-a-sample-app.md)
+* [Choose web-sys or stdweb](getting-started/choose-web-library.md)
+* [Learn through examples](getting-started/examples.md)
+
+## Core Concepts
+
+* [Using html!](concepts/html/README.md)
+ * [Lists](concepts/html/lists.md)
+ * [Elements](concepts/html/elements.md)
+ * [Literals & Expressions](concepts/html/literals-and-expressions.md)
+ * [Components](concepts/html/components.md)
+* [Components](concepts/components/README.md)
+ * [Properties](concepts/components/properties.md)
+ * [Callbacks](concepts/components/callbacks.md)
+ * [Refs](concepts/components/refs.md)
+* [Agents](concepts/agents.md)
+* [Services](concepts/services/README.md)
+ * [Format](concepts/services/format.md)
+* [Router](concepts/router.md)
+
+## Advanced Topics
+
+* [Optimisations & Best Practices](advanced-topics/optimizations.md)
+* [Low-level library internals](advanced-topics/how-it-works.md)
+
+## More
+
+* [CSS](more/css.md)
+* [Roadmap](more/roadmap.md)
+* [Testing](more/testing.md)
+* [Debugging](more/debugging.md)
+* [External Libs](more/external-libs.md)
+
diff --git a/docs/src/advanced-topics/how-it-works.md b/docs/src/advanced-topics/how-it-works.md
new file mode 100644
index 00000000000..88d5577c975
--- /dev/null
+++ b/docs/src/advanced-topics/how-it-works.md
@@ -0,0 +1,8 @@
+---
+description: Low level details about the framework
+---
+
+# Low-level library internals
+
+Component-lifecycle state machine, vdom diff algorithm.
+
diff --git a/docs/src/advanced-topics/optimizations.md b/docs/src/advanced-topics/optimizations.md
new file mode 100644
index 00000000000..08d6f5aa3ac
--- /dev/null
+++ b/docs/src/advanced-topics/optimizations.md
@@ -0,0 +1,178 @@
+---
+description: Make your app faster
+---
+
+# Optimizations & Best Practices
+
+## neq\_assign
+
+When a component receives props from its parent component, the `change` method is called. This, in
+addition to allowing you to update the component's state, also allows you to return a `ShouldRender`
+boolean value that indicates if the component should re-render itself in response to the prop
+changes.
+
+Re-rendering is expensive, and if you can avoid it, you should. As a general rule, you only want to
+re-render when the props actually changed. The following block of code represents this rule,
+returning `true` if the props differed from the previous props:
+
+```rust
+use yew::ShouldRender;
+
+#[derive(PartialEq)]
+struct ExampleProps;
+
+struct Example {
+ props: ExampleProps,
+};
+
+impl Example {
+ fn change(&mut self, props: ExampleProps) -> ShouldRender {
+ if self.props != props {
+ self.props = props;
+ true
+ } else {
+ false
+ }
+ }
+}
+```
+
+But we can go further! This is six lines of boilerplate can be reduced down to one by using a trait
+and a blanket implementation for anything that implements `PartialEq`. Check out the `yewtil`
+crate's `NeqAssign` trait [here](https://docs.rs/yewtil/*/yewtil/trait.NeqAssign.html).
+
+## RC
+
+In an effort to avoid cloning large chunks of data to create props when re-rendering, we can use
+smart pointers to only clone the pointer instead. If you use `Rc<_>`s in your props and child
+components instead of plain unboxed values, you can delay cloning until you need to modify the data
+in the child component, where you use `Rc::make_mut` to clone and get a mutable reference to the
+data you want to alter. By not cloning until mutation, child components can reject props identical
+to their state-owned props in `Component::change` for almost no performance cost, versus the case
+where the data itself needs to be copied into the props struct in the parent before it is compared
+and rejected in the child.
+
+This optimization is most useful for data types that aren't `Copy`. If you can copy your data
+easily, then it probably isn't worth putting it behind a smart pointer. For structures that can
+contain lots of data like `Vec`, `HashMap`, and `String`, this optimization should be worthwhile.
+
+This optimization works best if the values are never updated by the children, and even better, if
+they are rarely updated by parents. This makes `Rc<_>s` a good choice for wrapping property values
+in for pure components.
+
+## View Functions
+
+For code readability reasons, it often makes sense to migrate sections of `html!` to their own
+functions so you can avoid the rightward drift present in deeply nested HTML.
+
+## Pure Components/Function Components
+
+Pure components are components that don't mutate their state, only displaying content and
+propagating messages up to normal, mutable components. They differ from view functions in that they
+can be used from within the `html!` macro using the component syntax \(``\)
+instead of expression syntax \(`{some_view_function()}`\), and that depending on their
+implementation, they can be memoized - preventing re-renders for identical props using the
+aforementioned `neq_assign` logic.
+
+Yew doesn't natively support pure or function components, but they are available via external
+crates.
+
+Function components don't exist yet, but in theory, pure components could be generated by using
+proc macros and annotating functions.
+
+## Keyed DOM nodes when they arrive
+
+## Compile speed optimizations using Cargo Workspaces
+
+Arguably, the largest drawback to using Yew is the long time it takes to compile. Compile time
+seems to correlate with the quantity of code found within `html!` macro blocks. This tends to not
+be a significant problem for smaller projects, but for web apps that span multiple pages, it makes
+sense to break apart your code across multiple crates to minimize the amount of work the compiler
+has to do for each change made.
+
+You should try to make your main crate handle routing/page selection, move all commonly shared code
+to another crate, and then make a different crate for each page, where each page could be a
+different component, or just a big function that produces `Html`. In the best case scenario, you go
+from rebuilding all of your code on each compile to rebuilding only the main crate, and one of your
+page crates. In the worst case, where you edit something in the "common" crate, you will be right
+back to where you started: compiling all code that depends on that commonly shared crate, which is
+probably everything else.
+
+If your main crate is too heavyweight, or you want to rapidly iterate on a deeply nested page \(eg.
+a page that renders on top of another page\), you can use an example crate to create a simpler
+implementation of the main page and render your work-in-progress component on top of that.
+
+## Build size optimization
+
+* optimize Rust code
+ * `wee_aloc` \( using tiny allocator \)
+ * `cargo.toml` \( defining release profile \)
+* optimize wasm code using `wasm-opt`
+
+More information about code size profiling: [rustwasm book](https://rustwasm.github.io/book/reference/code-size.html#optimizing-builds-for-code-size)
+
+### wee\_alloc
+
+[wee\_alloc](https://github.com/rustwasm/wee_alloc) is a tiny allocator that is much smaller than
+the allocator that is normally used in Rust binaries. Replacing the default allocator with this one
+will result in smaller WASM file sizes, at the expense of speed and memory overhead.
+
+The slower speed and memory overhead are minor in comparison to the size gains made by not including
+the default allocator. This smaller file size means that your page will load faster, and so it is
+generally recommended that you use this allocator over the default, unless your app is doing some
+allocation-heavy work.
+
+```rust
+// Use `wee_alloc` as the global allocator.
+#[global_allocator]
+static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
+```
+
+### Cargo.toml
+
+It is possible to setup release build for smaller size using `[profile.release]` section in
+`Cargo.toml`
+
+[Rust profiles documentation](https://doc.rust-lang.org/cargo/reference/profiles.html)
+
+```text
+[profile.release]
+# less code to include into binary
+panic = 'abort'
+# optimization over all codebase ( better optimization, slower build )
+codegen-units = 1
+# optimization for size ( more aggressive )
+opt-level = 'z'
+# optimization for size
+# opt-level = 's'
+# link time optimization using using whole-program analysis
+lto = true
+```
+
+### wasm-opt
+
+Further more it is possible to optimize size of `wasm` code.
+
+wasm-opt info: [binaryen project](https://github.com/WebAssembly/binaryen)
+
+The Rust Wasm book features a section about reducing the size of WASM binaries:
+[Shrinking .wasm size](https://rustwasm.github.io/book/game-of-life/code-size.html)
+
+* using `wasm-pack` which by default optimizes `wasm` code in release builds
+* using `wasm-opt` directly on `wasm` files.
+
+```text
+wasm-opt wasm_bg.wasm -Os -o wasm_bg_opt.wasm
+```
+
+#### Build size of 'minimal' example in yew/examples/
+
+Note: `wasm-pack` combines optimization for Rust and Wasm code. `wasm-bindgen` is used in this
+example without any Rust size optimization.
+
+| used tool | size |
+| :--- | :--- |
+| wasm-bindgen | 158KB |
+| wasm-binggen + wasm-opt -Os | 116KB |
+| wasm-pack | 99 KB |
+
diff --git a/docs/src/concepts/agents.md b/docs/src/concepts/agents.md
new file mode 100644
index 00000000000..c532b16f7dc
--- /dev/null
+++ b/docs/src/concepts/agents.md
@@ -0,0 +1,69 @@
+---
+description: Yew's Actor System
+---
+
+# Agents
+
+Agents are similar to Angular's [Services](https://angular.io/guide/architecture-services)
+\(but without dependency injection\), and provide a Yew with an
+[Actor Model](https://en.wikipedia.org/wiki/Actor_model). Agents can be used to route messages
+between components independently of where they sit in the component hierarchy, or they can be used
+to create a shared state, and they can also be used to offload computationally expensive tasks from
+the main thread which renders the UI. There is also planned support for using agents to allow Yew
+applications to communicate across tabs \(in the future\).
+
+In order for agents to run concurrently, Yew uses
+[web-workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers).
+
+## Lifecycle
+
+
+
+## Types of Agents
+
+#### Reaches
+
+* Context - There will exist at most one instance of a Context Agent at any given time. Bridges will
+
+ spawn or connect to an already spawned agent on the UI thread. This can be used to coordinate state
+
+ between components or other agents. When no bridges are connected to this agent, the agent will
+
+ disappear.
+
+* Job - Spawn a new agent on the UI thread for every new bridge. This is good for moving shared but
+
+ independent behavior that communicates with the browser out of components. \(TODO verify\) When the
+
+ task is done, the agent will disappear.
+
+* Public - Same as Context, but runs on its own web worker.
+* Private - Same as Job, but runs on its own web worker.
+* Global \(WIP\)
+
+## Communication between Agents and Components
+
+### Bridges
+
+A bridge allows bi-directional communication between an agent and a component. Bridges also allow
+agents to communicate with one another.
+
+### Dispatchers
+
+A dispatcher allows uni-directional communication between a component and an agent. A dispatcher
+allows a component to send messages to an agent.
+
+## Overhead
+
+Agents that live in their own separate web worker \(Private and Public\) incur serialization
+overhead on the messages they send and receive. They use [bincode](https://github.com/servo/bincode)
+to communicate with other threads, so the cost is substantially higher than just calling a function.
+Unless the cost of computation will outweigh the cost of message passing, you should contain your
+logic in the UI thread agents \(Job or Context\).
+
+## Further reading
+
+* The [pub\_sub](https://github.com/yewstack/yew/tree/master/examples/pub_sub) example shows how
+
+ components can use agents to communicate with each other.
+
diff --git a/docs/src/concepts/components/README.md b/docs/src/concepts/components/README.md
new file mode 100644
index 00000000000..9e89e38db13
--- /dev/null
+++ b/docs/src/concepts/components/README.md
@@ -0,0 +1,205 @@
+---
+description: Components and their lifecycle hooks
+---
+
+# Components
+
+## What are Components?
+
+Components are the building blocks of Yew. They manage their own state and can render themselves to
+the DOM. Components are created by implementing the `Component` trait which describes the lifecycle
+of a component.
+
+## Lifecycle
+
+{% hint style="info" %}
+`Contribute to our docs:` [Add a diagram of the component lifecycle](https://github.com/yewstack/docs/issues/22)
+{% endhint %}
+
+## Lifecycle Methods
+
+### Create
+
+When a component is created, it receives properties from its parent component as well as a
+`ComponentLink`. The properties can be used to initialize the component's state and the "link" can
+be used to register callbacks or send messages to the component.
+
+It is common to store the props and the link in your component struct, like so:
+
+```rust
+pub struct MyComponent {
+ props: Props,
+ link: ComponentLink,
+}
+
+impl Component for MyComponent {
+ type Properties = Props;
+ // ...
+
+ fn create(props: Self::Properties, link: ComponentLink) -> Self {
+ MyComponent { props, link }
+ }
+
+ // ...
+}
+```
+
+### View
+
+Components declare their layout in the `view()` method. Yew provides the `html!` macro for declaring
+HTML and SVG nodes and their listeners as well as child components. The macro acts a lot like
+React's JSX, but uses Rust expressions instead of JavaScript.
+
+```rust
+impl Component for MyComponent {
+ // ...
+
+ fn view(&self) -> Html {
+ let onclick = self.link.callback(|_| Msg::Click);
+ html! {
+
+ }
+ }
+}
+```
+
+For usage details, check out the `html!` guide:
+
+{% page-ref page="../html/" %}
+
+### Rendered
+
+The `rendered()` component lifecycle method is called after `view()` is processed and Yew has
+rendered your component, but before the browser refreshes the page. A component may wish to
+implement this method to perform actions that can only be done after the component has rendered
+elements. You can check whether this is the first time the component was rendered via the
+`first_render` parameter.
+
+```rust
+use stdweb::web::html_element::InputElement;
+use stdweb::web::IHtmlElement;
+use yew::prelude::*;
+
+pub struct MyComponent {
+ node_ref: NodeRef,
+}
+
+impl Component for MyComponent {
+ // ...
+
+ fn view(&self) -> Html {
+ html! {
+
+ }
+ }
+
+ fn rendered(&mut self, first_render: bool) {
+ if first_render {
+ if let Some(input) = self.node_ref.try_into::() {
+ input.focus();
+ }
+ }
+ }
+}
+```
+
+{% hint style="info" %}
+Note that this lifecycle method does not require an implementation and will do nothing by default
+{% endhint %}
+
+### Update
+
+Components are dynamic and can register to receive asynchronous messages. The `update()` lifecycle
+method is called for each message. This allows the component to update itself based on what the
+message was, and determine if it needs to re-render itself. Messages can be triggered by HTML
+elements listeners or be sent by child components, Agents, Services, or Futures.
+
+Here's an example of what `update()` could look like:
+
+```rust
+pub enum Msg {
+ SetInputEnabled(bool)
+}
+
+impl Component for MyComponent {
+ type Message = Msg;
+
+ // ...
+
+ fn update(&mut self, msg: Self::Message) -> ShouldRender {
+ match msg {
+ Msg::SetInputEnabled(enabled) => {
+ if self.input_enabled != enabled {
+ self.input_enabled = enabled;
+ true // Re-render
+ } else {
+ false
+ }
+ }
+ }
+ }
+}
+```
+
+### Change
+
+Components may be re-rendered by their parents. When this happens, they could receive new properties
+and choose to re-render. This design facilitates parent to child component communication through
+changed properties.
+
+A typical implementation would look like:
+
+```rust
+impl Component for MyComponent {
+ // ...
+
+ fn change(&mut self, props: Self::Properties) -> ShouldRender {
+ if self.props != props {
+ self.props = props;
+ true
+ } else {
+ false
+ }
+ }
+}
+```
+
+### Destroy
+
+After Components are unmounted from the DOM, Yew calls the `destroy()` lifecycle method to support
+any necessary clean up operations. This method is optional and does nothing by default.
+
+## Associated Types
+
+The `Component` trait has two associated types: `Message` and `Properties`.
+
+```rust
+impl Component for MyComponent {
+ type Message = Msg;
+ type Properties = Props;
+
+ // ...
+}
+```
+
+`Message` represents a variety of messages that can be processed by the component to trigger some
+side effect. For example, you may have a `Click` message which triggers an API request or toggles
+the appearance of a UI component. It is common practice to create an enum called `Msg` in your
+component's module and use that as the message type in the component. It is common to shorten
+"message" to "msg".
+
+```rust
+enum Msg {
+ Click,
+}
+```
+
+`Properties` represents the information passed to a component from its parent. This type must
+implements the `Properties` trait \(usually by deriving it\) and can specify whether certain
+properties are required or optional. This type is used when creating and updating a component. It
+is common practice to create a struct called `Props` in your component's module and use that as the
+component's `Properties` type. It is common to shorten "properties" to "props". Since props are
+handed down from parent components, the root component of your application typically has a
+`Properties` type of `()`. If you wish to specify properties for your root component, use the
+`App::mount_with_props` method.
+
diff --git a/docs/src/concepts/components/callbacks.md b/docs/src/concepts/components/callbacks.md
new file mode 100644
index 00000000000..e828dc96d91
--- /dev/null
+++ b/docs/src/concepts/components/callbacks.md
@@ -0,0 +1,41 @@
+---
+description: ComponentLink and Callbacks
+---
+
+# Callbacks
+
+The component "link" is the mechanism through which components are able to register callbacks and
+update themselves.
+
+## ComponentLink API
+
+### callback
+
+Registers a callback that will send a message to the component's update mechanism when it is
+executed. Under the hood, it will call `send_self` with the message that is returned by the
+provided closure. A `Fn(IN) -> Vec` is provided and a `Callback` is returned.
+
+### send\_message
+
+Sends a message to the component immediately after the current loop finishes, causing another
+update loop to initiate.
+
+### send\_message\_batch
+
+Registers a callback that sends a batch of many messages at once when it is executed. If any of the
+messages cause the component to re-render, the component will re-render after all messages in the
+batch have been processed. A `Fn(IN) -> COMP::Message` is provided and a `Callback` is returned.
+
+## Callbacks
+
+_\(This might need its own short page.\)_
+
+Callbacks are used to communicate with services, agents, and parent components within Yew. They are
+just a `Fn` wrapped by an `Rc` to allow them to be cloned.
+
+They have an `emit` function that takes their `` type as an argument and converts that to a
+message expected by its destination. If a callback from a parent is provided in props to a child
+component, the child can call `emit` on the callback in its `update` lifecycle hook to send a
+message back to its parent. Closures or Functions provided as props inside the `html!` macro are
+automatically converted to Callbacks.
+
diff --git a/docs/src/concepts/components/properties.md b/docs/src/concepts/components/properties.md
new file mode 100644
index 00000000000..6c0f49c8ca3
--- /dev/null
+++ b/docs/src/concepts/components/properties.md
@@ -0,0 +1,95 @@
+---
+description: Parent to child communication
+---
+
+# Properties
+
+Properties enable child and parent components to communicate with each other.
+
+## Derive macro
+
+Don't try to implement `Properties` yourself, derive it by using `#[derive(Properties)]` instead.
+
+{% hint style="info" %}
+Types for which you derive `Properties` must also implement `Clone`. This can be done by either
+using `#[derive(Properties, Clone)` or manually implementing `Clone` for your type.
+{% endhint %}
+
+### Required attributes
+
+The fields within a struct that derives `Properties` are required by default. When a field is
+missing and the component is created in the `html!` macro, a compiler error is returned. For fields
+with optional properties, use the `#[prop_or_default]` attribute to use the default value for that
+type when the prop is not specified. To specify a value, use the `#[prop_or(value)]` attribute where
+value is the default value for the property or alternatively use `#[prop_or_else(function)]` where
+`function` returns the default value. For example, to default a boolean value as `true`, use the
+attribute `#[prop_or(true)]`. It is common for optional properties to use the `Option` enum which
+has the default value `None`.
+
+### PartialEq
+
+It is likely to make sense to derive `PartialEq` on your props if you can do this. Using `PartialEq`
+makes it much easier to avoid unnecessary rerendering \(this is explained in the **Optimizations &
+Best Practices** section\).
+
+## Memory/speed overhead of using Properties
+
+In `Component::view`, you take a reference to the component's state, and use that to create `Html`.
+Properties, however, are owned values. This means that in order to create them and pass them to
+child components, we need to take ownership of the references provided in the `view` function. This
+is done by implicitly cloning the references as they are passed to components in order to get owned
+values.
+
+This means that each component has its own distinct copy of the state passed down from its parent,
+and that whenever you re-render a component, the props for all child components of the re-rendering
+component will have to be cloned.
+
+The implication of this is if you would otherwise be passing _huge_ amounts of data down as props
+\(Strings that are 10s of kilobytes in size\), you may want to consider turning your child component
+into a function which returns `Html` that the parent calls, as this means that data does not have to
+be cloned.
+
+If you won't need to modify the data passed down through props you can wrap it in an `Rc` so that
+only a reference-counted pointer to the data is cloned, instead of the actual data itself.
+
+## Example
+
+```rust
+use std::rc::Rc;
+use yew::Properties;
+
+#[derive(Clone, PartialEq)]
+pub enum LinkColor {
+ Blue,
+ Red,
+ Green,
+ Black,
+ Purple,
+}
+
+impl Default for LinkColor {
+ fn default() -> Self {
+ // The link color will be blue unless otherwise specified.
+ LinkColor::Blue
+ }
+}
+
+#[derive(Properties, Clone, PartialEq)]
+pub struct LinkProps {
+ /// The link must have a target.
+ href: String,
+ /// If the link text is huge, this will make copying the string much cheaper.
+ /// This isn't usually recommended unless performance is known to be a problem.
+ text: Rc,
+ /// Color of the link.
+ #[prop_or_default]
+ color: LinkColor,
+ /// The view function will not specify a size if this is None.
+ #[prop_or_default]
+ size: Option,
+ /// When the view function doesn't specify active, it defaults to true.
+ #[prop_or(true)]
+ active: bool,
+}
+```
+
diff --git a/docs/src/concepts/components/refs.md b/docs/src/concepts/components/refs.md
new file mode 100644
index 00000000000..361da95681d
--- /dev/null
+++ b/docs/src/concepts/components/refs.md
@@ -0,0 +1,29 @@
+---
+description: Out-of-band DOM access
+---
+
+# Refs
+
+## Refs
+
+The `ref` keyword can be used inside of any HTML element or component to get the DOM `Element` that
+the item is attached to. This can be used to make changes to the DOM outside of the `view` lifecycle
+method.
+
+This is useful for getting ahold of canvas elements, or scrolling to different sections of a page.
+
+The syntax is:
+
+```rust
+// In create
+self.node_ref = NodeRef::default();
+
+// In view
+html! {
+
+}
+
+// In update
+let has_attributes = self.node_ref.try_into::().has_attributes();
+```
+
diff --git a/docs/src/concepts/html/README.md b/docs/src/concepts/html/README.md
new file mode 100644
index 00000000000..612fa8b2403
--- /dev/null
+++ b/docs/src/concepts/html/README.md
@@ -0,0 +1,37 @@
+---
+description: The procedural macro for generating HTML and SVG
+---
+
+# Using html!
+
+The `html!` macro allows you to write HTML and SVG code declaratively. It is similar to JSX
+\(a Javascript extension which allows you to write HTML-like code inside of Javascript\).
+
+**Important notes**
+
+1. The `html!` macro only accepts one root html node \(you can counteract this by
+
+ [using fragments or iterators](lists.md)\)
+
+2. An empty `html! {}` invocation is valid and will not render anything
+3. Literals must always be quoted and wrapped in braces: `html! { "Hello, World" }`
+
+{% hint style="info" %}
+The `html!` macro can reach easily the default recursion limit of the compiler. It is advised to
+bump its value if you encounter compilation errors. Use an attribute like
+`#![recursion_limit="1024"]` in the crate root \(i.e. either `lib.rs` or `main.rs`\) to overcome
+the problem. See the
+[official documentation](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute)
+and
+[this Stack Overflow question](https://stackoverflow.com/questions/27454761/what-is-a-crate-attribute-and-where-do-i-add-it)
+for details.
+{% endhint %}
+
+{% page-ref page="lists.md" %}
+
+{% page-ref page="elements.md" %}
+
+{% page-ref page="literals-and-expressions.md" %}
+
+{% page-ref page="components.md" %}
+
diff --git a/docs/src/concepts/html/components.md b/docs/src/concepts/html/components.md
new file mode 100644
index 00000000000..5a456bd5909
--- /dev/null
+++ b/docs/src/concepts/html/components.md
@@ -0,0 +1,115 @@
+---
+description: Create complex layouts with component hierarchies
+---
+
+# Components
+
+## Basic
+
+Any type that implements `Component` can be used in the `html!` macro:
+
+```rust
+html!{
+ <>
+ // No properties
+
+
+ // With Properties
+
+
+ // With the whole set of props provided at once
+
+ >
+}
+```
+
+## Nested
+
+Components can be passed children if they have a `children` field in their `Properties`.
+
+{% code title="parent.rs" %}
+```rust
+html! {
+
+
+ }
+ }
+}
+```
+{% endcode %}
+
+{% hint style="info" %}
+Types for which you derive `Properties` must also implement `Clone`. This can be done by either
+using `#[derive(Properties, Clone)]` or manually implementing `Clone` for your type.
+{% endhint %}
+
+## Nested Children with Props
+
+Nested component properties can be accessed and mutated if the containing component types its
+children. In the following example, the `List` component can wrap `ListItem` components. For a
+real world example of this pattern, check out the `yew-router` source code. For a more advanced
+example, check out the `nested-list` example in the main yew repository.
+
+{% code title="parent.rs" %}
+```rust
+html! {
+
+
+
+
+
+}
+```
+{% endcode %}
+
+{% code title="list.rs" %}
+```rust
+pub struct List(Props);
+
+#[derive(Properties, Clone)]
+pub struct Props {
+ pub children: ChildrenWithProps,
+}
+
+impl Component for List {
+ type Properties = Props;
+
+ // ...
+
+ fn view(&self) -> Html {
+ html!{{
+ for self.0.children.iter().map(|mut item| {
+ item.props.value = format!("item-{}", item.props.value);
+ item
+ })
+ }}
+ }
+}
+```
+{% endcode %}
+
diff --git a/docs/src/concepts/html/elements.md b/docs/src/concepts/html/elements.md
new file mode 100644
index 00000000000..07396d8ed30
--- /dev/null
+++ b/docs/src/concepts/html/elements.md
@@ -0,0 +1,262 @@
+---
+description: Both HTML and SVG elements are supported
+---
+
+# Elements
+
+## Tag Structure
+
+Element tags must either self-close `<... />` or have a corresponding close tag for each open tag
+
+{% tabs %}
+{% tab title="Open - Close" %}
+```rust
+html! {
+
+}
+```
+{% endtab %}
+
+{% tab title="INVALID" %}
+```rust
+html! {
+
// <- MISSING CLOSE TAG
+}
+```
+{% endtab %}
+
+{% tab title="Self-Closing" %}
+```rust
+html! {
+
+}
+```
+{% endtab %}
+
+{% tab title="INVALID" %}
+```rust
+html! {
+ // <- MISSING SELF-CLOSE
+}
+```
+{% endtab %}
+{% endtabs %}
+
+{% hint style="info" %}
+For convenience, elements which _usually_ require a closing tag are **allowed** to self-close. For example, writing `html! { }` is valid.
+{% endhint %}
+
+## Children
+
+Create complex nested HTML and SVG layouts with ease:
+
+{% tabs %}
+{% tab title="HTML" %}
+```rust
+html! {
+
+
+
+
+
+
+
+
+
+
+
+}
+```
+{% endtab %}
+
+{% tab title="SVG" %}
+```rust
+html! {
+
+}
+```
+{% endtab %}
+{% endtabs %}
+
+## Classes
+
+There are a number of convenient options for specifying classes for an element:
+
+{% tabs %}
+{% tab title="Literal" %}
+```rust
+html! {
+
+}
+```
+{% endtab %}
+
+{% tab title="Multiple" %}
+```rust
+html! {
+
+}
+```
+{% endtab %}
+
+{% tab title="Interpolated" %}
+```rust
+html! {
+
+}
+```
+{% endtab %}
+
+{% tab title="Expression" %}
+```rust
+html! {
+
+}
+```
+{% endtab %}
+
+{% tab title="Tuple" %}
+```rust
+html! {
+
+}
+```
+{% endtab %}
+
+{% tab title="Vector" %}
+```rust
+html! {
+
+}
+```
+{% endtab %}
+{% endtabs %}
+
+## Listeners
+
+Listener attributes need to be passed a `Callback` which is a wrapper around a closure. How you
+create your callback depends on how you wish your app to react to a listener event:
+
+{% tabs %}
+{% tab title="Component Handler" %}
+```rust
+struct MyComponent {
+ link: ComponentLink,
+}
+
+enum Msg {
+ Click,
+}
+
+impl Component for MyComponent {
+ type Message = Msg;
+ type Properties = ();
+
+ fn create(_: Self::Properties, link: ComponentLink) -> Self {
+ MyComponent { link }
+ }
+
+ fn update(&mut self, msg: Self::Message) -> ShouldRender {
+ match msg {
+ Msg::Click => {
+ // Handle Click
+ }
+ }
+ }
+
+ fn view(&self) -> Html {
+ // Create a callback from a component link to handle it in a component
+ let click_callback = self.link.callback(|_: ClickEvent| Msg::Click);
+ html! {
+
+ }
+ }
+}
+```
+{% endtab %}
+
+{% tab title="Agent Handler" %}
+```rust
+struct MyComponent {
+ worker: Dispatcher,
+}
+
+impl Component for MyComponent {
+ type Message = ();
+ type Properties = ();
+
+ fn create(_: Self::Properties, _: ComponentLink) -> Self {
+ MyComponent {
+ worker: MyWorker::dispatcher()
+ }
+ }
+
+ fn update(&mut self, _: Self::Message) -> ShouldRender {
+ false
+ }
+
+ fn view(&self) -> Html {
+ // Create a callback from a worker to handle it in another context
+ let click_callback = self.worker.callback(|_: ClickEvent| WorkerMsg::Process);
+ html! {
+
+ }
+ }
+}
+```
+{% endtab %}
+
+{% tab title="Other Cases" %}
+```rust
+struct MyComponent;
+
+impl Component for MyComponent {
+ type Message = ();
+ type Properties = ();
+
+ fn create(_: Self::Properties, _: ComponentLink) -> Self {
+ MyComponent
+ }
+
+ fn update(&mut self, _: Self::Message) -> ShouldRender {
+ false
+ }
+
+ fn view(&self) -> Html {
+ // Create an ephemeral callback
+ let click_callback = Callback::from(|| {
+ ConsoleService::new().log("clicked!");
+ });
+
+ html! {
+
+ }
+ }
+}
+```
+{% endtab %}
+{% endtabs %}
+
diff --git a/docs/src/concepts/html/lists.md b/docs/src/concepts/html/lists.md
new file mode 100644
index 00000000000..f324d23d6fd
--- /dev/null
+++ b/docs/src/concepts/html/lists.md
@@ -0,0 +1,57 @@
+# Lists
+
+## Fragments
+
+The `html!` macro always requires a single root node. In order to get around this restriction, it's
+valid to wrap content in empty tags:
+
+{% tabs %}
+{% tab title="Valid" %}
+```rust
+html! {
+ <>
+
+
+ >
+}
+```
+{% endtab %}
+
+{% tab title="Invalid" %}
+```rust
+/* error: only one root html element allowed */
+
+html! {
+
+
+}
+```
+{% endtab %}
+{% endtabs %}
+
+## Iterators
+
+Yew supports two different syntaxes for building html from an iterator:
+
+{% tabs %}
+{% tab title="Syntax Type 1" %}
+```rust
+html! {
+
+ { for self.props.items.iter().map(renderItem) }
+
+}
+```
+{% endtab %}
+{% endtabs %}
+
diff --git a/docs/src/concepts/html/literals-and-expressions.md b/docs/src/concepts/html/literals-and-expressions.md
new file mode 100644
index 00000000000..bb40a71c468
--- /dev/null
+++ b/docs/src/concepts/html/literals-and-expressions.md
@@ -0,0 +1,61 @@
+# Literals & Expressions
+
+## Literals
+
+If expressions resolve to types that implement `Display`, they will be converted to strings and
+inserted into the DOM as a [Text](https://developer.mozilla.org/en-US/docs/Web/API/Text) node.
+
+All display text must be enclosed by `{}` blocks because text is handled like an expression. This is
+the largest deviation from normal HTML syntax that Yew makes.
+
+```rust
+let text = "lorem ipsum";
+html!{
+ <>
+
{text}
+
{"dolor sit"}
+ {42}
+ >
+}
+```
+
+## Expressions
+
+You can insert expressions in your HTML using `{}` blocks, as long as they resolve to `Html`
+
+```rust
+html! {
+
+}
+```
+
+It often makes sense to extract these expressions into functions or closures to optimize for
+readability:
+
+```rust
+let show_link = true;
+let maybe_display_link = move || -> Html {
+ if show_link {
+ html! {
+ {"Link"}
+ }
+ } else {
+ html! {}
+ }
+};
+
+html! {
+
{maybe_display_link()}
+}
+```
+
diff --git a/docs/src/concepts/router.md b/docs/src/concepts/router.md
new file mode 100644
index 00000000000..6200e4cfc00
--- /dev/null
+++ b/docs/src/concepts/router.md
@@ -0,0 +1,103 @@
+---
+description: Yew's official router
+---
+
+# Router
+
+[https://crates.io/crates/yew-router](https://crates.io/crates/yew-router)
+
+Routers in Single Page Applications \(SPA\) handle displaying different pages depending on what the
+URL is. Instead of the default behavior of requesting a different remote resource when a link is
+clicked, the router instead sets the URL locally to point to a valid route in your application. The
+router then detects this change and then decides what to render.
+
+## Core Elements
+
+### Route
+
+Contains a String representing everything after the domain in the url and optionally the state
+stored in the history API.
+
+### RouteService
+
+Communicates with the browser to get and set Routes.
+
+### RouteAgent
+
+Owns a RouteService and is used to coordinate updates when the route changes, either from within
+the application logic or from an event fired from the browser.
+
+### Switch
+
+The `Switch` trait is used to convert a `Route` to and from the implementer of this trait.
+
+### Router
+
+The Router component communicates with `RouteAgent` and will automatically resolve Routes it gets
+from the agent into switches, which it will expose via a `render` prop that allows specifying how
+the resulting switch gets converted to `Html`.
+
+## How to use the Router
+
+First, you want to create a type that represents all the states of your application. Do note that
+while this typically is an enum, structs are supported as well, and that you can nest other items
+that implement `Switch` inside.
+
+Then you should derive `Switch` for your type. For enums, every variant must be annotated with
+`#[to = "/some/route"]`, or if you use a struct instead, that must appear outside the struct
+declaration.
+
+```rust
+#[derive(Switch)]
+enum AppRoute {
+ #[to="/login"]
+ Login,
+ #[to="/register"]
+ Register,
+ #[to="/delete_account"]
+ Delete,
+ #[to="/posts/{id}"]
+ ViewPost(i32),
+ #[to="/posts/view"]
+ ViewPosts,
+ #[to="/"]
+ Home
+}
+```
+
+Do note that the implementation generated by the derive macro for `Switch` will try to match each
+variant in order from first to last, so if any route could possibly match two of your specified
+`to` annotations, then the first one will match, and the second will never be tried. For example,
+if you defined the following `Switch`, the only route that would be matched would be `AppRoute::Home`.
+
+```rust
+#[derive(Switch)]
+enum AppRoute {
+ #[to="/"]
+ Home,
+ #[to="/login"]
+ Login,
+ #[to="/register"]
+ Register,
+ #[to="/delete_account"]
+ Delete,
+ #[to="/posts/{id}"]
+ ViewPost(i32),
+ #[to="/posts/view"]
+ ViewPosts,
+}
+```
+
+You can also capture sections using variations of `{}` within your `#[to = ""]` annotation.
+`{}` means capture text until the next separator \(either "/", "?", "&", or "\#" depending on the
+context\). `{*}` means capture text until the following characters match, or if no characters are
+present, it will match anything. `{}` means capture text until the specified number of
+separators are encountered \(example: `{2}` will capture until two separators are encountered\).
+
+For structs and enums with named fields, you must specify the field's name within the capture group
+like so: `{user_name}` or `{*:age}`.
+
+The Switch trait works with capture groups that are more structured than just Strings. You can
+specify any type that implements `Switch`. So you can specify that the capture group is a `usize`,
+and if the captured section of the URL can't be converted to it, then the variant won't match.
+
diff --git a/docs/src/concepts/services/README.md b/docs/src/concepts/services/README.md
new file mode 100644
index 00000000000..79111fffa07
--- /dev/null
+++ b/docs/src/concepts/services/README.md
@@ -0,0 +1,6 @@
+---
+description: Yew's glue to browser APIs
+---
+
+# Services
+
diff --git a/docs/src/concepts/services/format.md b/docs/src/concepts/services/format.md
new file mode 100644
index 00000000000..2a949fcf19a
--- /dev/null
+++ b/docs/src/concepts/services/format.md
@@ -0,0 +1,6 @@
+# Format
+
+{% hint style="info" %}
+`Contribute to our docs:` [Explain the format module in depth](https://github.com/yewstack/docs/issues/24)
+{% endhint %}
+
diff --git a/docs/src/getting-started/build-a-sample-app.md b/docs/src/getting-started/build-a-sample-app.md
new file mode 100644
index 00000000000..296fdddf109
--- /dev/null
+++ b/docs/src/getting-started/build-a-sample-app.md
@@ -0,0 +1,135 @@
+# Build a Sample App
+
+First create a new Rust library \(**important:** create a _library_, not a _binary_ by passing the
+`--lib` flag\):
+
+```bash
+cargo new --lib yew-app && cd yew-app
+```
+
+Add `yew` and `wasm-bindgen` to your dependencies \(refer [here](https://docs.rs/yew) for the latest
+version\)
+
+{% code title="Cargo.toml" %}
+```text
+[package]
+name = "yew-app"
+version = "0.1.0"
+authors = ["Yew App Developer "]
+edition = "2018"
+
+[lib]
+crate-type = ["cdylib", "rlib"]
+
+[dependencies]
+yew = "0.17"
+wasm-bindgen = "0.2"
+```
+{% endcode %}
+
+Copy the following template into your `src/lib.rs` file:
+
+{% code title="src/lib.rs" %}
+```rust
+use wasm_bindgen::prelude::*;
+use yew::prelude::*;
+
+struct Model {
+ link: ComponentLink,
+ value: i64,
+}
+
+enum Msg {
+ AddOne,
+}
+
+impl Component for Model {
+ type Message = Msg;
+ type Properties = ();
+ fn create(_: Self::Properties, link: ComponentLink) -> Self {
+ Self {
+ link,
+ value: 0,
+ }
+ }
+
+ fn update(&mut self, msg: Self::Message) -> ShouldRender {
+ match msg {
+ Msg::AddOne => self.value += 1
+ }
+ true
+ }
+
+ fn change(&mut self, _props: Self::Properties) -> ShouldRender {
+ // Should only return "true" if new properties are different to
+ // previously received properties.
+ // This component has no properties so we will always return "false".
+ false
+ }
+
+ fn view(&self) -> Html {
+ html! {
+
+
+
{ self.value }
+
+ }
+ }
+}
+
+#[wasm_bindgen(start)]
+pub fn run_app() {
+ App::::new().mount_to_body();
+}
+```
+{% endcode %}
+
+This template sets up your root `Component`, called `Model` which shows a button that updates
+itself when you click it. Take special note of `App::::new().mount_to_body()` inside
+`main()` which starts your app and mounts it to the page's `` tag. If you would like to start
+your application with any dynamic properties, you can instead use
+`App::::new().mount_to_body_with_props(..)`.
+
+Finally, add an `index.html` file into a new folder named `static` in your app.
+
+```bash
+mkdir static
+```
+
+{% code title="index.html" %}
+```markup
+
+
+
+
+ Yew Sample App
+
+
+
+
+```
+{% endcode %}
+
+## Run your App!
+
+Using [`wasm-pack`](https://rustwasm.github.io/docs/wasm-pack/) is the preferred way to get up and
+running. If you haven't already, install `wasm-pack` with `cargo install wasm-pack` and then build
+and start a development server by running:
+
+```bash
+wasm-pack build --target web --out-name wasm --out-dir ./static
+```
+
+`wasm-pack` generates a bundle in the `./static` directory with your app's compiled WebAssembly
+along with a JavaScript wrapper which will load your application's WebAssembly binary and run it.
+
+Then, use your favorite web server to server the files under `./static`. For example:
+
+```bash
+cargo +nightly install miniserve
+miniserve ./static --index index.html
+```
+
diff --git a/docs/src/getting-started/choose-web-library.md b/docs/src/getting-started/choose-web-library.md
new file mode 100644
index 00000000000..564c648e0a8
--- /dev/null
+++ b/docs/src/getting-started/choose-web-library.md
@@ -0,0 +1,125 @@
+# Choose web-sys or stdweb
+
+## Introduction
+
+Yew apps can be built with either [`web-sys`](https://docs.rs/web-sys) or
+[`stdweb`](https://docs.rs/stdweb). These two crates provide the bindings between Rust and Web APIs.
+You'll need to choose one or the other when adding `yew` to your cargo dependencies:
+
+{% code title="Cargo.toml" %}
+```rust
+# Choose `web-sys`
+yew = "0.17"
+
+# Choose `stdweb`
+yew = { version = "0.17", package = "yew-stdweb" }
+```
+{% endcode %}
+
+We recommend using `web-sys` due to its support from the
+[Rust / Wasm Working Group](https://rustwasm.github.io/).
+
+## Example Usage
+
+```rust
+// web-sys
+let window: web_sys::Window = web_sys::window().expect("window not available");
+window.alert_with_message("hello from wasm!").expect("alert failed");
+
+// stdweb
+let window: stdweb::web::Window = stdweb::web::window();
+window.alert("hello from wasm!");
+
+// stdweb with js! macro
+use stdweb::js;
+use stdweb::unstable::TryFrom;
+use stdweb::web::Window;
+
+let window_val: stdweb::Value = js!{ return window; }; // <- JS syntax inside!
+let window = Window::try_from(window_val).expect("conversion to window failed");
+window.alert("hello from wasm!");
+```
+
+The APIs for the two crates differ slightly but they serve roughly the same purpose with similar
+functionality.
+
+## Choosing One
+
+There are a few different angles to consider when choosing between using `web-sys` and `stdweb` for
+your app. Note that it's possible to use both in one app, but to minimize the binary size of your
+compiled crate it's best to use only one of the two.
+
+
Rust APIs are auto-generated from the Web IDL spec
+
Browser APIs are added as needed by the community
+
+
+
Rust API Design
+
Takes conservative approach by returning Result for most API
+ calls
+
Often avoids Result in favor of panics. For instance, stdweb::web::window() will
+ panic when called in a worker
+
+
+
Supported Build Tools
+
+
+
+
wasm-bindgen
+
+
wasm-pack
+
+
+
+
+
+
+
cargo-web
+
+
wasm-bindgen
+
+
wasm-pack
+
+
+
+
+
+
Supported Targets
+
+
+
wasm32-unknown-unknown
+
+
+
+
+
+
wasm32-unknown-unknown
+
+
wasm32-unknown-emscripten
+
+
asmjs-unknown-emscripten
+
+
+
+
+
+
+
diff --git a/docs/src/getting-started/examples.md b/docs/src/getting-started/examples.md
new file mode 100644
index 00000000000..86e5f1df167
--- /dev/null
+++ b/docs/src/getting-started/examples.md
@@ -0,0 +1,13 @@
+# Learn through examples
+
+The Yew repository is chock-full of [examples](https://github.com/yewstack/yew/tree/v0.17/examples)
+\(in various states of maintenance\). We recommend perusing them to get a feel for how to use
+different framework features. We also welcome Pull Requests and issues for when they inevitably
+get neglected and need some ♥️
+
+* [**Todo App** ](https://github.com/yewstack/yew/tree/v0.17/examples/todomvc)
+* [**Custom Components**](https://github.com/yewstack/yew/tree/v0.17/examples/custom_components)
+* [**Multi-threading \(Agents\)**](https://github.com/yewstack/yew/tree/v0.17/examples/multi_thread)
+* [**Timer Service**](https://github.com/yewstack/yew/tree/v0.17/examples/timer)
+* [**Nested Components**](https://github.com/yewstack/yew/tree/v0.16.0/examples/nested_list)
+
diff --git a/docs/src/getting-started/project-setup/README.md b/docs/src/getting-started/project-setup/README.md
new file mode 100644
index 00000000000..594b334eb6f
--- /dev/null
+++ b/docs/src/getting-started/project-setup/README.md
@@ -0,0 +1,135 @@
+---
+description: Set yourself up for success
+---
+
+# Project Setup
+
+## Rust
+
+First, you'll need Rust. To install Rust and the `cargo` build tool, follow the [official instructions](https://www.rust-lang.org/tools/install).
+
+## **Wasm Build Tools**
+
+Extra tooling is needed to facilitate the interop between WebAssembly and JavaScript. Additionally, depending on the tool you choose, they can help make deployment and packaging much less of a headache by generating all of the wrapper JavaScript code necessary to run the `.wasm` file from your app in the browser.
+
+### [**`wasm-pack`**](https://rustwasm.github.io/docs/wasm-pack/)
+
+A CLI tool developed by the Rust / Wasm Working Group for packaging up WebAssembly. Best used together with the [`wasm-pack-plugin`](https://github.com/wasm-tool/wasm-pack-plugin) for Webpack.
+
+{% page-ref page="using-wasm-pack.md" %}
+
+### [**`wasm-bindgen`**](https://rustwasm.github.io/docs/wasm-bindgen/)
+
+Both a library and CLI tool and is also developed by the Rust / Wasm Working Group. It is a low level tool \(used internally by `wasm-pack`\) which facilitates JS / WebAssembly interoperability. We don't recommend using `wasm-bindgen`directly because it requires hand-writing some JavaScript to bootstrap your WebAssembly binary. However, it is possible and more info can be found on the [**`wasm-bindgen` guide**](https://rustwasm.github.io/docs/wasm-bindgen/).
+
+{% page-ref page="using-wasm-bindgen.md" %}
+
+### [**`cargo-web`**](https://github.com/koute/cargo-web)
+
+The preferred web workflow tool before the introduction of `wasm-pack` and `wasm-bindgen`. It is still the **quickest** way to get up and running and worth installing to run examples that haven't been migrated to support `wasm-pack` yet.
+
+{% page-ref page="using-cargo-web.md" %}
+
+### Comparison
+
+
+
diff --git a/docs/src/getting-started/project-setup/using-cargo-web.md b/docs/src/getting-started/project-setup/using-cargo-web.md
new file mode 100644
index 00000000000..36a2b343a01
--- /dev/null
+++ b/docs/src/getting-started/project-setup/using-cargo-web.md
@@ -0,0 +1,32 @@
+# Using cargo-web
+
+Cargo web is a cargo subcommand for building client web apps. It makes building and deploying web applications incredibly easy. It is also the only toolchain that supports Emscripten targets. Read more [here](https://github.com/koute/cargo-web).
+
+**Install**
+
+```bash
+cargo install cargo-web
+```
+
+## Build
+
+```bash
+cargo web build
+```
+
+## Run
+
+```bash
+cargo web start
+```
+
+## Supported Targets
+
+* `wasm32-unknown-unknown`
+* `wasm32-unknown-emscripten`
+* `asmjs-unknown-emscripten`
+
+{% hint style="info" %}
+For `*-emscripten` targets, you'll need to install the Emscripten SDK
+{% endhint %}
+
diff --git a/docs/src/getting-started/project-setup/using-wasm-bindgen.md b/docs/src/getting-started/project-setup/using-wasm-bindgen.md
new file mode 100644
index 00000000000..6faeb13786d
--- /dev/null
+++ b/docs/src/getting-started/project-setup/using-wasm-bindgen.md
@@ -0,0 +1,6 @@
+# Using wasm-bindgen
+
+{% hint style="info" %}
+`Contribute to our docs:` [Explain how to use wasm-bindgen to build an app](https://github.com/yewstack/docs/issues/34)
+{% endhint %}
+
diff --git a/docs/src/getting-started/project-setup/using-wasm-pack.md b/docs/src/getting-started/project-setup/using-wasm-pack.md
new file mode 100644
index 00000000000..d2b8630980f
--- /dev/null
+++ b/docs/src/getting-started/project-setup/using-wasm-pack.md
@@ -0,0 +1,42 @@
+# Using wasm-pack
+
+This tool was created by the Rust / Wasm Working Group and is the most actively developed tool for building WebAssembly applications. It supports packaging code into `npm` modules and has an accompanying [Webpack plugin](https://github.com/wasm-tool/wasm-pack-plugin) for easy integration with an existing JavaScript application. More information is given in [the `wasm-pack` documentation](https://rustwasm.github.io/docs/wasm-pack/introduction.html).
+
+{% hint style="info" %}
+Note that the crate-type in your `Cargo.toml` will need to be `cdylib` when using `wasm-pack`
+{% endhint %}
+
+## Install
+
+```bash
+cargo install wasm-pack
+```
+
+## Build
+
+This command will produce a bundle in the `./pkg` directory with your app's compiled WebAssembly along with a JavaScript wrapper which can be used to start your application.
+
+```bash
+wasm-pack build --target web
+```
+
+## Bundle
+
+For more information on Rollup visit this [guide](https://rollupjs.org/guide/en/#quick-start)
+
+```bash
+rollup ./main.js --format iife --file ./pkg/bundle.js
+```
+
+## Serve
+
+Feel free to use your preferred server. Here we use a simple python server to serve to
+
+```bash
+python -m http.server 8000
+```
+
+## Supported Targets
+
+* `wasm32-unknown-unknown`
+
diff --git a/docs/src/getting-started/starter-templates.md b/docs/src/getting-started/starter-templates.md
new file mode 100644
index 00000000000..b377240d1d2
--- /dev/null
+++ b/docs/src/getting-started/starter-templates.md
@@ -0,0 +1,45 @@
+# Starter Templates
+
+## `wasm-pack`
+
+* [Minimal Template](https://github.com/yewstack/yew-wasm-pack-minimal) - Uses `wasm-pack` and
+
+ `rollup` to build your application, and your own server to serve it. No bells or whistles here.
+
+* [Webpack Template](https://github.com/yewstack/yew-wasm-pack-template) - Uses `wasm-pack` and the
+
+ [`wasm-pack-plugin`](https://github.com/wasm-tool/wasm-pack-plugin) for Webpack to streamline
+ development.
+
+The important distinction between these templates and using `cargo-web` is that this approach uses
+a `lib`, not a `bin` crate, and the entry-point to your program is annotated with a `#[wasm_bindgen]`
+annotation.
+
+Your `Cargo.toml` also should specify that your crate's type is a "cdylib".
+
+{% code title="Cargo.toml" %}
+```text
+[package]
+name = "yew-app"
+version = "0.1.0"
+authors = ["Yew App Developer "]
+edition = "2018"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+# for web_sys
+yew = "0.17"
+# or for stdweb
+# yew = { version = "0.17", package = "yew-stdweb" }
+wasm-bindgen = "0.2"
+```
+{% endcode %}
+
+## Other templates
+
+* [Parcel Template](https://github.com/spielrs/yew-parcel-template) - Created by a community member
+
+ and uses [Parcel](https://parceljs.org/)
+
diff --git a/docs/src/lib.rs b/docs/src/lib.rs
new file mode 100644
index 00000000000..69b0734640b
--- /dev/null
+++ b/docs/src/lib.rs
@@ -0,0 +1,20 @@
+use doc_comment::{doc_comment, doctest};
+use wasm_bindgen_test::*;
+
+#[wasm_bindgen_test]
+fn test_sample_app() {
+ doc_comment!(include_str!(concat!(
+ env!("OUT_DIR"),
+ "/getting-started/build-a-sample-app.md"
+ )));
+}
+
+#[wasm_bindgen_test]
+fn test_optimizations() {
+ doctest!("advanced-topics/optimizations.md");
+}
+
+#[wasm_bindgen_test]
+fn test_properties() {
+ doctest!("concepts/components/properties.md");
+}
diff --git a/docs/src/more/css.md b/docs/src/more/css.md
new file mode 100644
index 00000000000..cd2f0151e0a
--- /dev/null
+++ b/docs/src/more/css.md
@@ -0,0 +1,7 @@
+# CSS
+
+<TODO>
+
+A proposal for integrated CSS support can be found here:
+[https://github.com/yewstack/yew/issues/533](https://github.com/yewstack/yew/issues/533)
+
diff --git a/docs/src/more/debugging.md b/docs/src/more/debugging.md
new file mode 100644
index 00000000000..602cfcbdc0f
--- /dev/null
+++ b/docs/src/more/debugging.md
@@ -0,0 +1,62 @@
+# Debugging
+
+## Panics
+
+Please use the [`console_error_panic`](https://github.com/rustwasm/console_error_panic_hook) crate
+for nicer stacktraces with Rust symbols. Note, that it is not compatible with apps built with
+`cargo-web`.
+
+## Console Logging
+
+In general, Wasm web apps are able to interact with Browser APIs, and the `console.log` api is no
+exception. There are a few options available:
+
+### [`wasm-logger`](https://crates.io/crates/wasm-logger)
+
+This crate integrates with the familiar Rust `log` crate:
+
+```rust
+// setup
+fn main() {
+ wasm_logger::init(wasm_logger::Config::default());
+}
+
+// usage
+log::info!("Update: {:?}", msg);
+```
+
+### [`ConsoleService`](https://docs.rs/yew/latest/yew/services/console/struct.ConsoleService.html)
+
+This service is included within yew and is available when the `"services"` feature is enabled:
+
+```rust
+// usage
+ConsoleService::new()::info(format!("Update: {:?}", msg));
+```
+
+## Source Maps
+
+There is currently no first-class support for source maps for Rust / Wasm web apps. This, of course,
+is subject to change. If this is no longer true or if progress is made, please suggest a change!
+
+### Latest Info
+
+\[Dec 2019\] [Chrome DevTools update](https://developers.google.com/web/updates/2019/12/webassembly#the_future)
+
+> There is still quite a bit of work to do though. For example, on the tooling side, Emscripten
+>\(Binaryen\) and wasm-pack \(wasm-bindgen\) don’t support updating DWARF information on
+>transformations they perform yet.
+
+\[2020\] [Rust Wasm debugging guide](https://rustwasm.github.io/book/reference/debugging.html#using-a-debugger)
+
+> Unfortunately, the debugging story for WebAssembly is still immature. On most Unix systems,
+>[DWARF](http://dwarfstd.org/) is used to encode the information that a debugger needs to provide
+>source-level inspection of a running program. There is an alternative format that encodes similar
+>information on Windows. Currently, there is no equivalent for WebAssembly.
+
+\[2019\] [Rust Wasm roadmap](https://rustwasm.github.io/rfcs/007-2019-roadmap.html#debugging)
+
+> Debugging is tricky because much of the story is out of this working group's hands, and depends
+>on both the WebAssembly standardization bodies and the folks implementing browser developer tools
+>instead.
+
diff --git a/docs/src/more/external-libs.md b/docs/src/more/external-libs.md
new file mode 100644
index 00000000000..c56d67b42ce
--- /dev/null
+++ b/docs/src/more/external-libs.md
@@ -0,0 +1,39 @@
+---
+description: Libraries that can help with yew development
+---
+
+# External Libs
+
+### Yewtil
+
+Yewtil is a collection of common utilities that help you write Yew programs. It includes:
+
+* NeqAssign - As discussed earlier, is the best way to assign props to ensure minimal re-rendering.
+* PureComponents - Components that don't update any of their state. Using NeqAssign under the hood,
+they act as memoized
+
+ functions that are called from inside the `html!` macro like normal components are.
+
+* Lrc - linked list reference counted smart pointer functions like `Rc` does, but allows for novel
+data update patterns.
+* Mrc/Irc - Mutable/Immutable reference counted smart pointers that function like `Rc` but are more
+ergonomic to use
+
+ within Yew, due to implementing `DerefMut` and `BorrowMut`for `Mrc`. This allows `Mrc` to be used
+ with `NeqAssign`.
+
+ `Irc` acts as an immutable view into the data, which makes this ideal for holding data used in
+ display-only tasks.
+
+* History - A history tracking wrapper that uses a `VecDeque` to hold on to previous values that it
+has represented.
+* Futures - Support for running futures that send messages to component update loops.
+* Fetch - Abstractions for handling fetch requests made using `web_sys` and the aforementioned
+futures feature.
+
+## Looking For
+
+Libraries that the ecosystem needs, but doesn't have yet.
+
+Bootstrap/MaterialUi/arbitrary css framework component wrappers.
+
diff --git a/docs/src/more/roadmap.md b/docs/src/more/roadmap.md
new file mode 100644
index 00000000000..ae5a40bc14f
--- /dev/null
+++ b/docs/src/more/roadmap.md
@@ -0,0 +1,49 @@
+---
+description: The planned feature roadmap for the Yew framework
+---
+
+# Roadmap
+
+## Prioritization
+
+The prioritization of upcoming features and focuses of the framework are determined by the
+community. In Spring 2020, a developer survey was sent out to collect feedback on the direction of
+the project. You can find the summary in the
+[Yew Wiki](https://github.com/yewstack/yew/wiki/Dev-Survey-%5BSpring-2020%5D).
+
+{% hint style="info" %}
+Status of all major initiatives can be tracked on the Yew Github
+[Project board](https://github.com/yewstack/yew/projects)
+{% endhint %}
+
+## Focuses
+
+1. Top Requested Features
+2. Production Readiness
+3. Documentation
+4. Pain Points
+
+### Top Requested Features
+
+1. [Functional Components](https://github.com/yewstack/yew/projects/3)
+2. [Component Library](https://github.com/yewstack/yew/projects/4)
+3. Better state management
+4. [Server side rendering](https://github.com/yewstack/yew/projects/5)
+
+### Production Readiness
+
+* Improve Yew test coverage
+* Reduce binary size
+* [Benchmark performance](https://github.com/yewstack/yew/issues/5)
+
+### Documentation
+
+* Create tutorial
+* Simplify project setup
+
+### Pain Points
+
+* [Component boilerplate](https://github.com/yewstack/yew/issues/830)
+* Fetch API
+* [Agents](https://github.com/yewstack/yew/projects/6)
+
diff --git a/docs/src/more/testing.md b/docs/src/more/testing.md
new file mode 100644
index 00000000000..e0486687a9a
--- /dev/null
+++ b/docs/src/more/testing.md
@@ -0,0 +1,16 @@
+---
+description: Testing your app
+---
+
+# Testing
+
+<TODO>
+
+## wasm\_bindgen\_test
+
+The Rust Wasm working group maintains a crate called
+[`wasm_bindgen_test`](https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/index.html)
+which allows you to run tests in a browser in similar fashion to how the built-in `#[test]`
+procedural macro works. More information is given in the
+[Rust WASM working group's documentation](https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/index.html)
+for this module.