The project
allowedHosts must list localhost: the build prerenders pages by requesting http://localhost (see Prerender at build time).
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 });