react-router-kiss-routes
v1.0.2
Published
Build cleanly structured routes for React Router using folders.
Maintainers
Readme
React Router Keep It Super Simple (KISS) Routes
Originally developed for Remix as
remix-kiss-router, this has been ported to React Router.
The goal of this package is to provide a simple way to define routes in React Router using a structured file system.
The routing method in React Router is OK, but has many nuances and arbitrary rules that make it difficult to onboard new developers, leaves file/folder names littered with _,[,+ amongst other special characters with little meaning unless you know the rules and odd nuances.
🤷♂️ Why?
Frustration with a flat folder routing system, a project with 1000's of routes is not fun to open in VSCode, the sidebar becomes unmanageably long, scrolling up and down becomes tedious very quickly.
We want to be able to define our routes in a way that makes intuitive sense, maps to the web in a logical predictable way, and is easy to keep well organized across teams.
💡 Concepts
- Routes are defined and nested using folders, very similar to how you'd layout HTML files on an nginx server.
_layoutfiles wrap all routes downstream, these need an<Outlet />to render the child routes._indexfiles are the default file for a folder, eg:/users/_index.tsxwould become/users.- Variables are denoted using
$in the file path, eg:/users/$id/edit.tsxwould become/users/123/edit - You can replace folders with a "virtual" folder using a
.in the filename, eg:/users.$id.edit.tsxwould become/users/123/edit. - You can escape special characters in the file path using
[], eg:/make-[$$$]-fast-online.tsxwould become/make-$$$-fast-online - Files and folders prefixed with an
_become invisible, allowing for folder organization without affecting the route path eg:/_legal-pages/privacy-policy.tsxwould become/privacy-policy - Files not ending in
.jsx,.tsx,.mdx,.js,.ts,.mdare ignored, allowing you to keep assets and other files in the same folder as your routes. - Break out of a layout using
parentRouteIdmagic comment or export, see Break out of a layout
🔮 Example
📂 File System
├── _index.jsx
├── _layout.jsx
├── users
│ ├── _index.jsx
│ ├── _layout.jsx
│ ├── $id
│ │ ├── _index.jsx
│ │ ├── _layout.jsx
│ │ └── edit.jsx
| └── $id.view.jsx
└── _legal-pages
└── privacy-policy.jsx🧬 Routes Generated
/_index.jsx -> /
/users/_index.jsx -> /users
/users/$id/_index.jsx -> /users/$id
/users/$id/edit.jsx -> /users/$id/edit
/users/$id.view.jsx -> /users/$id/view
/_legal-pages/privacy-policy.jsx -> /privacy-policy✨ See how super simple that is!
🔨 Usage
🚀 Install the package:
npm install -D react-router-kiss-routes
⚙️ React Router Config
// app/routes.ts
import { type RouteConfig } from "@react-router/dev/routes";
import { kissRoutes } from "react-router-kiss-routes"
export default kissRoutes() satisfies RouteConfig; Parameters:
const ReactRouterKissRoutesOptions = {
app: './app', // where your root.jsx file is located
routes: 'routes', // where your routes are located relative to app
caseSensitive: false, // whether or not to use case sensitive routes
variableCharacter: '$', // the character to denote a variable in the route path
pathlessCharacter: '_', // the character to make a file or folder pathless (invisible)
delimiterCharacter: '.', // used for virtual folders, internally replaced with '/'
layoutFileName: '_layout', // the name of the layout file
indexFileName: '_index', // the name of the index file
}🌟 Break out of a layout
Sometimes you may want a child route to break out of a parents layout, for example you may want to have a login page that doesn't have the websites layout applied to it.
To do this you can use the parentRouteId magic comment or export in your route or layout file.
If used within a layout file, it will apply to all child routes to that layout. If used within a route file, it will only apply to that route.
// @parentRouteId routes/_layout
/* @parentRouteId routes/_layout */
export const parentRouteId = 'routes/_layout'You can even target root so there's no _layout files applied.
// @parentRouteId root
/* @parentRouteId root */
export const parentRouteId = 'root'The value used for parentRouteId is the routeId, the same value you'd use inside useRouteLoaderData in React Router.
