diff --git a/website/src/app/pages/documentation.component.ts b/website/src/app/pages/documentation.component.ts
index 8047a786b..a02a8f88e 100644
--- a/website/src/app/pages/documentation.component.ts
+++ b/website/src/app/pages/documentation.component.ts
@@ -76,6 +76,7 @@ import { PlatformHelper } from '@app/app/utils';
Reflection
Serialization
Validation
+ Extend
Custom serializer
External Types
Bytecode
diff --git a/website/src/pages/documentation/runtime-types/extend.md b/website/src/pages/documentation/runtime-types/extend.md
new file mode 100644
index 000000000..d66271d47
--- /dev/null
+++ b/website/src/pages/documentation/runtime-types/extend.md
@@ -0,0 +1,56 @@
+# Extend
+
+## Custom Serialization
+
+You can extend the serialization of a type by defining either write your own `Serializer` or extend the default `serializer`.
+
+This example shows how to serialize and deserialize a class `Point` to a tuple `[number, number]`.
+
+```typescript
+import { serializer, SerializationError } from '@deepkit/type';
+
+class Point {
+ constructor(public x: number, public y: number) {
+ }
+}
+
+// deserialize means from JSON to (class) instance.
+serializer.deserializeRegistry.registerClass(Point, (type, state) => {
+ state.convert((v: any) => {
+ // if it's already a Point instance, we are done
+ if (v instanceof Point) return v;
+
+ // at this point `v` could be anything (except undefined), so we need to check
+ if (!Array.isArray(v)) throw new SerializationError('Expected array');
+ if (v.length !== 2) throw new SerializationError('Expected array with two elements');
+ if (typeof v[0] !== 'number' || typeof v[1] !== 'number') throw new SerializationError('Expected array with two numbers');
+ return new Point(v[0], v[1]);
+ });
+});
+
+serializer.serializeRegistry.registerClass(Point, (type, state) => {
+ state.convert((v: Point) => {
+ // at this point `v` is always a Point instance
+ return [v.x, v.y];
+ });
+});
+
+// cast and deserialize use `serializer` by default
+const point = cast([1, 2], undefined, serializer);
+expect(point).toBeInstanceOf(Point);
+expect(point.x).toBe(1);
+expect(point.y).toBe(2);
+
+{
+ expect(() => deserialize(['vbb'])).toThrowError(SerializationError);
+ expect(() => deserialize(['vbb'])).toThrow('Expected array with two elements')
+}
+
+// serialize uses `serializer` by default
+const json = serialize(point);
+expect(json).toEqual([1, 2]);
+```
+
+Please note that this is only working for the regular `@deepkit/type` functions like `cast`, `deserialize`, and `serialize`.
+
+This won't be transferred to the database layer, since the database layer uses the types as defined in the Entity class for migration and serialization (e.g. BSON serialization).