CORE CONCEPTS
Rasengan.js introduces a powerful and intuitive file-based routing system, inspired by modern frameworks but tailored to its own conventions.
All route definitions live inside the special folder: app/_routes/
The file and folder structure under this directory determines your app’s routing automatically.
bashapp/ ├── _routes/ │ ├── index.page.tsx # → / │ ├── home.page.tsx # → /home │ ├── about/ │ │ ├── layout.tsx # Layout for /about/* │ │ └── index.page.tsx # → /about │ ├── blog/ │ │ ├── index.page.tsx # → /blog │ │ ├── [id].page.tsx # → /blog/:id │ │ └── [slug]/ │ │ └── index.page.tsx # → /blog/:slug │ ├── _settings/ │ │ └── index.page.tsx # → /, /settings │ └── [_locale]/ │ └── home.page.tsx # → /home, /en/home, /fr/home, etc. └── app.router.ts # Entry point to register the routes
Note: The
app.router.tsfile is the entry point to register the routes.
The file-based routing system in Rasengan.js automatically generates a Router component based on your folder and file structure.
To integrate this generated router into your app, create a file at:
txtsrc/app/app.router.ts
And add the following:
tsximport { RouterComponent, defineRouter } from 'rasengan'; import Router from 'virtual:rasengan/router'; class AppRouter extends RouterComponent {} export default defineRouter({ imports: [Router], })(AppRouter);
virtual:rasengan/router./app/_routes.AppRouter using the defineRouter helper.This setup ensures that your routing configuration stays fully synchronized with your file structure — no manual registration required.
Every file ending with .page.tsx defines a route.
| File Name | Route Path | Description |
|---|---|---|
index.page.tsx | / | Index route |
home.page.tsx | /home | Normal route |
about/index.page.tsx | /about | Index route in about folder |
blog/index.page.tsx | /blog | Index route in blog folder |
blog/[id].page.tsx | /blog/:id | Dynamic route on file page |
blog/[_slug].page.tsx | /blog/:slug? | Optional dynamic route on file page |
[_locale]/home.page.tsx | /:locale?/home | Optional dynamic route on folder |
🖱 Only files located in
app/_routes/are considered valid route definitions.
Page components have to be exported as default in order to be registered as routes.
tsximport React from "react"; import { PageComponent } from "rasengan"; const Home: PageComponent = () => { return <div>Home Page</div>; }; Home.metadata = { title: "Home", description: "Home Page" }; export default Home;
Use layout.tsx files to define reusable structures (headers, sidebars, wrappers, etc.). A layout wraps all the routes inside its folder unless overridden by a deeper layout.
pages located at the same level of the layout or deeper will be wrapped by the layout.
bashapp/ ├── _routes/ │ ├── layout.tsx # Root Layout for all pages │ ├── index.page.tsx # → / │ ├── about/ │ │ ├── layout.tsx # Layout for /about/* │ │ └── index.page.tsx # → /about │ └── [_locale]/ │ ├── layout.tsx # Layout for /:locale?/* │ └── home.page.tsx # → /home, /en/home, /fr/home, etc. └── app.router.ts # Entry point to register the routes
From this file structure, the app/_routes/about/index.page.tsx will be wrapped by the app/_routes/about/layout.tsx and the app/_routes/layout.tsx.
The Layout Component has the be exported by default in order to be registered as a layout.
tsximport React from "react"; import { LayoutComponent, Outlet } from "rasengan"; const AppLayout: LayoutComponent = () => { return ( <div> <header>My Header</header> <Outlet /> {/* Renders the current page */} <footer>My Footer</footer> </div> ); }; export default AppLayout;
| Layout Path | Applies To |
|---|---|
app/_routes/layout.tsx | All routes |
app/_routes/about/layout.tsx | Routes under /about |
To create dynamic routes, wrap folder names in square brackets:
txtapp/_routes/blog/[slug]/index.page.tsx → /blog/:slug or app/_routes/blog/[slug].page.tsx → /blog/:slug
You can access dynamic params using:
tsxconst { slug } = useParams(); // Rasengan.js core hook
Rasengan.js supports optional static and dynamic segments using the underscore (_) prefix.
To create a route that optionally includes a folder, prefix it with an underscore:
txtapp/_routes/_settings/index.page.tsx
Routes matched:
//settingsWrap the param in brackets and prefix with _ to make it optional:
txtapp/_routes/[_locale]/home.page.tsx
Routes matched:
/home/en/home/fr/homeInside the component:
tsxconst { locale } = useParams(); // Might be undefined
You can create deeply nested routes by nesting folders:
txtapp/_routes/dashboard/settings/index.page.tsx → /dashboard/settings
If you include a layout.tsx in dashboard/, it will wrap both /dashboard and /dashboard/settings.
A route group is a folder used for organizational purposes only. It helps structure your codebase without affecting the actual URL path.
(groupName)md/app/_routes/(blog)/home.page.tsx → /home
Even if the page is inside the (blog) folder, the URL does not include /blog.
(marketing), (dashboard), (auth))"Route Groups using parentheses ( ) to organize routes without affecting the final path."
| Type | Convention | Example Path | Matches |
|---|---|---|---|
| Routes folder | app/_routes/ | app/_routes/home.page.tsx | /home |
| Page file | *.page.tsx | index.page.tsx, profile.page.tsx | /, /profile |
| Dynamic segment | [param]/index.page.tsx | app/_routes/blog/[slug]/index.page.tsx | /blog/:slug |
| Optional segment | _folder/, [_param]/ | _settings, [_locale] | /, /settings, /en |
| Layout wrapper | layout.tsx in any folder | app/_routes/about/layout.tsx | Applies to /about/* |
Rasengan.js plans to support:
[...param]app/_routes/index.page.tsx for folder roots