Route Config (route.json)
Route configuration files allow you to add type-safe path parameters and query parameters to your pages. Each route.json file defines how URL segments and query strings should be parsed and formatted.
File Location
Place a route.json file in the same directory as your dynamic route or page folders:
src/Pages/
├── Users/
│ └── _Id/ # Dynamic route
│ └── route.json # Route configuration with dynamic path parameter
│ └── Page.fs # Page
└── Blog/
├── Page.fs # Page
└── route.json # Route configuration with query parameters
Configuration Options
pathParameter
Configures how the dynamic path parameter (e.g., _Id, _Slug) should be parsed and formatted.
Properties
module(string, required): Fully qualified module name containing the type and functionstype(string, required): Type name for the path parameterparse(string, optional): Function name to parse the URL path value to the typeformat(string, optional): Function name to format the type to a string used in the URL path
Example
{
"$schema": "https://elmish.land/schemas/v1/route.schema.json",
"pathParameter": {
"module": "System",
"type": "Guid",
"parse": "parseGuid",
"format": "formatGuid"
}
}
queryParameters
Array of typed query parameters that can be read from the URL query string.
Properties
name(string, required): Name as it appears in the URL (will be converted to PascalCase in generated code)module(string, required): Fully qualified module name containing the type and functionstype(string, optional): Type name for the parameter (defaults to "string")parse(string, optional): Function name to parse string to the typeformat(string, optional): Function name to format the type to stringrequired(boolean, optional): Whether the parameter is required (defaults to false)
Example
{
"$schema": "https://elmish.land/schemas/v1/route.schema.json",
"queryParameters": [
{
"name": "page",
"module": "System",
"type": "int",
"parse": "parseInt",
"format": "formatInt"
},
{
"name": "sort-by",
"module": "System",
"type": "string",
"required": false
}
]
}
Query parameter names are converted to PascalCase in the generated code. For example, "sort-by" becomes SortBy in your F# code.
Built-in Types
Elmish Land provides built-in parse and format functions for common types:
| Type | Parse Function | Format Function |
|---|---|---|
Guid | parseGuid | formatGuid |
int | parseInt | formatInt |
int64 | parseInt64 | formatInt64 |
bool | parseBool | formatBool |
float | parseFloat | formatFloat |
decimal | parseDecimal | formatDecimal |
Custom Types
Define custom types for route and query parameters using shared project references. This enables domain-specific types with custom parsing and formatting logic.
Setup
Configure a project reference in elmish-land.json:
{
"projectReferences": [
"src/Common/Common.fsproj"
]
}
Defining the Custom Types
Create types with parse and format functions in your shared library:
module MyProject.Common
open System
type Age = Age of int
module Age =
let parse (value: string) =
match Int32.TryParse value with
| true, i when i >= 0 && i <= 150 -> Some (Age i)
| _ -> None
let format (Age age) = string age
Parse functions must have signature string -> 'T option. Format functions must have signature 'T -> string.
Examples
One Path Parameter Only
For a page at src/Pages/Users/_Id/Page.fs:
// src/Pages/Users/_Id/route.json
{
"$schema": "https://elmish.land/schemas/v1/route.schema.json",
"pathParameter": {
"module": "System",
"type": "Guid",
"parse": "parseGuid",
"format": "formatGuid"
}
}
This allows you to use Guid directly in your page:
type Model = { userId: Guid }
let init (routeParams: Route.Path) =
// routeParams.Id is a Guid, not a string
{ userId = routeParams.Id }, Cmd.none
Multiple Path Parameters
For a page at src/Pages/Users/_Active/_Id/Page.fs:
// src/Pages/Vehicles/_Active/route.json
{
"$schema": "https://elmish.land/schemas/v1/route.schema.json",
"pathParameter": {
"module": "System",
"type": "bool",
"parse": "parseBool",
"format": "formatBool"
}
}
// src/Pages/Vehicles/_Active/_Id/route.json
{
"$schema": "https://elmish.land/schemas/v1/route.schema.json",
"pathParameter": {
"module": "System",
"type": "Guid",
"parse": "parseGuid",
"format": "formatGuid"
}
}
This allows you to use bool and Guid directly in your page:
type Model = {
isActive: bool
userId: Guid
}
let init (routeParams: Route.Path) =
// routeParams.Active is a bool, not a string
// routeParams.Id is a Guid, not a string
{
isActive = routeParams.active
userId = routeParams.Id
}, Cmd.none
Query Parameters Only
For a page at src/Pages/Search/Page.fs:
// src/Pages/Search/route.json
{
"$schema": "https://elmish.land/schemas/v1/route.schema.json",
"queryParameters": [
{
"name": "page",
"module": "System",
"type": "int",
"parse": "parseInt",
"format": "formatInt"
},
{
"name": "sort-by",
"module": "System",
"type": "string"
}
]
}
Access query parameters in your page:
let init (routeParams: Route.Path) =
let page = routeParams.Query.Page |> Option.defaultValue 1
let sortBy = routeParams.Query.SortBy |> Option.defaultValue "name"
// ...
Combined Path and Query Parameters
For a page at src/Pages/Posts/_Id/Page.fs:
// src/Pages/Posts/_Id/route.json
{
"$schema": "https://elmish.land/schemas/v1/route.schema.json",
"pathParameter": {
"module": "System",
"type": "int",
"parse": "parseInt",
"format": "formatInt"
},
"queryParameters": [
{
"name": "age",
"module": "System",
"type": "int",
"parse": "parseInt",
"format": "formatInt",
"required": false
},
{
"name": "highlight",
"module": "System",
"type": "string"
}
]
}
Custom Types
For a page at src/Pages/User/Page.fs:
// src/Pages/User/route.json
{
"$schema": "https://elmish.land/schemas/v1/route.schema.json",
"queryParameters": [
{
"module": "MyProject.Common",
"name": "age",
"type": "Age",
"required": false,
"parse": "Age.parse",
"format": "Age.format"
}
]
}
This allows you to use Age directly in your page:
type Model = { age: Age }
let init (routeParams: Route.Path) =
// routeParams.Age is a type Age, not a string
{ age = routeParams.Age }, Cmd.none
Related Documentation
- Routing - Learn about Elmish.Land's routing system
- Project Structure - Understanding the project layout
- Pages - Working with page modules