Skip to main content
Veryfront uses file-system based routing. Folders and files under 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

A page exports a default React component:
Run veryfront dev and open http://localhost:3000. The page should render Welcome.

Layouts

Layouts wrap pages and persist across navigation. Create layout.tsx at any level:
Nested layouts compose automatically:
/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:
On .tsx/.jsx/.ts/.js pages, export a layout constant:
You can also put the same value in an exported frontmatter object:
The frontmatter.layout property accepts the same false and named-layout values as the direct layout export. Supported values in both cases:
  • layout: false renders 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.
An explicit project path with a file extension, such as @/layouts/custom.tsx or @components/CustomLayout.tsx, loads that file directly, without falling back to convention-based discovery. Plain names resolve from, in order:
  1. layouts/<name>.{tsx,mdx,md,jsx,ts,js} - anything in layouts/ is a layout.
  2. components/<Name>Layout.* or components/Layout.*.
A project-wide default can also be set with 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:
Access params via the usePageContext hook:
Open http://localhost:3000/blog/hello. The page should render 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:
MDX pages support frontmatter:
Access frontmatter from components using 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 with MDXProvider to replace generated elements:
Nested providers inherit entries from outer providers. A nearer provider wins for duplicate keys. Call 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’s getServerData 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:
Use the Link component for client-side navigation:
Veryfront can prefetch eligible internal links before navigation. Use 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:
By default a query-only navigation refetches the page so server data that depends on the query is never shown stale. If a page’s query is purely client-side state (tabs, filters), opt into the soft fast path, updating the URL and re-rendering without a refetch, with the router’s shouldRevalidate option.

Verify it worked

Start the dev server and request each page you added:
Each request should return HTTP/1.1 200 OK. Visit the same URLs in a browser to confirm the React component renders without console errors.