app/ (or pages/) define routes; layouts compose down the tree; brackets in path segments mark dynamic params.
Examples below use the default app router. Set router: "pages" in veryfront.config.ts to switch to the pages router.
Prerequisites
- A project created with
veryfront init(see Create project). - The dev server is the easiest way to test routes:
veryfront dev.
Router equivalents
Veryfront supports both router styles. The main difference is file shape:
Use the app router when you want the newer directory-per-route shape. Use the pages router when you want the flatter file-per-route layout.
Basic pages
veryfront dev and open http://localhost:3000. The page should render Welcome.
Layouts
Layouts wrap pages and persist across navigation. Createlayout.tsx at any level:
/dashboard/settings renders inside both the root layout and the dashboard layout.
layout.tsx and the other supported layout.* extensions are reserved layout metadata at every
directory level in both routers. They wrap descendant pages and never create a /layout route.
Overriding or disabling a layout
A page can opt out of the nested layout chain, or replace it with a named layout. On.md/.mdx pages, set layout in the frontmatter:
.tsx/.jsx/.ts/.js pages, export a layout constant:
frontmatter object:
frontmatter.layout property accepts the same false and named-layout values as the direct
layout export.
Supported values in both cases:
layout: falserenders the page bare: no ancestor layouts, no default layout.layout: "name"replaces the entire nested chain with the named layout. Ancestor layouts (including the root layout) are not applied.
@/layouts/custom.tsx or
@components/CustomLayout.tsx, loads that file directly, without falling back to
convention-based discovery. Plain names resolve from, in order:
layouts/<name>.{tsx,mdx,md,jsx,ts,js}- anything inlayouts/is a layout.components/<Name>Layout.*orcomponents/Layout.*.
layout in veryfront.config.ts; a page’s
layout frontmatter or export always wins over the config default.
Dynamic routes
Use brackets for dynamic segments:usePageContext hook:
Post: hello.
Catch-all routes
Use[...segments] to match multiple path segments:
MDX pages
Rename any page to.mdx to write content in Markdown with JSX:
usePageContext() from veryfront/context:
Lazy JSX imports
Veryfront bounds the on-disk JSX transform cache. A loaded MDX module keeps a recovery snapshot for its literal dynamic JSX imports, so a delayed import can restore an evicted artifact. Recovery uses the original transformed code, not the latest source at that path. Load the updated MDX module to use changed source. Recovery snapshots have a combined limit of 2 MiB per MDX module. Recovery follows the same cache capacity limits as initial compilation and can fail when active artifacts occupy the available capacity. Recovery snapshots share a process-wide cache with a 16 MiB storage budget and a 256-entry limit. Identical transformed sources share one snapshot. Least-recently used snapshots are evicted when either limit is reached. Existing on-disk artifacts remain usable. If both an artifact and its snapshot are evicted, the delayed import fails. Reload the MDX module to capture its recovery data again. Temporary parent modules use the same disk quota and maintenance sweeps as JSX artifacts. If immediate cleanup fails, a later sweep retires the file, including after a process restart. Active evaluations keep their parent artifacts pinned. During a rolling upgrade, automatic cleanup preserves prior-version JSX artifacts. Their timestamps cannot prove that older runtimes have stopped using them. Before you remove legacy artifacts, you must ensure all runtimes using those versions have drained and cannot resume. Legacy files remain outside the current version’s quota and require operator-managed cleanup; total disk usage across versions is not bounded by the current version’s quota.Override rendered MDX elements
Wrap an MDX page or layout withMDXProvider to replace generated elements:
useMDXComponents(localOverrides) when a component
needs the effective map; local entries take final precedence.
MDXProvider supplies application-owned React components to already compiled
MDX. It does not compile or sanitize arbitrary strings. Render runtime Markdown
strings with veryfront/markdown.
Reading server data from a layout or nested component
A page’sgetServerData props are passed to the page
component. To read them from a layout or a deeply-nested component without
prop-drilling, use usePageContext().data:
data is the object your page returned as getServerData’s props. It is
populated identically on the server render, in the hydration markup, and after
client-side navigation. A page without getServerData sees an empty object.
Client components
By default, components render on the server. Add'use client' to make a component interactive:
Navigation
Use theLink component for client-side navigation:
prefetch={false} when a link must not prefetch.
Programmatic navigation:
Reading the live location
useRouter() is the single hook for location and navigation. Its pathname,
query, and params update reactively on client-side navigation:
shouldRevalidate
option.
Verify it worked
Start the dev server and request each page you added:HTTP/1.1 200 OK. Visit the same URLs in a browser
to confirm the React component renders without console errors.