When the route of two pages match the same URL, there is a routing conflict: Vike has to decide which one to render for that URL.

Upon Route String conflicts, Vike chooses the first route from most specific to least specific. For example:

  1. /about/team (most specific: it matches only a single URL)
  2. /about/@path (less specific: it also matches /about/company, /about/vision, ...)
  3. /about/* (less specific: it also matches /about/some/nested/path)
  4. /* (least specific: it matches all URLs)

You can find more examples at resolvePrecedence_route-strings.spec.ts.

Upon conflicts between Filesystem Routing, Route Strings and Route Functions, Vike chooses the first route in following order:

  1. Route Function, returned high positive precedence number (e.g. 99)
  2. Route Function, returned low positive precedence number (e.g. 1)
  3. Filesystem Routing
  4. Route String, static (i.e. without @/* parameter segment, e.g. /about/company)
  5. Route Function, returned no precedence number (or 0)
  6. Route String, parameterized (i.e. with @/* parameter segment, e.g. /product/@productId or /product/*)
  7. Route Function, returned low negative precedence number (e.g. -1)
  8. Route Function, returned high negative precedence number (e.g. -99)

Example (4) + (6) + (7):

// product/list/+route.js
export default '/product'
// product/item/+route.js
export default '/product/@productId'
// product/catch-all/+route.js
export default pageContext => {
  if (!pageContext.urlPathname.startsWith('/product/')) return false
  return {
    precedence: -1,
    pageContext: {
      // E.g. redirect `/product/wrong/url` to `/product`
      redirectTo: '/product'
    }
  }
}
URL                           MATCHES                                WINNER
==================            ===============================        ======
/product/42                   product/item/+route.js      (6)        ⬅️
                              product/catch-all/+route.js (7)
URL                           MATCHES                                WINNER
==================            ===============================        ======
/product                      product/list/+route.js      (4)        ⬅️
                              product/catch-all/+route.js (7)
URL                           MATCHES                                WINNER
==================            ===============================        ======
/product/wrong/url            product/catch-all/+route.js (7)        ⬅️

4: Route String, static (without @param segment, e.g. /about/company)
6: Route String, parameterized (with @param segments, e.g. /product/@productId or /product/*)
7: Route Function, returned low negative precedence number (e.g. -1)

Example (1) + (4):

// admin/+route.js
export default '/admin'
// login/+route.js
 
export default pageContext => {
  if( pageContext.user === null ) {
    return {
      precedence: 99
    }
  }
  return false
}
URL                   pageContext.user       MATCHES                   WINNER
======                ================       ===================       ======
/admin                null                   login/+route.js (1)       ⬅️
                                             admin/+route.js (4)
URL                   pageContext.user       MATCHES                   WINNER
======                ================       ===================       ======
/admin                'brillout'             admin/+route.js (4)       ⬅️

1: Route Function, returned high positive precedence number
4: Route String, static (without @param segment, e.g. /about/company)

More examples at resolvePrecedence_overall.spec.ts.