Index: pages/star-wars/@id/+Page.tsx
===================================================================
--- pages/star-wars/@id/+Page.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/star-wars/@id/+Page.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,16 @@
+import { useData } from "vike-react/useData";
+import type { Data } from "./+data.js";
+
+export default function Page() {
+  const { movie } = useData<Data>();
+  return (
+    <>
+      <h1>{movie.title}</h1>
+      Release Date: {movie.release_date}
+      <br />
+      Director: {movie.director}
+      <br />
+      Producer: {movie.producer}
+    </>
+  );
+}
Index: pages/star-wars/@id/+data.ts
===================================================================
--- pages/star-wars/@id/+data.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/star-wars/@id/+data.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,31 @@
+// https://vike.dev/data
+
+import type { PageContextServer } from "vike/types";
+import { useConfig } from "vike-react/useConfig";
+import type { MovieDetails } from "../types.js";
+
+export type Data = Awaited<ReturnType<typeof data>>;
+
+export async function data(pageContext: PageContextServer) {
+  // https://vike.dev/useConfig
+  const config = useConfig();
+
+  const response = await fetch(`https://brillout.github.io/star-wars/api/films/${pageContext.routeParams.id}.json`);
+  let movie = (await response.json()) as MovieDetails;
+
+  config({
+    // Set <title>
+    title: movie.title,
+  });
+
+  // We remove data we don't need because the data is passed to
+  // the client; we should minimize what is sent over the network.
+  movie = minimize(movie);
+
+  return { movie };
+}
+
+function minimize(movie: MovieDetails): MovieDetails {
+  const { id, title, release_date, director, producer } = movie;
+  return { id, title, release_date, director, producer };
+}
Index: pages/star-wars/index/+Page.tsx
===================================================================
--- pages/star-wars/index/+Page.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/star-wars/index/+Page.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,21 @@
+import { useData } from "vike-react/useData";
+import type { Data } from "./+data.js";
+
+export default function Page() {
+  const { movies } = useData<Data>();
+  return (
+    <>
+      <h1>Star Wars Movies</h1>
+      <ol>
+        {movies.map(({ id, title, release_date }) => (
+          <li key={id}>
+            <a href={`/star-wars/${id}`}>{title}</a> ({release_date})
+          </li>
+        ))}
+      </ol>
+      <p>
+        Source: <a href="https://brillout.github.io/star-wars">brillout.github.io/star-wars</a>.
+      </p>
+    </>
+  );
+}
Index: pages/star-wars/index/+data.ts
===================================================================
--- pages/star-wars/index/+data.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/star-wars/index/+data.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,32 @@
+// https://vike.dev/data
+
+import { useConfig } from "vike-react/useConfig";
+import type { Movie, MovieDetails } from "../types.js";
+
+export type Data = Awaited<ReturnType<typeof data>>;
+
+export async function data() {
+  // https://vike.dev/useConfig
+  const config = useConfig();
+
+  const response = await fetch("https://brillout.github.io/star-wars/api/films.json");
+  const moviesData = (await response.json()) as MovieDetails[];
+
+  config({
+    // Set <title>
+    title: `${moviesData.length} Star Wars Movies`,
+  });
+
+  // We remove data we don't need because the data is passed to the client; we should
+  // minimize what is sent over the network.
+  const movies = minimize(moviesData);
+
+  return { movies };
+}
+
+function minimize(movies: MovieDetails[]): Movie[] {
+  return movies.map((movie) => {
+    const { title, release_date, id } = movie;
+    return { title, release_date, id };
+  });
+}
Index: pages/star-wars/types.ts
===================================================================
--- pages/star-wars/types.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/star-wars/types.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,10 @@
+export type Movie = {
+  id: string;
+  title: string;
+  release_date: string;
+};
+
+export type MovieDetails = Movie & {
+  director: string;
+  producer: string;
+};
