A folder with frontend: { stack: "mdx" }. Pages are .mdx, layouts are layout.mdx. Routing, fetch clients and validation behave the same for every frontend. MDX folders ›
No TypeScript in .mdx
This is the MDX-specific trap, and it has no workaround. .mdx is parsed as plain JavaScript with JSX - no type annotations, no type arguments, no type imports:
{/* MDX: pages/users/[id]/index.mdx */}
import { useLoaderData } from "_/use";
export const Profile = () => {
// no type argument - the result is untyped
const user = useLoaderData();
return <p>{user?.name}</p>;
};
<Profile />useParams<"users/[id]">() and import type { X } are both syntax errors here. Keep typed code in a .tsx component and import it into the page.
Hooks run during render
_/use exists in MDX folders with the full set, plus useFrontmatter. export const x = useHook() at module scope runs on import, not during render - always call hooks inside a component function:
export const P = () => useParams(); // runs during renderA loader cannot use hooks either; it receives the resolved route object, which carries paramsEntries and frontmatter.
Frontmatter drives head and static params
staticParams is declared in frontmatter rather than as an export, since a .mdx page has no typed export surface:
---
title: Documentation
staticParams:
- [getting-started]
- [routing]
---Layouts
<!-- MDX: layout.mdx -->
<nav>
<a href="/">Home</a>
<a href="/docs">Docs</a>
</nav>
<main>
{props.children}
</main>
<footer>
Built with KosmoJS
</footer>Layouts must be .mdx. A plain .md file cannot render {props.children} and will not work as one.
Worth knowing
- SSR is string-only.
renderMode: "stream"is not available for MDX folders. - MDX has no third-party router, so KosmoJS supplies the matcher and emits its own
RawRouteshape. Routing › - The seeded
Linkcomponent is typed inLink.tsx, but.mdxcall sites are not type-checked, so a wrong route name surfaces at runtime. - Curly braces in prose are parsed as JSX - wrap them in backticks.
- The default plugin is
@mdx-js/rollupwith a Preact JSX runtime.