Dev tools and CLI for Remix applications providing build tools, development server, Vite integration, and command-line utilities.
—
Advanced routing system supporting flat routes, custom route definitions, nested routes, and dynamic route generation with TypeScript support.
Programmatic route definition for creating custom routing structures beyond filesystem conventions.
/**
* Define custom routes programmatically (unstable API)
* @param callback - Function that receives defineRoutes helper
* @returns Route manifest with defined routes
*/
function UNSAFE_defineRoutes(
callback: (defineRoutes: DefineRouteFunction) => void
): RouteManifest;
/**
* Function for defining individual routes
*/
interface DefineRouteFunction {
(
/** Route path or undefined for pathless layout routes */
path: string | undefined,
/** File path relative to app directory */
file: string,
/** Route options or children callback */
optionsOrChildren?: DefineRouteOptions | (() => void),
/** Children callback for nested routes */
children?: () => void
): void;
}
interface DefineRouteOptions {
/** Whether this is an index route */
index?: boolean;
/** Whether route matching is case sensitive */
caseSensitive?: boolean;
/** Unique route identifier */
id?: string;
}
type DefineRoutesFunction = typeof UNSAFE_defineRoutes;Flat route system that creates route hierarchy from filesystem structure using naming conventions.
/**
* Create flat routes from app directory structure (unstable API)
* @param appDirectory - Path to app directory
* @param ignoredFilePatterns - Patterns for files to ignore
* @param prefix - Route prefix
* @returns Route manifest generated from flat routes
*/
function UNSAFE_flatRoutes(
appDirectory: string,
ignoredFilePatterns?: string[],
prefix?: string
): RouteManifest;
/**
* Universal flat routes implementation
* @param appDirectory - App directory path
* @param routes - Explicit route definitions
* @param prefix - Route prefix
* @param visitFiles - Function to visit files
* @returns Route manifest
*/
function flatRoutesUniversal(
appDirectory: string,
routes: string[],
prefix?: string,
visitFiles?: (dir: string) => string[]
): RouteManifest;Functions for working with route manifests and converting between different route representations.
/**
* Convert route manifest to route configuration (unstable API)
* @param routeManifest - Route manifest to convert
* @param rootDirectory - Root directory path
* @returns Route configuration array
*/
function UNSAFE_routeManifestToRouteConfig(
routeManifest: RouteManifest,
rootDirectory: string
): RouteConfig;
/**
* Get app directory for route configuration (unstable API)
* @returns Current app directory path
*/
function UNSAFE_getRouteConfigAppDirectory(): string;
/**
* Set app directory for route configuration (unstable API)
* @param directory - App directory path to set
*/
function setRouteConfigAppDirectory(directory: string): void;
/**
* Get current app directory for route configuration
* @returns App directory path
*/
function getRouteConfigAppDirectory(): string;Schema validation and configuration processing for routes.
/**
* Validate route configuration against schema
* @param options - Validation options
* @returns Validation result with errors or success
*/
function validateRouteConfig(options: {
routeConfig: unknown;
rootDirectory: string;
}): { success: true; config: RouteConfig } | { success: false; errors: string[] };
/**
* Convert route configuration to route manifest
* @param routeConfig - Route configuration to convert
* @param rootDirectory - Root directory path
* @param appDirectory - App directory path
* @returns Route manifest
*/
function configRoutesToRouteManifest(
routeConfig: RouteConfig,
rootDirectory: string,
appDirectory: string
): RouteManifest;Core types for route management and configuration.
/**
* Route manifest containing all application routes
*/
interface RouteManifest {
[routeId: string]: RouteManifestEntry;
}
/**
* Individual route entry in the manifest
*/
interface RouteManifestEntry {
/** Unique route identifier */
id: string;
/** Parent route ID for nested routes */
parentId?: string;
/** URL path pattern */
path?: string;
/** Whether this is an index route */
index?: boolean;
/** Whether route matching is case sensitive */
caseSensitive?: boolean;
/** File path relative to app directory */
file: string;
/** Whether route has action export */
hasAction: boolean;
/** Whether route has loader export */
hasLoader: boolean;
/** Whether route has clientAction export */
hasClientAction: boolean;
/** Whether route has clientLoader export */
hasClientLoader: boolean;
/** Whether route has ErrorBoundary export */
hasErrorBoundary: boolean;
/** Import dependencies */
imports?: string[];
}
/**
* Route configuration entry
*/
interface RouteConfigEntry {
/** Route file path */
file: string;
/** Route ID */
id?: string;
/** Route path */
path?: string;
/** Whether this is an index route */
index?: boolean;
/** Whether route matching is case sensitive */
caseSensitive?: boolean;
/** Parent route ID */
parentId?: string;
}
/** Schema for validating route configuration entries */
const routeConfigEntrySchema: ValidationSchema<RouteConfigEntry>;
/** Schema for validating resolved route configuration */
const resolvedRouteConfigSchema: ValidationSchema<RouteConfig>;
/** Resolved route configuration array */
type ResolvedRouteConfig = RouteConfigEntry[];
/** Route configuration (resolved or promise of resolved) */
type RouteConfig = ResolvedRouteConfig | Promise<ResolvedRouteConfig>;Utilities for working with route paths and segments.
/**
* Get route segments from route ID
* @param routeId - Route ID to parse
* @returns Tuple of path segments and layout segments
*/
function getRouteSegments(routeId: string): [string[], string[]];
/**
* Create route path from segments
* @param routeId - Route ID
* @param segments - Route segments
* @param isIndex - Whether this is an index route
* @returns Generated route path
*/
function createRoutePath(
routeId: string,
segments: string[],
isIndex: boolean
): string | undefined;
/**
* Create route ID from file path
* @param file - File path to convert
* @returns Route ID
*/
function createRouteId(file: string): string;
/**
* Normalize slashes in file path
* @param file - File path to normalize
* @returns Normalized file path
*/
function normalizeSlashes(file: string): string;Constants used in flat routes naming conventions.
/** Supported route module file extensions */
const routeModuleExts: string[];
/** Character used to prefix route parameters */
const paramPrefixChar: "$";
/** Character to start escaped route segments */
const escapeStart: "[";
/** Character to end escaped route segments */
const escapeEnd: "]";
/** Character to start optional route segments */
const optionalStart: "(";
/** Character to end optional route segments */
const optionalEnd: ")";
/**
* Check if character is a segment separator
* @param checkChar - Character to check
* @returns Whether character is a segment separator
*/
function isSegmentSeparator(checkChar: string | undefined): boolean;Functions for generating helpful error messages for route conflicts.
/**
* Generate error message for route path conflicts
* @param routeId - Conflicting route ID
* @param routePath - Conflicting route path
* @param existingRouteId - Existing route ID
* @param existingRoutePath - Existing route path
* @returns Formatted error message
*/
function getRoutePathConflictErrorMessage(
routeId: string,
routePath: string,
existingRouteId: string,
existingRoutePath: string
): string;
/**
* Generate error message for route ID conflicts
* @param routeId - Conflicting route ID
* @param existingRouteId - Existing route ID
* @returns Formatted error message
*/
function getRouteIdConflictErrorMessage(
routeId: string,
existingRouteId: string
): string;// remix.config.js
import { UNSAFE_defineRoutes } from "@remix-run/dev";
export default {
routes(defineRoutes) {
return defineRoutes((route) => {
// Root route
route("/", "routes/home.tsx");
// Nested routes
route("/blog", "routes/blog.tsx", () => {
route("", "routes/blog/index.tsx", { index: true });
route(":slug", "routes/blog/post.tsx");
});
// Admin routes with layout
route("/admin", "routes/admin.tsx", () => {
route("dashboard", "routes/admin/dashboard.tsx");
route("users", "routes/admin/users.tsx");
route("users/:id", "routes/admin/user.tsx");
});
// Pathless layout route
route(undefined, "routes/auth-layout.tsx", () => {
route("/login", "routes/login.tsx");
route("/register", "routes/register.tsx");
});
});
},
};app/
├── routes/
│ ├── _index.tsx # /
│ ├── about.tsx # /about
│ ├── blog._index.tsx # /blog
│ ├── blog.$slug.tsx # /blog/:slug
│ ├── blog_.special.tsx # /blog/special (escapes parent layout)
│ ├── admin.tsx # /admin (layout)
│ ├── admin._index.tsx # /admin (index)
│ ├── admin.users.tsx # /admin/users
│ ├── admin.users.$id.tsx # /admin/users/:id
│ ├── admin.settings.tsx # /admin/settings
│ └── ($lang)._index.tsx # /:lang (optional param)import {
UNSAFE_flatRoutes,
UNSAFE_routeManifestToRouteConfig,
validateRouteConfig
} from "@remix-run/dev";
// Generate routes from flat routes
const routeManifest = UNSAFE_flatRoutes("./app", ["**/.*"]);
// Convert to route config
const routeConfig = UNSAFE_routeManifestToRouteConfig(
routeManifest,
process.cwd()
);
// Validate configuration
const validation = validateRouteConfig({
routeConfig,
rootDirectory: process.cwd(),
});
if (validation.success) {
console.log("Valid route configuration:", validation.config);
} else {
console.error("Route validation errors:", validation.errors);
}import { formatRoutes } from "@remix-run/dev";
const routeManifest = {
"routes/_index": {
id: "routes/_index",
file: "routes/_index.tsx",
path: "/",
index: true,
},
"routes/blog": {
id: "routes/blog",
file: "routes/blog.tsx",
path: "/blog",
},
"routes/blog.$slug": {
id: "routes/blog.$slug",
parentId: "routes/blog",
file: "routes/blog.$slug.tsx",
path: ":slug",
},
};
// Format as JSX tree
const jsxOutput = formatRoutes(routeManifest, "jsx");
console.log(jsxOutput);
// Format as JSON
const jsonOutput = formatRoutes(routeManifest, "json");
console.log(jsonOutput);Install with Tessl CLI
npx tessl i tessl/npm-remix-run--dev