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 36ab8ecdc7 π synced local 'docs/guide/' with remote 'docs/guide/'
36ab8ecdc7 is described below
commit 36ab8ecdc7567375c5e5383ba2be34446509abfa
Author: chaokunyang <[email protected]>
AuthorDate: Mon Apr 13 08:50:14 2026 +0000
π synced local 'docs/guide/' with remote 'docs/guide/'
---
docs/guide/dart/_category_.json | 6 ++
docs/guide/dart/basic-serialization.md | 142 +++++++++++++++++++++++++
docs/guide/dart/code-generation.md | 120 +++++++++++++++++++++
docs/guide/dart/configuration.md | 110 +++++++++++++++++++
docs/guide/dart/cross-language.md | 187 +++++++++++++++++++++++++++++++++
docs/guide/dart/custom-serializers.md | 156 +++++++++++++++++++++++++++
docs/guide/dart/field-configuration.md | 136 ++++++++++++++++++++++++
docs/guide/dart/index.md | 143 +++++++++++++++++++++++++
docs/guide/dart/schema-evolution.md | 90 ++++++++++++++++
docs/guide/dart/supported-types.md | 122 +++++++++++++++++++++
docs/guide/dart/troubleshooting.md | 105 ++++++++++++++++++
docs/guide/dart/type-registration.md | 96 +++++++++++++++++
12 files changed, 1413 insertions(+)
diff --git a/docs/guide/dart/_category_.json b/docs/guide/dart/_category_.json
new file mode 100644
index 0000000000..47b8891a2e
--- /dev/null
+++ b/docs/guide/dart/_category_.json
@@ -0,0 +1,6 @@
+{
+ "label": "Dart",
+ "position": 11,
+ "collapsible": true,
+ "collapsed": true
+}
diff --git a/docs/guide/dart/basic-serialization.md
b/docs/guide/dart/basic-serialization.md
new file mode 100644
index 0000000000..e7fa79d95d
--- /dev/null
+++ b/docs/guide/dart/basic-serialization.md
@@ -0,0 +1,142 @@
+---
+title: Basic Serialization
+sidebar_position: 2
+id: dart_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 page covers the root serialization APIs in Apache Foryβ’ Dart.
+
+## Create and Reuse `Fory`
+
+```dart
+import 'package:fory/fory.dart';
+
+final fory = Fory();
+```
+
+Reuse the same runtime instance across calls. `Fory` owns the reusable
`Buffer`, `WriteContext`, `ReadContext`, and `TypeResolver` services for that
runtime.
+
+## Serialize and Deserialize Annotated Types
+
+```dart
+import 'package:fory/fory.dart';
+
+part 'person.fory.dart';
+
+@ForyStruct()
+class Person {
+ Person();
+
+ String name = '';
+ Int32 age = Int32(0);
+}
+
+void main() {
+ final fory = Fory();
+ PersonFory.register(
+ fory,
+ Person,
+ namespace: 'example',
+ typeName: 'Person',
+ );
+
+ final person = Person()
+ ..name = 'Ada'
+ ..age = Int32(36);
+
+ final bytes = fory.serialize(person);
+ final roundTrip = fory.deserialize<Person>(bytes);
+ print(roundTrip.name);
+}
+```
+
+`deserialize<T>` uses the wire metadata first, then checks that the result is
assignable to `T`.
+
+## Null Root Values
+
+The root xlang frame starts with a one-byte bitmap. A null root payload is
encoded by the root header, so serializing `null` works directly:
+
+```dart
+final fory = Fory();
+final bytes = fory.serialize(null);
+final value = fory.deserialize<Object?>(bytes);
+```
+
+## Serialize Collections and Dynamic Payloads
+
+You can serialize collection values directly:
+
+```dart
+final fory = Fory();
+final bytes = fory.serialize(<Object?>[
+ 'hello',
+ Int32(42),
+ true,
+]);
+final value = fory.deserialize<List<Object?>>(bytes);
+```
+
+For heterogeneous collections, deserialize to `Object?`, `List<Object?>`,
`Map<Object?, Object?>`, or a generated struct type that matches the wire
schema.
+
+## Root Reference Tracking
+
+Use `trackRef: true` only when the root value itself is a graph or container
with repeated references and there is no field metadata to request reference
tracking.
+
+```dart
+final fory = Fory();
+final shared = String.fromCharCodes('shared'.codeUnits);
+final bytes = fory.serialize(<Object?>[shared, shared], trackRef: true);
+final roundTrip = fory.deserialize<List<Object?>>(bytes);
+print(identical(roundTrip[0], roundTrip[1]));
+```
+
+Inside generated structs, prefer field-level reference metadata with
`@ForyField(ref: true)`.
+
+## Buffer-Based APIs
+
+Use `serializeTo` and `deserializeFrom` when you want explicit `Buffer` reuse.
+
+```dart
+final fory = Fory();
+final buffer = Buffer();
+
+fory.serializeTo(Int32(42), buffer);
+final value = fory.deserializeFrom<Int32>(buffer);
+```
+
+`serializeTo` clears the target buffer before writing. `deserializeFrom`
consumes bytes from the buffer's current reader position.
+
+## Generated Registration Before Use
+
+Generated and manual user-defined types must be registered before use.
+
+```dart
+PersonFory.register(
+ fory,
+ Person,
+ id: 100,
+);
+```
+
+See [Type Registration](type-registration.md) and [Code
Generation](code-generation.md).
+
+## Related Topics
+
+- [Configuration](configuration.md)
+- [Type Registration](type-registration.md)
+- [Field Configuration](field-configuration.md)
diff --git a/docs/guide/dart/code-generation.md
b/docs/guide/dart/code-generation.md
new file mode 100644
index 0000000000..5a65135a97
--- /dev/null
+++ b/docs/guide/dart/code-generation.md
@@ -0,0 +1,120 @@
+---
+title: Code Generation
+sidebar_position: 3
+id: dart_code_generation
+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 Dart uses source generation for structs and enums defined in your Dart
libraries.
+
+## Annotate Struct Types
+
+Mark classes with `@ForyStruct()` and include the generated part file.
+
+```dart
+import 'package:fory/fory.dart';
+
+part 'models.fory.dart';
+
+@ForyStruct()
+class Address {
+ Address();
+
+ String city = '';
+ String street = '';
+}
+
+@ForyStruct()
+class User {
+ User();
+
+ String name = '';
+ Int32 age = Int32(0);
+ Address address = Address();
+}
+```
+
+Enums in the same library also participate in generated registration.
+
+## Run the Generator
+
+From `dart/packages/fory` or the package that depends on the generator:
+
+```bash
+dart run build_runner build --delete-conflicting-outputs
+```
+
+The builder emits a `.fory.dart` part file next to the source library.
+
+## Register Through the Generated Namespace
+
+Generated code exposes a library-level namespace that knows how to install
generated metadata into `Fory`.
+
+```dart
+final fory = Fory();
+ModelsFory.register(fory, Address, id: 1);
+ModelsFory.register(fory, User, id: 2);
+```
+
+Or use named registration:
+
+```dart
+ModelsFory.register(
+ fory,
+ User,
+ namespace: 'example',
+ typeName: 'User',
+);
+```
+
+Exactly one registration mode is required:
+
+- `id: ...`
+- `namespace: ...` plus `typeName: ...`
+
+## Choosing `evolving`
+
+`@ForyStruct()` defaults to `evolving: true`.
+
+```dart
+@ForyStruct(evolving: true)
+class Event {
+ Event();
+
+ String name = '';
+}
+```
+
+Use `evolving: true` when you want compatible-mode field evolution. Use
`evolving: false` for a fixed schema when you want schema-consistent behavior.
+
+## Generated Registration Design
+
+Generated registration keeps serializer metadata private to the defining
library while exposing a public wrapper API. Applications should call the
generated wrapper instead of private helper functions.
+
+## When to Use Customized Serializers Instead
+
+Use [Custom Serializers](custom-serializers.md) when:
+
+- the type is external and cannot be annotated
+- you need custom payload layout
+- you are implementing a union or extension type manually
+
+## Related Topics
+
+- [Type Registration](type-registration.md)
+- [Field Configuration](field-configuration.md)
+- [Schema Evolution](schema-evolution.md)
diff --git a/docs/guide/dart/configuration.md b/docs/guide/dart/configuration.md
new file mode 100644
index 0000000000..a213cca77d
--- /dev/null
+++ b/docs/guide/dart/configuration.md
@@ -0,0 +1,110 @@
+---
+title: Configuration
+sidebar_position: 1
+id: dart_configuration
+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 `Config` options and default runtime values for Apache Foryβ’
Dart.
+
+## Create a Runtime
+
+```dart
+import 'package:fory/fory.dart';
+
+final fory = Fory(
+ compatible: true,
+ maxDepth: 512,
+ maxCollectionSize: 1 << 18,
+ maxBinarySize: 16 * 1024 * 1024,
+);
+```
+
+The same `Fory` instance should be reused across many operations. `Fory`
resets operation-local read and write state for each root call.
+
+## Options
+
+### `compatible`
+
+Enables compatible struct encoding and decoding.
+
+```dart
+final fory = Fory(compatible: true);
+```
+
+In compatible mode, generated evolving structs exchange shared `TypeDef`
metadata rather than relying on the schema-consistent struct hash checks used
by fixed-schema mode.
+
+### `checkStructVersion`
+
+Controls struct schema-version validation in schema-consistent mode.
+
+```dart
+final fory = Fory(
+ compatible: false,
+ checkStructVersion: true,
+);
+```
+
+This option is forced to `false` whenever `compatible` is `true`.
+
+### `maxDepth`
+
+Maximum nesting depth accepted during one serialization or deserialization
operation.
+
+```dart
+const config = Config(maxDepth: 128);
+```
+
+Use this to bound recursive payloads and fail fast on malformed or
unexpectedly deep graphs.
+
+### `maxCollectionSize`
+
+Maximum number of entries accepted for a single collection or map payload.
+
+```dart
+const config = Config(maxCollectionSize: 100000);
+```
+
+### `maxBinarySize`
+
+Maximum number of bytes accepted for a single binary payload.
+
+```dart
+const config = Config(maxBinarySize: 8 * 1024 * 1024);
+```
+
+## Defaults
+
+`Config()` defaults to:
+
+- `compatible: false`
+- `checkStructVersion: true`
+- `maxDepth: 256`
+- `maxCollectionSize: 1 << 20`
+- `maxBinarySize: 64 * 1024 * 1024`
+
+## Cross-Language Notes
+
+- The Dart runtime always reads and writes xlang frames.
+- Match `compatible` mode across communicating services when you depend on
schema evolution.
+- Registration choices still matter: use the same numeric IDs or the same
`namespace + typeName` mapping across all runtimes.
+
+## Related Topics
+
+- [Basic Serialization](basic-serialization.md)
+- [Schema Evolution](schema-evolution.md)
+- [Cross-Language](cross-language.md)
diff --git a/docs/guide/dart/cross-language.md
b/docs/guide/dart/cross-language.md
new file mode 100644
index 0000000000..2c700865b2
--- /dev/null
+++ b/docs/guide/dart/cross-language.md
@@ -0,0 +1,187 @@
+---
+title: Cross-Language Serialization
+sidebar_position: 9
+id: dart_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β’ Dart supports cross-language serialization with other Fory
runtimes.
+
+## Cross-Language Runtime
+
+The Dart runtime only supports xlang payloads, so you do not enable a separate
cross-language mode.
+
+```dart
+final fory = Fory();
+```
+
+Configure only the runtime behavior that still varies, such as compatible mode
and safety limits.
+
+## Use Stable Registration Identity
+
+Choose one registration strategy and keep it stable across all peers.
+
+### Numeric ID example
+
+```dart
+ModelsFory.register(fory, Person, id: 100);
+```
+
+### Name-based example
+
+```dart
+ModelsFory.register(
+ fory,
+ Person,
+ namespace: 'example',
+ typeName: 'Person',
+);
+```
+
+## Dart to Java Example
+
+### Dart
+
+```dart
+import 'package:fory/fory.dart';
+
+part 'person.fory.dart';
+
+@ForyStruct()
+class Person {
+ Person();
+
+ String name = '';
+ Int32 age = Int32(0);
+}
+
+final fory = Fory();
+PersonFory.register(fory, Person, id: 100);
+final bytes = fory.serialize(Person()
+ ..name = 'Alice'
+ ..age = Int32(30));
+```
+
+### Java
+
+```java
+Fory fory = Fory.builder()
+ .withLanguage(Language.XLANG)
+ .build();
+
+fory.register(Person.class, 100);
+Person value = (Person) fory.deserialize(bytesFromDart);
+```
+
+## Dart to C# Example
+
+### Dart
+
+```dart
+final fory = Fory(compatible: true);
+PersonFory.register(fory, Person, id: 100);
+final bytes = fory.serialize(Person()
+ ..name = 'Alice'
+ ..age = Int32(30));
+```
+
+### CSharp
+
+```csharp
+[ForyObject]
+public sealed class Person
+{
+ public string Name { get; set; } = string.Empty;
+ public int Age { get; set; }
+}
+
+Fory fory = Fory.Builder()
+ .Compatible(true)
+ .Build();
+
+fory.Register<Person>(100);
+Person person = fory.Deserialize<Person>(payloadFromDart);
+```
+
+## Dart to Go Example
+
+### Dart
+
+```dart
+final fory = Fory();
+PersonFory.register(fory, Person, id: 100);
+final bytes = fory.serialize(Person()
+ ..name = 'Alice'
+ ..age = Int32(30));
+```
+
+### Go
+
+```go
+type Person struct {
+ Name string
+ Age int32
+}
+
+f := fory.New(fory.WithXlang(true))
+_ = f.RegisterStruct(Person{}, 100)
+
+var person Person
+_ = f.Deserialize(bytesFromDart, &person)
+```
+
+## Field Matching Rules
+
+The xlang spec is the source of truth, but for application authors the
practical rules are:
+
+1. Register the same logical type identity on every side.
+2. Keep field meaning aligned across languages.
+3. For evolving schemas, keep field IDs stable.
+4. Use compatible type mappings for numeric widths, timestamps, collections,
and nullability.
+5. Validate real payload round trips.
+
+Dart model fields often use lowerCamelCase. Go fields are exported PascalCase.
C# commonly uses PascalCase properties. What matters is that the peer runtimes
agree on the logical field mapping and wire schema. Stable field IDs are the
safest option when models evolve independently.
+
+## Type Mapping Notes for Dart
+
+Because Dart `int` is not itself a promise about the exact xlang wire width,
prefer wrappers or numeric field annotations when exact cross-language
interpretation matters:
+
+- `Int32` for xlang `int32`
+- `UInt32` for xlang `uint32`
+- `Float16` and `Float32` for reduced-width floating point
+- `Timestamp` and `LocalDate` for explicit temporal semantics
+
+See [Supported Types](supported-types.md) and [xlang type
mapping](../../specification/xlang_type_mapping.md).
+
+## Validation Advice
+
+Before relying on an interop contract, test the same payload through every
runtime you support.
+
+At minimum for Dart runtime work:
+
+```bash
+cd dart
+dart run build_runner build --delete-conflicting-outputs
+dart analyze
+dart test
+```
+
+## Related Topics
+
+- [Type Registration](type-registration.md)
+- [Schema Evolution](schema-evolution.md)
+- [Cross-language guide](../xlang/index.md)
diff --git a/docs/guide/dart/custom-serializers.md
b/docs/guide/dart/custom-serializers.md
new file mode 100644
index 0000000000..91ddc69455
--- /dev/null
+++ b/docs/guide/dart/custom-serializers.md
@@ -0,0 +1,156 @@
+---
+title: Custom Serializers
+sidebar_position: 5
+id: dart_custom_serializers
+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 customized serializers when generated struct support is not the right fit.
+
+## When Customized Serializers Make Sense
+
+Typical cases include:
+
+- external types you cannot annotate
+- custom payload layouts
+- customized extension types
+- unions built on the `UnionSerializer<T>` base class
+
+## Implement `Serializer<T>`
+
+```dart
+import 'package:fory/fory.dart';
+
+final class Person {
+ Person(this.name, this.age);
+
+ final String name;
+ final int age;
+}
+
+final class PersonSerializer extends Serializer<Person> {
+ const PersonSerializer();
+
+ @override
+ void write(WriteContext context, Person value) {
+ final buffer = context.buffer;
+ buffer.writeUtf8(value.name);
+ buffer.writeInt64(value.age);
+ }
+
+ @override
+ Person read(ReadContext context) {
+ final buffer = context.buffer;
+ return Person(buffer.readUtf8(), buffer.readInt64());
+ }
+}
+```
+
+Register it before use:
+
+```dart
+final fory = Fory();
+fory.registerSerializer(
+ Person,
+ const PersonSerializer(),
+ namespace: 'example',
+ typeName: 'Person',
+);
+```
+
+## Use `WriteContext` and `ReadContext`
+
+Manual serializers should do nested xlang work through the context rather than
calling root APIs recursively.
+
+### Write nested values with reference handling
+
+```dart
+@override
+void write(WriteContext context, Wrapper value) {
+ context.writeRef(value.child);
+}
+
+@override
+Wrapper read(ReadContext context) {
+ return Wrapper(context.readRef() as Child);
+}
+```
+
+### Write values without seeding references
+
+`writeNonRef` writes a non-reference payload and does not seed later
back-references.
+
+```dart
+context.writeNonRef(value.child);
+```
+
+### Fine-grained ref/value control
+
+Use `writeRefValueFlag` when your serializer needs explicit control over
whether payload bytes follow.
+
+```dart
+if (context.writeRefValueFlag(value.payload)) {
+ context.writeNonRef(value.payload);
+}
+```
+
+## Unions
+
+Manual union serializers should extend `UnionSerializer<T>`.
+
+```dart
+final class ShapeSerializer extends UnionSerializer<Shape> {
+ const ShapeSerializer();
+
+ @override
+ void write(WriteContext context, Shape value) {
+ // write active alternative
+ }
+
+ @override
+ Shape read(ReadContext context) {
+ // read active alternative
+ throw UnimplementedError();
+ }
+}
+```
+
+The xlang spec defines `UNION`, `TYPED_UNION`, `NAMED_UNION`, and `NONE` wire
types. Use registrations that match the peers you interoperate with.
+
+## Early Reference Binding During Reads
+
+If your serializer allocates an object before all nested fields are read, bind
it early so back-references can resolve to that instance.
+
+```dart
+final value = Node.empty();
+context.reference(value);
+value.next = context.readRef() as Node?;
+return value;
+```
+
+## Best Practices
+
+- Keep payload code focused on the payload only.
+- Let `Fory` own the root frame and top-level reset lifecycle.
+- Prefer direct buffer access for repeated primitive IO inside hot serializers.
+- Register serializers consistently across all peers.
+
+## Related Topics
+
+- [Type Registration](type-registration.md)
+- [Cross-Language](cross-language.md)
+- [Troubleshooting](troubleshooting.md)
diff --git a/docs/guide/dart/field-configuration.md
b/docs/guide/dart/field-configuration.md
new file mode 100644
index 0000000000..8a9402de01
--- /dev/null
+++ b/docs/guide/dart/field-configuration.md
@@ -0,0 +1,136 @@
+---
+title: Field Configuration
+sidebar_position: 6
+id: dart_field_configuration
+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 `@ForyField(...)` to override generated serializer behavior for individual
fields.
+
+## Options Overview
+
+```dart
+@ForyField(
+ skip: false,
+ id: 10,
+ nullable: true,
+ ref: true,
+ dynamic: false,
+)
+```
+
+## `skip`
+
+Exclude a field from generated serialization.
+
+```dart
+@ForyField(skip: true)
+String cachedDisplayName = '';
+```
+
+## `id`
+
+Provides a stable field identifier for compatible structs.
+
+```dart
+@ForyField(id: 1)
+String name = '';
+```
+
+In compatible mode, stable field IDs matter more than declaration order. Keep
IDs fixed once payloads are shared.
+
+## `nullable`
+
+Overrides inferred nullability.
+
+```dart
+@ForyField(nullable: true)
+String nickname = '';
+```
+
+`null` means "use the Dart type as written." In cross-language scenarios, make
sure your nullability contract also matches peer runtimes.
+
+## `ref`
+
+Enables reference tracking for that field.
+
+```dart
+@ForyField(ref: true)
+List<Object?> sharedNodes = <Object?>[];
+```
+
+Basic scalar values never track references even if `ref` is set to `true`.
+
+## `dynamic`
+
+Controls whether generated code writes runtime type metadata for the field.
+
+```dart
+@ForyField(dynamic: true)
+Object? payload;
+```
+
+- `null`: auto
+- `false`: use the declared field type
+- `true`: write runtime type information
+
+This is the key knob for polymorphic fields and heterogeneous object payloads.
+
+## Numeric Encoding Overrides
+
+Use numeric annotations to control the xlang wire type used for integer fields.
+
+```dart
+@ForyStruct()
+class Sample {
+ Sample();
+
+ @Int32Type(compress: false)
+ int fixedWidthInt = 0;
+
+ @Int64Type(encoding: LongEncoding.tagged)
+ int compactLong = 0;
+
+ @Uint32Type(compress: true)
+ int smallUnsigned = 0;
+}
+```
+
+Available numeric annotations include:
+
+- `@Int32Type(...)`
+- `@Int64Type(...)`
+- `@Uint8Type()`
+- `@Uint16Type()`
+- `@Uint32Type(...)`
+- `@Uint64Type(...)`
+
+These should be chosen to match the intended xlang wire type and peer-language
expectations.
+
+## Field Alignment Across Languages
+
+Cross-language decoding depends on matching field names or stable field IDs.
When models differ across languages:
+
+- keep equivalent logical fields aligned
+- prefer stable `id` values for evolving structs
+- use `dynamic: true` only when the field is genuinely polymorphic
+
+## Related Topics
+
+- [Code Generation](code-generation.md)
+- [Schema Evolution](schema-evolution.md)
+- [Cross-Language](cross-language.md)
diff --git a/docs/guide/dart/index.md b/docs/guide/dart/index.md
new file mode 100644
index 0000000000..e52ef5f187
--- /dev/null
+++ b/docs/guide/dart/index.md
@@ -0,0 +1,143 @@
+---
+title: Dart Serialization Guide
+sidebar_position: 0
+id: dart_serialization_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β’ Dart is a cross-language serialization runtime for Dart. It reads
and writes the xlang wire format defined by the [xlang serialization
specification](../../specification/xlang_serialization_spec.md) and is designed
around generated serializers with an advanced customized serializer escape
hatch.
+
+## Why Fory Dart?
+
+- Cross-language compatibility with other Fory xlang runtimes
+- Generated serializers for annotated Dart models
+- Compatible mode for schema evolution
+- Optional reference tracking for shared and circular object graphs
+- Manual serializer support for external types, custom wire behavior, and
unions
+- A small public API centered on `Fory`, `Config`, annotations, and xlang
value wrappers
+
+## Runtime Model
+
+The Dart runtime only supports xlang payloads. There is no separate
native-mode builder. Root operations happen through `Fory`, while nested
payload work stays in explicit `WriteContext` and `ReadContext` instances. This
mirrors the ownership model described in the [xlang implementation
guide](../../specification/xlang_implementation_guide.md).
+
+## Quick Start
+
+### Requirements
+
+- Dart SDK 3.6 or later
+- `build_runner` for generated serializers
+
+### Install
+
+Add the package from your Dart workspace or package source. In this
repository, the runtime lives under `dart/packages/fory`.
+
+```yaml
+dependencies:
+ fory:
+ path: packages/fory
+
+dev_dependencies:
+ build_runner: ^2.4.0
+```
+
+### Basic Example
+
+```dart
+import 'package:fory/fory.dart';
+
+part 'person.fory.dart';
+
+enum Color {
+ red,
+ blue,
+}
+
+@ForyStruct()
+class Person {
+ Person();
+
+ String name = '';
+ Int32 age = Int32(0);
+ Color favoriteColor = Color.red;
+ List<String> tags = <String>[];
+}
+
+void main() {
+ final fory = Fory();
+ PersonFory.register(
+ fory,
+ Color,
+ namespace: 'example',
+ typeName: 'Color',
+ );
+ PersonFory.register(
+ fory,
+ Person,
+ namespace: 'example',
+ typeName: 'Person',
+ );
+
+ final person = Person()
+ ..name = 'Ada'
+ ..age = Int32(36)
+ ..favoriteColor = Color.blue
+ ..tags = <String>['engineer', 'mathematician'];
+
+ final bytes = fory.serialize(person);
+ final roundTrip = fory.deserialize<Person>(bytes);
+ print(roundTrip.name);
+}
+```
+
+Generate the companion file before running the program:
+
+```bash
+cd dart/packages/fory
+dart run build_runner build --delete-conflicting-outputs
+```
+
+## Core API
+
+- `Fory({bool compatible = false, bool checkStructVersion = true, int maxDepth
= Config.defaultMaxDepth, int maxCollectionSize =
Config.defaultMaxCollectionSize, int maxBinarySize =
Config.defaultMaxBinarySize})`
+- `serialize(Object? value, {bool trackRef = false})`
+- `deserialize<T>(Uint8List bytes)`
+- `register(Type type, {int? id, String? namespace, String? typeName})`
+- `registerSerializer(Type type, Serializer serializer, ...)`
+- `@ForyStruct()` and `@ForyField(...)` for generated serializers
+- xlang value wrappers such as `Int8`, `Int16`, `Int32`, `UInt8`, `UInt16`,
`UInt32`, `Float16`, `Float32`, `LocalDate`, and `Timestamp`
+
+## Documentation
+
+| Topic | Description
|
+| --------------------------------------------- |
--------------------------------------------------------------- |
+| [Configuration](configuration.md) | Runtime options, compatible
mode, and safety limits |
+| [Basic Serialization](basic-serialization.md) | `serialize`, `deserialize`,
generated registration, root graphs |
+| [Code Generation](code-generation.md) | `@ForyStruct`, build runner,
and generated namespaces |
+| [Type Registration](type-registration.md) | ID-based vs name-based
registration and registration rules |
+| [Custom Serializers](custom-serializers.md) | Manual `Serializer<T>`
implementations and unions |
+| [Field Configuration](field-configuration.md) | `@ForyField`, field IDs,
nullability, references, polymorphism |
+| [Supported Types](supported-types.md) | Built-in xlang values,
wrappers, collections, and structs |
+| [Schema Evolution](schema-evolution.md) | Compatible structs and
evolving schemas |
+| [Cross-Language](cross-language.md) | Interoperability rules and
field alignment |
+| [Troubleshooting](troubleshooting.md) | Common errors, diagnostics,
and validation steps |
+
+## Related Resources
+
+- [Xlang serialization
specification](../../specification/xlang_serialization_spec.md)
+- [Xlang implementation
guide](../../specification/xlang_implementation_guide.md)
+- [Cross-language guide](../xlang/index.md)
+- [Dart runtime source
directory](https://github.com/apache/fory/tree/main/dart)
diff --git a/docs/guide/dart/schema-evolution.md
b/docs/guide/dart/schema-evolution.md
new file mode 100644
index 0000000000..778c39bce0
--- /dev/null
+++ b/docs/guide/dart/schema-evolution.md
@@ -0,0 +1,90 @@
+---
+title: Schema Evolution
+sidebar_position: 8
+id: dart_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 Dart supports schema evolution through compatible structs.
+
+## Two Struct Modes
+
+### Schema-Consistent Mode
+
+This is the default when `Config.compatible` is `false`.
+
+- Structs use the schema-consistent path.
+- `checkStructVersion` can validate schema-version compatibility.
+- This mode is appropriate when both sides evolve in lockstep or when you want
stricter validation.
+
+### Compatible Mode
+
+Enable compatible mode when you want evolving field metadata on the wire.
+
+```dart
+final fory = Fory(compatible: true);
+```
+
+In compatible mode:
+
+- evolving structs use compatible struct encoding
+- `checkStructVersion` is disabled
+- field IDs become the stability anchor for changed schemas
+- TypeDef metadata is shared and reused across payloads
+
+## Generated Struct Controls
+
+`@ForyStruct(evolving: true)` is the default and is the right choice when the
type may evolve over time.
+
+```dart
+@ForyStruct(evolving: true)
+class UserProfile {
+ UserProfile();
+
+ @ForyField(id: 1)
+ String name = '';
+
+ @ForyField(id: 2, nullable: true)
+ String? nickname;
+}
+```
+
+Use explicit stable field IDs when a schema may change.
+
+## Safe Evolution Practices
+
+Typical compatible changes include:
+
+- adding a new optional field with a new field ID
+- keeping existing field IDs stable
+- widening consumer behavior to tolerate missing data
+
+Changes that require extra care include:
+
+- reusing an old field ID for different semantics
+- changing a field's logical cross-language meaning
+- changing registration identity for an existing type
+
+## Cross-Language Guidance
+
+Schema evolution only works when all runtimes agree on the type registration
identity and the logical meaning of field IDs. Validate rolling upgrades with
real round trips across the languages you support.
+
+## Related Topics
+
+- [Configuration](configuration.md)
+- [Field Configuration](field-configuration.md)
+- [Cross-Language](cross-language.md)
diff --git a/docs/guide/dart/supported-types.md
b/docs/guide/dart/supported-types.md
new file mode 100644
index 0000000000..edf2f29f99
--- /dev/null
+++ b/docs/guide/dart/supported-types.md
@@ -0,0 +1,122 @@
+---
+title: Supported Types
+sidebar_position: 7
+id: dart_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 xlang-facing types in Apache Fory Dart.
+
+## Primitive-Like Dart Values
+
+The runtime supports common Dart values directly where they map cleanly to
xlang types:
+
+- `bool`
+- `int`
+- `double`
+- `String`
+- `Uint8List` and other supported typed byte containers
+- `List`, `Set`, and `Map`
+- `DateTime`-adjacent values through explicit wrappers such as `Timestamp` and
`LocalDate`
+
+Because Dart `int` and `double` are broader runtime concepts than many xlang
scalar types, wrapper types and field annotations are used when the exact wire
type matters.
+
+## Integer Wrappers
+
+Use wrapper classes when you need an exact xlang fixed-width integer type.
+
+```dart
+final Int8 tiny = Int8(-1);
+final Int16 shortValue = Int16(7);
+final Int32 age = Int32(36);
+final UInt8 flags = UInt8(255);
+final UInt16 port = UInt16(65535);
+final UInt32 count = UInt32(4000000000);
+```
+
+Available wrappers:
+
+- `Int8`
+- `Int16`
+- `Int32`
+- `UInt8`
+- `UInt16`
+- `UInt32`
+
+Each wrapper normalizes the stored value to the target bit width.
+
+## Floating-Point Wrappers
+
+Use explicit wrapper types when you need a precise non-`float64` wire type.
+
+- `Float16`
+- `Float32`
+
+Dart `double` maps naturally to the xlang `float64` family.
+
+## Time and Date Types
+
+The runtime exposes explicit xlang-friendly temporal wrappers:
+
+- `Timestamp` for seconds-plus-nanoseconds UTC instants
+- `LocalDate` for timezone-free calendar dates
+
+```dart
+final timestamp = Timestamp.fromDateTime(DateTime.now().toUtc());
+final birthday = LocalDate(1990, 12, 1);
+```
+
+## Structs and Enums
+
+User-defined structs and enums are supported through generated registration or
customized serializers.
+
+```dart
+@ForyStruct()
+class User {
+ User();
+
+ String name = '';
+ Int32 age = Int32(0);
+}
+```
+
+## Collections
+
+Fory Dart supports the core xlang collection shapes:
+
+- `List<T>`
+- `Set<T>`
+- `Map<K, V>`
+
+Cross-language compatibility still depends on element and key types having
compatible peer-language mappings. Avoid mutable collection keys.
+
+## Typed Arrays and Binary Values
+
+The xlang spec defines dedicated wire types for binary payloads and numeric
arrays. In Dart, use the typed values exported by the runtime and test the
exact round trip you need with your peer languages.
+
+## Exact Mapping Rules
+
+For the complete cross-language mapping, see:
+
+- [Xlang type mapping](../../specification/xlang_type_mapping.md)
+- [Cross-Language](cross-language.md)
+
+## Related Topics
+
+- [Field Configuration](field-configuration.md)
+- [Cross-Language](cross-language.md)
+- [Schema Evolution](schema-evolution.md)
diff --git a/docs/guide/dart/troubleshooting.md
b/docs/guide/dart/troubleshooting.md
new file mode 100644
index 0000000000..1d9fd2fc2b
--- /dev/null
+++ b/docs/guide/dart/troubleshooting.md
@@ -0,0 +1,105 @@
+---
+title: Troubleshooting
+sidebar_position: 10
+id: dart_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 Dart runtime issues and fixes.
+
+## `Only xlang payloads are supported by the Dart runtime.`
+
+The Dart runtime only deserializes xlang frames. Make sure the peer runtime is
writing xlang payloads rather than a language-native format.
+
+- Java must use `withLanguage(Language.XLANG)`.
+- Go must enable `WithXlang(true)`.
+- Other peers must use their xlang-compatible path.
+
+## `Type ... is not registered.`
+
+Generated and manual user-defined types must be registered before reading or
writing them.
+
+Checklist:
+
+1. Run code generation.
+2. Register the type through the generated namespace or `registerSerializer`.
+3. Register all nested user-defined types, not only the root type.
+
+## Generated part file is missing or stale
+
+Regenerate code:
+
+```bash
+cd dart/packages/fory
+dart run build_runner build --delete-conflicting-outputs
+```
+
+If you moved files or renamed types, rebuild before re-running analysis or
tests.
+
+## `Deserialized value has type ..., expected ...`
+
+`deserialize<T>` validates the runtime result after decoding. This error
usually means:
+
+- the payload describes a different root type than the requested `T`
+- registration points to a different logical type than expected
+- a dynamic payload should be decoded as `Object?` or a container type first
+
+## Unexpected reference identity behavior
+
+Check whether reference tracking is enabled in the correct place:
+
+- root graph or root container: `trackRef: true`
+- generated field graph: `@ForyField(ref: true)`
+- customized serializer: use `writeRef`, `readRef`, and
`context.reference(...)` correctly
+
+`writeNonRef` intentionally does not seed later back-references.
+
+## Cross-language field mismatch
+
+Symptoms include missing data, default values, or type errors on peers.
+
+Check:
+
+- same registration identity on both sides
+- stable field IDs for evolving structs
+- matching logical field names and meanings
+- compatible numeric widths and temporal types
+
+## Validation Commands
+
+For the main Dart workspace:
+
+```bash
+cd dart
+dart run build_runner build --delete-conflicting-outputs
+dart analyze
+dart test
+```
+
+For the integration-style test package:
+
+```bash
+cd dart/packages/fory-test
+dart run build_runner build --delete-conflicting-outputs
+dart test
+```
+
+## Related Topics
+
+- [Cross-Language](cross-language.md)
+- [Code Generation](code-generation.md)
+- [Custom Serializers](custom-serializers.md)
diff --git a/docs/guide/dart/type-registration.md
b/docs/guide/dart/type-registration.md
new file mode 100644
index 0000000000..5d74560251
--- /dev/null
+++ b/docs/guide/dart/type-registration.md
@@ -0,0 +1,96 @@
+---
+title: Type Registration
+sidebar_position: 4
+id: dart_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.
+---
+
+This page covers how to register user-defined types in Apache Foryβ’ Dart.
+
+## Registration Modes
+
+Fory Dart supports the same two registration styles used by other xlang
runtimes.
+
+### Register by Numeric ID
+
+Numeric IDs are compact on the wire and fast to resolve.
+
+```dart
+ModelsFory.register(fory, User, id: 100);
+```
+
+Use the same numeric ID for the same logical type in every language.
+
+### Register by Namespace and Type Name
+
+Name-based registration avoids global numeric ID coordination and is often
easier across multiple teams.
+
+```dart
+ModelsFory.register(
+ fory,
+ User,
+ namespace: 'example',
+ typeName: 'User',
+);
+```
+
+The same `namespace + typeName` pair must be used by every runtime that reads
or writes the type.
+
+## Generated Type Registration
+
+Generated types should normally be registered through the generated namespace
wrapper:
+
+```dart
+UserModelsFory.register(fory, User, id: 100);
+```
+
+Internally, the wrapper installs generated metadata and then calls
`Fory.register(...)`.
+
+## Register a Manual Serializer
+
+Customized serializers register through `registerSerializer`:
+
+```dart
+fory.registerSerializer(
+ ExternalType,
+ const ExternalTypeSerializer(),
+ namespace: 'example',
+ typeName: 'ExternalType',
+);
+```
+
+## Cross-Language Requirements
+
+Registration must match across runtimes:
+
+- same numeric ID, or
+- same namespace and type name
+
+The wire format distinguishes built-in xlang type IDs from user-registered
type IDs. The user ID is encoded separately as an unsigned varint32, as
described in the [xlang serialization
specification](../../specification/xlang_serialization_spec.md).
+
+## Common Rules
+
+- Register before the first serialize or deserialize call.
+- Register nested user-defined types as well as root types.
+- Keep IDs stable once payloads are persisted or exchanged across services.
+- Do not mix a numeric ID on one side with a name-based registration on the
other side for the same type.
+
+## Related Topics
+
+- [Code Generation](code-generation.md)
+- [Cross-Language](cross-language.md)
+- [Custom Serializers](custom-serializers.md)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]