or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-system.mdcli-commands.mdconfiguration.mddevelopment-server.mdindex.mdroute-management.mdvite-integration.md

route-management.mddocs/

0

# Route Management

1

2

Advanced routing system supporting flat routes, custom route definitions, nested routes, and dynamic route generation with TypeScript support.

3

4

## Capabilities

5

6

### Route Definition

7

8

Programmatic route definition for creating custom routing structures beyond filesystem conventions.

9

10

```typescript { .api }

11

/**

12

* Define custom routes programmatically (unstable API)

13

* @param callback - Function that receives defineRoutes helper

14

* @returns Route manifest with defined routes

15

*/

16

function UNSAFE_defineRoutes(

17

callback: (defineRoutes: DefineRouteFunction) => void

18

): RouteManifest;

19

20

/**

21

* Function for defining individual routes

22

*/

23

interface DefineRouteFunction {

24

(

25

/** Route path or undefined for pathless layout routes */

26

path: string | undefined,

27

/** File path relative to app directory */

28

file: string,

29

/** Route options or children callback */

30

optionsOrChildren?: DefineRouteOptions | (() => void),

31

/** Children callback for nested routes */

32

children?: () => void

33

): void;

34

}

35

36

interface DefineRouteOptions {

37

/** Whether this is an index route */

38

index?: boolean;

39

/** Whether route matching is case sensitive */

40

caseSensitive?: boolean;

41

/** Unique route identifier */

42

id?: string;

43

}

44

45

type DefineRoutesFunction = typeof UNSAFE_defineRoutes;

46

```

47

48

### Flat Routes

49

50

Flat route system that creates route hierarchy from filesystem structure using naming conventions.

51

52

```typescript { .api }

53

/**

54

* Create flat routes from app directory structure (unstable API)

55

* @param appDirectory - Path to app directory

56

* @param ignoredFilePatterns - Patterns for files to ignore

57

* @param prefix - Route prefix

58

* @returns Route manifest generated from flat routes

59

*/

60

function UNSAFE_flatRoutes(

61

appDirectory: string,

62

ignoredFilePatterns?: string[],

63

prefix?: string

64

): RouteManifest;

65

66

/**

67

* Universal flat routes implementation

68

* @param appDirectory - App directory path

69

* @param routes - Explicit route definitions

70

* @param prefix - Route prefix

71

* @param visitFiles - Function to visit files

72

* @returns Route manifest

73

*/

74

function flatRoutesUniversal(

75

appDirectory: string,

76

routes: string[],

77

prefix?: string,

78

visitFiles?: (dir: string) => string[]

79

): RouteManifest;

80

```

81

82

### Route Manifest Management

83

84

Functions for working with route manifests and converting between different route representations.

85

86

```typescript { .api }

87

/**

88

* Convert route manifest to route configuration (unstable API)

89

* @param routeManifest - Route manifest to convert

90

* @param rootDirectory - Root directory path

91

* @returns Route configuration array

92

*/

93

function UNSAFE_routeManifestToRouteConfig(

94

routeManifest: RouteManifest,

95

rootDirectory: string

96

): RouteConfig;

97

98

/**

99

* Get app directory for route configuration (unstable API)

100

* @returns Current app directory path

101

*/

102

function UNSAFE_getRouteConfigAppDirectory(): string;

103

104

/**

105

* Set app directory for route configuration (unstable API)

106

* @param directory - App directory path to set

107

*/

108

function setRouteConfigAppDirectory(directory: string): void;

109

110

/**

111

* Get current app directory for route configuration

112

* @returns App directory path

113

*/

114

function getRouteConfigAppDirectory(): string;

115

```

116

117

### Route Configuration Validation

118

119

Schema validation and configuration processing for routes.

120

121

```typescript { .api }

122

/**

123

* Validate route configuration against schema

124

* @param options - Validation options

125

* @returns Validation result with errors or success

126

*/

127

function validateRouteConfig(options: {

128

routeConfig: unknown;

129

rootDirectory: string;

130

}): { success: true; config: RouteConfig } | { success: false; errors: string[] };

131

132

/**

133

* Convert route configuration to route manifest

134

* @param routeConfig - Route configuration to convert

135

* @param rootDirectory - Root directory path

136

* @param appDirectory - App directory path

137

* @returns Route manifest

138

*/

139

function configRoutesToRouteManifest(

140

routeConfig: RouteConfig,

141

rootDirectory: string,

142

appDirectory: string

143

): RouteManifest;

144

```

145

146

### Route Types

147

148

Core types for route management and configuration.

149

150

```typescript { .api }

151

/**

152

* Route manifest containing all application routes

153

*/

154

interface RouteManifest {

155

[routeId: string]: RouteManifestEntry;

156

}

157

158

/**

159

* Individual route entry in the manifest

160

*/

161

interface RouteManifestEntry {

162

/** Unique route identifier */

163

id: string;

164

/** Parent route ID for nested routes */

165

parentId?: string;

166

/** URL path pattern */

167

path?: string;

168

/** Whether this is an index route */

169

index?: boolean;

170

/** Whether route matching is case sensitive */

171

caseSensitive?: boolean;

172

/** File path relative to app directory */

173

file: string;

174

/** Whether route has action export */

175

hasAction: boolean;

176

/** Whether route has loader export */

177

hasLoader: boolean;

178

/** Whether route has clientAction export */

179

hasClientAction: boolean;

180

/** Whether route has clientLoader export */

181

hasClientLoader: boolean;

182

/** Whether route has ErrorBoundary export */

183

hasErrorBoundary: boolean;

184

/** Import dependencies */

185

imports?: string[];

186

}

187

188

/**

189

* Route configuration entry

190

*/

191

interface RouteConfigEntry {

192

/** Route file path */

193

file: string;

194

/** Route ID */

195

id?: string;

196

/** Route path */

197

path?: string;

198

/** Whether this is an index route */

199

index?: boolean;

200

/** Whether route matching is case sensitive */

201

caseSensitive?: boolean;

202

/** Parent route ID */

203

parentId?: string;

204

}

205

206

/** Schema for validating route configuration entries */

207

const routeConfigEntrySchema: ValidationSchema<RouteConfigEntry>;

208

209

/** Schema for validating resolved route configuration */

210

const resolvedRouteConfigSchema: ValidationSchema<RouteConfig>;

211

212

/** Resolved route configuration array */

213

type ResolvedRouteConfig = RouteConfigEntry[];

214

215

/** Route configuration (resolved or promise of resolved) */

216

type RouteConfig = ResolvedRouteConfig | Promise<ResolvedRouteConfig>;

217

```

218

219

### Route Path Utilities

220

221

Utilities for working with route paths and segments.

222

223

```typescript { .api }

224

/**

225

* Get route segments from route ID

226

* @param routeId - Route ID to parse

227

* @returns Tuple of path segments and layout segments

228

*/

229

function getRouteSegments(routeId: string): [string[], string[]];

230

231

/**

232

* Create route path from segments

233

* @param routeId - Route ID

234

* @param segments - Route segments

235

* @param isIndex - Whether this is an index route

236

* @returns Generated route path

237

*/

238

function createRoutePath(

239

routeId: string,

240

segments: string[],

241

isIndex: boolean

242

): string | undefined;

243

244

/**

245

* Create route ID from file path

246

* @param file - File path to convert

247

* @returns Route ID

248

*/

249

function createRouteId(file: string): string;

250

251

/**

252

* Normalize slashes in file path

253

* @param file - File path to normalize

254

* @returns Normalized file path

255

*/

256

function normalizeSlashes(file: string): string;

257

```

258

259

### Flat Routes Constants

260

261

Constants used in flat routes naming conventions.

262

263

```typescript { .api }

264

/** Supported route module file extensions */

265

const routeModuleExts: string[];

266

267

/** Character used to prefix route parameters */

268

const paramPrefixChar: "$";

269

270

/** Character to start escaped route segments */

271

const escapeStart: "[";

272

273

/** Character to end escaped route segments */

274

const escapeEnd: "]";

275

276

/** Character to start optional route segments */

277

const optionalStart: "(";

278

279

/** Character to end optional route segments */

280

const optionalEnd: ")";

281

282

/**

283

* Check if character is a segment separator

284

* @param checkChar - Character to check

285

* @returns Whether character is a segment separator

286

*/

287

function isSegmentSeparator(checkChar: string | undefined): boolean;

288

```

289

290

### Error Messages

291

292

Functions for generating helpful error messages for route conflicts.

293

294

```typescript { .api }

295

/**

296

* Generate error message for route path conflicts

297

* @param routeId - Conflicting route ID

298

* @param routePath - Conflicting route path

299

* @param existingRouteId - Existing route ID

300

* @param existingRoutePath - Existing route path

301

* @returns Formatted error message

302

*/

303

function getRoutePathConflictErrorMessage(

304

routeId: string,

305

routePath: string,

306

existingRouteId: string,

307

existingRoutePath: string

308

): string;

309

310

/**

311

* Generate error message for route ID conflicts

312

* @param routeId - Conflicting route ID

313

* @param existingRouteId - Existing route ID

314

* @returns Formatted error message

315

*/

316

function getRouteIdConflictErrorMessage(

317

routeId: string,

318

existingRouteId: string

319

): string;

320

```

321

322

## Usage Examples

323

324

### Custom Route Definition

325

326

```typescript

327

// remix.config.js

328

import { UNSAFE_defineRoutes } from "@remix-run/dev";

329

330

export default {

331

routes(defineRoutes) {

332

return defineRoutes((route) => {

333

// Root route

334

route("/", "routes/home.tsx");

335

336

// Nested routes

337

route("/blog", "routes/blog.tsx", () => {

338

route("", "routes/blog/index.tsx", { index: true });

339

route(":slug", "routes/blog/post.tsx");

340

});

341

342

// Admin routes with layout

343

route("/admin", "routes/admin.tsx", () => {

344

route("dashboard", "routes/admin/dashboard.tsx");

345

route("users", "routes/admin/users.tsx");

346

route("users/:id", "routes/admin/user.tsx");

347

});

348

349

// Pathless layout route

350

route(undefined, "routes/auth-layout.tsx", () => {

351

route("/login", "routes/login.tsx");

352

route("/register", "routes/register.tsx");

353

});

354

});

355

},

356

};

357

```

358

359

### Flat Routes Structure

360

361

```

362

app/

363

├── routes/

364

│ ├── _index.tsx # /

365

│ ├── about.tsx # /about

366

│ ├── blog._index.tsx # /blog

367

│ ├── blog.$slug.tsx # /blog/:slug

368

│ ├── blog_.special.tsx # /blog/special (escapes parent layout)

369

│ ├── admin.tsx # /admin (layout)

370

│ ├── admin._index.tsx # /admin (index)

371

│ ├── admin.users.tsx # /admin/users

372

│ ├── admin.users.$id.tsx # /admin/users/:id

373

│ ├── admin.settings.tsx # /admin/settings

374

│ └── ($lang)._index.tsx # /:lang (optional param)

375

```

376

377

### Route Manifest Processing

378

379

```typescript

380

import {

381

UNSAFE_flatRoutes,

382

UNSAFE_routeManifestToRouteConfig,

383

validateRouteConfig

384

} from "@remix-run/dev";

385

386

// Generate routes from flat routes

387

const routeManifest = UNSAFE_flatRoutes("./app", ["**/.*"]);

388

389

// Convert to route config

390

const routeConfig = UNSAFE_routeManifestToRouteConfig(

391

routeManifest,

392

process.cwd()

393

);

394

395

// Validate configuration

396

const validation = validateRouteConfig({

397

routeConfig,

398

rootDirectory: process.cwd(),

399

});

400

401

if (validation.success) {

402

console.log("Valid route configuration:", validation.config);

403

} else {

404

console.error("Route validation errors:", validation.errors);

405

}

406

```

407

408

### Route Information Display

409

410

```typescript

411

import { formatRoutes } from "@remix-run/dev";

412

413

const routeManifest = {

414

"routes/_index": {

415

id: "routes/_index",

416

file: "routes/_index.tsx",

417

path: "/",

418

index: true,

419

},

420

"routes/blog": {

421

id: "routes/blog",

422

file: "routes/blog.tsx",

423

path: "/blog",

424

},

425

"routes/blog.$slug": {

426

id: "routes/blog.$slug",

427

parentId: "routes/blog",

428

file: "routes/blog.$slug.tsx",

429

path: ":slug",

430

},

431

};

432

433

// Format as JSX tree

434

const jsxOutput = formatRoutes(routeManifest, "jsx");

435

console.log(jsxOutput);

436

437

// Format as JSON

438

const jsonOutput = formatRoutes(routeManifest, "json");

439

console.log(jsonOutput);

440

```