Skip to content

Rewrite yew.rs with Yew#4069

Draft
Madoshakalaka wants to merge 12 commits intomasterfrom
yew-docs
Draft

Rewrite yew.rs with Yew#4069
Madoshakalaka wants to merge 12 commits intomasterfrom
yew-docs

Conversation

@Madoshakalaka
Copy link
Member

@Madoshakalaka Madoshakalaka commented Mar 11, 2026

fixes #2779
Replace the Docusaurus-based website with a pure Rust/Yew implementation.

The SSG pipeline compiles each page to WASM, runs wasm-bindgen and wasm-opt, then captures SSR output for SEO-friendly HTML. All docs (5 versions x 4 languages), blog posts, community pages, search, and 404 are generated as static files.

This is a quite faithful rewrite of our old docusaurus based website.

Key features:

  • Content model with dual HTML/Markdown rendering which enables a copy-as-markdown button on each page (new feature)
  • Syntax highlighting via syntect (rust solution) with light/dark themes (old site used prism.js)
  • Collapsible sidebar, table of contents, breadcrumbs, and pagination (matching old site)
  • 3-state theme toggle (light/dark/system) (matching old site)
  • Blog with date-prefixed URLs, index, sidebar, RSS and Atom feeds (matching old site)
  • Full-page Algolia search with version faceting (matching old site)
  • OpenSearch descriptor, sitemap, robots.txt, 404 page (matching old site)
  • SEO: hreflang, OG tags, JSON-LD breadcrumbs, canonical URLs (matching old site)
  • wasm bundle and javascript hashing for cache control
  • CI workflow builds with Rust toolchain instead of Node.js

Some design choices and notes:

  • fantoccini is used for e2e testing the website. Site navigation needs to be tested because version + i18n selectors + side menu interaction can get very tricky. Alternatives to Fantoccini like thirtyfour, chromiumoxide were considered and Fantoccini has the most downloads, most stars, most recent release cadence.
  • Code snippet testing and tutorial testing preserved.
  • Data-as-code allows us to deduplicate greatly. Next, 0.23, and 0.22 docs are not diverged, which allows 0.23 docs and 0.22 docs to reuse the same data. This reduces 100, 000 lines of mdx to 50 ,000 lines of Rust.
  • stylist-rs is used for more concise styling. Its SSR support renders the same styling during SSG and runtime, causing no content flickering at all.
  • the new build tool, at ./yew-rs/ssg/, accepts page filtering, --jobs N flags, and --skip-wasm-opt flags that can shrink build time greatly. Since we don't have beefy runners and we do have to run wasm-opt in the CI, a fresh build might take a lot longer (10 minutes)
  • the new website uses stable yew (pinned to 0.23 at the moment) for cache friendliness and ecosystem support (stylist-rs won't work with Yew Next)
  • We have version and locale aware home pages now. The Get Started button and the Learn More buttons on each feature card now consume the version and locale too. (new feature)
  • Categories and subcategories all had {category}/introduction.mdx files. Most pages (7 out of 9) had a slug in the old mdx files so that the slug {category} by itself shows the introduction page, (and {category}/introduction gives a 404). The only two exceptions were: https://yew.rs/docs/next/getting-started/introduction and https://yew.rs/docs/advanced-topics/struct-components/introduction. The new code unifies the aliasing behaviour. It means old urls to docs/next/getting-started/introduction and docs/advanced-topics/struct-components/introduction will hit 404.

Todos

  • Verify localized and versioned home page SSG (important SEO)
  • remove mdx references from the workflow and the website directory.
  • site-ssg only works on workspace root for now
  • the url of the tutorial page currently is prefixed with the /docs/ slug. It doesn't make sense as the nav bar suggests "tutorial" and "docs" are on the same level, handled just like the Community pages and Blog pages with no "docs" prefix. We should remove the docs prefix from the tutorial's url. This will also cause some 404s to old references.
image image
  • we might want to embed the playground directly into yew.rs now. (Should we make code blocks actually runnable ?)
  • SPA: we still generate all static pages. But we make it have dynamic navigation between them. Thanks @kirillsemyonkin for the idea. (!!) Docusaurus actually does this. See a comment from me below.
  • terrible readibility of some highlighting in codeblock in dark mode
  • Some meta description mismatch
  • Table rendering on the /docs/concepts/function-components/state page
  • Language and version menu on small height phone overflows and can't be scrolled
  • use const fn magic or macros to groups localized strings together, further reduction of code size.

@github-actions
Copy link

github-actions bot commented Mar 11, 2026

Size Comparison

Details
examples master (KB) pull request (KB) diff (KB) diff (%)
async_clock 101.096 101.057 -0.039 -0.039%
boids 168.883 168.901 +0.019 +0.011%
communication_child_to_parent 94.508 94.510 +0.002 +0.002%
communication_grandchild_with_grandparent 106.348 106.349 +0.001 +0.001%
communication_grandparent_to_grandchild 102.691 102.693 +0.002 +0.002%
communication_parent_to_child 91.920 91.921 +0.001 +0.001%
contexts 106.417 106.412 -0.005 -0.005%
counter 87.232 87.232 0 0.000%
counter_functional 89.269 89.269 0 0.000%
dyn_create_destroy_apps 91.148 91.148 0 0.000%
file_upload 100.326 100.325 -0.001 -0.001%
function_delayed_input 95.241 95.238 -0.003 -0.003%
function_memory_game 174.095 174.102 +0.007 +0.004%
function_router 395.814 395.818 +0.004 +0.001%
function_todomvc 165.382 165.397 +0.016 +0.009%
futures 235.985 235.982 -0.003 -0.001%
game_of_life 105.533 105.533 0 0.000%
immutable 260.232 260.240 +0.008 +0.003%
inner_html 81.775 81.775 0 0.000%
js_callback 110.396 110.396 0 0.000%
keyed_list 180.709 180.709 0 0.000%
mount_point 85.148 85.148 0 0.000%
nested_list 114.090 114.092 +0.002 +0.002%
node_refs 92.521 92.521 -0.001 -0.001%
password_strength 1719.351 1719.715 +0.364 +0.021%
portals 93.993 93.993 0 0.000%
router 366.456 366.471 +0.015 +0.004%
suspense 114.399 114.395 -0.005 -0.004%
timer 89.370 89.370 0 0.000%
timer_functional 99.805 99.802 -0.003 -0.003%
todomvc 143.097 143.097 0 0.000%
two_apps 87.146 87.146 0 0.000%
web_worker_fib 137.050 137.049 -0.001 -0.001%
web_worker_prime 188.230 188.235 +0.005 +0.003%
webgl 83.921 83.920 -0.001 -0.001%

✅ None of the examples has changed their size significantly.

@Madoshakalaka Madoshakalaka added documentation A-ci Area: The continuous integration labels Mar 11, 2026
@Madoshakalaka Madoshakalaka force-pushed the yew-docs branch 2 times, most recently from 832800f to 0ec8ecd Compare March 11, 2026 12:24
@github-actions
Copy link

github-actions bot commented Mar 11, 2026

Visit the preview URL for this PR (updated for commit c3fec70):

https://yew-rs--pr4069-yew-docs-185gwe7t.web.app

(expires Thu, 26 Mar 2026 06:17:48 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Madoshakalaka added a commit that referenced this pull request Mar 13, 2026
Replace the Docusaurus-based website with a pure Rust/Yew implementation.

The SSG pipeline compiles each page to WASM, runs wasm-bindgen and
wasm-opt, then captures SSR output for SEO-friendly HTML. All docs
(5 versions x 4 languages), blog posts, community pages, search, and
404 are generated as static files.

Key features:
- Content model with dual HTML/Markdown rendering for copy-as-markdown
- Syntax highlighting via syntect with light/dark themes
- Collapsible sidebar, table of contents, breadcrumbs, pagination
- 3-state theme toggle (light/dark/system)
- Blog with date-prefixed URLs, index, sidebar, RSS and Atom feeds
- Full-page Algolia search with version faceting
- SEO: hreflang, OG tags, JSON-LD breadcrumbs, canonical URLs
- E2E tests with fantoccini/geckodriver
- Deduplicated versioned docs across 0.20/0.21/0.22/0.23/next
Madoshakalaka added a commit that referenced this pull request Mar 13, 2026
Replace the Docusaurus-based website with a pure Rust/Yew implementation.

The SSG pipeline compiles each page to WASM, runs wasm-bindgen and
wasm-opt, then captures SSR output for SEO-friendly HTML. All docs
(5 versions x 4 languages), blog posts, community pages, search, and
404 are generated as static files.

Key features:
- Content model with dual HTML/Markdown rendering for copy-as-markdown
- Syntax highlighting via syntect with light/dark themes
- Collapsible sidebar, table of contents, breadcrumbs, pagination
- 3-state theme toggle (light/dark/system)
- Blog with date-prefixed URLs, index, sidebar, RSS and Atom feeds
- Full-page Algolia search with version faceting
- SEO: hreflang, OG tags, JSON-LD breadcrumbs, canonical URLs
- E2E tests with fantoccini/geckodriver
- Deduplicated versioned docs across 0.20/0.21/0.22/0.23/next
@Madoshakalaka Madoshakalaka force-pushed the yew-docs branch 6 times, most recently from ce3a6d7 to 15b5594 Compare March 14, 2026 11:51
@Madoshakalaka
Copy link
Member Author

@WorldSEnder still a draft PR but any opinions are welcome. you can already try the wasm website in the preview URL

@Madoshakalaka
Copy link
Member Author

Size Note:
every doc page is ~1.7 MB of WASM (700 kB after compression). Home pages (which skip syntect) are only ~378 KB (120 kB after compression).

@Madoshakalaka
Copy link
Member Author

Madoshakalaka commented Mar 16, 2026

SPA: we still generate all static pages. But we make it have dynamic navigation between them.

This is now implemented. Each locale (en, ja, zh-Hans, zh-Hant) has one SPA binary powered by yew-router that covers all 5 doc versions + migration guides. Version switching is client-side (no WASM re-download), locale switching triggers a full reload. This is identical to docusaurus behavior. The rationale I think is version switching is much frequent than locale switching.

Architecture:

  • 4 new SPA crates (spa-en/, spa-ja/, spa-zh-hans/, spa-zh-hant/) with Route enums using wildcard paths
  • SSG compiles 4 SPA binaries instead of ~1,100 per-page binaries, then hardlinks WASM/JS to each page directory
  • SSR unchanged: each page still gets unique meta tags, hreflang, JSON-LD, descriptions
  • Blog, community, and home pages are unchanged (still per-page binaries)

Per-page WASM download went from ~1.7 MB (per navigation) to ~2.8 MB (once per session, then all version/page switches are instant. 930 kB after compression, seems acceptible). Full build time in CI reduces tenfold (90 minutes -> 11 minutes).

@Madoshakalaka
Copy link
Member Author

Madoshakalaka commented Mar 16, 2026

more todos:

  • the get started button on the home page is a hard link
  • dropdown doesn't retract after same-locale version change
  • side menu has style shift when switching locale.
  • maybe try isolating syntect to ssr/ssg only to reduce bundle size

@Madoshakalaka
Copy link
Member Author

Madoshakalaka commented Mar 16, 2026

As previously commented, a huge bloat is syntect. We don't have codeblocks on a lot of pages like the home page and the getting-started/examples page.

But the SPA approach now inevitably bundles it.

after #3932 lands though, we can delay loading the CodeBlock component.

This will even beat docusaurus. Note docusaurs based getting-started/examples and getting-started/editor-setup currently load JavaScript of identical size.

@WorldSEnder
Copy link
Member

I had a quick look over it and it looks good already, visually. I haven't dug too deep into the generation process.

I noticed that in dark mode, some code highlighting could have improved readability. An explicit worst case is .sy-variable.sy-parameter which gets the color #323232 on #1b1b1d background (almost invisible).

Build times being down to 12m-15m is also great, not quite at the 5 minutes from before but acceptable. Definitely an area that could be improved.

Small thing: The version selection button changes width when swapping from Next to a concrete version, which shifts the rest of the header.

Do we want the generated rust files to live in the repository or is the source for the page supposed to get generated on the fly each time?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-ci Area: The continuous integration documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Build Yew website with Yew

2 participants