diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index cb99cd2..1a39b5c 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -5,12 +5,16 @@ on:
jobs:
test:
- name: Test on ${{ matrix.os }}
+ name: Test ${{ matrix.example }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
+ example:
+ - examples/basic
+ - examples/onBeforeRender
+ - examples/ssr-spa
steps:
- uses: actions/checkout@v4
@@ -20,16 +24,10 @@ jobs:
- name: Build vike-solid
run: pnpm run build
- - name: Test building examples/basic
+ - name: Test building example
run: pnpm run build
- working-directory: ./examples/basic
- - name: Test building examples/ssr-spa
- run: pnpm run build
- working-directory: ./examples/ssr-spa
+ working-directory: ./${{ matrix.example }}
- - name: Test TypeScript examples/basic
- run: pnpm run test
- working-directory: ./examples/basic
- - name: Test TypeScript examples/ssr-spa
+ - name: Test TypeScript example
run: pnpm run test
- working-directory: ./examples/ssr-spa
+ working-directory: ./${{ matrix.example }}
diff --git a/examples/basic/README.md b/examples/basic/README.md
index a3fa07a..9b13f9a 100644
--- a/examples/basic/README.md
+++ b/examples/basic/README.md
@@ -1,4 +1,10 @@
-Basic example of using `vike-solid`.
+Basic example of using `vike-solid`, showcasing:
+
+- [layouts](https://vike.dev/layouts)
+- rendering to `
`
+- fetching data with [`data()`](https://vike.dev/data) hooks
+- [configs](https://vike.dev/config)
+- [error pages](https://vike.dev/error-page)
```bash
git clone git@github.com:vikejs/vike-solid
diff --git a/examples/basic/pages/star-wars/@id/+Page.tsx b/examples/basic/pages/star-wars/@id/+Page.tsx
index 017de2a..9efe771 100644
--- a/examples/basic/pages/star-wars/@id/+Page.tsx
+++ b/examples/basic/pages/star-wars/@id/+Page.tsx
@@ -1,14 +1,16 @@
-import type { MovieDetails } from "../types";
+import type { Data } from "./+data";
+import { useData } from "vike-solid/useData";
-export default function Page(props: { movie: MovieDetails }) {
+export default function Page() {
+ const { movie } = useData();
return (
<>
-
{props.movie.title}
- Release Date: {props.movie.release_date}
+
{movie.title}
+ Release Date: {movie.release_date}
- Director: {props.movie.director}
+ Director: {movie.director}
- Producer: {props.movie.producer}
+ Producer: {movie.producer}
>
);
}
diff --git a/examples/basic/pages/star-wars/@id/+data.ts b/examples/basic/pages/star-wars/@id/+data.ts
new file mode 100644
index 0000000..f1df58f
--- /dev/null
+++ b/examples/basic/pages/star-wars/@id/+data.ts
@@ -0,0 +1,29 @@
+// https://vike.dev/data
+export { data };
+export type { Data };
+
+import fetch from "cross-fetch";
+import type { PageContextServer } from "vike/types";
+import { filterMovieData } from "../filterMovieData";
+import type { MovieDetails } from "../types";
+
+type Data = Awaited>;
+
+const data = async (pageContext: PageContextServer) => {
+ const response = await fetch(
+ `https://star-wars.brillout.com/api/films/${pageContext.routeParams?.id}.json`
+ );
+ let movie = (await response.json()) as MovieDetails;
+
+ // We remove data we don't need because we pass `pageContext.movie` to
+ // the client; we want to minimize what is sent over the network.
+ movie = filterMovieData(movie);
+
+ const { title } = movie;
+
+ return {
+ movie,
+ // The page's
+ title,
+ };
+};
diff --git a/examples/basic/pages/star-wars/index/+Page.tsx b/examples/basic/pages/star-wars/index/+Page.tsx
index 0d36d2f..563ad92 100644
--- a/examples/basic/pages/star-wars/index/+Page.tsx
+++ b/examples/basic/pages/star-wars/index/+Page.tsx
@@ -1,12 +1,14 @@
import { For } from "solid-js";
-import type { Movie } from "../types";
+import type { Data } from "./+data";
+import { useData } from "vike-solid/useData";
-export default function Page(props: { movies: Movie[] }) {
+export default function Page() {
+ const { movies } = useData();
return (
<>
Star Wars Movies
-
+
{(movie, i) => (
{movie.title} (
diff --git a/examples/basic/pages/star-wars/index/+data.ts b/examples/basic/pages/star-wars/index/+data.ts
new file mode 100644
index 0000000..f2693a6
--- /dev/null
+++ b/examples/basic/pages/star-wars/index/+data.ts
@@ -0,0 +1,80 @@
+// https://vike.dev/data
+export { data };
+export type { Data };
+
+import fetch from "node-fetch";
+//import { filterMovieData } from '../filterMovieData'
+import type { Movie, MovieDetails } from "../types";
+
+// export { onBeforePrerenderStart }
+
+type Data = Awaited>;
+
+const data = async () => {
+ const movies = await getStarWarsMovies();
+ return {
+ // We remove data we don't need because we pass `pageContext.movies` to
+ // the client; we want to minimize what is sent over the network.
+ movies: filterMoviesData(movies),
+ // The page's
+ title: getTitle(movies),
+ };
+};
+
+async function getStarWarsMovies(): Promise {
+ const response = await fetch("https://star-wars.brillout.com/api/films.json");
+ let movies: MovieDetails[] = ((await response.json()) as any).results;
+ movies = movies.map((movie: MovieDetails, i: number) => ({
+ ...movie,
+ id: String(i + 1),
+ }));
+ return movies;
+}
+
+function filterMoviesData(movies: MovieDetails[]): Movie[] {
+ return movies.map((movie: MovieDetails) => {
+ const { title, release_date, id } = movie;
+ return { title, release_date, id };
+ });
+}
+
+/*
+async function onBeforePrerenderStart() {
+ const movies = await getStarWarsMovies()
+ return [
+ {
+ url: '/star-wars',
+ // We already provide `pageContext` here so that vike-solid
+ // will *not* have to call the `data()` hook defined
+ // above in this file.
+ pageContext: {
+ data: {
+ movies: filterMoviesData(movies),
+ title: getTitle(movies)
+ },
+ }
+ },
+ ...movies.map((movie) => {
+ const url = `/star-wars/${movie.id}`
+ return {
+ url,
+ // Note that we can also provide the `pageContext` of other pages.
+ // This means that vike-solid will not call any
+ // `data()` hook and the Star Wars API will be called
+ // only once (in this `onBeforePrerenderStart()` hook).
+ pageContext: {
+ data: {
+ movie: filterMovieData(movie),
+ title: movie.title
+ },
+ }
+ }
+ })
+ ]
+}
+*/
+
+function getTitle(movies: Movie[] | MovieDetails[]): string {
+ const title = `${movies.length} Star Wars Movies`;
+ return title;
+}
diff --git a/examples/onBeforeRender/README.md b/examples/onBeforeRender/README.md
new file mode 100644
index 0000000..7562bc2
--- /dev/null
+++ b/examples/onBeforeRender/README.md
@@ -0,0 +1,18 @@
+Basic example of using `vike-solid`, showcasing:
+
+- [layouts](https://vike.dev/layouts)
+- rendering to ``
+- fetching data with [`onBeforeRender()`](https://vike.dev/onBeforeRender) hooks
+- [configs](https://vike.dev/config)
+- [error pages](https://vike.dev/error-page)
+
+```bash
+git clone git@github.com:vikejs/vike-solid
+cd vike-solid/examples/basic/
+pnpm install
+pnpm run dev
+```
+
+> **NOTE:** for now `pnpm` is required because of the `workspace:` specifier in
+> `package.json`. With this, the example makes use of the local `vike-solid`
+> implementation instead of the downloading it from npm.
diff --git a/examples/onBeforeRender/assets/logo.svg b/examples/onBeforeRender/assets/logo.svg
new file mode 100644
index 0000000..94d3caa
--- /dev/null
+++ b/examples/onBeforeRender/assets/logo.svg
@@ -0,0 +1,36 @@
+
+
diff --git a/examples/onBeforeRender/components/Link.tsx b/examples/onBeforeRender/components/Link.tsx
new file mode 100644
index 0000000..361010d
--- /dev/null
+++ b/examples/onBeforeRender/components/Link.tsx
@@ -0,0 +1,16 @@
+import { createMemo } from "solid-js";
+import { usePageContext } from "vike-solid/usePageContext";
+
+export function Link(props: { href: string; children: string }) {
+ const pageContext = usePageContext();
+ const isActive = createMemo(() =>
+ props.href === "/"
+ ? pageContext.urlPathname === props.href
+ : pageContext.urlPathname.startsWith(props.href)
+ );
+ return (
+
+ {props.children}
+
+ );
+}
diff --git a/examples/onBeforeRender/layouts/LayoutDefault.tsx b/examples/onBeforeRender/layouts/LayoutDefault.tsx
new file mode 100644
index 0000000..4c947a2
--- /dev/null
+++ b/examples/onBeforeRender/layouts/LayoutDefault.tsx
@@ -0,0 +1,73 @@
+import "./style.css";
+import logoUrl from "../assets/logo.svg";
+import { Link } from "../components/Link";
+import type { JSX } from "solid-js";
+
+export default function LayoutDefault(props: { children?: JSX.Element }) {
+ return (
+