diff --git a/packages/endpoint/src/schemas/EntitySchema.ts b/packages/endpoint/src/schemas/EntitySchema.ts
index 52e86a745b62..631b1ab01406 100644
--- a/packages/endpoint/src/schemas/EntitySchema.ts
+++ b/packages/endpoint/src/schemas/EntitySchema.ts
@@ -12,7 +12,7 @@ import { AbstractInstanceType } from '../normal.js';
* Represents data that should be deduped by specifying a primary key.
* @see https://dataclient.io/rest/api/schema.Entity
*/
-export default function EntitySchema(
+export default function EntityMixin(
Base: TBase,
options: EntityOptions> = {},
) {
diff --git a/website/blog/2024-06-17-v0.13-nextjs-app-router-expogo-native.md b/website/blog/2024-06-17-v0.13-nextjs-app-router-expogo-native.md
index c5d8161dcb9d..99468d07cc9a 100644
--- a/website/blog/2024-06-17-v0.13-nextjs-app-router-expogo-native.md
+++ b/website/blog/2024-06-17-v0.13-nextjs-app-router-expogo-native.md
@@ -41,6 +41,7 @@ Version 0.12 was skipped due to a publishing mishap.
import Grid from '@site/src/components/Grid';
import TypeScriptEditor from '@site/src/components/TypeScriptEditor';
import DiffEditor from '@site/src/components/DiffEditor';
+import AutoPlayVideo from '@site/src/components/AutoPlayVideo';
## Platforms
@@ -74,13 +75,7 @@ xychart-beta
-
-
-
-
+
Data Client performs streaming SSR of the HTML, streamlining the initial
application load experience. Uniquely, Data Client is then immediately interactive
@@ -117,16 +112,13 @@ export default function RootLayout({ children }) {
Full NextJS Guide
-#### Demo
+#### Mutations demo
-
+#### Live data demo
-
- Open in new tab
- Github
-
+
#### Other SSR
@@ -233,6 +225,7 @@ This makes it more straightforward to manipulate the store with [Managers](/docs
For example we can directly set our `Ticker` entity when receiving websocket messages:
import StackBlitz from '@site/src/components/StackBlitz';
+import Embed from '@site/src/components/Embed';
diff --git a/website/src/components/AutoPlayVideo.tsx b/website/src/components/AutoPlayVideo.tsx
new file mode 100644
index 000000000000..1099e7450020
--- /dev/null
+++ b/website/src/components/AutoPlayVideo.tsx
@@ -0,0 +1,64 @@
+import React, { useEffect, useRef } from 'react';
+
+const AutoPlayVideo = ({
+ src,
+ type = 'video/mp4',
+ ...props
+}: React.VideoHTMLAttributes & { type?: string }) => {
+ const videoRef = useRef(null);
+
+ useEffect(() => {
+ const videoElement = videoRef.current;
+ if (!videoElement) return;
+
+ // Ensure IntersectionObserver is supported
+ if (!('IntersectionObserver' in window)) {
+ // Fallback to always play if not supported
+ videoElement.play();
+ return;
+ }
+
+ const observerOptions = {
+ root: null, // Use the viewport as the container
+ rootMargin: '0px',
+ threshold: 0.25, // Play when 25% of the video is visible
+ };
+
+ const handleIntersect = entries => {
+ entries.forEach(entry => {
+ if (entry.isIntersecting) {
+ videoElement.play();
+ } else {
+ videoElement.pause();
+ }
+ });
+ };
+
+ const observer = new IntersectionObserver(handleIntersect, observerOptions);
+ observer.observe(videoElement);
+
+ // Clean up the observer on unmount
+ return () => {
+ observer.unobserve(videoElement);
+ };
+ }, []);
+
+ return (
+