getStaticPaths
List the params a dynamic page is exported for when gio export writes a static site.
app/posts/[id]/page.tsx
import type { GetStaticPaths } from '@gio.js/core';
import { db } from '../../../lib/db.server.ts';
export const getStaticPaths: GetStaticPaths<'/posts/:id'> = async () => {
const ids = await db.posts.allIds();
return { paths: ids.map((id) => ({ params: { id } })) };
};A static host has no server to render /posts/42 on demand, so gio export needs the list up front. It calls getStaticPaths once per dynamic page and renders one HTML file per entry. The GioJS server never calls it: there, any params render on demand.
Reference
Returns
getStaticPaths takes no arguments and returns (or resolves to) { paths }:
| Field | Type | Default | Description |
|---|---|---|---|
paths (required) | Array<{ params }> | - | One entry per page to write. |
paths[].params (required) | StaticParamsOf<Route> | - | A value for every dynamic segment of the route. [id] takes a string. A catch-all ([...slug]) takes the path below it as one string ('guides/setup') or as its segments (['guides', 'setup']). An optional catch-all ([[...slug]]) may also be left out, '' or [], for the bare parent path. |
Behavior
- Each entry becomes a URL path, and the page renders for it as on the server -
getServerSidePropsandgenerateMetadataincluded - with the params filled in and no query, headers or cookies./posts/1is written toout/posts/1/index.html. - An invalid entry is skipped with a reason, and the rest are exported:
getStaticPaths entry is missing param "id"param "id" is a single segment but "a/b" contains '/'param "slug" has an empty, relative or backslashed segment: "../x"- nothing is ever written outsideout/
- A rendered entry that answers
404(notFound()) is skipped (notFound() - nothing written), and so is a redirect (redirect (303) - server only) or a render error (with its error reference). - A dynamic page without
getStaticPathsis skipped:dynamic route without getStaticPaths(). - If
getStaticPathsthrows or rejects,gio exportstops with the error and exits with code1.
Types
GetStaticPaths<Route> types the function and checks every entry against the route's params; Route is a pattern of your app ('/posts/:id', '/docs/*slug', '/shop/*path?') or a params shape. StaticPathsResult<Route> types the result alone.
Examples
A catch-all route
app/docs/[[...slug]]/page.tsx
import type { GetStaticPaths, PageProps } from '@gio.js/core';
export default function Doc({ params }: PageProps<'/docs/*slug?'>) {
return <h1>{params.slug === '' ? 'Docs' : params.slug}</h1>;
}
export const getStaticPaths: GetStaticPaths<'/docs/*slug?'> = () => ({
paths: [
{ params: { slug: [] } }, // /docs
{ params: { slug: 'intro' } }, // /docs/intro
{ params: { slug: ['guides', 'setup'] } }, // /docs/guides/setup
],
});Run the export; its summary lists every page written and every entry skipped:
npx gio exportpnpm gio exportyarn gio exportbunx gio exporttext
[giojs] rendered 3 page(s):
✓ /docs
✓ /docs/guides/setup
✓ /docs/introGood to know
- There is no
fallback: a path that was not listed does not exist on the static host, which serves the exported404.html. - Pages with no dynamic segment need no
getStaticPaths; they are exported once. - The data is frozen at export time: re-run
gio exportto publish new posts. getStaticPathsand the modules only it imports are left out of the browser bundle.- Exported pages carry their
getServerSidePropsprops as JSON for hydration, so never return secrets from it.
Related
Version history
| Version | Changes |
|---|---|
v0.1.0-beta.8 | Catch-all and optional catch-all routes, with strings or segment arrays; invalid entries are skipped with a reason; nothing is written outside out/; typed with GetStaticPaths. |
v0.1.0-beta.5 | Removed from browser bundles, with the modules only it imports. |
v0.1.0-beta.2 | Introduced, with gio export. |