> ## Documentation Index
> Fetch the complete documentation index at: https://docs.replo.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Routing

> Redirects, locale negotiation, and geo lookup in middleware.

These run in the site's middleware to evaluate redirect rules, negotiate a locale, and read the visitor's country.

## `routing/evaluate`

`@replohq/sdk/routing/evaluate`

**Exports**

| Export            | Kind     | Type                                                                                                                                                   |
| ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `evaluateRouting` | function | `({ request, rules, localeRouting, }: { request: NextRequest; rules: readonly RedirectRule[]; localeRouting?: LocaleRoutingConfig; }) => NextResponse` |

## `routing/rules`

`@replohq/sdk/routing/rules`

#### `reploRedirect`

Validates a redirect rule, returning it unchanged. Throws `RedirectRuleValidationError` carrying the first failing check's message.

```ts theme={null}
import { reploRedirect } from "@replohq/sdk/routing/rules";
```

```ts theme={null}
reploRedirect: (input: RedirectRule) => RedirectRule
```

**Also exported**

| Export           | Kind | Type                                                                          |
| ---------------- | ---- | ----------------------------------------------------------------------------- |
| `RedirectRule`   | type | `{ source: string; destination: string; status?: 301 \| 302 \| 307 \| 308; }` |
| `RedirectStatus` | type | `301 \| 302 \| 307 \| 308`                                                    |

## `routing/locale`

`@replohq/sdk/routing/locale`

#### `localeUrl`

The URL of a logical path in another locale — the one primitive a language switcher and hreflang alternates need. Within the current host's scope (or with no domains configured) it is the locale-prefixed path; a locale served by a different domain gets an absolute URL there, dropping the prefix when that domain serves only the one locale. Hidden-mode sites use the prefixed form too: the runtime converts an explicit locale prefix into a cookie plus a clean-URL redirect on arrival.

```ts theme={null}
import { localeUrl } from "@replohq/sdk/routing/locale";
```

```ts theme={null}
localeUrl: ({ locale, path, config, currentHost, }: { locale: string; path: string; config: LocaleRoutingConfig; currentHost?: string | null; }) => string
```

#### `REPLO_COUNTRY_OVERRIDE_COOKIE`

Overrides the visitor's IP-derived country for testing geo behavior without a VPN — works identically in dev sandboxes and on the published site. At worst it lets a visitor pick which locale they see, which the locale cookie already allows deliberately.

```ts theme={null}
import { REPLO_COUNTRY_OVERRIDE_COOKIE } from "@replohq/sdk/routing/locale";
```

```ts theme={null}
REPLO_COUNTRY_OVERRIDE_COOKIE: "replo-country-override"
```

#### `REPLO_LOCALE_COOKIE`

Set by the runtime when a visitor explicitly picks a locale (a language switcher link, or landing on a locale-prefixed URL). Negotiation reads it ahead of any detection, so an explicit choice always wins.

```ts theme={null}
import { REPLO_LOCALE_COOKIE } from "@replohq/sdk/routing/locale";
```

```ts theme={null}
REPLO_LOCALE_COOKIE: "replo-locale"
```

#### `reploLocaleRouting`

Validates a locale routing config, returning it with every tag canonicalized and defaults applied. Throws `LocaleRoutingValidationError` carrying the first failing check's message.

```ts theme={null}
import { reploLocaleRouting } from "@replohq/sdk/routing/locale";
```

```ts theme={null}
reploLocaleRouting: (input: LocaleRoutingConfigInput) => LocaleRoutingConfig
```

**Also exported**

| Export                     | Kind | Type                                                                                                                                                                                              |
| -------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `LocaleDetection`          | type | `"country" \| "language"`                                                                                                                                                                         |
| `LocaleRoutingConfig`      | type | `{ locales: string[]; detection: "country" \| "language"; urlMode: "prefixed" \| "hidden"; defaultLocale?: string; domains?: Record<string, { locales: string[]; defaultLocale?: string; }>; }`   |
| `LocaleRoutingConfigInput` | type | `{ locales: string[]; defaultLocale?: string; detection?: "country" \| "language"; urlMode?: "prefixed" \| "hidden"; domains?: Record<string, { locales: string[]; defaultLocale?: string; }>; }` |
| `LocaleUrlMode`            | type | `"prefixed" \| "hidden"`                                                                                                                                                                          |

## `routing/geo`

`@replohq/sdk/routing/geo`

#### `ipCountry`

The visitor's ISO 3166-1 alpha-2 country, or null when unknown. The override cookie wins so geo behavior is testable without a VPN — in dev sandboxes, where the Cloudflare header never exists, and on the published site alike. At worst the override lets a visitor pick which locale they see, which the locale cookie already allows deliberately.

```ts theme={null}
import { ipCountry } from "@replohq/sdk/routing/geo";
```

```ts theme={null}
ipCountry: (request: NextRequest) => string | null
```
