Skip to content

Route names come from the filesystem, which is what makes them predictable.

Occasionally a URL has to be something else: /feed.xml rather than /rss, or a path a previous system published that you cannot break.

alias in the backend block serves an existing route at an additional URL:

kosmo.config.ts
ts
export default defineConfig({
  backend: {
    stack: "hono",
    base: "/api",
    alias: {
      "/feed.xml": "rss",
      "/members/[id]": "users/[id]",
    },
  },
});

The key is the URL to serve. The value is the name of the route that handles it.

The key is absolute

An alias URL is not prefixed by backend.base. It is the whole path, from the root of the host:

ts
backend: {
  base: "/api",
  alias: {
    // served at /feed.xml, not /api/feed.xml
    "/feed.xml": "rss",
  },
}

That is the point of the feature - a well-known URL like /feed.xml or /healthz usually has to sit outside the API prefix, where a filesystem route could not put it.

Dynamic segments must match by name

When the alias carries parameters, the target route's parameters must all be present, with the same names and the same kind. Their positions may differ:

ts
alias: {
  // ok - same parameter, different surrounding path
  "/members/[id]": "users/[id]",

  // ok - same two parameters, reordered
  "/[org]/team/[id]": "orgs/[org]/members/[id]",

  // 404 - target expects "id", alias supplies "userId"
  "/members/[userId]": "users/[id]",

  // 404 - target expects a parameter the alias never supplies
  "/members": "users/[id]",
}

A mismatch is not a startup error. The alias is registered and the request 404s, so check the shape when an alias silently fails to resolve.

What the alias shares

An alias is another entry pointing at the same route - not a copy of it, and not a redirect. No 3xx is issued; the URL the client asked for is the URL it keeps.

The handler is the same function, so everything attached to the route comes with it: its middleware, the cascading middleware of the directories above it, and its runtime validation. There is nothing to duplicate and nothing that can drift between the two URLs.

What it does not touch

Aliases are a server-side routing concern only.

The fetch client is keyed by the route's own name, so client code calls fetchClients["users/[id]"] whichever URL the route also answers on.

The OpenAPI spec documents the route once, under its route name.

Reach for an alias when an outside consumer needs a particular URL. For an extra path your own frontend calls, a route file is simpler.

Supported everywhere

hono, h3 and koa all accept alias, and the semantics above are identical on each - only the router pattern the alias compiles to differs.

Released under the MIT License.