Dynamic Route Triggering for All Paths

Current behavior

Our root-level dynamic route [username]/page.tsx is causing our rate limiting middleware to execute for every path in the application, including the landing page (/) and all static routes. This happens despite having dedicated static routes for these paths.

Expected behavior

Static routes should take precedence over dynamic routes. When visiting the landing page (/) or any static route, the dynamic [username] route’s server action and its middleware should not execute at all.

Code that reproduces the issue

app/
  [username]/
    page.tsx
    lookup.action.ts
  page.tsx (landing page)
// app/[username]/lookup.action.ts
export const lookupUser = action
  .schema(LookupSchema)
  .use(withRateLimit) // Rate limiting middleware runs for ALL routes
  .action(async ({ parsedInput: { username } }) => {
    // ...
  })

// app/[username]/page.tsx
export default async function Profile({ params }: { params: { username: string } }) {
  const { username } = params
  
  const res = await lookupUser({ username }) // This triggers rate limit middleware
  
  // ...
}

The issue is that the rate limiting middleware in our server action is being triggered for every route in the application, including the root landing page (/).

What’s the recommended pattern for implementing username routes at the root level while ensuring our middleware doesn’t execute for static routes like the landing page?

We discovered that browser requests for /favicon.ico are triggering our root-level dynamic route [username]/page.tsx (with “favicon.ico” as the username parameter).

This causes our rate limiting middleware to execute on every page load, even for static routes, as each page load generates a favicon request.

Is this expected behavior? What’s the recommended way to handle root-level dynamic routes for biolink-style applications (domain.com/username) without having asset requests like favicon.ico trigger the dynamic route’s middleware?

While we can exclude favicon.ico in our middleware, this seems like an architectural issue where static asset requests shouldn’t be processed by dynamic routes.