[]previous and next page

The project

allowedHosts must list localhost: the build prerenders pages by requesting http://localhost (see Prerender at build time).

For agentsUpdated
vite.config.tsts
import { dusk } from "@shadow-js/dusk/vite";
import { defineConfig } from "vite";

export default defineConfig({ plugins: [dusk()] });

allowedHosts must list localhost: the build prerenders pages by requesting http://localhost (see Prerender at build time).

src/entry-server.tsts
import type { HandlerOptions } from "@shadow-js/dusk/server";

const options: Omit<HandlerOptions, "manifest"> = {
  security: { allowedHosts: ["localhost", "example.com"] },
};

export default options;
src/routes/index.tsxtsx
import type { HeadTag, JSX } from "@shadow-js/web";

export const head = (): HeadTag[] => [{ tag: "title", children: "Home" }];

export default function Home(): JSX.Element {
  return <p>Welcome</p>;
}
src/routes/about.tsxtsx
import type { JSX } from "@shadow-js/web";

export const prerender = true;

export default function About(): JSX.Element {
  return <p>About this site</p>;
}
src/routes/posts/[id].tsxtsx
import { type LoaderArgs, useLoaderData } from "@shadow-js/router";
import type { JSX } from "@shadow-js/web";

export const prerender = ["/posts/1", "/posts/2"];

export const loader = ({ params }: LoaderArgs<"/posts/:id", unknown>) => ({
  title: `Post ${params.id}`,
});

export default function PostPage(): JSX.Element {
  const post = useLoaderData<{ title: string }>();
  return <h1>{post()?.title}</h1>;
}
src/routes/dashboard.tsxtsx
import type { JSX } from "@shadow-js/web";

export const ssr = false;

export default function Dashboard(): JSX.Element {
  return <p>Dashboard</p>;
}
src/routes/api/info.tsts
import { json, type RequestEvent } from "@shadow-js/dusk/server";

export const GET = (event: RequestEvent) =>
  json({ url: event.url.href, address: event.clientAddress ?? null });