Dynamic Routes

Wrap a folder name in brackets to capture a path segment.

FolderMatchesrouter.params
app/blog/[slug]/page.jsx/blog/hello{ slug: "hello" }
app/docs/[...path]/page.jsx/docs/a/b/c{ path: "a/b/c" }

[param] matches one segment; [...rest] is a catch-all matching the remainder.

Reading params

Params are exposed on the reactive router:

JSX
import { router } from "@opentf/web";

export default function Post() {
  return <h1>Post: {router.params.slug}</h1>;
}

Reading router.params inside a binding keeps the view in sync as you navigate between matching routes.

Per-path metadata

Export generateMetadata({ params }) on a dynamic page when each path needs its own <title>, description, or share image. With otfw build --ssg, pair it with getStaticPaths so every enumerated path is pre-rendered with the correct head. A dynamic route without getStaticPaths is skipped at build time but still resolves generateMetadata on each request under otfw serve / SSR. See Metadata & SEO.