July 11th, 2025

Introduction to the Lynx Web Platform

Haoyang Wang

Software Engineer

Hao Ai

Software Engineer

Lynx Everywhere

lynx-for-everywhere

With Lynx, we provide first-class browser support for developers.

The Lynx Web Platform is now in beta. Here are some highlights of the Web Platform.

We have many use cases at TikTok. Here's a simple showcase.

tiktok-preview-demo

Our web platform—a Lynx FFI implementation for browsers—provides the same rendering and appearance as the Lynx engine.

Inspired by Concurrency in Lynx

On the Lynx Web Platform, we're bringing Lynx's dual-threading model to the web community.

We're trying to give Web community an idea about the multi-threading web application. With Lynx's dual-thread architecture, we use the Web Workers to implement Lynx's multi-threaded rendering. On Lynx's Web Platform, developers can easily render their ReactLynx pages in an HTML document. With ReactLynx, your code is automatically and gracefully split into two threads. With fast First Meaningful Paint (FMP) and non-blocking effect execution, we help you catch users' eyes as soon as possible.

As we all know, over the past decade, multi-threaded performance has outpaced single-thread performance on modern hardware. In a single-threaded model, applications can only process tasks sequentially. When faced with computationally intensive tasks, the interface may become unresponsive or even freeze, severely affecting the user experience.

Here's a demo showing a page with complex effects that don't block the main thread.

Reactlynx
React

web-platform-demo

react-demo

In this demo, we emulate a scenario where we have to decode HEIC images in JavaScript. Decoding is a CPU-intensive task. Even if we move the decoding into useEffect, the main thread is still blocked. This causes CSS animations to lag. In Lynx, effects don't wait for rendering to finish and don't block rendering. This design prioritizes high-priority rendering tasks and keeps effects executing quickly.

lynx-web-all-on-ui-thread-model

One codebase, one Lynx

The core idea of our web platform is to provide a solution that lets developers render their Lynx pages in a browser with high performance and minimal cost.

Therefore, we provide an implementation of the Lynx Engine APIs for browsers.

lynx-web-arch

__SetAttribute on Web Platform
__SetAttribute on Lynx Engine
// lynx/runtime/papi.ts
const __SetAttribute: SetAttributePAPI = (
  element,
  key,
  value,
) => {
  if (value == null) {
    element.removeAttribute(key)
  } else {
    element.setAttribute(key, value + '')
  }
};
RENDERER_FUNCTION_CC(FiberSetAttribute) {
  CONVERT_ARG_AND_CHECK_FOR_ELEMENT_API(arg0, 0, RefCounted, FiberSetAttribute);
  auto element = fml::static_ref_ptr_cast<FiberElement>(arg0->RefCounted());
  CONVERT_ARG(arg1, 1);
  CONVERT_ARG(arg2, 2);
  auto string_type = arg1->StringView();
  CHECK_ILLEGAL_ATTRIBUTE_CONFIG(element, FiberSetAttribute);
  element->SetAttribute(arg1->String(), arg2->ToLepusValue());
  ON_NODE_MODIFIED(element);
  RETURN_UNDEFINED();
}

This means that developers and Rspeedy (Rsbuild) plugin authors don't need extra work to support the web platform. There are no platform-specific variants of your code. The only difference in the output is that for the web platform we skip AOT optimizations. One Lynx!

One CSS Spec — the Web CSS Spec

For most Lynx-supported CSS properties and all selectors, the Lynx Engine follows W3C specs or subsets of the corresponding specs. This lets us emit these declarations as-is into the document.

lynx-web-height-transform

However, there are properties and values implemented for performance reasons. That's why our web platform includes a CSS transformer that converts some values into CSS custom properties. Then we use CSS techniques to switch and apply different properties on HTML elements. This achieves maximum compatibility while maintaining high performance.

lynx-web-display-linear-transform

Native Components, Web Components

native-elements-on-different-platform

https://lynxjs.org/zh/guide/ui/elements-components.html

One of Lynx's core ideas is rendering based on native UI components, which means that on every platform we provide a corresponding UI component implementation with similar behavior. Just like Lynx's elements on iOS and Android, in browsers we provide a series of custom elements using Web Components. By using the lifecycles provided by web browsers, we don't depend on any JavaScript framework. This minimizes I/O overhead for applications built with Lynx.

Faster, Easier, and a Rust-powered Future

Boosted by Rust and WebAssembly

An ongoing optimization will introduce a Rust-implemented WebAssembly module. Our in-house benchmarking shows that rewriting the style transformer in Rust can reduce rendering time by 30–40%.

Ready for PWA

We're exploring more possibilities with PWA technologies, such as push notifications and service workers, to improve user experience. Imagine non-blocking content streaming without a separate SSR server. Let's make it work with workers!

SSR support

We know SSR is an important way to improve user experience. The web platform's SSR support will ship with built-in 'zero-JavaScript-ready' SSR output. We will integrate with solutions powered by the HTML template element.

See our presentation on React Universe Conf 2025

React Universe Conf 2025

Integrate with your web app now

Learn more

Current Status

We're still in active development—our team is working closely to refine and expand the platform. As a result, a few capabilities remain in the pipeline and haven't been fully implemented yet. For instance, Hot Module Replacement (HMR) is under active development and hasn't rolled out yet. We're working hard to make it better.

Except as otherwise noted, this work is licensed under a Creative Commons Attribution 4.0 International License, and code samples are licensed under the Apache License 2.0.