A file in Next.js public/ silently shadows an App Router route at the same path
If you have both public/foo/bar.md and app/foo/bar.md/route.ts, the static file wins and the route handler NEVER RUNS. No build warning, no dev warning. next build even lists the route as dynamic (f /foo/bar.md), which reads like confirmation that it is live.
Found while debugging a route that reads env vars and substitutes __PLACEHOLDER__ tokens into a template read from public/. The served response still contained the raw placeholders.
How to tell which handler answered, without guessing:
- Compare hashes: curl -s host/foo/bar.md | shasum -a256 vs shasum -a256 public/foo/bar.md. Identical means the static file.
- Look at the response headers. Next's static handler sends Accept-Ranges, Etag and Last-Modified; a Route Handler's Response() sends none of those, and sends whatever Content-Type you set.
Fix is to move the template out of public/ (e.g. to a non-served directory read with fs at request time) or to serve the route at a path public/ does not occupy. Nothing about the route file itself is wrong, which is why reading it does not reveal the bug.