diff --git a/.agents/docs-and-formatting.md b/.agents/docs-and-formatting.md
index 1d1d6da40c..e4d2d60dda 100644
--- a/.agents/docs-and-formatting.md
+++ b/.agents/docs-and-formatting.md
@@ -37,7 +37,7 @@ Load this file when changing documentation, public APIs, protocol specs, benchma
- Keep user-facing configuration text action focused. Do not put cache ownership,
cold/hot path, publish ordering, exact-local schema bypass, or TypeDef/TypeMeta routing
invariants there; put implementation invariants in `docs/specification/xlang_implementation_guide.md`,
- security classifications in `docs/object-serialization/deserialization-security-model.md`, and agent-only workflow rules in
+ security classifications in `docs/security/deserialization.md`, and agent-only workflow rules in
`.agents/**`.
- Documentation examples should use normal explicit imports, avoid unused imports, and keep common Fory types unqualified where that is the idiom.
- Generated Markdown under `docs/benchmarks/**` should satisfy markdownlint blank-line rules at generation time: no repeated blank lines and no extra blank line after final content.
diff --git a/.github/sync.yml b/.github/sync.yml
index 05c5290b32..ce497fe804 100644
--- a/.github/sync.yml
+++ b/.github/sync.yml
@@ -18,6 +18,9 @@
apache/fory-site@main:
- source: docs/index.md
dest: docs/index.md
+ - source: docs/images/
+ dest: docs/images/
+ deleteOrphaned: true
- source: docs/introduction/
dest: docs/introduction/
deleteOrphaned: true
@@ -45,9 +48,6 @@ apache/fory-site@main:
- source: docs/development/
dest: docs/development/
deleteOrphaned: true
- - source: docs/images/
- dest: docs/images/
- deleteOrphaned: true
- source: docs/specification/
dest: docs/specification/
deleteOrphaned: true
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index db809611bb..5585589a19 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -2011,6 +2011,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: 3.8
+ - name: Test release documentation updater
+ run: python -m unittest ci.test_release
- name: Set up .NET 8
uses: actions/setup-dotnet@v4
with:
diff --git a/AGENTS.md b/AGENTS.md
index 6f6dc1a67f..1d458373f2 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -9,11 +9,11 @@ This is the entry point for AI guidance in Apache Fory. Read this file first, th
- `.agents/docs-and-formatting.md`: documentation, specification, and markdown rules.
- `.agents/ci-and-pr.md`: code review workflow, CI triage, PR expectations, and commit conventions.
- `.agents/testing/integration-tests.md`: `integration_tests/` prerequisites, regeneration rules, and commands.
-- `docs/object-serialization/security.md`: user-facing security guidance for binary object
- serialization.
+- `docs/security/index.md`: contributor-facing security model index. This directory is internal
+ documentation and is intentionally excluded from the website sync.
+- `docs/security/threat-model.md`: project trust boundaries and downstream responsibilities.
+- `docs/security/deserialization.md`: implementation boundaries for untrusted deserialization.
- `docs/json/security.md`: user-facing security guidance for Fory JSON.
-- `docs/object-serialization/deserialization-security-model.md`: implementation boundaries for
- untrusted deserialization classification.
- `.agents/languages/java.md`
- `.agents/languages/csharp.md`
- `.agents/languages/cpp.md`
@@ -34,7 +34,7 @@ This is the entry point for AI guidance in Apache Fory. Read this file first, th
- Respect ownership. Keep logic, state, and helpers in their natural owner, and do not move serializer-local, context-local, runtime-type-local, or protocol-local problems into global utilities.
- Check the spec before implementation. For wire behavior and xlang mapping, use the specs as the source of truth and never copy one runtime's bug into another runtime just to make tests pass.
- Do not make assumptions about runtime behavior, ownership, registration, metadata construction, protocol semantics, or test coverage. Read the current code, owning docs/specs, and relevant tests before making a design judgment or implementation decision. If the evidence is incomplete, inspect more or state the uncertainty explicitly instead of filling gaps from memory or analogy with another runtime.
-- For untrusted deserialization, read `docs/object-serialization/deserialization-security-model.md` before changing allocation, stream filling, skip, reference, metadata, or policy validation behavior. Variable-length deserialization must not allocate or reserve backing/output capacity from attacker-declared lengths or counts before the byte owner has proven proportional readable bytes with `checkReadableBytes` or the runtime equivalent. Root graph memory reservation is accounting only and may happen before that byte check, but it must not replace the byte check.
+- For untrusted deserialization, read `docs/security/deserialization.md` before changing allocation, stream filling, skip, reference, metadata, or policy validation behavior. Variable-length deserialization must not allocate or reserve backing/output capacity from attacker-declared lengths or counts before the byte owner has proven proportional readable bytes with `checkReadableBytes` or the runtime equivalent. Root graph memory reservation is accounting only and may happen before that byte check, but it must not replace the byte check.
- Malformed input must surface as a controlled root-operation error and still run
root cleanup, but the exact exception type, error code, message, detection
layer, and detection point are not contracts unless a public API or
@@ -331,7 +331,8 @@ This is the entry point for AI guidance in Apache Fory. Read this file first, th
## Security
-User-facing security guidance lives only under Object Serialization and Fory JSON. Read
-`docs/object-serialization/security.md` or `docs/json/security.md` for the selected product. Before
-reporting or changing allocation, stream filling, skip, reference, metadata, or policy validation
-behavior, read `docs/object-serialization/deserialization-security-model.md`.
+User-facing object-serialization security guidance lives in each runtime directory, such as
+`docs/object-serialization/java/security.md`; Fory JSON guidance lives in `docs/json/security.md`.
+Contributor-facing security models remain under `docs/security/` and are excluded from the website.
+Before reporting or changing allocation, stream filling, skip, reference, metadata, or policy
+validation behavior, read `docs/security/deserialization.md`.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1cd0c63552..3b2d53c4dd 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -42,7 +42,7 @@ Key points:
## Testing
-For environmental requirements, please check [DEVELOPMENT.md](./docs/development/building.md).
+For environmental requirements, see the [Development guide](./docs/development/index.md).
### Python
@@ -229,7 +229,7 @@ To use Jetbrains IDEA IDE for Java Development, you need to configure the projec
And due to the usage of `sun.misc.Unsafe` API, which is not visible in Java 11+, you need to configure java compiler with `--releaese` option disabled.
-
+
## Website
@@ -244,4 +244,4 @@ If you want write a blog, or update other contents about the website, please sub
## Development
-For more information, please refer to [Development Guide](./docs/development/building.md).
+For more information, see the [Development guide](./docs/development/index.md).
diff --git a/README.md b/README.md
index dc5d5cd4a4..4a5e7bcb86 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
[](https://github.com/apache/fory/actions/workflows/ci.yml)
@@ -305,19 +305,19 @@ serializer setup.
**Development From Source**
-See [docs/development/building.md](docs/development/building.md).
+See [docs/development/index.md](docs/development/index.md).
Snapshots for Java, Scala, and Kotlin are available from
`https://repository.apache.org/snapshots/` with the matching `-SNAPSHOT` version.
## Choose a Serialization Format
-| Format | Use it when | Start here |
-| ------------- | ------------------------------------------------------------- | ------------------------------------------------------- |
-| Xlang binary | Data crosses language boundaries | [Xlang guide](docs/object-serialization/xlang/index.md) |
-| Native binary | Producer and consumer are in the same runtime family | [Native guide](docs/object-serialization/native.md) |
-| Row format | You need random field access or analytics-style partial reads | [Row Format](docs/row-format/index.md) |
-| Fory JSON | Java applications need high-performance standard JSON | [Fory JSON](java/fory-json/README.md) |
+| Format | Use it when | Start here |
+| ---------------------- | ------------------------------------------------------------- | --------------------------------------------------------------------- |
+| Xlang binary (default) | Data crosses language boundaries | [Cross-language interoperability](docs/object-serialization/xlang.md) |
+| Native binary | Producer and consumer are in the same runtime family | [Native guide](docs/object-serialization/native.md) |
+| Row format | You need random field access or analytics-style partial reads | [Row Format](docs/row-format/index.md) |
+| Fory JSON | Java applications need high-performance standard JSON | [Fory JSON](java/fory-json/README.md) |
For Java, Scala, Kotlin, Python, C++, Go, and Rust, use native mode for
same-language traffic. It avoids xlang's cross-language type mapping and
@@ -616,7 +616,7 @@ fun main() {
```
For shared/circular references, polymorphism, numeric IDs versus names, and
-type-mapping rules, see the [cross-language guide](docs/object-serialization/xlang) and
+type-mapping rules, see the [cross-language guide](docs/object-serialization/xlang.md) and
[type mapping specification](docs/specification/xlang_type_mapping.md).
## Native Serialization
@@ -909,11 +909,11 @@ security, and platform guides.
| Dart | [docs/object-serialization/dart](docs/object-serialization/dart) | [View](https://fory.apache.org/docs/object-serialization/dart/) |
| Scala | [docs/object-serialization/scala](docs/object-serialization/scala) | [View](https://fory.apache.org/docs/object-serialization/scala/) |
| Kotlin | [docs/object-serialization/kotlin](docs/object-serialization/kotlin) | [View](https://fory.apache.org/docs/object-serialization/kotlin/) |
-| Cross-language xlang | [docs/object-serialization/xlang](docs/object-serialization/xlang) | [View](https://fory.apache.org/docs/object-serialization/xlang/) |
+| Cross-language xlang | [docs/object-serialization/xlang.md](docs/object-serialization/xlang.md) | [View](https://fory.apache.org/docs/object-serialization/xlang) |
| Schema IDL/compiler | [docs/compiler](docs/compiler) | [View](https://fory.apache.org/docs/compiler/) |
| GraalVM native image | [docs/object-serialization/java/graalvm.md](docs/object-serialization/java/graalvm.md) | [View](https://fory.apache.org/docs/object-serialization/java/graalvm) |
| Android | [docs/object-serialization/java/android.md](docs/object-serialization/java/android.md) | [View](https://fory.apache.org/docs/object-serialization/java/android) |
-| Development | [docs/development/building.md](docs/development/building.md) | [View](docs/development/building.md) |
+| Development | [docs/development/index.md](docs/development/index.md) | [View](docs/development/index.md) |
**Specifications**
@@ -934,7 +934,7 @@ security, and platform guides.
## Contributing
Read [CONTRIBUTING.md](CONTRIBUTING.md) and
-[docs/development/building.md](docs/development/building.md) before sending pull requests. Bug
+[docs/development/index.md](docs/development/index.md) before sending pull requests. Bug
reports, docs fixes, tests, benchmarks, and implementation improvements are welcome.
## License
diff --git a/SECURITY.md b/SECURITY.md
index d83379eae6..f90a9fafc2 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -24,10 +24,11 @@ GitHub issues or pull requests for security reports.
## Security Models
-User-facing guidance is product-specific:
+User-facing guidance is capability- and runtime-specific:
-- [Object Serialization Security](docs/object-serialization/security.md)
+- [Object Serialization runtime guides](docs/object-serialization/index.md) (each runtime section
+ ends with its own Security page)
- [Fory JSON Security](docs/json/security.md)
For detailed implementation classification rules for untrusted deserialization, see the
-[Deserialization Security Model](docs/object-serialization/deserialization-security-model.md).
+[Deserialization Security Model](docs/security/deserialization.md).
diff --git a/ci/release.py b/ci/release.py
index 1bc7ef12c9..258836eeb4 100644
--- a/ci/release.py
+++ b/ci/release.py
@@ -1237,6 +1237,19 @@ def _update_release_doc_lines(lines, release_version):
def _update_release_doc_line(line, release_version):
+ scoped_patterns = (
+ r"(\bpyfory(?:\[[^\]]+\])?==)" + VERSION_PATTERN,
+ r"(\bgithub\.com/apache/fory/go/fory@v)" + VERSION_PATTERN,
+ r"(@apache-fory/(?:core|hps)@)" + VERSION_PATTERN,
+ )
+ scoped_update = line
+ has_scoped_dependency = False
+ for pattern in scoped_patterns:
+ if re.search(pattern, scoped_update):
+ has_scoped_dependency = True
+ scoped_update = re.sub(pattern, r"\g<1>" + release_version, scoped_update)
+ if has_scoped_dependency:
+ return scoped_update
if not _is_release_doc_line(line):
return line
if "crates.io-v" in line:
diff --git a/ci/test_release.py b/ci/test_release.py
new file mode 100644
index 0000000000..f06acf3bbb
--- /dev/null
+++ b/ci/test_release.py
@@ -0,0 +1,68 @@
+# 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.
+
+import unittest
+
+if __package__:
+ from . import release
+else:
+ import release
+
+
+class ReleaseDocVersionTest(unittest.TestCase):
+ def test_updates_release_doc_dependencies(self):
+ lines = [
+ "python -m pip install pyfory==1.5.0\n",
+ 'python -m pip install "pyfory[format]==1.5.0"\n',
+ "go get github.com/apache/fory/go/fory@v1.5.0\n",
+ "npm install @apache-fory/core@1.5.0 @apache-fory/hps@1.5.0\n",
+ "python -m pip install pyfory==1.5.0 grpcio==1.73.0 # Fory 1.4.0\n",
+ "go get github.com/apache/fory/go/fory@v1.5.0 # Fory 1.4.0\n",
+ "npm install @apache-fory/core@1.5.0 grpc@1.73.0 @apache-fory/hps@1.5.0\n",
+ 'fory = "1.5.0"\n',
+ " fory: 1.5.0\n",
+ ' .package(url: "https://github.com/apache/fory.git", exact: "1.5.0")\n',
+ 'implementation("org.apache.fory:fory-core:1.5.0")\n',
+ 'libraryDependencies += "org.apache.fory" %% "fory-scala" % "1.5.0"\n',
+ 'implementation("io.grpc:grpc-api:1.73.0")\n',
+ "The wire format was introduced in version 1.5.0.\n",
+ ]
+ expected = [
+ "python -m pip install pyfory==1.6.0\n",
+ 'python -m pip install "pyfory[format]==1.6.0"\n',
+ "go get github.com/apache/fory/go/fory@v1.6.0\n",
+ "npm install @apache-fory/core@1.6.0 @apache-fory/hps@1.6.0\n",
+ "python -m pip install pyfory==1.6.0 grpcio==1.73.0 # Fory 1.4.0\n",
+ "go get github.com/apache/fory/go/fory@v1.6.0 # Fory 1.4.0\n",
+ "npm install @apache-fory/core@1.6.0 grpc@1.73.0 @apache-fory/hps@1.6.0\n",
+ 'fory = "1.6.0"\n',
+ " fory: 1.6.0\n",
+ ' .package(url: "https://github.com/apache/fory.git", exact: "1.6.0")\n',
+ 'implementation("org.apache.fory:fory-core:1.6.0")\n',
+ 'libraryDependencies += "org.apache.fory" %% "fory-scala" % "1.6.0"\n',
+ 'implementation("io.grpc:grpc-api:1.73.0")\n',
+ "The wire format was introduced in version 1.5.0.\n",
+ ]
+
+ updated = release._update_release_doc_lines(lines, "1.6.0")
+
+ self.assertEqual(expected, updated)
+ self.assertEqual(expected, release._update_release_doc_lines(updated, "1.6.0"))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/ci/test_validate_fory_site_sync.py b/ci/test_validate_fory_site_sync.py
new file mode 100644
index 0000000000..d7856f4c3c
--- /dev/null
+++ b/ci/test_validate_fory_site_sync.py
@@ -0,0 +1,49 @@
+# 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.
+
+import pathlib
+import tempfile
+import unittest
+
+if __package__:
+ from . import validate_fory_site_sync
+else:
+ import validate_fory_site_sync
+
+
+class ForySiteSyncTest(unittest.TestCase):
+ def test_rejects_forbidden_doc_roots(self):
+ for source, dest in (
+ ("docs/security/", "docs/security/"),
+ ("docs/development/", "docs/security/"),
+ ):
+ content = f"""apache/fory-site@main:
+ - source: {source}
+ dest: {dest}
+"""
+ with (
+ self.subTest(source=source, dest=dest),
+ tempfile.TemporaryDirectory() as directory,
+ ):
+ sync_file = pathlib.Path(directory) / "sync.yml"
+ sync_file.write_text(content, encoding="utf-8")
+ with self.assertRaisesRegex(RuntimeError, "must not be synced"):
+ validate_fory_site_sync.parse_sync_mappings(sync_file)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/ci/validate_fory_site_sync.py b/ci/validate_fory_site_sync.py
index cce69c0411..83794e2f8b 100644
--- a/ci/validate_fory_site_sync.py
+++ b/ci/validate_fory_site_sync.py
@@ -26,6 +26,16 @@
from typing import List, Tuple
TARGET_REPO = "apache/fory-site@main"
+FORBIDDEN_SYNC_ROOTS = (
+ pathlib.PurePosixPath("docs/security"),
+)
+
+
+def is_forbidden_sync_path(path: str) -> bool:
+ candidate = pathlib.PurePosixPath(path.rstrip("/"))
+ return any(
+ candidate == root or root in candidate.parents for root in FORBIDDEN_SYNC_ROOTS
+ )
def parse_sync_mappings(sync_file: pathlib.Path) -> List[Tuple[str, str]]:
@@ -55,6 +65,10 @@ def parse_sync_mappings(sync_file: pathlib.Path) -> List[Tuple[str, str]]:
dest_match = re.match(r"^dest:\s*(.+)$", stripped)
if dest_match and source:
dest = dest_match.group(1).strip().strip("'\"")
+ if is_forbidden_sync_path(source) or is_forbidden_sync_path(dest):
+ raise RuntimeError(
+ f"path must not be synced to fory-site: {source} -> {dest}"
+ )
mappings.append((source, dest))
source = None
diff --git a/csharp/README.md b/csharp/README.md
index 1deff49129..690a428bd4 100644
--- a/csharp/README.md
+++ b/csharp/README.md
@@ -127,7 +127,7 @@ public sealed class User : Entity
An inaccessible base member is serialized only when it has `[ForyField]`.
Unmodifiable third-party bases use an external `BaseOnly` declaration. See the
-[class inheritance guide](https://fory.apache.org/docs/object-serialization/csharp/core-api/#class-inheritance).
+[class inheritance guide](https://fory.apache.org/docs/object-serialization/csharp/basic-serialization/#class-inheritance).
### 3. Shared and Circular References
diff --git a/docs/benchmarks/index.md b/docs/benchmarks/index.md
index 46af48783d..f9a50cc987 100644
--- a/docs/benchmarks/index.md
+++ b/docs/benchmarks/index.md
@@ -1,5 +1,5 @@
---
-title: Benchmarks
+title: Results
sidebar_position: 1
id: index
license: |
diff --git a/docs/benchmarks/object-serialization/xlang/swift/README.md b/docs/benchmarks/object-serialization/xlang/swift/README.md
index f3322f902b..91d4568221 100644
--- a/docs/benchmarks/object-serialization/xlang/swift/README.md
+++ b/docs/benchmarks/object-serialization/xlang/swift/README.md
@@ -2,11 +2,11 @@
This benchmark compares serialization and deserialization throughput for Apache Fory, Protocol Buffers, and JSON in Swift.
-## Benchmark Products
+## Benchmark Executables
The ordinary/xlang cases are built by `swift-benchmark`. External-type and
carrier comparisons are built by the separate `swift-external-benchmark`
-product, so building the ordinary product does not compile those models or
+executable, so building the ordinary executable does not compile those models or
serializer specializations.
## Throughput Plot
diff --git a/docs/compiler/generated-code/index.md b/docs/compiler/generated-code/index.md
index bf76e92ae3..ac9908fa7b 100644
--- a/docs/compiler/generated-code/index.md
+++ b/docs/compiler/generated-code/index.md
@@ -1,5 +1,5 @@
---
-title: Generated Code
+title: Overview
sidebar_position: 1
id: index
license: |
diff --git a/docs/development/building.md b/docs/development/building.md
deleted file mode 100644
index 4e6bb13846..0000000000
--- a/docs/development/building.md
+++ /dev/null
@@ -1,135 +0,0 @@
----
-title: Development
-sidebar_position: 20
-id: building
-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.
----
-
-## How to build Apache Fory™
-
-Clone the source tree from https://github.com/apache/fory.
-
-### Build Apache Fory™ Java
-
-```bash
-cd java
-mvn -T16 package
-```
-
-#### Environment Requirements
-
-- JDK 17+
-- Maven 3.6.3+
-
-### Build Apache Fory™ Python
-
-```bash
-cd python
-pip install -v -e .
-
-# Optional: build Cython extension (replace X.Y with your Python version)
-bazel build //:cp_fory_so --@rules_python//python/config_settings:python_version=X.Y
-```
-
-#### Environment Requirements
-
-- CPython 3.8+
-- Bazel 8+ (required when building Cython extensions)
-
-### Build Apache Fory™ C++
-
-```bash
-cd cpp
-bazel build //cpp/...
-```
-
-#### Environment Requirements
-
-- C++17 compiler
-- Bazel 8+
-
-### Build Apache Fory™ Go
-
-```bash
-cd go/fory
-go test -v ./...
-```
-
-Run Go xlang tests from Java test module:
-
-```bash
-cd java
-mvn -T16 install -DskipTests
-cd fory-core
-FORY_GO_JAVA_CI=1 ENABLE_FORY_DEBUG_OUTPUT=1 mvn test -Dtest=org.apache.fory.xlang.GoXlangTest
-```
-
-#### Environment Requirements
-
-- Go 1.24+
-
-### Build Apache Fory™ Rust
-
-```bash
-cd rust
-cargo build
-cargo test --features tests
-
-# Debug a specific test
-RUST_BACKTRACE=1 FORY_PANIC_ON_ERROR=1 ENABLE_FORY_DEBUG_OUTPUT=1 \
- cargo test --test mod $dir$::$test_file::$test_method -- --nocapture
-```
-
-#### Environment Requirements
-
-- Rust toolchain via rustup
-- `cargo-expand` (optional, for macro expansion debugging)
-
-### Build Apache Fory™ JavaScript
-
-```bash
-cd javascript
-npm install
-
-npm run build
-node ./node_modules/.bin/jest --ci --reporters=default --reporters=jest-junit
-```
-
-#### Environment Requirements
-
-- Node.js (LTS)
-- npm
-
-### Lint Markdown Docs
-
-```bash
-cd docs
-npx prettier --write "**/*.md"
-```
-
-#### Environment Requirements
-
-- Node.js (LTS)
-- npm
-
-## Contributing
-
-For contribution details, see [How to contribute to Apache Fory™](https://github.com/apache/fory/blob/main/CONTRIBUTING.md).
-For AI-assisted contributions, follow the
-[AI Contribution Policy](https://github.com/apache/fory/blob/main/AI_POLICY.md), including the
-required self-review, two-reviewer AI review loop, disclosure, and verification evidence for
-substantial AI assistance.
diff --git a/docs/development/cpp-debugging.md b/docs/development/cpp-debugging.md
index 360eef894b..761a972e42 100644
--- a/docs/development/cpp-debugging.md
+++ b/docs/development/cpp-debugging.md
@@ -18,9 +18,9 @@ license: |
limitations under the License.
---
-import JumpGeneratedFile from "@site/docs/images/jmp_generate_file.png";
-import VscodeDebugFory from "@site/docs/images/vscode_debug_fory.jpg";
-import VscodeSelectDebugRun from "@site/docs/images/vscode_select_debug_run.png";
+import JumpGeneratedFile from "@site/docs/development/jmp_generate_file.png";
+import VscodeDebugFory from "@site/docs/development/vscode_debug_fory.jpg";
+import VscodeSelectDebugRun from "@site/docs/development/vscode_select_debug_run.png";
## Debugging C++
diff --git a/docs/development/index.md b/docs/development/index.md
index 7044b921de..1584659bb0 100644
--- a/docs/development/index.md
+++ b/docs/development/index.md
@@ -1,5 +1,5 @@
---
-title: Development
+title: Build and Test
sidebar_position: 1
id: index
license: |
@@ -22,11 +22,121 @@ license: |
Contributor documentation covers repository setup, builds, tests, debugging, and release-oriented
workflows. It is separate from the user guides for released artifacts.
-## Start here
+Clone the source tree from https://github.com/apache/fory.
-- [Build and test the repository](building.md)
-- [Debug the C++ implementation](cpp-debugging.md)
-- [Contributing guide](https://github.com/apache/fory/blob/main/CONTRIBUTING.md)
+## Java
+
+```bash
+cd java
+mvn -T16 package
+```
+
+Requirements:
+
+- JDK 17+
+- Maven 3.6.3+
+
+## Python
+
+```bash
+cd python
+pip install -v -e .
+
+# Optional: build Cython extension (replace X.Y with your Python version)
+bazel build //:cp_fory_so --@rules_python//python/config_settings:python_version=X.Y
+```
+
+Requirements:
+
+- CPython 3.8+
+- Bazel 8+ (required when building Cython extensions)
+
+## C++
+
+```bash
+cd cpp
+bazel build //cpp/...
+```
+
+Requirements:
+
+- C++17 compiler
+- Bazel 8+
+
+## Go
+
+```bash
+cd go/fory
+go test -v ./...
+```
+
+Run Go xlang tests from the Java test module:
+
+```bash
+cd java
+mvn -T16 install -DskipTests
+cd fory-core
+FORY_GO_JAVA_CI=1 ENABLE_FORY_DEBUG_OUTPUT=1 mvn test -Dtest=org.apache.fory.xlang.GoXlangTest
+```
+
+Requirement: Go 1.24+.
+
+## Rust
+
+```bash
+cd rust
+cargo build
+cargo test --features tests
+
+# Debug a specific test
+RUST_BACKTRACE=1 FORY_PANIC_ON_ERROR=1 ENABLE_FORY_DEBUG_OUTPUT=1 \
+ cargo test --test mod $dir$::$test_file::$test_method -- --nocapture
+```
+
+Requirements:
+
+- Rust toolchain via rustup
+- `cargo-expand` (optional, for macro expansion debugging)
+
+## JavaScript
+
+```bash
+cd javascript
+npm install
+
+npm run build
+node ./node_modules/.bin/jest --ci --reporters=default --reporters=jest-junit
+```
+
+Requirements:
+
+- Node.js (LTS)
+- npm
+
+## Markdown
+
+```bash
+cd docs
+npx prettier --write "**/*.md"
+```
+
+Requirements:
+
+- Node.js (LTS)
+- npm
+
+## Debugging
+
+See [Debugging C++](cpp-debugging.md) for the repository's VS Code, Bazel, LLDB, and GDB setup.
Runtime-specific contributor instructions remain in each runtime's source tree and contributor
README when they are not part of the shared repository build.
+
+## Contributing
+
+For contribution details, see
+[How to contribute to Apache Fory™](https://github.com/apache/fory/blob/main/CONTRIBUTING.md).
+For AI-assisted contributions, follow the
+[AI Contribution Policy](https://github.com/apache/fory/blob/main/AI_POLICY.md), including the
+required self-review, two-reviewer AI review loop, disclosure, and verification evidence for
+substantial AI assistance.
diff --git a/docs/images/jmp_generate_file.png b/docs/development/jmp_generate_file.png
similarity index 100%
rename from docs/images/jmp_generate_file.png
rename to docs/development/jmp_generate_file.png
diff --git a/docs/images/vscode_debug_fory.jpg b/docs/development/vscode_debug_fory.jpg
similarity index 100%
rename from docs/images/vscode_debug_fory.jpg
rename to docs/development/vscode_debug_fory.jpg
diff --git a/docs/images/vscode_select_debug_run.png b/docs/development/vscode_select_debug_run.png
similarity index 100%
rename from docs/images/vscode_select_debug_run.png
rename to docs/development/vscode_select_debug_run.png
diff --git a/docs/grpc/architecture.md b/docs/grpc/architecture.md
deleted file mode 100644
index ffe4c30162..0000000000
--- a/docs/grpc/architecture.md
+++ /dev/null
@@ -1,41 +0,0 @@
----
-title: Architecture
-sidebar_position: 2
-id: architecture
-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.
----
-
-Generated service companions use normal gRPC servers, channels, method descriptors, deadlines,
-status codes, interceptors, and streaming APIs. Fory-generated marshallers encode and decode the
-generated request and response models.
-
-## Ownership boundary
-
-Fory can generate service companions for application-provided gRPC runtimes.
-Those companions provide Fory serialization for request and response objects;
-the application and gRPC stack still own listeners, channels, credentials,
-authentication, authorization, deadlines, retries, and transport lifecycle.
-
-Fory packages do not add a gRPC implementation as a hard dependency. The application selects and
-configures the runtime's gRPC libraries.
-
-## Generated service surface
-
-The compiler emits runtime-idiomatic service bases, clients or stubs, method metadata, and Fory
-marshallers. Model generation is documented under
-[Generated Code](../compiler/generated-code/index.md); the runtime pages document server and client
-integration.
diff --git a/docs/grpc/index.md b/docs/grpc/index.md
index 5e019a79ff..a0c4712e0a 100644
--- a/docs/grpc/index.md
+++ b/docs/grpc/index.md
@@ -1,5 +1,5 @@
---
-title: Fory gRPC
+title: Overview
sidebar_position: 1
id: index
license: |
@@ -54,8 +54,52 @@ generation with `--grpc-python-mode=sync`. JavaScript uses `@grpc/grpc-js` for
Node.js; browser clients are generated separately with `--grpc-web` and use
`grpc-web`.
+## Architecture
+
+Generated service companions use normal gRPC servers, channels, method descriptors, deadlines,
+status codes, interceptors, and streaming APIs. Fory-generated marshallers encode and decode the
+generated request and response models.
+
+### Ownership Boundary
+
+Fory can generate service companions for application-provided gRPC runtimes. Those companions
+provide Fory serialization for request and response objects; the application and gRPC stack still
+own listeners, channels, credentials, authentication, authorization, deadlines, retries, and
+transport lifecycle.
+
+Fory packages do not add a gRPC implementation as a hard dependency. The application selects and
+configures the runtime's gRPC libraries.
+
+### Generated Service Surface
+
+The compiler emits runtime-idiomatic service bases, clients or stubs, method metadata, and Fory
+marshallers. Model generation is documented under
+[Generated Code](../compiler/generated-code/index.md); the runtime pages document server and client
+integration.
+
+## Interoperability
+
+Fory gRPC peers interoperate only when they use the same generated service contract, matching Fory
+type identities, and compatible generated model schemas.
+
+### Protocol Boundary
+
+The transport is gRPC, but the message bytes are Fory payloads. Generic protobuf clients and server
+reflection tools cannot decode those payloads as protobuf messages. Generate every peer through a
+supported Fory compiler frontend.
+
+### Verification
+
+Test at least one unary call and every streaming shape used by the service. A protobuf
+`UNIMPLEMENTED` or decode failure usually means the peer used an ordinary protobuf stub or a
+different generated service contract.
+
## Runtime Guides
+Java, Python, C++, Go, Rust, JavaScript/TypeScript, C#, Dart, Scala, and Kotlin have documented gRPC
+companions. Use the [support matrix](../introduction/support-matrix.md) and the selected runtime page
+for current dependencies and streaming support.
+
| Runtime | Guide |
| --------------------- | ------------------------------------- |
| Java | [Java](java.md) |
@@ -68,6 +112,3 @@ Node.js; browser clients are generated separately with `--grpc-web` and use
| Dart | [Dart](dart.md) |
| Scala | [Scala](scala.md) |
| Kotlin | [Kotlin](kotlin.md) |
-
-See [Architecture](architecture.md) for payload and transport ownership and
-[Interoperability](interoperability.md) for peer compatibility.
diff --git a/docs/grpc/interoperability.md b/docs/grpc/interoperability.md
deleted file mode 100644
index 1de36c4885..0000000000
--- a/docs/grpc/interoperability.md
+++ /dev/null
@@ -1,41 +0,0 @@
----
-title: Interoperability
-sidebar_position: 3
-id: interoperability
-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 gRPC peers interoperate only when they use the same generated service contract, matching Fory
-type identities, and compatible generated model schemas.
-
-## Protocol boundary
-
-The transport is gRPC, but the message bytes are Fory payloads. Generic protobuf clients and server
-reflection tools cannot decode those payloads as protobuf messages. Generate every peer through a
-supported Fory compiler frontend.
-
-## Supported generated companions
-
-Java, Python, C++, Go, Rust, JavaScript/TypeScript, C#, Dart, Scala, and Kotlin have documented gRPC
-companions. Use the [support matrix](../introduction/support-matrix.md) and the selected runtime page
-for current dependencies and streaming support.
-
-## Verification
-
-Test at least one unary call and every streaming shape used by the service. A protobuf
-`UNIMPLEMENTED` or decode failure usually means the peer used an ordinary protobuf stub or a
-different generated service contract.
diff --git a/docs/images/logo/fory-horizontal.png b/docs/images/fory-logo.png
similarity index 100%
rename from docs/images/logo/fory-horizontal.png
rename to docs/images/fory-logo.png
diff --git a/docs/images/idea_jdk11.png b/docs/images/idea-jdk11.png
similarity index 100%
rename from docs/images/idea_jdk11.png
rename to docs/images/idea-jdk11.png
diff --git a/docs/images/logo/fory-horizontal-black.png b/docs/images/logo/fory-horizontal-black.png
deleted file mode 100644
index 2fff2442c4..0000000000
Binary files a/docs/images/logo/fory-horizontal-black.png and /dev/null differ
diff --git a/docs/images/logo/fory-horizontal-black1.png b/docs/images/logo/fory-horizontal-black1.png
deleted file mode 100644
index d2495dc8d6..0000000000
Binary files a/docs/images/logo/fory-horizontal-black1.png and /dev/null differ
diff --git a/docs/images/logo/fory-horizontal-white.png b/docs/images/logo/fory-horizontal-white.png
deleted file mode 100644
index 759074c222..0000000000
Binary files a/docs/images/logo/fory-horizontal-white.png and /dev/null differ
diff --git a/docs/images/logo/fory-horizontal-white1.png b/docs/images/logo/fory-horizontal-white1.png
deleted file mode 100644
index a310816cf9..0000000000
Binary files a/docs/images/logo/fory-horizontal-white1.png and /dev/null differ
diff --git a/docs/images/logo/fory-horizontal1.png b/docs/images/logo/fory-horizontal1.png
deleted file mode 100644
index eb7039f122..0000000000
Binary files a/docs/images/logo/fory-horizontal1.png and /dev/null differ
diff --git a/docs/images/logo/fory-icon-black.png b/docs/images/logo/fory-icon-black.png
deleted file mode 100644
index 5056720de4..0000000000
Binary files a/docs/images/logo/fory-icon-black.png and /dev/null differ
diff --git a/docs/images/logo/fory-icon-white.png b/docs/images/logo/fory-icon-white.png
deleted file mode 100644
index 6f75304c23..0000000000
Binary files a/docs/images/logo/fory-icon-white.png and /dev/null differ
diff --git a/docs/images/logo/fory-icon.png b/docs/images/logo/fory-icon.png
deleted file mode 100644
index fb3c9749f3..0000000000
Binary files a/docs/images/logo/fory-icon.png and /dev/null differ
diff --git a/docs/images/logo/fory-vertical-black.png b/docs/images/logo/fory-vertical-black.png
deleted file mode 100644
index 4a6cba6723..0000000000
Binary files a/docs/images/logo/fory-vertical-black.png and /dev/null differ
diff --git a/docs/images/logo/fory-vertical-black1.png b/docs/images/logo/fory-vertical-black1.png
deleted file mode 100644
index 2bef2eda27..0000000000
Binary files a/docs/images/logo/fory-vertical-black1.png and /dev/null differ
diff --git a/docs/images/logo/fory-vertical-white.png b/docs/images/logo/fory-vertical-white.png
deleted file mode 100644
index d2daf413e8..0000000000
Binary files a/docs/images/logo/fory-vertical-white.png and /dev/null differ
diff --git a/docs/images/logo/fory-vertical-white1.png b/docs/images/logo/fory-vertical-white1.png
deleted file mode 100644
index c56e4a66bf..0000000000
Binary files a/docs/images/logo/fory-vertical-white1.png and /dev/null differ
diff --git a/docs/images/logo/fory-vertical.png b/docs/images/logo/fory-vertical.png
deleted file mode 100644
index 8962eba810..0000000000
Binary files a/docs/images/logo/fory-vertical.png and /dev/null differ
diff --git a/docs/images/logo/fory-vertical1.png b/docs/images/logo/fory-vertical1.png
deleted file mode 100644
index 1fa11e55c4..0000000000
Binary files a/docs/images/logo/fory-vertical1.png and /dev/null differ
diff --git a/docs/introduction/choose-a-format.md b/docs/introduction/choose-a-format.md
index 0d7225c6a4..240590d1c5 100644
--- a/docs/introduction/choose-a-format.md
+++ b/docs/introduction/choose-a-format.md
@@ -19,12 +19,16 @@ license: |
limitations under the License.
---
-| Format | Use it when | Start here |
-| ------------- | ------------------------------------------------------------- | -------------------------------------------------------------- |
-| Xlang binary | Data crosses language boundaries | [Cross-language guide](../object-serialization/xlang/index.md) |
-| Native binary | Producer and consumer are in the same language | Language guide |
-| Row format | You need random field access or analytics-style partial reads | [Row format spec](../row-format/index.md) |
-| Fory JSON | Java applications need high-performance standard JSON | [Fory JSON guide](../json/index.md) |
+| Format or mode | Data model | Use it when | Interoperability | Start here |
+| -------------- | ------------------------------------ | ------------------------------------------------------------- | --------------------------------------------------------------------------- | -------------------------------------------------------- |
+| Xlang binary | Portable object graphs | Data crosses language boundaries | Shared wire format across supported runtimes | [Cross-language guide](../object-serialization/xlang.md) |
+| Native binary | Runtime-native object graphs | Producer and consumer use the same language | Same runtime family only | [Object Serialization](../object-serialization/index.md) |
+| Row Format | Random-access binary rows | You need random field access or analytics-style partial reads | Standard Row is shared by Java, Python, C++, and Rust; Compact is Java-only | [Row Format guide](../row-format/index.md) |
+| Fory JSON | Standard JSON mapped to Java objects | Java applications need high-performance standard JSON | Standard JSON text | [Fory JSON guide](../json/index.md) |
+
+Xlang and native are sibling modes of Object Serialization. Use them when the receiver needs to
+reconstruct an object graph. Row Format and Fory JSON are separate formats, not additional Object
+Serialization modes.
For Java, Scala, Kotlin, Python, C++, Go, and Rust, use native mode for
same-language traffic. It avoids xlang's cross-language type mapping and
@@ -59,3 +63,12 @@ Choose xlang or native mode when you need to reconstruct object graphs. Choose R
trusted analytical data that benefits from random field access. Choose Fory JSON for standard JSON
in Java applications. Use Fory IDL and the compiler when multiple teams need one schema-first
contract; it generates models that use the relevant Fory capability.
+
+## Related capabilities
+
+[Fory IDL and the compiler](../compiler/index.md) generate native models for supported runtimes.
+Service definitions can also generate [Fory gRPC](../grpc/index.md) code. Neither capability defines
+another serialization format.
+
+Protocol implementers should follow the normative format documentation under
+[Specifications](../specification/xlang_serialization_spec.md).
diff --git a/docs/introduction/index.md b/docs/introduction/index.md
index 3f0bd9eed0..2245ef3700 100644
--- a/docs/introduction/index.md
+++ b/docs/introduction/index.md
@@ -1,5 +1,5 @@
---
-title: Introduction
+title: Overview
sidebar_position: 1
id: index
license: |
diff --git a/docs/introduction/product-model.md b/docs/introduction/product-model.md
deleted file mode 100644
index 3379dd6b52..0000000000
--- a/docs/introduction/product-model.md
+++ /dev/null
@@ -1,47 +0,0 @@
----
-title: Product Model
-sidebar_position: 3
-id: product-model
-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 exposes three serialization products and one schema toolchain. Start from the data
-contract you need, then choose a runtime API.
-
-## Serialization products
-
-| Product | Data model | Interoperability boundary |
-| ---------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------- |
-| Binary Object Serialization: xlang mode | Portable object graphs | Shared wire format across supported runtimes |
-| Binary Object Serialization: native mode | Runtime-native object graphs | Same runtime family only |
-| Row Format | Random-access binary rows | Standard Row is shared by Java, Python, C++, and Rust; Compact Row is Java-only |
-| Fory JSON | Standard JSON mapped to Java objects | Java API with text interoperability |
-
-Xlang and native are sibling modes of Binary Object Serialization. Row Format and Fory JSON are
-separate products; neither is a third object-serialization mode.
-
-## Schema and services
-
-[Fory IDL and the compiler](../compiler/index.md) generate native models for supported runtimes.
-Service definitions can also generate [Fory gRPC](../grpc/index.md) companions. The compiler and
-gRPC integration do not define additional serialization formats.
-
-## Normative formats
-
-Protocol implementers should use the unchanged [Specification](../specification/xlang_serialization_spec.md)
-surface. User guides explain tasks and link to the exact specification instead of duplicating its
-wire-level rules.
diff --git a/docs/introduction/support-matrix.md b/docs/introduction/support-matrix.md
index 5127bd48fb..7fee55a395 100644
--- a/docs/introduction/support-matrix.md
+++ b/docs/introduction/support-matrix.md
@@ -20,7 +20,7 @@ license: |
---
Use this matrix to confirm the documented API surface before choosing a capability. A runtime page
-does not imply support for every Fory product.
+does not imply support for every Fory capability.
| Capability | Documented runtimes | Interoperability |
| --------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------- |
@@ -33,5 +33,5 @@ does not imply support for every Fory product.
| Fory gRPC | Java, Python, C++, Go, Rust, JavaScript/TypeScript, C#, Dart, Scala, Kotlin | Peers must use matching generated Fory service contracts |
Platform constraints such as [Android](../object-serialization/java/android.md) and
-[GraalVM Native Image](../object-serialization/java/graalvm.md) are documented by the owning Java
-object-serialization and Fory JSON products.
+[GraalVM Native Image](../object-serialization/java/graalvm.md) are documented in the Java Object
+Serialization and Fory JSON guides.
diff --git a/docs/json/index.md b/docs/json/index.md
index 6ab963dd7a..47a2e3683f 100644
--- a/docs/json/index.md
+++ b/docs/json/index.md
@@ -1,5 +1,5 @@
---
-title: Fory JSON
+title: Overview
sidebar_position: 1
id: index
license: |
@@ -63,6 +63,6 @@ native or xlang protocol when reference identity or cycles are required.
## Related Java guides
For binary serialization, start with [Java Object Serialization](../object-serialization/java/index.md)
-and choose [xlang](../object-serialization/java/xlang.md) or
+and choose [xlang](../object-serialization/java/basic-serialization.md#cross-language-interoperability) or
[native](../object-serialization/java/native.md). Binary builder options are documented separately
in [Java Configuration](../object-serialization/java/configuration.md).
diff --git a/docs/object-serialization/core-concepts.md b/docs/object-serialization/core-concepts.md
new file mode 100644
index 0000000000..c122e6d450
--- /dev/null
+++ b/docs/object-serialization/core-concepts.md
@@ -0,0 +1,122 @@
+---
+title: Core Concepts
+sidebar_position: 1
+id: core-concepts
+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 object serialization turns an object graph into bytes and reconstructs that graph later. The
+same concepts apply to the default [xlang mode](xlang.md) and to supported
+[native modes](native.md); the selected mode determines which types and wire rules are available.
+
+## Object graphs
+
+A root value may contain scalar fields, collections, maps, nested objects, repeated references, and
+cycles. Serialization walks that graph from the root. Deserialization creates a new graph from the
+encoded type and field data.
+
+This is different from serializing a row or a JSON document. Object serialization can preserve
+runtime types and object identity so the reader can reconstruct application objects rather than
+only values. Use [Row Format](../row-format/index.md) for trusted analytical rows and
+[Fory JSON](../json/index.md) for JSON interchange.
+
+## Runtime instances and registration
+
+A Fory instance owns its mode, schema behavior, reference settings, registered types, custom
+serializers, and read limits. Configure and register the instance before its first root
+serialization or deserialization operation, then reuse it. Registration is frozen after the first
+root operation so the same instance always resolves a type in the same way.
+
+Thread-safety differs by runtime. Some runtimes provide a thread-safe wrapper or pool; others use
+one instance per thread or task. Follow the selected language guide instead of sharing an ordinary
+instance without checking its concurrency contract.
+
+## Types and type identity
+
+Built-in types have identities owned by Fory. Application structs, classes, enums, unions, and
+extension types use a registered numeric ID or name. Type identity answers _which serializer and
+model should read this value_; a field schema describes _what data that model contains_.
+
+A statically known field can use its declared type directly. A dynamic field also carries the
+concrete runtime type needed for interfaces, abstract classes, trait objects, broad object types,
+or heterogeneous values. Dynamic typing is more flexible but requires every possible concrete type
+to be registered and supported by the selected mode.
+
+In xlang mode, peers must coordinate the same portable type identity and mapping. Native mode may
+use runtime-specific identities and types. See [Xlang Serialization](xlang.md) for the portable
+rules and each language's Type Registration page for its exact API.
+
+## Schemas and evolution
+
+A schema describes the fields and nested types of a structured value. Compatible mode carries
+metadata that lets a reader handle supported additions, removals, reordering, and type adaptations.
+Use it when readers and writers may deploy independently.
+
+Same-schema mode assumes both sides use the same type identity, fields, nested types, nullability,
+and reference metadata. It reduces metadata and payload size, but a schema mismatch is an error.
+Use it only when one release process keeps every reader and writer aligned.
+
+Field IDs or names should remain stable after a contract is published. Renaming or reusing an
+identity can turn an intended evolution into a different field or type.
+
+## Nullability
+
+Nullability determines whether a value position may contain no value. Languages express it through
+nullable references, option types, pointers, annotations, or schema metadata. A nullable field is
+not the same as a field whose value happens to use a default.
+
+Keep nullability consistent across readers and writers. Compatible mode can handle documented
+nullable and missing-field cases, but it cannot place a remote null into a local carrier that has
+no valid null or missing-value representation.
+
+## Reference tracking
+
+Reference tracking preserves object identity. Enable it when a graph contains the same object more
+than once or contains a cycle. Without reference tracking, repeated values may become separate
+objects and cycles may recurse until the operation fails.
+
+Leave reference tracking disabled for value-shaped, acyclic data when identity does not matter; it
+adds per-object metadata and lookup work. Some runtimes combine a global setting with field-level
+metadata, so use the language-specific References or Basic Serialization page for exact behavior.
+
+## Polymorphism
+
+Polymorphism stores the concrete type of a value whose declared position is broader. The reader
+must know and accept that concrete type, and the type must be representable in the selected mode.
+
+Host-language inheritance alone does not create a portable contract. For cross-language data,
+model only alternatives that have xlang mappings on every peer. For same-runtime data, native mode
+may support additional runtime-specific class, trait, or hook behavior.
+
+## Custom serializers
+
+Use a custom serializer when a type needs a representation that built-in schema inference cannot
+provide. Registration connects the custom serializer to the application type. A custom serializer
+must follow the selected mode's rules: xlang serializers need a portable representation, while
+native serializers may use runtime-specific data and hooks.
+
+Prefer built-in serializers and generated models when they already describe the type. They keep
+schema evolution, reference handling, and cross-language behavior easier to reason about.
+
+## Continue with a mode
+
+- [Xlang Serialization](xlang.md) is the default and is required when different language runtimes
+ exchange bytes.
+- [Native Serialization](native.md) is for supported same-runtime use cases that need native types
+ or behavior.
+- Choose a language section after selecting a mode to find installation, API, configuration,
+ registration, platform, security, and troubleshooting guidance.
diff --git a/docs/object-serialization/cpp/core-api.md b/docs/object-serialization/cpp/basic-serialization.md
similarity index 51%
rename from docs/object-serialization/cpp/core-api.md
rename to docs/object-serialization/cpp/basic-serialization.md
index c9ca5cbc3d..275ad53ed4 100644
--- a/docs/object-serialization/cpp/core-api.md
+++ b/docs/object-serialization/cpp/basic-serialization.md
@@ -1,7 +1,7 @@
---
title: Basic Serialization
-sidebar_position: 3
-id: core-api
+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
@@ -19,7 +19,7 @@ license: |
limitations under the License.
---
-This page covers basic object graph serialization and the core serialization APIs.
+This page covers basic object graph serialization and the core serialization APIs in the default xlang mode.
## Object Graph Serialization
@@ -355,6 +355,285 @@ fory.register_struct(2);
- **Disable Tracking**: Use `track_ref(false)` when references aren't needed
- **Compact Encoding**: Variable-length encoding for space efficiency
+## Cross-Language Interoperability
+
+The default xlang format is shared by all Fory runtimes. The following sections cover its cross-language type mapping, type identity, and interoperability requirements.
+
+This page explains how to use Fory xlang serialization between C++ and other languages.
+
+### Overview
+
+Apache Fory™ enables seamless data exchange between C++, Java, Python, Go, Rust,
+JavaScript/TypeScript, C#, Swift, Dart, Scala, and Kotlin. Xlang mode ensures
+binary compatibility across all supported languages.
+
+### Xlang Configuration
+
+C++ defaults to xlang mode. Compatible schema evolution is also the xlang default. Set the mode explicitly in xlang examples:
+
+```cpp
+#include "fory/serialization/fory.h"
+
+using namespace fory::serialization;
+
+auto fory = Fory::builder().xlang(true).build();
+```
+
+### Xlang Example
+
+#### C++ Producer
+
+```cpp
+#include "fory/serialization/fory.h"
+#include
+
+using namespace fory::serialization;
+
+struct Message {
+ std::string topic;
+ int64_t timestamp;
+ std::map headers;
+ std::vector payload;
+
+ bool operator==(const Message &other) const {
+ return topic == other.topic && timestamp == other.timestamp &&
+ headers == other.headers && payload == other.payload;
+ }
+};
+FORY_STRUCT(Message, topic, timestamp, headers, payload);
+
+int main() {
+ auto fory = Fory::builder().xlang(true).build();
+ fory.register_struct(100);
+
+ Message msg{
+ "events.user",
+ 1699999999000,
+ {{"content-type", "application/json"}},
+ {'h', 'e', 'l', 'l', 'o'}
+ };
+
+ auto result = fory.serialize(msg);
+ if (result.ok()) {
+ auto bytes = std::move(result).value();
+ // write to file, send over network, etc.
+ std::ofstream file("message.bin", std::ios::binary);
+ file.write(reinterpret_cast(bytes.data()), bytes.size());
+ }
+ return 0;
+}
+```
+
+#### Java Consumer
+
+```java
+import org.apache.fory.Fory;
+
+public class Message {
+ public String topic;
+ public long timestamp;
+ public Map headers;
+ public byte[] payload;
+}
+
+public class Consumer {
+ public static void main(String[] args) throws Exception {
+ Fory fory = Fory.builder()
+ .withXlang(true)
+ .build();
+ fory.register(Message.class, 100); // Same ID as C++
+
+ byte[] bytes = Files.readAllBytes(Path.of("message.bin"));
+ Message msg = (Message) fory.deserialize(bytes);
+
+ System.out.println("Topic: " + msg.topic);
+ System.out.println("Timestamp: " + msg.timestamp);
+ }
+}
+```
+
+#### Python Consumer
+
+```python
+import pyfory
+
+class Message:
+ topic: str
+ timestamp: int
+ headers: dict[str, str]
+ payload: bytes
+
+fory = pyfory.Fory(xlang=True)
+fory.register(Message, type_id=100) # Same ID as C++
+
+with open("message.bin", "rb") as f:
+ data = f.read()
+
+msg = fory.deserialize(data)
+print(f"Topic: {msg.topic}")
+print(f"Timestamp: {msg.timestamp}")
+```
+
+### Type Mapping
+
+#### Primitive Types
+
+| C++ Type | Java Type | Python Type | Go Type | Rust Type |
+| ------------------ | ---------- | ----------------- | ------------------- | ---------- |
+| `bool` | `boolean` | `bool` | `bool` | `bool` |
+| `int8_t` | `byte` | `int` | `int8` | `i8` |
+| `int16_t` | `short` | `int` | `int16` | `i16` |
+| `int32_t` | `int` | `int` | `int32` | `i32` |
+| `int64_t` | `long` | `int` | `int64` | `i64` |
+| `float` | `float` | `float` | `float32` | `f32` |
+| `double` | `double` | `float` | `float64` | `f64` |
+| `fory::float16_t` | `Float16` | `pyfory.Float16` | `float16.Float16` | `Float16` |
+| `fory::bfloat16_t` | `BFloat16` | `pyfory.BFloat16` | `bfloat16.BFloat16` | `BFloat16` |
+
+#### String Types
+
+| C++ Type | Java Type | Python Type | Go Type | Rust Type |
+| ------------- | --------- | ----------- | -------- | --------- |
+| `std::string` | `String` | `str` | `string` | `String` |
+
+#### Collection Types
+
+| C++ Type | Java Type | Python Type | Go Type | Rust Type |
+| ------------------------------------------- | -------------- | --------------- | --------------------- | --------------- |
+| `std::vector` | `List` | `list` | `[]T` | `Vec` |
+| `std::vector` | `Float16List` | `Float16Array` | `[]float16.Float16` | `Vec` |
+| `std::vector` | `BFloat16List` | `BFloat16Array` | `[]bfloat16.BFloat16` | `Vec` |
+| `std::set` | `Set` | `set` | `map[T]struct{}` | `HashSet` |
+| `std::map` / `std::unordered_map` | `Map` | `dict` | `map[K]V` | `HashMap` |
+
+#### Lists and Dense Arrays
+
+`std::vector` maps to Fory `list` by default in handwritten C++ structs.
+Use the field metadata DSL's array node when the schema is dense `array`.
+
+| Fory schema | C++ metadata sketch |
+| ----------------- | ---------------------------------------- |
+| `list` | `fory::F(id).list(fory::T::int32())` |
+| `array` | `fory::F(id).array(fory::T::bool_())` |
+| `array` | `fory::F(id).array(fory::T::int8())` |
+| `array` | `fory::F(id).array(fory::T::int16())` |
+| `array` | `fory::F(id).array(fory::T::int32())` |
+| `array` | `fory::F(id).array(fory::T::int64())` |
+| `array` | `fory::F(id).array(fory::T::uint8())` |
+| `array` | `fory::F(id).array(fory::T::uint16())` |
+| `array` | `fory::F(id).array(fory::T::uint32())` |
+| `array` | `fory::F(id).array(fory::T::uint64())` |
+| `array` | `fory::F(id).array(fory::T::float16())` |
+| `array` | `fory::F(id).array(fory::T::bfloat16())` |
+| `array` | `fory::F(id).array(fory::T::float32())` |
+| `array` | `fory::F(id).array(fory::T::float64())` |
+
+#### Temporal Types
+
+| C++ Type | Java Type | Python Type | Go Type |
+| ----------------- | ----------- | --------------- | --------------- |
+| `fory::Timestamp` | `Instant` | `datetime` | `time.Time` |
+| `fory::Duration` | `Duration` | `timedelta` | `time.Duration` |
+| `fory::Date` | `LocalDate` | `datetime.date` | `time.Time` |
+
+### Field Order Requirements
+
+**Critical:** Fields are sorted by snake_case field name. The converted names must match across languages.
+
+#### C++
+
+```cpp
+struct Person {
+ std::string name; // Field 0
+ int32_t age; // Field 1
+ std::string email; // Field 2
+};
+FORY_STRUCT(Person, name, age, email); // Order matters!
+```
+
+#### Java
+
+```java
+public class Person {
+ public String name; // Field 0
+ public int age; // Field 1
+ public String email; // Field 2
+}
+```
+
+#### Python
+
+```python
+class Person:
+ name: str # Field 0
+ age: int # Field 1
+ email: str # Field 2
+```
+
+### Type ID Consistency
+
+All languages must use the same type IDs:
+
+```cpp
+// C++
+fory.register_struct(100);
+fory.register_struct(101);
+fory.register_struct(102);
+```
+
+```java
+// Java
+fory.register(Person.class, 100);
+fory.register(Address.class, 101);
+fory.register(Order.class, 102);
+```
+
+```python
+# Python
+fory.register(Person, type_id=100)
+fory.register(Address, type_id=101)
+fory.register(Order, type_id=102)
+```
+
+### Compatible Mode
+
+Xlang mode already uses compatible schema evolution by default. Keep that default for schemas that
+may evolve independently:
+
+```cpp
+auto fory = Fory::builder().xlang(true).build();
+```
+
+Compatible mode allows:
+
+- Adding new fields (with defaults)
+- Removing unused fields
+- Reordering fields
+
+### Interoperability Troubleshooting
+
+#### Type Mismatch Errors
+
+```
+Error: Type mismatch: expected 100, got 101
+```
+
+**Solution:** Ensure type IDs match across all languages.
+
+#### Encoding Errors
+
+```
+Error: Invalid UTF-8 sequence
+```
+
+**Solution:** Ensure strings are valid UTF-8 in all languages.
+
+### Related Guides
+
+- [Configuration](configuration.md) - Builder options
+- [Type Registration](type-registration.md) - Registering types
+- [Supported Types](supported-types.md) - Type compatibility
+
## Related Topics
- [Configuration](configuration.md) - Builder options
diff --git a/docs/object-serialization/cpp/configuration.md b/docs/object-serialization/cpp/configuration.md
index 389636732f..78c77939d2 100644
--- a/docs/object-serialization/cpp/configuration.md
+++ b/docs/object-serialization/cpp/configuration.md
@@ -252,20 +252,10 @@ auto fory = Fory::builder().build_thread_safe(); // Returns ThreadSafeFory
## Security
-Security-related configuration:
-
-- Register all structs and polymorphic implementations before deserializing untrusted payloads.
-- Use `check_struct_version(true)` with `compatible(false)` for intentional same-schema payloads.
-- Keep `max_graph_memory_bytes(...)` at the fixed `128 MiB` default for most inputs, or set a
- positive value for a trusted workload that needs a different collection/map/struct gate.
-- Keep `max_dyn_depth(...)` as low as your model permits to reject unexpectedly deep polymorphic
- graphs.
-- Keep the remote schema metadata limits at their defaults unless the data is not malicious and a
- trusted peer sends larger metadata or many schema versions.
-- Prefer concrete fields over broad polymorphic fields for untrusted input.
+See [C++ Security](security.md) for trust boundaries, safe reader configuration, and verification.
## Related Topics
-- [Basic Serialization](core-api.md) - Using configured Fory
-- [Xlang Serialization](xlang.md) - xlang mode details
+- [Basic Serialization](basic-serialization.md) - Using configured Fory
+- [Cross-Language Interoperability](basic-serialization.md#cross-language-interoperability) - xlang mode details
- [Type Registration](type-registration.md) - Registering types
diff --git a/docs/object-serialization/cpp/custom-serializers.md b/docs/object-serialization/cpp/custom-serializers.md
index bc7106e79e..089e10df08 100644
--- a/docs/object-serialization/cpp/custom-serializers.md
+++ b/docs/object-serialization/cpp/custom-serializers.md
@@ -366,6 +366,6 @@ static MyType read_data(ReadContext &ctx) {
## Related Topics
- [Type Registration](type-registration.md) - Registering serializers
-- [Basic Serialization](core-api.md) - Using FORY_STRUCT macro
+- [Basic Serialization](basic-serialization.md) - Using FORY_STRUCT macro
- [Schema Evolution](schema-evolution.md) - Compatible mode
-- [Xlang Serialization](xlang.md) - Cross-language serialization
+- [Cross-Language Interoperability](basic-serialization.md#cross-language-interoperability) - Cross-language serialization
diff --git a/docs/object-serialization/cpp/index.md b/docs/object-serialization/cpp/index.md
index c69bcd5215..a18ee4f393 100644
--- a/docs/object-serialization/cpp/index.md
+++ b/docs/object-serialization/cpp/index.md
@@ -222,7 +222,7 @@ Use xlang mode for cross-language payloads and schemas shared with other Fory im
Use native mode for C++-only traffic. Native mode is selected with `.xlang(false)` and keeps C++ object serialization in C++-native form. It is optimized for C++ types and avoids portable xlang type-mapping constraints when the payload never leaves C++. Compatible mode is enabled by default. Set `.compatible(false)` only when every reader and writer uses the same C++ schema and you want faster serialization and smaller size.
-See [Xlang Serialization](xlang.md) for C++ xlang registration and interoperability rules, and [Native Serialization](native.md) for C++-only payloads.
+See [Cross-Language Interoperability](basic-serialization.md#cross-language-interoperability) for C++ xlang registration and interoperability rules, and [Native Serialization](native.md) for C++-only payloads.
## Thread Safety
@@ -264,8 +264,7 @@ std::thread t2([&]() {
## Next Steps
- [Configuration](configuration.md) - Builder options and modes
-- [Basic Serialization](core-api.md) - Object graph serialization
-- [Xlang Serialization](xlang.md) - xlang mode and interoperability
+- [Basic Serialization](basic-serialization.md) - Default xlang object graphs and interoperability
- [Native Serialization](native.md) - C++-only serialization
- [Schema Metadata](schema-metadata.md) - Field-level metadata (nullable, ref tracking)
- [Schema Evolution](schema-evolution.md) - Compatible mode and schema changes
@@ -274,3 +273,6 @@ std::thread t2([&]() {
- [Custom Serializers](custom-serializers.md) - Extend serialization behavior
- [Row Format](../../row-format/cpp.md) - Zero-copy row-based format
- [gRPC Support](../../grpc/cpp.md) - Fory payloads over gRPC C++
+
+Before decoding bytes from outside the application trust boundary, read
+[C++ Security](security.md).
diff --git a/docs/object-serialization/cpp/native.md b/docs/object-serialization/cpp/native.md
index a93c9ed06d..70df2a91ba 100644
--- a/docs/object-serialization/cpp/native.md
+++ b/docs/object-serialization/cpp/native.md
@@ -23,7 +23,7 @@ C++ native serialization is the C++-only wire mode selected with `.xlang(false)`
writer and reader is C++ and the payload should follow C++ type behavior instead of the portable
xlang type system.
-Use [Xlang Serialization](xlang.md), the default C++ mode, when
+Use [Cross-Language Interoperability](basic-serialization.md#cross-language-interoperability), the default C++ mode, when
bytes must be read by Java, Python, Go, Rust, JavaScript/TypeScript, C#, Swift,
Dart, Scala, Kotlin, or another non-C++ Fory implementation.
@@ -206,9 +206,9 @@ Enable `.track_ref(true)` and verify the graph uses supported pointer patterns.
## Related Topics
-- [Xlang Serialization](xlang.md) - Cross-language C++ payloads
+- [Cross-Language Interoperability](basic-serialization.md#cross-language-interoperability) - Cross-language C++ payloads
- [Configuration](configuration.md) - Builder options
-- [Basic Serialization](core-api.md) - Object graph serialization
+- [Basic Serialization](basic-serialization.md) - Object graph serialization
- [Supported Types](supported-types.md) - C++ type support
- [Polymorphic Serialization](polymorphism.md) - Polymorphic object models
- [Schema Evolution](schema-evolution.md) - Compatible mode
diff --git a/docs/object-serialization/cpp/polymorphism.md b/docs/object-serialization/cpp/polymorphism.md
index 3f609ad280..383ba7c36d 100644
--- a/docs/object-serialization/cpp/polymorphism.md
+++ b/docs/object-serialization/cpp/polymorphism.md
@@ -487,4 +487,4 @@ if (!decoded_result.ok()) {
- [Schema Metadata](schema-metadata.md) - Field-level metadata and options
- [Supported Types](supported-types.md) - Smart pointers and collections
- [Configuration](configuration.md) - `max_dyn_depth` and other settings
-- [Basic Serialization](core-api.md) - Core serialization concepts
+- [Basic Serialization](basic-serialization.md) - Core serialization concepts
diff --git a/docs/object-serialization/cpp/schema-evolution.md b/docs/object-serialization/cpp/schema-evolution.md
index 8ca540479d..4b7ab928f8 100644
--- a/docs/object-serialization/cpp/schema-evolution.md
+++ b/docs/object-serialization/cpp/schema-evolution.md
@@ -421,4 +421,4 @@ Both instances can exchange data even with different schema versions.
- [Configuration](configuration.md) - Enabling compatible mode
- [Type Registration](type-registration.md) - Type ID management
-- [Xlang Serialization](xlang.md) - Cross-language considerations
+- [Cross-Language Interoperability](basic-serialization.md#cross-language-interoperability) - Cross-language considerations
diff --git a/docs/object-serialization/cpp/security.md b/docs/object-serialization/cpp/security.md
new file mode 100644
index 0000000000..fe86e37d2d
--- /dev/null
+++ b/docs/object-serialization/cpp/security.md
@@ -0,0 +1,57 @@
+---
+title: Security
+sidebar_position: 99
+id: security
+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.
+---
+
+Use this page when a C++ reader accepts bytes from outside the application's trust boundary.
+Fory reconstructs application values; it does not authenticate the sender, protect transport
+integrity, or decide whether a valid value is authorized for a business operation.
+
+## Application boundary
+
+Before deserialization:
+
+- Authenticate the sender and protect message integrity at the transport or storage layer.
+- Enforce request or file size, timeout, and concurrency limits outside Fory.
+- Register only the application types the endpoint accepts and configure the reader before its
+ first root operation.
+- Validate the deserialized value against application authorization and domain rules before use.
+
+## Runtime safeguards
+
+Security-related configuration:
+
+- Register all structs and polymorphic implementations before deserializing untrusted payloads.
+- Use `check_struct_version(true)` with `compatible(false)` for intentional same-schema payloads.
+- Keep `max_graph_memory_bytes(...)` at the fixed `128 MiB` default for most inputs, or set a
+ positive value for a trusted workload that needs a different collection/map/struct gate.
+- Keep `max_dyn_depth(...)` as low as your model permits to reject unexpectedly deep polymorphic
+ graphs.
+- Keep the remote schema metadata limits at their defaults unless the data is not malicious and a
+ trusted peer sends larger metadata or many schema versions.
+- Prefer concrete fields over broad polymorphic fields for untrusted input.
+
+## Verification
+
+Add negative tests for the boundary as well as normal round trips. Verify that the configured reader
+rejects unexpected application types, excessive nesting, resource-limit violations, and malformed
+input. After a failed read, verify that a valid root can still be read with the reusable runtime.
+
+See [Configuration](configuration.md) for the complete option reference and
+[Type Registration](type-registration.md) for the runtime's registration API.
diff --git a/docs/object-serialization/cpp/supported-types.md b/docs/object-serialization/cpp/supported-types.md
index 11f21a9e33..4c95f5307e 100644
--- a/docs/object-serialization/cpp/supported-types.md
+++ b/docs/object-serialization/cpp/supported-types.md
@@ -295,6 +295,6 @@ Currently not supported:
## Related Topics
-- [Basic Serialization](core-api.md) - Using these types
+- [Basic Serialization](basic-serialization.md) - Using these types
- [Type Registration](type-registration.md) - Registering types
-- [Xlang Serialization](xlang.md) - Cross-language compatibility
+- [Cross-Language Interoperability](basic-serialization.md#cross-language-interoperability) - Cross-language compatibility
diff --git a/docs/object-serialization/cpp/type-registration.md b/docs/object-serialization/cpp/type-registration.md
index 6e2a3e5189..62f525ef94 100644
--- a/docs/object-serialization/cpp/type-registration.md
+++ b/docs/object-serialization/cpp/type-registration.md
@@ -249,6 +249,6 @@ if (!result.ok()) {
## Related Topics
-- [Basic Serialization](core-api.md) - Using registered types
-- [Xlang Serialization](xlang.md) - Cross-language considerations
+- [Basic Serialization](basic-serialization.md) - Using registered types
+- [Cross-Language Interoperability](basic-serialization.md#cross-language-interoperability) - Cross-language considerations
- [Supported Types](supported-types.md) - All supported types
diff --git a/docs/object-serialization/cpp/xlang.md b/docs/object-serialization/cpp/xlang.md
deleted file mode 100644
index 726f63bda5..0000000000
--- a/docs/object-serialization/cpp/xlang.md
+++ /dev/null
@@ -1,295 +0,0 @@
----
-title: Xlang Serialization
-sidebar_position: 1
-id: xlang
-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 explains how to use Fory xlang serialization between C++ and other languages.
-
-## Overview
-
-Apache Fory™ enables seamless data exchange between C++, Java, Python, Go, Rust,
-JavaScript/TypeScript, C#, Swift, Dart, Scala, and Kotlin. Xlang mode ensures
-binary compatibility across all supported languages.
-
-## Create an Xlang Fory Instance
-
-C++ defaults to xlang mode. Compatible schema evolution is also the xlang default. Set the mode explicitly in xlang examples:
-
-```cpp
-#include "fory/serialization/fory.h"
-
-using namespace fory::serialization;
-
-auto fory = Fory::builder().xlang(true).build();
-```
-
-## Xlang Example
-
-### C++ Producer
-
-```cpp
-#include "fory/serialization/fory.h"
-#include
-
-using namespace fory::serialization;
-
-struct Message {
- std::string topic;
- int64_t timestamp;
- std::map headers;
- std::vector payload;
-
- bool operator==(const Message &other) const {
- return topic == other.topic && timestamp == other.timestamp &&
- headers == other.headers && payload == other.payload;
- }
-};
-FORY_STRUCT(Message, topic, timestamp, headers, payload);
-
-int main() {
- auto fory = Fory::builder().xlang(true).build();
- fory.register_struct(100);
-
- Message msg{
- "events.user",
- 1699999999000,
- {{"content-type", "application/json"}},
- {'h', 'e', 'l', 'l', 'o'}
- };
-
- auto result = fory.serialize(msg);
- if (result.ok()) {
- auto bytes = std::move(result).value();
- // write to file, send over network, etc.
- std::ofstream file("message.bin", std::ios::binary);
- file.write(reinterpret_cast(bytes.data()), bytes.size());
- }
- return 0;
-}
-```
-
-### Java Consumer
-
-```java
-import org.apache.fory.Fory;
-
-public class Message {
- public String topic;
- public long timestamp;
- public Map headers;
- public byte[] payload;
-}
-
-public class Consumer {
- public static void main(String[] args) throws Exception {
- Fory fory = Fory.builder()
- .withXlang(true)
- .build();
- fory.register(Message.class, 100); // Same ID as C++
-
- byte[] bytes = Files.readAllBytes(Path.of("message.bin"));
- Message msg = (Message) fory.deserialize(bytes);
-
- System.out.println("Topic: " + msg.topic);
- System.out.println("Timestamp: " + msg.timestamp);
- }
-}
-```
-
-### Python Consumer
-
-```python
-import pyfory
-
-class Message:
- topic: str
- timestamp: int
- headers: dict[str, str]
- payload: bytes
-
-fory = pyfory.Fory(xlang=True)
-fory.register(Message, type_id=100) # Same ID as C++
-
-with open("message.bin", "rb") as f:
- data = f.read()
-
-msg = fory.deserialize(data)
-print(f"Topic: {msg.topic}")
-print(f"Timestamp: {msg.timestamp}")
-```
-
-## Type Mapping
-
-### Primitive Types
-
-| C++ Type | Java Type | Python Type | Go Type | Rust Type |
-| ------------------ | ---------- | ----------------- | ------------------- | ---------- |
-| `bool` | `boolean` | `bool` | `bool` | `bool` |
-| `int8_t` | `byte` | `int` | `int8` | `i8` |
-| `int16_t` | `short` | `int` | `int16` | `i16` |
-| `int32_t` | `int` | `int` | `int32` | `i32` |
-| `int64_t` | `long` | `int` | `int64` | `i64` |
-| `float` | `float` | `float` | `float32` | `f32` |
-| `double` | `double` | `float` | `float64` | `f64` |
-| `fory::float16_t` | `Float16` | `pyfory.Float16` | `float16.Float16` | `Float16` |
-| `fory::bfloat16_t` | `BFloat16` | `pyfory.BFloat16` | `bfloat16.BFloat16` | `BFloat16` |
-
-### String Types
-
-| C++ Type | Java Type | Python Type | Go Type | Rust Type |
-| ------------- | --------- | ----------- | -------- | --------- |
-| `std::string` | `String` | `str` | `string` | `String` |
-
-### Collection Types
-
-| C++ Type | Java Type | Python Type | Go Type | Rust Type |
-| ------------------------------------------- | -------------- | --------------- | --------------------- | --------------- |
-| `std::vector` | `List` | `list` | `[]T` | `Vec` |
-| `std::vector` | `Float16List` | `Float16Array` | `[]float16.Float16` | `Vec` |
-| `std::vector` | `BFloat16List` | `BFloat16Array` | `[]bfloat16.BFloat16` | `Vec` |
-| `std::set` | `Set` | `set` | `map[T]struct{}` | `HashSet` |
-| `std::map` / `std::unordered_map` | `Map` | `dict` | `map[K]V` | `HashMap` |
-
-### Lists and Dense Arrays
-
-`std::vector` maps to Fory `list` by default in handwritten C++ structs.
-Use the field metadata DSL's array node when the schema is dense `array`.
-
-| Fory schema | C++ metadata sketch |
-| ----------------- | ---------------------------------------- |
-| `list` | `fory::F(id).list(fory::T::int32())` |
-| `array` | `fory::F(id).array(fory::T::bool_())` |
-| `array` | `fory::F(id).array(fory::T::int8())` |
-| `array` | `fory::F(id).array(fory::T::int16())` |
-| `array` | `fory::F(id).array(fory::T::int32())` |
-| `array` | `fory::F(id).array(fory::T::int64())` |
-| `array` | `fory::F(id).array(fory::T::uint8())` |
-| `array` | `fory::F(id).array(fory::T::uint16())` |
-| `array` | `fory::F(id).array(fory::T::uint32())` |
-| `array` | `fory::F(id).array(fory::T::uint64())` |
-| `array` | `fory::F(id).array(fory::T::float16())` |
-| `array` | `fory::F(id).array(fory::T::bfloat16())` |
-| `array` | `fory::F(id).array(fory::T::float32())` |
-| `array` | `fory::F(id).array(fory::T::float64())` |
-
-### Temporal Types
-
-| C++ Type | Java Type | Python Type | Go Type |
-| ----------------- | ----------- | --------------- | --------------- |
-| `fory::Timestamp` | `Instant` | `datetime` | `time.Time` |
-| `fory::Duration` | `Duration` | `timedelta` | `time.Duration` |
-| `fory::Date` | `LocalDate` | `datetime.date` | `time.Time` |
-
-## Field Order Requirements
-
-**Critical:** Fields are sorted by snake_case field name. The converted names must match across languages.
-
-### C++
-
-```cpp
-struct Person {
- std::string name; // Field 0
- int32_t age; // Field 1
- std::string email; // Field 2
-};
-FORY_STRUCT(Person, name, age, email); // Order matters!
-```
-
-### Java
-
-```java
-public class Person {
- public String name; // Field 0
- public int age; // Field 1
- public String email; // Field 2
-}
-```
-
-### Python
-
-```python
-class Person:
- name: str # Field 0
- age: int # Field 1
- email: str # Field 2
-```
-
-## Type ID Consistency
-
-All languages must use the same type IDs:
-
-```cpp
-// C++
-fory.register_struct(100);
-fory.register_struct(101);
-fory.register_struct(102);
-```
-
-```java
-// Java
-fory.register(Person.class, 100);
-fory.register(Address.class, 101);
-fory.register(Order.class, 102);
-```
-
-```python
-# Python
-fory.register(Person, type_id=100)
-fory.register(Address, type_id=101)
-fory.register(Order, type_id=102)
-```
-
-## Compatible Mode
-
-Xlang mode already uses compatible schema evolution by default. Keep that default for schemas that
-may evolve independently:
-
-```cpp
-auto fory = Fory::builder().xlang(true).build();
-```
-
-Compatible mode allows:
-
-- Adding new fields (with defaults)
-- Removing unused fields
-- Reordering fields
-
-## Troubleshooting
-
-### Type Mismatch Errors
-
-```
-Error: Type mismatch: expected 100, got 101
-```
-
-**Solution:** Ensure type IDs match across all languages.
-
-### Encoding Errors
-
-```
-Error: Invalid UTF-8 sequence
-```
-
-**Solution:** Ensure strings are valid UTF-8 in all languages.
-
-## Related Topics
-
-- [Configuration](configuration.md) - Builder options
-- [Type Registration](type-registration.md) - Registering types
-- [Supported Types](supported-types.md) - Type compatibility
diff --git a/docs/object-serialization/csharp/core-api.md b/docs/object-serialization/csharp/basic-serialization.md
similarity index 55%
rename from docs/object-serialization/csharp/core-api.md
rename to docs/object-serialization/csharp/basic-serialization.md
index 43020f8130..7c77560a7d 100644
--- a/docs/object-serialization/csharp/core-api.md
+++ b/docs/object-serialization/csharp/basic-serialization.md
@@ -1,7 +1,7 @@
---
title: Basic Serialization
-sidebar_position: 3
-id: core-api
+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
@@ -19,7 +19,7 @@ license: |
limitations under the License.
---
-This page covers typed serialization APIs in Apache Fory™ C#.
+This page covers typed serialization APIs in the default xlang mode for Apache Fory™ C#.
## Object Graph Serialization
@@ -159,6 +159,125 @@ fory.Serialize