# How to Configure path_separator (Dash vs Slash) in AirRouter

> Configure AirRouter path_separator to use dashes or slashes for URL path segments, controlling how Python function names are converted for cleaner URLs.

- Repository: [Feldroy/air](https://github.com/feldroy/air)
- Tags: how-to-guide
- Published: 2026-03-01

---

**AirRouter accepts a `path_separator` parameter that controls whether generated URLs use dashes (`"-"`) or slashes (`"/"`) when converting Python function names to URL path segments.**

The feldroy/air framework automatically maps Python functions to URL endpoints by transforming underscored names like `about_us` into path segments. By configuring the `path_separator` parameter during router or application initialization, you determine whether these generated routes use hyphenated paths (`/about-us`) or nested directory-style paths (`/about/us`).

## How path_separator Works in the Source Code

### Core Implementation in routing.py

The routing mechanism centers on `RouterMixin`, which declares `path_separator` as a class attribute in [`src/air/routing.py`](https://github.com/feldroy/air/blob/main/src/air/routing.py) (lines 131-133). When you instantiate `AirRouter`, the `__init__` method accepts the `path_separator` parameter (defaulting to `"-"`) and assigns it to `self.path_separator` (lines 333-336). This value persists throughout the router's lifecycle and dictates how all registered pages generate their paths.

The actual URL construction occurs in the `page()` method, which calls `compute_page_path(func.__name__, separator=self.path_separator)` (lines 447-449), passing your configured separator to the utility function responsible for string transformation.

### Utility Function in utils.py

The path generation logic resides in [`src/air/utils.py`](https://github.com/feldroy/air/blob/main/src/air/utils.py) within the `compute_page_path` function (lines 22-28). This implementation replaces underscores in function names with your chosen separator:

```python
def compute_page_path(endpoint_name: str, separator: Literal["/", "-"] = "-") -> str:
    return "/" if endpoint_name == "index" else f"/{endpoint_name.replace('_', separator)}"

```

### Application-Level Support

The top-level `Air` application class also supports this configuration. In [`src/air/applications.py`](https://github.com/feldroy/air/blob/main/src/air/applications.py) (lines 222-226), `Air.__init__` accepts `path_separator` (default `"-"`) and stores it in `self.path_separator`. Since `Air` inherits routing behavior from `RouterMixin`, all pages registered directly on the application respect this setting.

## Configuring path_separator at Initialization

Pass the `path_separator` argument when creating routers or applications to establish your preferred URL style globally for that component.

**When creating a router:**

```python
import air

# Use slash separator: function about_us → "/about/us"

router = air.AirRouter(path_separator="/")

```

**When creating the top-level app:**

```python
import air

# All page decorators on the app will use slash-separated URLs

app = air.Air(path_separator="/")

```

**Modifying after instantiation:**

While the typical pattern sets this at creation, you can modify the attribute directly:

```python
router.path_separator = "-"  # Switch back to dash-separated URLs

```

## Practical URL Generation Examples

### Dash Separator (Default Behavior)

By default, `Air` and `AirRouter` use dashes, converting underscores to hyphens:

```python
import air

app = air.Air()  # path_separator defaults to "-"

@app.page
def about_us():
    return air.H1("About")

# Generated URL: "/about-us"

```

### Slash Separator

Configure `path_separator="/"` to create nested path structures:

```python
import air

router = air.AirRouter(path_separator="/")

@router.page
def about_us():
    return air.H1("About")

# Generated URL: "/about/us"

```

### Mixing Routers with Different Separators

You can mount multiple routers with distinct separators under different prefixes:

```python
import air

dash_router = air.AirRouter()                    # Defaults to "-"

slash_router = air.AirRouter(path_separator="/")

app = air.Air()
app.include_router(dash_router, prefix="/dash")
app.include_router(slash_router, prefix="/slash")

@dash_router.page
def contact_us():
    return air.H1("Contact")   # → "/dash/contact-us"

@slash_router.page
def contact_us():
    return air.H1("Contact")   # → "/slash/contact/us"

```

## Summary

- **`path_separator`** controls the character used to replace underscores in function names when generating URLs in feldroy/air.
- The default value is `"-"` (dash), producing URLs like `/about-us`.
- Set `path_separator="/"` in `AirRouter` or `Air` initialization to generate nested paths like `/about/us`.
- The logic resides in [`src/air/routing.py`](https://github.com/feldroy/air/blob/main/src/air/routing.py) (routing components) and [`src/air/utils.py`](https://github.com/feldroy/air/blob/main/src/air/utils.py) (path computation utility).
- Different routers within the same application can use different separators when mounted with prefixes.

## Frequently Asked Questions

### What is the default path_separator in AirRouter?

The default `path_separator` is `"-"` (dash). When you instantiate `AirRouter` or `Air` without specifying this parameter, the framework automatically uses dashes to replace underscores in function names, generating URLs like `/contact-us` for a function named `contact_us`.

### Can I use both dash and slash separators in the same application?

Yes. You can create multiple router instances with different `path_separator` values and mount them under different URL prefixes using `app.include_router()`. For example, mount a dash-based router at `/api` and a slash-based router at `/pages` to serve different URL schemes within the same feldroy/air application.

### Where does the URL path generation logic live in the source code?

The transformation logic lives in [`src/air/utils.py`](https://github.com/feldroy/air/blob/main/src/air/utils.py) within the `compute_page_path` function (lines 22-28), which performs the string replacement of underscores with your chosen separator. The routing integration occurs in [`src/air/routing.py`](https://github.com/feldroy/air/blob/main/src/air/routing.py), where `AirRouter` stores the separator attribute (lines 131-133 and 333-336) and the `page()` decorator passes it to the utility function (lines 447-449).

### Can I change the path_separator after creating a router?

Yes, you can modify `router.path_separator` or `app.path_separator` after instantiation, though this is not the typical pattern. Changes affect only subsequently registered pages; routes already defined maintain the separator value that was active at the time of their registration, as the path is computed immediately when the `@page` decorator executes.