This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory-site.git


The following commit(s) were added to refs/heads/main by this push:
     new 644a8a6caf 🔄 synced local 'docs/guide/' with remote 'docs/guide/'
644a8a6caf is described below

commit 644a8a6cafaaef6d06faa82549b4d3b7e96e8ab1
Author: chaokunyang <[email protected]>
AuthorDate: Mon Apr 13 09:10:38 2026 +0000

    🔄 synced local 'docs/guide/' with remote 'docs/guide/'
---
 docs/guide/javascript/basic-serialization.md | 244 +++++++++++++++++++++++++++
 docs/guide/javascript/cross-language.md      | 137 +++++++++++++++
 docs/guide/javascript/index.md               | 164 ++++++++++++++++++
 docs/guide/javascript/references.md          | 105 ++++++++++++
 docs/guide/javascript/schema-evolution.md    | 102 +++++++++++
 docs/guide/javascript/supported-types.md     | 194 +++++++++++++++++++++
 docs/guide/javascript/troubleshooting.md     | 113 +++++++++++++
 docs/guide/javascript/type-registration.md   | 217 ++++++++++++++++++++++++
 8 files changed, 1276 insertions(+)

diff --git a/docs/guide/javascript/basic-serialization.md 
b/docs/guide/javascript/basic-serialization.md
new file mode 100644
index 0000000000..077ba9c541
--- /dev/null
+++ b/docs/guide/javascript/basic-serialization.md
@@ -0,0 +1,244 @@
+---
+title: Basic Serialization
+sidebar_position: 1
+id: basic_serialization
+license: |
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+---
+
+This guide covers the core serialization flow in Apache Fory JavaScript.
+
+## Create and Reuse a `Fory` Instance
+
+```ts
+import Fory from "@apache-fory/core";
+
+const fory = new Fory();
+```
+
+Create one instance, register your schemas, and reuse it. A `Fory` instance 
caches generated serializers and type metadata, so recreating it for every 
request adds unnecessary overhead.
+
+## Define a Schema with `Type.struct`
+
+The most common path is to define a schema and register it.
+
+```ts
+import Fory, { Type } from "@apache-fory/core";
+
+const accountType = Type.struct(
+  { typeName: "example.account" },
+  {
+    id: Type.int64(),
+    owner: Type.string(),
+    active: Type.bool(),
+    nickname: Type.string().setNullable(true),
+  },
+);
+
+const fory = new Fory();
+const { serialize, deserialize } = fory.register(accountType);
+```
+
+## Serialize and Deserialize
+
+```ts
+const bytes = serialize({
+  id: 42n,
+  owner: "Alice",
+  active: true,
+  nickname: null,
+});
+
+const value = deserialize(bytes);
+console.log(value);
+// { id: 42n, owner: 'Alice', active: true, nickname: null }
+```
+
+The returned `bytes` value is a `Uint8Array`/platform buffer and can be sent 
over the network or written to storage.
+
+## Root-Level Dynamic Serialization
+
+`Fory` can also serialize dynamic root values without first binding a 
schema-specific serializer.
+
+```ts
+const fory = new Fory();
+
+const bytes = fory.serialize(
+  new Map([
+    ["name", "Alice"],
+    ["age", 30],
+  ]),
+);
+
+const value = fory.deserialize(bytes);
+```
+
+This is convenient for dynamic payloads, but explicit schemas are usually 
better for stable interfaces and cross-language contracts.
+
+## Primitive Values
+
+```ts
+const fory = new Fory();
+
+fory.deserialize(fory.serialize(true));
+// true
+
+fory.deserialize(fory.serialize("hello"));
+// 'hello'
+
+fory.deserialize(fory.serialize(123));
+// 123
+
+fory.deserialize(fory.serialize(123n));
+// 123n
+
+fory.deserialize(fory.serialize(new Date("2021-10-20T09:13:00Z")));
+// Date
+```
+
+### Number and `bigint` behavior
+
+JavaScript has both `number` and `bigint`, but xlang distinguishes between 
32-bit, 64-bit, floating-point, and tagged integer representations. For any 
cross-language or long-lived contract, prefer explicit field types in schemas 
instead of depending on dynamic root-type inference.
+
+- use `Type.int32()` for 32-bit integers
+- use `Type.int64()` for 64-bit integers and pass `bigint`
+- use `Type.float32()` or `Type.float64()` for floating-point values
+
+Dynamic root serialization is convenient, but the exact heuristic for whether 
a value comes back as `number` or `bigint` should not be treated as a stable 
API contract.
+
+## Arrays, Maps, and Sets
+
+```ts
+const inventoryType = Type.struct("example.inventory", {
+  tags: Type.array(Type.string()),
+  counts: Type.map(Type.string(), Type.int32()),
+  labels: Type.set(Type.string()),
+});
+
+const fory = new Fory({ ref: true });
+const { serialize, deserialize } = fory.register(inventoryType);
+
+const bytes = serialize({
+  tags: ["hot", "new"],
+  counts: new Map([
+    ["apple", 3],
+    ["pear", 8],
+  ]),
+  labels: new Set(["featured", "seasonal"]),
+});
+
+const value = deserialize(bytes);
+```
+
+## Nested Structs
+
+```ts
+const addressType = Type.struct("example.address", {
+  city: Type.string(),
+  country: Type.string(),
+});
+
+const userType = Type.struct("example.user", {
+  name: Type.string(),
+  address: Type.struct("example.address", {
+    city: Type.string(),
+    country: Type.string(),
+  }),
+});
+
+const fory = new Fory();
+const { serialize, deserialize } = fory.register(userType);
+
+const bytes = serialize({
+  name: "Alice",
+  address: { city: "Hangzhou", country: "CN" },
+});
+
+const user = deserialize(bytes);
+```
+
+If a nested value can be missing, mark it nullable:
+
+```ts
+const wrapperType = Type.struct("example.wrapper", {
+  child: Type.struct("example.child", {
+    name: Type.string(),
+  }).setNullable(true),
+});
+```
+
+## Decorator-Based Registration
+
+TypeScript decorators are also supported.
+
+```ts
+import Fory, { Type } from "@apache-fory/core";
+
[email protected]("example.user")
+class User {
+  @Type.int64()
+  id!: bigint;
+
+  @Type.string()
+  name!: string;
+}
+
+const fory = new Fory();
+const { serialize, deserialize } = fory.register(User);
+
+const user = new User();
+user.id = 1n;
+user.name = "Alice";
+
+const copy = deserialize(serialize(user));
+console.log(copy instanceof User); // true
+```
+
+## Nullability
+
+Field nullability is explicit in schema-based structs.
+
+```ts
+const nullableType = Type.struct("example.optional_user", {
+  name: Type.string(),
+  email: Type.string().setNullable(true),
+});
+```
+
+If a field is not marked nullable and you try to write `null`, serialization 
throws.
+
+## Debugging Generated Code
+
+You can inspect generated serializer code with `hooks.afterCodeGenerated`.
+
+```ts
+const fory = new Fory({
+  hooks: {
+    afterCodeGenerated(code) {
+      console.log(code);
+      return code;
+    },
+  },
+});
+```
+
+This is useful when debugging schema behavior, field ordering, or generated 
fast paths.
+
+## Related Topics
+
+- [Type Registration](type-registration.md)
+- [Supported Types](supported-types.md)
+- [References](references.md)
diff --git a/docs/guide/javascript/cross-language.md 
b/docs/guide/javascript/cross-language.md
new file mode 100644
index 0000000000..06f5c3e2cc
--- /dev/null
+++ b/docs/guide/javascript/cross-language.md
@@ -0,0 +1,137 @@
+---
+title: Cross-Language Serialization
+sidebar_position: 80
+id: cross_language
+license: |
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+---
+
+Apache Fory JavaScript always uses the xlang wire format. Interoperability 
depends on matching schemas and compatible type mappings rather than on 
enabling a separate mode switch.
+
+Current limits to keep in mind:
+
+- JavaScript deserializes xlang payloads only
+- out-of-band mode is not currently supported in the JavaScript runtime
+
+## Interop rules
+
+For a payload to round-trip between JavaScript and another runtime:
+
+1. **Register the same logical type identity** on both sides.
+   - same numeric type ID, or
+   - same namespace + type name
+2. **Use compatible field types** according to the [type mapping 
spec](../../specification/xlang_type_mapping.md).
+3. **Match nullability and reference-tracking expectations** where object 
graphs require them.
+4. **Use compatible mode** when independent schema evolution is expected.
+
+## Interoperability workflow
+
+When wiring JavaScript to another runtime in production code:
+
+1. define the JavaScript schema with the same type identity used by the other 
runtime
+2. register the same type name or type ID in every participating runtime
+3. keep field types, nullability, enum layout, and schema-evolution settings 
aligned
+4. validate the end-to-end payload before relying on it in a shared contract
+
+Example JavaScript side:
+
+```ts
+import Fory, { Type } from "@apache-fory/core";
+
+const messageType = Type.struct(
+  { typeName: "example.message" },
+  {
+    id: Type.int64(),
+    content: Type.string(),
+  },
+);
+
+const fory = new Fory();
+const { serialize } = fory.register(messageType);
+
+const bytes = serialize({
+  id: 1n,
+  content: "hello from JavaScript",
+});
+```
+
+On the receiving side, register the same `example.message` type identity and 
compatible field types using that runtime's public API and guide:
+
+- [Go guide](../go/index.md)
+- [Python guide](../python/index.md)
+- [Java guide](../java/index.md)
+- [Rust guide](../rust/index.md)
+
+## Field naming and ordering
+
+Cross-language matching depends on consistent field identity. When multiple 
runtimes model the same struct, use a naming scheme that maps cleanly across 
languages.
+
+Practical guidance:
+
+- prefer stable snake_case or clearly corresponding names across runtimes
+- avoid accidental renames without updating every participating runtime
+- use compatible mode when fields may be added or removed over time
+
+## Numeric mapping guidance
+
+JavaScript needs extra care because `number` is IEEE 754 double precision.
+
+- use `Type.int64()` with `bigint` for true 64-bit integers
+- use `Type.float32()` or `Type.float64()` for floating-point fields
+- avoid assuming that a dynamic JavaScript `number` maps cleanly to every 
integer width in another language
+
+## Time mapping guidance
+
+- `Type.timestamp()` maps to a point in time and deserializes as `Date`
+- `Type.duration()` should be treated as a duration value, but JavaScript 
currently exposes typed duration fields as numeric time values rather than a 
dedicated duration class
+- `Type.date()` corresponds to a date-without-timezone type in the 
specification and deserializes as `Date`
+
+## Polymorphism and `Type.any()`
+
+Use `Type.any()` only when you genuinely need runtime-dispatched values.
+
+```ts
+const wrapperType = Type.struct(
+  { typeId: 3001 },
+  {
+    payload: Type.any(),
+  },
+);
+```
+
+This works for polymorphic values, but explicit field schemas are easier to 
keep aligned across languages.
+
+## Enums
+
+Enums must also be registered consistently across languages.
+
+```ts
+const Color = { Red: 1, Green: 2, Blue: 3 };
+const fory = new Fory();
+fory.register(Type.enum({ typeId: 210 }, Color));
+```
+
+Use the same type ID or type name in Java, Python, Go, and other runtimes.
+
+## Limits and safety
+
+Deserialization guardrails such as `maxDepth`, `maxBinarySize`, and 
`maxCollectionSize` are local runtime protections. They do not affect the wire 
format, but they can reject payloads that exceed local policy.
+
+## Related Topics
+
+- [Supported Types](supported-types.md)
+- [Schema Evolution](schema-evolution.md)
+- [Xlang Serialization 
Specification](../../specification/xlang_serialization_spec.md)
diff --git a/docs/guide/javascript/index.md b/docs/guide/javascript/index.md
new file mode 100644
index 0000000000..c715ad8cf1
--- /dev/null
+++ b/docs/guide/javascript/index.md
@@ -0,0 +1,164 @@
+---
+title: JavaScript Serialization Guide
+sidebar_position: 0
+id: index
+license: |
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+---
+
+Apache Fory JavaScript provides cross-language serialization for JavaScript 
and TypeScript applications. It uses the xlang wire format described in the 
[xlang serialization 
specification](../../specification/xlang_serialization_spec.md), so it is 
designed to interoperate with other Fory runtimes such as Java, Python, Go, 
Rust, Swift, and C++.
+
+The JavaScript runtime is schema-driven: you describe your data shape with 
`Type.*` builders or TypeScript decorators, register that schema with `Fory`, 
and then reuse the returned serializer pair for serialization and 
deserialization.
+
+## Why Fory JavaScript?
+
+- **Cross-language by design**: JavaScript uses the xlang wire format and 
interoperates with other Fory runtimes.
+- **Generated hot paths**: serializers are generated at runtime and cached per 
`Fory` instance.
+- **Reference-aware object graphs**: shared references and circular structures 
are supported when enabled.
+- **Explicit schemas**: field types, nullability, dynamic dispatch, and type 
identity are declared up front.
+- **Guardrails for untrusted data**: configurable depth, binary size, and 
collection size limits help bound deserialization work.
+- **Modern numeric support**: `bigint`, typed arrays, `Map`, `Set`, `Date`, 
`float16`, and `bfloat16` are supported.
+
+## Installation
+
+Install the JavaScript packages from npm:
+
+```bash
+npm install @apache-fory/core
+```
+
+Optional Node.js string fast-path support is available through 
`@apache-fory/hps`:
+
+```bash
+npm install @apache-fory/core @apache-fory/hps
+```
+
+`@apache-fory/hps` depends on Node.js 20+ and is optional. If it is 
unavailable, Fory still works correctly; omit `hps` from the configuration.
+
+## Quick Start
+
+```ts
+import Fory, { Type } from "@apache-fory/core";
+
+const userType = Type.struct(
+  { typeName: "example.user" },
+  {
+    id: Type.int64(),
+    name: Type.string(),
+    age: Type.int32(),
+  },
+);
+
+const fory = new Fory();
+const { serialize, deserialize } = fory.register(userType);
+
+const bytes = serialize({
+  id: 1n,
+  name: "Alice",
+  age: 30,
+});
+
+const user = deserialize(bytes);
+console.log(user);
+// { id: 1n, name: 'Alice', age: 30 }
+```
+
+## Core Model
+
+### `Fory`
+
+A `Fory` instance owns:
+
+- the type registry
+- generated serializers
+- read/write contexts
+- configuration such as reference tracking and guardrails
+
+Reuse the same `Fory` instance across many operations. Registration is per 
instance.
+
+### `Type`
+
+`Type` is the schema DSL. It is used to describe:
+
+- primitive fields such as `Type.int32()` and `Type.string()`
+- collections such as `Type.array(...)`, `Type.map(...)`, and `Type.set(...)`
+- user types such as `Type.struct(...)` and `Type.enum(...)`
+- field-level metadata such as nullability, reference tracking, and dynamic 
dispatch
+
+### Registration
+
+`fory.register(...)` compiles and registers a serializer. It returns:
+
+- `serializer`: the generated serializer object
+- `serialize(value)`: serialize using that schema
+- `deserialize(bytes)`: deserialize using that schema
+
+```ts
+const personType = Type.struct("example.person", {
+  name: Type.string(),
+  email: Type.string().setNullable(true),
+});
+
+const fory = new Fory();
+const personSerde = fory.register(personType);
+```
+
+## Configuration
+
+The JavaScript runtime always uses xlang serialization. The most important 
options are:
+
+```ts
+import Fory from "@apache-fory/core";
+import hps from "@apache-fory/hps";
+
+const fory = new Fory({
+  ref: true,
+  compatible: true,
+  maxDepth: 100,
+  maxBinarySize: 64 * 1024 * 1024,
+  maxCollectionSize: 1_000_000,
+  useSliceString: false,
+  hps,
+});
+```
+
+| Option                     | Default            | Meaning                    
                                                                                
                       |
+| -------------------------- | ------------------ | 
---------------------------------------------------------------------------------------------------------------------------------
 |
+| `ref`                      | `false`            | Enables reference tracking 
for graphs with shared or circular references.                                  
                       |
+| `compatible`               | `false`            | Uses compatible struct 
encoding for schema evolution.                                                  
                           |
+| `maxDepth`                 | `50`               | Maximum nesting depth 
accepted during deserialization. Must be `>= 2`.                                
                            |
+| `maxBinarySize`            | `64 * 1024 * 1024` | Maximum allowed binary 
payload for guarded binary reads.                                               
                           |
+| `maxCollectionSize`        | `1_000_000`        | Maximum number of elements 
accepted for lists, sets, and maps.                                             
                       |
+| `useSliceString`           | `false`            | Optional string-reading 
mode for Node.js environments. Leave it at the default unless you have 
benchmarked a reason to change it. |
+| `hps`                      | unset              | Optional Node.js string 
fast-path helper from `@apache-fory/hps`.                                       
                          |
+| `hooks.afterCodeGenerated` | unset              | Callback to inspect or 
transform generated serializer code. Useful for debugging.                      
                           |
+
+## Documentation
+
+| Topic                                         | Description                  
                           |
+| --------------------------------------------- | 
------------------------------------------------------- |
+| [Basic Serialization](basic-serialization.md) | Core APIs and everyday usage 
                           |
+| [Type Registration](type-registration.md)     | Numeric IDs, names, 
decorators, and schema registration |
+| [Supported Types](supported-types.md)         | Primitive, collection, time, 
enum, and struct mappings  |
+| [References](references.md)                   | Shared references and 
circular object graphs            |
+| [Schema Evolution](schema-evolution.md)       | Compatible mode and evolving 
structs                    |
+| [Cross-Language](cross-language.md)           | Interop guidance and mapping 
rules                      |
+| [Troubleshooting](troubleshooting.md)         | Common issues, limits, and 
debugging tips               |
+
+## Related Resources
+
+- [Xlang Serialization 
Specification](../../specification/xlang_serialization_spec.md)
+- [Cross-Language Type Mapping](../../specification/xlang_type_mapping.md)
diff --git a/docs/guide/javascript/references.md 
b/docs/guide/javascript/references.md
new file mode 100644
index 0000000000..583dcc52c9
--- /dev/null
+++ b/docs/guide/javascript/references.md
@@ -0,0 +1,105 @@
+---
+title: References
+sidebar_position: 50
+id: references
+license: |
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+---
+
+Fory can preserve shared references and circular object graphs, but in 
JavaScript you should enable reference tracking globally and mark the specific 
struct fields that participate in shared or circular references.
+
+## Enable reference tracking globally
+
+```ts
+const fory = new Fory({ ref: true });
+```
+
+Without `ref: true`, Fory treats values as ordinary tree-shaped data.
+
+## Mark reference-capable fields
+
+For schema-based structs, mark fields that can hold shared or circular 
references with `.setTrackingRef(true)`.
+
+```ts
+const nodeType = Type.struct("example.node", {
+  value: Type.string(),
+  next: Type.struct("example.node").setNullable(true).setTrackingRef(true),
+});
+```
+
+## Circular self-reference example
+
+```ts
+import Fory, { Type } from "@apache-fory/core";
+
+const nodeType = Type.struct("example.node", {
+  name: Type.string(),
+  selfRef: Type.struct("example.node").setNullable(true).setTrackingRef(true),
+});
+
+const fory = new Fory({ ref: true });
+const { serialize, deserialize } = fory.register(nodeType);
+
+const node: any = { name: "root", selfRef: null };
+node.selfRef = node;
+
+const copy = deserialize(serialize(node));
+console.log(copy.selfRef === copy); // true
+```
+
+## Shared nested reference example
+
+```ts
+const innerType = Type.struct(501, {
+  value: Type.string(),
+});
+
+const outerType = Type.struct(502, {
+  left: Type.struct(501).setNullable(true).setTrackingRef(true),
+  right: Type.struct(501).setNullable(true).setTrackingRef(true),
+});
+
+const fory = new Fory({ ref: true });
+const { serialize, deserialize } = fory.register(outerType);
+
+const shared = { value: "same-object" };
+const copy = deserialize(serialize({ left: shared, right: shared }));
+console.log(copy.left === copy.right); // true
+```
+
+## When to enable it
+
+Enable reference tracking when:
+
+- the same object instance is reused in multiple fields
+- your graph can be cyclic
+- identity preservation matters after deserialization
+
+Leave it disabled when:
+
+- the data is a plain tree
+- you want the lowest overhead
+- object identity does not matter
+
+## Cross-language note
+
+Reference tracking is part of the xlang protocol, but every participating 
runtime still needs compatible schema and configuration. If one side models a 
graph as plain values and the other depends on object identity, behavior may 
not match your expectations.
+
+## Related Topics
+
+- [Basic Serialization](basic-serialization.md)
+- [Schema Evolution](schema-evolution.md)
+- [Cross-Language](cross-language.md)
diff --git a/docs/guide/javascript/schema-evolution.md 
b/docs/guide/javascript/schema-evolution.md
new file mode 100644
index 0000000000..7956e7a074
--- /dev/null
+++ b/docs/guide/javascript/schema-evolution.md
@@ -0,0 +1,102 @@
+---
+title: Schema Evolution
+sidebar_position: 60
+id: schema_evolution
+license: |
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+---
+
+Fory JavaScript supports two struct encodings:
+
+- **schema-consistent mode**: more compact, assumes the schema matches exactly
+- **compatible mode**: writes extra metadata so readers can tolerate added or 
missing fields
+
+## Enable compatible mode
+
+```ts
+const fory = new Fory({ compatible: true });
+```
+
+Compatible mode is the right choice when:
+
+- multiple services roll out schema changes independently
+- older readers may see newer payloads
+- newer readers may see older payloads
+
+## Example
+
+Writer schema:
+
+```ts
+const writerType = Type.struct(
+  { typeId: 1001 },
+  {
+    name: Type.string(),
+    age: Type.int32(),
+  },
+);
+```
+
+Reader schema with fewer fields:
+
+```ts
+const readerType = Type.struct(
+  { typeId: 1001 },
+  {
+    name: Type.string(),
+  },
+);
+```
+
+With `compatible: true`, the reader can ignore fields it does not know about.
+
+## Per-struct evolving override
+
+In JavaScript, struct schemas can explicitly disable evolving metadata even 
when type identity is otherwise compatible.
+
+```ts
+const fixedType = Type.struct(
+  { typeId: 1002, evolving: false },
+  {
+    name: Type.string(),
+  },
+);
+```
+
+This produces a smaller payload than an otherwise evolving-compatible struct, 
but the reader must then assume the schema matches. In cross-language use, both 
sides must agree on whether that struct is evolving; if one side treats the 
type as compatible and the other uses `evolving: false`, the on-wire type kind 
no longer matches.
+
+## Practical guidance
+
+Choose **schema-consistent mode** when:
+
+- both ends deploy together
+- size and throughput matter most
+- schema drift is tightly controlled
+
+Choose **compatible mode** when:
+
+- services evolve independently
+- you need forward/backward tolerance
+- operational safety is more important than the last bytes of payload size
+
+## Cross-language requirement
+
+Compatible mode only helps when the logical type identity still matches across 
runtimes. The same struct must still be registered with the same numeric ID or 
name across languages.
+
+## Related Topics
+
+- [Type Registration](type-registration.md)
+- [Cross-Language](cross-language.md)
diff --git a/docs/guide/javascript/supported-types.md 
b/docs/guide/javascript/supported-types.md
new file mode 100644
index 0000000000..0186a18726
--- /dev/null
+++ b/docs/guide/javascript/supported-types.md
@@ -0,0 +1,194 @@
+---
+title: Supported Types
+sidebar_position: 40
+id: supported_types
+license: |
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+---
+
+This page summarizes the main JavaScript and TypeScript values supported by 
Fory JavaScript.
+
+## Primitive and Scalar Types
+
+| JavaScript/TypeScript    | Fory schema                                       
                                                        | Notes                 
                                                            |
+| ------------------------ | 
---------------------------------------------------------------------------------------------------------
 | 
---------------------------------------------------------------------------------
 |
+| `boolean`                | `Type.bool()`                                     
                                                        | Boolean value         
                                                            |
+| `number`                 | `Type.int8()` / `Type.int16()` / `Type.int32()` / 
`Type.float32()` / `Type.float64()` / unsigned variants | Pick explicit numeric 
width/encoding in schemas                                   |
+| `bigint`                 | `Type.int64()` / `Type.varInt64()` / 
`Type.uint64()` / tagged variants                                    | Use for 
64-bit integer fields                                                     |
+| `string`                 | `Type.string()`                                   
                                                        | Encoded as Latin1, 
UTF-16, or UTF-8 depending on content/runtime path             |
+| `Uint8Array`             | `Type.binary()`                                   
                                                        | Variable-length 
binary payload                                                    |
+| `Date`                   | `Type.timestamp()` / dynamic root date            
                                                        | Timestamps round-trip 
as `Date`                                                   |
+| `Date` or day count      | `Type.date()`                                     
                                                        | Date values 
deserialize as `Date`; some typed APIs also accept numeric day counts |
+| duration in milliseconds | `Type.duration()`                                 
                                                        | JavaScript currently 
exposes duration fields as numeric millisecond values        |
+| `BFloat16` or `number`   | `Type.bfloat16()`                                 
                                                        | Deserializes to 
`BFloat16`                                                        |
+| `number`                 | `Type.float16()`                                  
                                                        | Half-precision 
floating-point support                                             |
+
+## Integer Types
+
+Use explicit integer schema helpers when the wire contract matters.
+
+```ts
+Type.int8();
+Type.int16();
+Type.int32();
+Type.varInt32();
+Type.int64();
+Type.varInt64();
+Type.sliInt64();
+Type.uint8();
+Type.uint16();
+Type.uint32();
+Type.varUInt32();
+Type.uint64();
+Type.varUInt64();
+Type.taggedUInt64();
+```
+
+### Important JavaScript notes
+
+- `number` cannot safely represent all 64-bit integers.
+- For 64-bit integer fields, prefer `bigint` values in application code.
+- Dynamic root deserialization may return `bigint` for integer values that 
exceed JavaScript's safe integer range.
+
+## Floating-Point Types
+
+```ts
+Type.float16();
+Type.float32();
+Type.float64();
+Type.bfloat16();
+```
+
+`float16` and `bfloat16` are useful when interoperating with runtimes or 
payloads that use reduced-precision numeric formats.
+
+## Arrays and Typed Arrays
+
+### Generic arrays
+
+```ts
+Type.array(Type.string());
+Type.array(
+  Type.struct("example.item", {
+    id: Type.int64(),
+  }),
+);
+```
+
+These map to JavaScript arrays.
+
+### Optimized typed arrays
+
+Fory JavaScript supports specialized array schemas for compact numeric and 
boolean arrays.
+
+```ts
+Type.boolArray();
+Type.int16Array();
+Type.int32Array();
+Type.int64Array();
+Type.float16Array();
+Type.bfloat16Array();
+Type.float32Array();
+Type.float64Array();
+```
+
+Typical runtime values are:
+
+| Schema                 | Typical JavaScript value                            
                 |
+| ---------------------- | 
-------------------------------------------------------------------- |
+| `Type.boolArray()`     | `boolean[]`                                         
                 |
+| `Type.int16Array()`    | `Int16Array`                                        
                 |
+| `Type.int32Array()`    | `Int32Array`                                        
                 |
+| `Type.int64Array()`    | `BigInt64Array`                                     
                 |
+| `Type.float32Array()`  | `Float32Array`                                      
                 |
+| `Type.float64Array()`  | `Float64Array`                                      
                 |
+| `Type.float16Array()`  | `number[]`                                          
                 |
+| `Type.bfloat16Array()` | `BFloat16Array` or `number[]` as input; 
deserializes to `BFloat16[]` |
+
+## Maps and Sets
+
+```ts
+Type.map(Type.string(), Type.int32());
+Type.set(Type.string());
+```
+
+These map to JavaScript `Map` and `Set` values.
+
+## Structs
+
+```ts
+Type.struct("example.user", {
+  id: Type.int64(),
+  name: Type.string(),
+  tags: Type.array(Type.string()),
+});
+```
+
+Structs can be declared inline, by decorators, or nested within other schemas.
+
+## Enums
+
+```ts
+Type.enum("example.color", {
+  Red: 1,
+  Green: 2,
+  Blue: 3,
+});
+```
+
+Both numeric and string enum values are supported. JavaScript encodes enum 
members by ordinal position in the declared enum object order and maps that 
ordinal back to the corresponding JavaScript value on read, so cross-language 
peers must agree on the enum member order and shape, not only the literal 
values.
+
+## Nullable fields
+
+Use `.setNullable(true)` when a field may be `null`.
+
+```ts
+Type.string().setNullable(true);
+```
+
+## Dynamic fields
+
+Use `Type.any()` for dynamically typed content.
+
+```ts
+const eventType = Type.struct("example.event", {
+  kind: Type.string(),
+  payload: Type.any(),
+});
+```
+
+This is useful for polymorphic payload slots, but more explicit field types 
are preferable when the schema is stable.
+
+## Reference-tracked fields
+
+Fields that can participate in shared or circular graphs should opt in:
+
+```ts
+Type.struct("example.node").setTrackingRef(true).setNullable(true);
+```
+
+This requires `new Fory({ ref: true })` at the instance level.
+
+## Extension types and advanced areas
+
+JavaScript supports extension types through `Type.ext(...)` plus a custom 
serializer passed to `fory.register(...)`.
+
+The xlang specification also includes additional kinds such as unions. If you 
plan to depend on advanced features beyond the documented JavaScript surface, 
validate the exact API and interoperability behavior in your target runtime 
versions before committing to a shared wire contract.
+
+## Related Topics
+
+- [Basic Serialization](basic-serialization.md)
+- [References](references.md)
+- [Cross-Language](cross-language.md)
diff --git a/docs/guide/javascript/troubleshooting.md 
b/docs/guide/javascript/troubleshooting.md
new file mode 100644
index 0000000000..fa2dc61358
--- /dev/null
+++ b/docs/guide/javascript/troubleshooting.md
@@ -0,0 +1,113 @@
+---
+title: Troubleshooting
+sidebar_position: 90
+id: troubleshooting
+license: |
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+---
+
+This page covers common problems when using Fory JavaScript.
+
+## Non-xlang payloads cannot be deserialized
+
+The JavaScript runtime reads xlang payloads only. If you try to deserialize a 
non-xlang payload, deserialization fails.
+
+Make sure the producer is writing Fory xlang data.
+
+## `maxDepth must be an integer >= 2`
+
+`maxDepth` protects the deserializer from excessive nesting.
+
+```ts
+new Fory({ maxDepth: 100 });
+```
+
+Use a larger value only when your payloads genuinely need it.
+
+## `Binary size ... exceeds maxBinarySize`
+
+A binary field or payload exceeded the configured safety limit.
+
+```ts
+new Fory({ maxBinarySize: 128 * 1024 * 1024 });
+```
+
+Increase the limit only if the input size is expected and trusted.
+
+## `Collection size ... exceeds maxCollectionSize`
+
+A list, set, or map exceeded the configured collection limit.
+
+```ts
+new Fory({ maxCollectionSize: 2_000_000 });
+```
+
+This is commonly hit when a producer sends unexpectedly large arrays or maps.
+
+## `Field "..." is not nullable`
+
+A schema field was written as `null` but was not marked nullable.
+
+```ts
+const userType = Type.struct("example.user", {
+  name: Type.string(),
+  email: Type.string().setNullable(true),
+});
+```
+
+Mark nullable fields explicitly.
+
+## Reference graphs do not preserve identity
+
+Check both conditions:
+
+1. `new Fory({ ref: true })` is enabled
+2. the relevant schema fields use `.setTrackingRef(true)`
+
+Missing either one will usually turn the graph into ordinary value-based 
serialization.
+
+## Large integers come back as `bigint`
+
+This is expected for 64-bit integer values or for dynamic numbers that exceed 
JavaScript's safe integer range. Use explicit numeric schemas and `bigint` in 
your application when exact 64-bit integer semantics matter.
+
+## Debugging generated serializers
+
+Use `hooks.afterCodeGenerated` to inspect generated code.
+
+```ts
+const fory = new Fory({
+  hooks: {
+    afterCodeGenerated(code) {
+      console.error(code);
+      return code;
+    },
+  },
+});
+```
+
+## Optional `@apache-fory/hps` install issues
+
+`@apache-fory/hps` is optional and Node-specific. If installation fails, 
remove it from your config and continue with `@apache-fory/core` alone.
+
+```ts
+const fory = new Fory();
+```
+
+## Related Topics
+
+- [Basic Serialization](basic-serialization.md)
+- [References](references.md)
+- [Cross-Language](cross-language.md)
diff --git a/docs/guide/javascript/type-registration.md 
b/docs/guide/javascript/type-registration.md
new file mode 100644
index 0000000000..07e908aec8
--- /dev/null
+++ b/docs/guide/javascript/type-registration.md
@@ -0,0 +1,217 @@
+---
+title: Type Registration
+sidebar_position: 30
+id: type_registration
+license: |
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+---
+
+Type registration tells Fory JavaScript how to identify and encode 
user-defined structs and enums.
+
+## Registering Structs
+
+You can register a struct by numeric ID or by name.
+
+### Register by numeric type ID
+
+```ts
+const userType = Type.struct(
+  { typeId: 1001 },
+  {
+    id: Type.int64(),
+    name: Type.string(),
+  },
+);
+
+const fory = new Fory();
+const userSerde = fory.register(userType);
+```
+
+Use numeric IDs when:
+
+- you want compact metadata on the wire
+- you control IDs across all participating languages
+- the same logical type is registered everywhere with the same ID
+
+### Register by name
+
+```ts
+const userType = Type.struct(
+  { typeName: "example.user" },
+  {
+    id: Type.int64(),
+    name: Type.string(),
+  },
+);
+
+const fory = new Fory();
+const userSerde = fory.register(userType);
+```
+
+Named registration is usually easier to evolve operationally because it avoids 
central numeric ID allocation, but it writes more metadata than numeric IDs.
+
+### Explicit namespace and type name
+
+```ts
+const userType = Type.struct(
+  {
+    namespace: "example",
+    typeName: "user",
+  },
+  {
+    id: Type.int64(),
+    name: Type.string(),
+  },
+);
+```
+
+This corresponds to the named xlang type identity carried in metadata.
+
+## Registering with Decorators
+
+```ts
[email protected]({ typeId: 1001 })
+class User {
+  @Type.int64()
+  id!: bigint;
+
+  @Type.string()
+  name!: string;
+}
+
+const fory = new Fory();
+const { serialize, deserialize } = fory.register(User);
+```
+
+Decorator-based registration is convenient when you want your TypeScript class 
declaration and schema to live together.
+
+## Registering Enums
+
+Fory JavaScript supports both plain JavaScript enum-like objects and 
TypeScript enums.
+
+### JavaScript object enum
+
+```ts
+const Color = {
+  Red: 1,
+  Green: 2,
+  Blue: 3,
+};
+
+const fory = new Fory();
+const colorSerde = fory.register(Type.enum("example.color", Color));
+```
+
+### TypeScript enum
+
+```ts
+enum Status {
+  Pending = "pending",
+  Active = "active",
+}
+
+const fory = new Fory();
+fory.register(Type.enum("example.status", Status));
+```
+
+## Registration Scope
+
+Registration is per `Fory` instance.
+
+```ts
+const fory1 = new Fory();
+const fory2 = new Fory();
+
+fory1.register(
+  Type.struct("example.user", {
+    id: Type.int64(),
+  }),
+);
+
+// fory2 does not know that schema until you register it again there.
+```
+
+## Schema Handles Returned by `register`
+
+`register` returns a bound serializer pair:
+
+```ts
+const orderType = Type.struct("example.order", {
+  id: Type.int64(),
+  total: Type.float64(),
+});
+
+const { serializer, serialize, deserialize } = new Fory().register(orderType);
+```
+
+Use these bound functions for repeated operations on the same type.
+
+## Field Metadata
+
+Each field type can be refined with schema metadata.
+
+### Nullability
+
+```ts
+Type.string().setNullable(true);
+```
+
+### Reference tracking on a field
+
+```ts
+Type.struct("example.node").setTrackingRef(true);
+```
+
+This matters only when `new Fory({ ref: true })` is also enabled globally.
+
+### Dynamic dispatch
+
+```ts
+import { Dynamic, Type } from "@apache-fory/core";
+
+Type.struct("example.child").setDynamic(Dynamic.FALSE);
+```
+
+Use `dynamic` when the runtime type behavior must be controlled explicitly. In 
this implementation, `Dynamic.FALSE` forces monomorphic handling, 
`Dynamic.TRUE` forces polymorphic handling, and `Dynamic.AUTO` leaves the 
decision to the runtime. This is especially relevant for polymorphic fields in 
xlang payloads, while most users should keep the default behavior unless they 
are tuning a specific schema edge case.
+
+## Choosing IDs vs names
+
+Use **numeric IDs** when:
+
+- you want the smallest wire representation
+- your organization can keep IDs stable and unique
+- multiple runtimes are coordinated tightly
+
+Use **names** when:
+
+- you want easier decentralized coordination
+- schemas are shared by package/module name already
+- slightly larger metadata is acceptable
+
+## Cross-language requirement
+
+For xlang interoperability, the serializer and deserializer must agree on the 
same type identity:
+
+- same numeric ID, or
+- same namespace + type name
+
+The field schema must also match in a cross-language-compatible way. See 
[Cross-Language](cross-language.md).
+
+## Related Topics
+
+- [Basic Serialization](basic-serialization.md)
+- [Schema Evolution](schema-evolution.md)
+- [Cross-Language](cross-language.md)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to