Skip to content

Route Alias Guide

This guide explains how route aliases work in Zova within the Cabloy monorepo.

Why route aliases exist

In a modular routing system, the real page path and the user-facing path are not always the same.

A home-page example shows this clearly:

  • a module may provide a real internal page path
  • users may still expect a simpler public-facing path such as /

Route aliases bridge that gap.

Aliases are an explicit public-URL contract, not a default convenience layer. Ordinary business routes without locale params should keep their canonical module path and omit an app-config alias. Use an alias when the route is a documented system entry, compatibility path, or intentionally designed user-facing URL; locale-aware public routes are another common exception.

Basic routing flow

The navigation flow can be described in terms of:

  1. navigate to a path
  2. resolve the owning module
  3. load the module
  4. inject the module routes into the route table
  5. find the matching route and render the component

This is important because route aliasing is part of module-aware navigation, not an isolated string rewrite.

Global config for aliases

Aliases belong in global config.

Representative pattern:

typescript
config.routes = {
  path: {
    '/home/index': { alias: '/' },
    '/home/login': { alias: '/login' },
  },
  name: {
    'demo-todo:item': { alias: '/todo/:id' },
  },
};

path vs name

The distinction matters after an alias has a documented reason:

  • use routes.path for an approved static path-based alias;
  • use routes.name when the approved alias depends on params-aware naming.

Do not introduce a static route name solely to use routes.name: a static exception can use routes.path instead.

Locale-aware aliases

For a public route whose URL includes an optional locale segment, use the shared LocalePattern exported by Zova instead of hard-coding one language or copying a regular expression:

typescript
import { LocalePattern } from 'zova';

config.routes = {
  name: {
    'commerce-catalog:product': {
      alias: `/:locale(${LocalePattern})?/product/:id`,
    },
  },
};

The current pattern accepts the common xx and xx-yy forms, such as en-us, zh-cn, and fr-fr. It defines the URL shape; it is not a whitelist of installed languages. The languages that the application actually offers still come from config.locale.items and the corresponding locale resources. When adding a language, update those locale registrations and resources, but do not duplicate the language in each route alias.

When the route declares meta.locale: true, $router.getAliasPath(..., { params: { locale: true } }) uses the current locale and omits the configured default locale from an optional locale segment. Thus, with en-us as the default, the same alias can produce /product/42 for en-us and /zh-cn/product/42 for zh-cn.

Generate a configured alias path

When application code needs a user-facing URL for a named route, use the canonical route name with $router.getAliasPath(...):

ts
const path = this.$router.getAliasPath('demo-todo:item', {
  params: {
    id: '42',
    locale: true,
  },
});
const absoluteUrl = this.$router.getAliasPath(
  'demo-todo:item',
  { params: { id: '42', locale: true } },
  true,
);

The helper returns the configured alias path, such as /zh-cn/todo/42, or undefined when that route name has no configured alias. Pass true as the third argument when an absolute URL is required; it uses the same host and public-path conversion as $router.getPagePath(..., true). locale: true uses the active locale and omits the configured default locale from an optional locale segment.

Use the canonical generated route name. Do not construct $alias:<name> or strip /__alias__ in application code: those are private router implementation details.

Use $router.getPagePath(...) for a known canonical path template, $router.getAliasPath(...) for a configured public alias by canonical route name, and $router.resolveName(...) for canonical named-route resolution. Do not add alias behavior to getPagePath(...), because aliases are configured against route names rather than page-path templates.

Implementation checks for route-alias changes

When changing user-facing routes, ask:

  1. is this a real route change or just an alias change?
  2. does the alias have an explicit system, compatibility, locale-aware, or user-facing URL reason?
  3. does the alias belong in global config?
  4. is the page params-aware, meaning the name-based alias path is the correct layer?
  5. if the route is static, can getPagePath(...) and a path-keyed alias preserve the canonical route without adding a name?

That helps avoid breaking modular routing semantics and keeps ordinary business routes on their canonical paths.

  • If you want the broader public routing surface first, continue with Page Route Guide.
  • If the alias decision depends on route metadata or shell behavior, continue with Page Meta Guide.
  • If you want the deeper routing runtime after the public surface is clear, descend into Zova Router Under the Hood.

Released under the MIT License.