Routing
File-based routing
x uses the file system as your route table. Drop a file in src/pages/, get a route.
How it works
Every .tsx file in your pages directory becomes a route. The file path determines the URL pattern.
routing table
pages/index.tsx -> /pages/about.tsx -> /aboutpages/contact.tsx -> /contactpages/blog/index.tsx -> /blogpages/blog/[slug].tsx -> /blog/:slugpages/dashboard/ settings.tsx -> /dashboard/settings profile.tsx -> /dashboard/profilepages/_404.tsx -> catch-all 404Static routes
Simple files map to exact URL paths. pages/about.tsx becomes /about.
src/pages/about.tsx
export default function About() { return <h1 className="text-3xl font-bold">About us</h1>;}Dynamic segments
Wrap a filename in square brackets to create a dynamic segment. The value is available via the params object in loaders.
src/pages/blog/[slug].tsx
import type { RouteProps, LoaderArgs } from "@thexjs/core";export async function loader({ params }: LoaderArgs) { const post = await getPost(params.slug); return { title: post.title, content: post.content };}export default function BlogPost({ loaderData }: RouteProps<typeof loader>) { return ( <article> <h1 className="text-3xl font-bold">{loaderData.title}</h1> <div>{loaderData.content}</div> </article> );}Multiple dynamic segments work too: pages/product/[category]/[id].tsx → /product/:category/:id.
Nested routes with folders
Organize routes in folders for nested URL structures. Each folder can have its own index.tsx.
pages/dashboard/index.tsx -> /dashboardsettings.tsx -> /dashboard/settingsprofile.tsx -> /dashboard/profilebilling/index.tsx -> /dashboard/billinghistory.tsx -> /dashboard/billing/history
Catch-all 404 page
Create pages/_404.tsx to show a custom not-found page for unmatched routes.
src/pages/_404.tsx
export default function NotFound() { return ( <div className="text-center py-20"> <h1 className="text-6xl font-bold text-muted-foreground">404</h1> <p className="mt-4 text-lg text-muted-foreground">Page not found</p> <a href="/docs" className="mt-6 inline-block text-primary hover:underline"> Go home </a> </div> );}