Routing Conventions

QUI Docs builds on Remix Flat Routes to provide flexible file-based routing. Use these conventions to understand how page file paths map to URL segments.

Choose a routing strategy

These conventions apply when the React Router route configuration uses hybridRoutes (the default). See Custom Routing when the application defines file-based routes manually.

The routingStrategy setting controls how folders participate in route discovery. Both built-in strategies preserve Remix Flat Routes filename behavior in the React Router route manifest.

To enable hybridRoutes in a fresh application, install the dependencies:

npm i @react-router/remix-routes-option-adapter @qualcomm-ui/react-router-utils @react-router/dev

Then set up your routes.ts file:

import type {RouteConfigEntry} from "@react-router/dev/routes"
import {remixRoutesOptionAdapter} from "@react-router/remix-routes-option-adapter"

import {hybridRoutes} from "@qualcomm-ui/react-router-utils/node"

export const routes: Promise<RouteConfigEntry[]> = remixRoutesOptionAdapter(
  (defineRoutes) => {
    return hybridRoutes("routes", defineRoutes, {
      appDir: "src",
      // optional: ignore files that match specific patterns
      ignoredRouteFiles: ["**/*demos/**/*"],
      // optional: refer to the next section for more details
      routingStrategy: "react-router-directory-groups",
    })
  },
)

export default routes

Default routing strategy

The default strategy follows Remix Flat Routes naming. A folder ending in + turns its child filenames into flat route segments. Plain folders use the flat-folder convention and only recognize route module filenames such as route.mdx, _layout.tsx, or page.route.mdx.

The default strategy requires + on folders that organize regular route files:

Directory groups

Set routingStrategy to "react-router-directory-groups" for a simpler file tree approach. Plain folders and + folders both turn child filenames into route segments. Plain folders beginning with _ are private and excluded from discovery.

Route moduleURL
help/troubleshooting.mdx/help/troubleshooting
guide/content-creation/overview.mdx/guide/content-creation/overview

The + form remains valid in directory-group mode:

Route moduleURL
public+/login.mdx/public/login

These MDX directory examples produce the same URLs in the React Router route manifest, QUI Docs page map, side navigation, and search index.

Private folders

In directory-group mode, a plain folder whose name begins with _ is private. QUI Docs skips every route file inside it. Use private folders for demos, components, fixtures, and other files that support a page without creating pages of their own.

FileDiscovery result
components/button.mdxCreates /components/button
components/_demos/basic.tsxExcluded by the _demos folder
components/_components/example.mdxExcluded by the _components folder
components/_button.mdxCreates /components; underscore-prefixed files remain route modules

The private-folder rule does not apply to a folder containing +, such as _public+. The route manifest treats _public+ as a pathless group, but the QUI Docs page map retains _public in indexed URLs. Do not use an underscore-plus folder for indexed MDX pages.

React Router route-module conventions

Both routing strategies support the remaining Remix Flat Routes conventions for JSX and TSX route modules. These examples describe the React Router route manifest. QUI Docs does not apply pathless-segment, trailing-underscore, or optional-segment normalization when it builds the MDX page map, side navigation, and search index. Do not use these advanced filenames for indexed MDX pages. You may still use them for JSX and TSX route modules.

Flat filenames

Dots in a route filename create URL segments. Route nesting uses the longest matching route filename as the parent layout.

Route moduleURLRoute relationship
privacy.jsx/privacyRoot child
pages.tos.jsx/pages/tosRoot child; no pages.jsx layout exists
about.jsx/aboutParent layout
about.contact.jsx/about/contactChild of about.jsx
about.index.jsx/aboutIndex child of about.jsx
about._index.jsx/aboutAlias for about.index.jsx
dashboard.route.jsx/dashboardRoot child; .route does not add a URL segment

about.index.jsx and about._index.jsx are alternative names for the same index route. Use one of them, not both.

Layouts and parent overrides

A route becomes a layout when another route has a matching filename prefix. The layout component must render an outlet for its child routes.

Route moduleURLLayout behavior
about.jsx/aboutURL layout for about.* children
about.contact.jsx/about/contactRenders inside about.jsx
_auth.jsxNo URL segmentPathless layout for _auth.* children
_auth.login.jsx/loginRenders inside _auth.jsx

A leading underscore creates a pathless segment. The segment still determines layout nesting but does not appear in the URL.

Append an underscore to a segment to keep the URL segment while opting out of the matching parent layout:

Route moduleURLLayout behavior
about_.company.jsx/about/companyDoes not render inside about.jsx
app_.projects.$id.roadmap.tsx/app/projects/:id/roadmapDoes not render inside app.jsx

Dynamic and optional segments

A segment beginning with $ creates a dynamic parameter. A bare $ creates a splat that matches the remaining URL. Parentheses make a static or dynamic segment optional.

Route moduleURL pattern
users.$userId.jsx/users/:userId
docs.$.jsx/docs/*
reports.(archive).jsx/reports/archive?
reports.($year).jsx/reports/:year?

TIP

QUI Docs excludes filenames containing $ from its page map, side navigation, and search index.

Custom file-based routing

Use this approach to create your own file-based routing strategy.

When to Configure Routing

React Router's Framework Mode supports manually defined route definitions. When you use manual routes, QUI Docs can still discover MDX files, but it cannot infer the page URL from React Router's route config.

Add a routingStrategy so QUI Docs can map each discovered page file to the same URL React Router uses.

Example Routes

Assume that the app defines these route files:

src
routes
index.mdx
setup.mdx
help
contact-us.mdx
troubleshooting.mdx

The React Router route config can map those files explicitly:

// src/routes.ts
import {type RouteConfig, index, prefix, route} from "@react-router/dev/routes"

export default [
  index("routes/index.mdx"),
  route("setup", "routes/setup.mdx"),

  ...prefix("help", [
    route("contact-us", "routes/help/contact-us.mdx"),
    route("troubleshooting", "routes/help/troubleshooting.mdx"),
  ]),
] satisfies RouteConfig

Routing Strategy

In qui-docs.config.ts, provide a function that receives each file path relative to pageDirectory and returns the URL path segments for that file.

// qui-docs.config.ts
import {QuiDocsConfig} from "@qualcomm-ui/mdx-vite"

export default {
  // ...
  routingStrategy: (filePath: string) => {
    const routePath = filePath.replace(/\.(mdx|tsx)$/, "")
    const segments = routePath.split("/")

    if (segments.at(-1) === "index") {
      return segments.slice(0, -1)
    }

    return segments
  },
} satisfies QuiDocsConfig

The home route returns an empty array because it renders at /.

filePathexpected path segments
index.mdx[]
setup.mdx["setup"]
help/contact-us.mdx["help", "contact-us"]
help/troubleshooting.mdx["help", "troubleshooting"]

Keep Routes in Sync

The routingStrategy should describe the same URLs as routes.ts. If the React Router route config changes, update the strategy in the same PR so navigation, page links, breadcrumbs, and search results continue to point to the rendered page.

For the default file-based convention, omit routingStrategy and follow the naming rules in Page Configuration.

Last updated on by Ryan Bower