Skip to main content

Route Module

The Route module provides functions for working with routes in your Elmish Land application. Routes are automatically generated based on your page structure and provide type-safe navigation and URL formatting.

Where is this defined?

The Route module is automatically generated during the build process:

  • Generated Location: .elmish-land/Base/Routes.fs (in your project)
  • Generated By: Running elmish-land restore, elmish-land server and elmish-land build commands
  • Namespace: ElmishLand with [<AutoOpen>] module Routes
  • Generation Source: Based on your src/Pages/ folder structure

Unlike the other generated modules, the Route types are dynamically created based on your page structure. Each page in src/Pages/ gets its own route type, and folders starting with _ create route parameters. You can customize route parameters using route.json configuration files in your page directories.

warning

The .elmish-land/Base/Routes.fs file is auto-generated and should not be edited directly. Any changes will be overwritten on the next build.

Generated Route Types

Elmish Land automatically generates a discriminated union type for all your routes. Each page in your application gets its own route case.

Example

Given this page structure:

src/Pages/
├── Page.fs # Home page
├── Blog/
├── Page.fs # Blog index
└── _Slug/
└── Page.fs # Individual blog post

Elmish Land generates:

type HomeRoute = unit

type BlogRoute = unit

type Blog_SlugRoute = { Slug: string }

[<RequireQualifiedAccess>]
type Route =
| Home of HomeRoute
| Blog of BlogRoute
| Blog_Slug of Blog_SlugRoute

Route.format

Converts a route to a URL string that can be used in links and navigation.

Signature

Route.format : Route -> string

Parameters

  • route - The route to format as a URL string

Example

// Simple route
Route.format (Route.Home ())
// Returns: "#/"

// Static route
Route.format (Route.About ())
// Returns: "#/about"

// Dynamic route with parameter
Route.format (Route.Users_Id { Id = "123" })
// Returns: "#/users/123"

// Route with parameter and query parameters
Route.format (Route.Blog_Slug {
Slug = "my-post"
Highlight = Some true
Ref = Some "home"
})
// Returns: "#/blog/my-post?highlight=true&ref=home"

Use Route.format with anchor elements to create type-safe links:

Html.a [
prop.text "View Profile"
prop.href (Route.format (Route.Users_Id { Id = user.Id }))
]

Route.isEqualWithoutPathAndQuery

Compares two routes for equality, ignoring path parameters and query strings. Useful for determining if the user is on a specific page type regardless of parameters.

Signature

Route.isEqualWithoutPathAndQuery : Route -> Route -> bool

Parameters

  • route1 - First route to compare
  • route2 - Second route to compare

Example

let currentRoute = Route.Users_Id { Id = "123"; Tab = None }
let otherRoute = Route.Users_Id { Id = "456"; Tab = Some "tab" }

// Check if both routes are the same page (ignoring parameters)
Route.isEqualWithoutPathAndQuery currentRoute otherRoute
// Returns: true (both are Users_Id pages)

let homeRoute = Route.Home ()
Route.isEqualWithoutPathAndQuery currentRoute homeRoute
// Returns: false (different page types)

Use Cases

Highlight navigation links when on the corresponding page:

let currentRoute = Route.parse (Feliz.Router.Router.currentPath())

let isActive route =
Route.isEqualWithoutPathAndQuery route currentRoute

Html.a [
prop.text "Users"
prop.href (Route.format (Route.Users_Id { Id = "123" }))
if isActive (Route.Users_Id { Id = "123" }) then
prop.className "active"
]

Best Practices

Always use Route.format instead of manually constructing URLs. This ensures type safety and prevents broken links:

// Good - Type-safe and refactor-friendly
Html.a [
prop.href (Route.format (Route.About ()))
]

// Avoid - Fragile and error-prone
Html.a [
prop.href "#/about"
]