Custom Pages
Add landing pages, API routes and other pages outside your content.
For a landing page or other custom UI, add a file under src/pages. It uses Astro's routing, and takes priority over a plugin page at the same path.
Creating a Page
---
import HomeLayout from "@fumapress/astro/components/HomeLayout.astro";
---
<HomeLayout title="About" description="About this project.">
<main>
<h1>About</h1>
<p>Built with Fumapress.</p>
</main>
</HomeLayout>It is available at /about. React components are islands on your page, like <Stars client:load />.
To render the page on demand, add export const prerender = false. The site then needs a server.
Don't give a custom page the same URL as a content page. Astro warns about the collision. To leave
/ free, put your content under a
baseDir.
Layouts
HomeLayout.astro adds the navbar and the head tags of your site. Content in its head slot goes into <head>. Your editor lists its props.
---
import HomeLayout from "@fumapress/astro/components/HomeLayout.astro";
import { getPressContext } from "@fumapress/astro/runtime";
---
<HomeLayout title="My Docs" description="The docs of my project.">
<main class="flex flex-1 flex-col items-center justify-center">
<h1 class="text-xl font-bold">Hello World</h1>
<a href={getPressContext().withBase("/docs")}>Open Docs</a>
</main>
</HomeLayout>Dynamic Routes
---
import HomeLayout from "@fumapress/astro/components/HomeLayout.astro";
const items: Record<string, { title: string; description: string }> = {
acme: { title: "Acme", description: "Docs of Acme" },
};
export function getStaticPaths() {
return Object.keys(items).map((slug) => ({ params: { slug } }));
}
const item = items[Astro.params.slug];
---
<HomeLayout title={item.title}>
<main>{item.description}</main>
</HomeLayout>404 Page
---
import HomeLayout from "@fumapress/astro/components/HomeLayout.astro";
---
<HomeLayout title="Not Found">
<main class="p-8 text-center">This page doesn't exist.</main>
</HomeLayout>Without this file, Fumapress renders the not found page of Fumadocs UI. Pass notFound to HomeLayout.astro to reuse it.
With internationalization, the built-in page uses the language of the URL when a server renders it. In static builds, 404.html is in the default language.
Reading Content
getPressContext() gives you the loader and helpers of your site. To get its types, export app from your config:
export const app = createPress(content).plugins(/* ... */);
export default app.config({/* ... */});See the Loader API for its other methods. If you are coming from Fumadocs, getPressContext() replaces your lib/source.ts.
Page URLs don't include your base setting. Add it with withBase().
Rendering a Collection
A collection you leave out of createPress() has no docs pages. Render its entries yourself, and pass getProviderData(Astro) so that links and your MDX components work:
---
import { getCollection, render } from "astro:content";
import HomeLayout from "@fumapress/astro/components/HomeLayout.astro";
import { getProviderData } from "@fumapress/astro/runtime";
import type { app } from "../../../press.config";
export async function getStaticPaths() {
const guides = await getCollection("guides");
return guides.map((entry) => ({ params: { slug: entry.id }, props: { entry } }));
}
const { entry } = Astro.props;
const { Content } = await render(entry);
const provider = getProviderData<typeof app>(Astro);
---
<HomeLayout title={entry.data.title}>
<Content provider={provider} />
</HomeLayout>API Routes
import type { APIRoute } from "astro";
export const prerender = false;
export const GET: APIRoute = () => Response.json({ version: "1.0.0" });Handlers can read getPressContext(). A route with prerender = false needs a server.
Feature Support
Some features of content pages work differently on custom pages:
- Languages: create a page per language.
- Sitemap: pages with params aren't listed, so add them.
- Open Graph images: add
og:imagetags to theheadslot ofHomeLayout.astro. - Markdown: custom pages have no Markdown version.
Last updated on