vercel-functions: skip default-export rule for App Router pages#73
Open
mvanhorn wants to merge 1 commit intovercel:mainfrom
Open
vercel-functions: skip default-export rule for App Router pages#73mvanhorn wants to merge 1 commit intovercel:mainfrom
mvanhorn wants to merge 1 commit intovercel:mainfrom
Conversation
The rule
pattern: export\s+default\s+function
message: 'Use named exports (GET, POST, ...) instead of default
export for route handlers'
fires on every page.tsx, layout.tsx, loading.tsx, error.tsx, not-found.tsx,
sitemap.ts, and template.tsx in a Next.js App Router project, where a default
export is *required*. Reported in anthropics/claude-code#54989 with concrete
reproduction (a 44-page App Router project firing the error on every page
write/edit).
Add a skipIfFileContains regex that matches the strongest signals of an
App Router file (and not a route handler):
- 'use client' directive
- App Router config exports (metadata / dynamic / revalidate / fetchCache /
runtime)
- export default function whose name ends in Page / Layout / Loading /
Error / NotFound / Sitemap / Template / Default (also lowercase
sitemap / robots / opengraph / manifest for the convention files)
- JSX with a capitalised component tag
- a destructured `{ children }` parameter (layouts / templates)
- a `MetadataRoute` reference (sitemap, robots, manifest helpers)
- imports from next/font, next/image, next/link, next/navigation,
next/headers, next/cookies
Each of these is overwhelmingly common in App Router pages and overwhelmingly
absent from route.ts handlers. A bug `export default function handler` in
a route.ts still fires the rule because none of the patterns match.
Melkeydev
approved these changes
Apr 30, 2026
Collaborator
Melkeydev
left a comment
There was a problem hiding this comment.
approved but:
- can you resolve the conflicts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the false-positive
Use named exports (GET, POST, PUT, DELETE) instead of default export for route handlersERROR that fires on everypage.tsx,layout.tsx,loading.tsx,error.tsx,not-found.tsx,sitemap.ts, andtemplate.tsxin a Next.js App Router project.Refs anthropics/claude-code#54989 (the bug was reported in
claude-code, but the validation rule lives here inskills/vercel-functions/SKILL.mdlines 25-29).Problem
The current rule:
matches any default-exported function. Next.js App Router requires default exports for
page.tsx,layout.tsx,loading.tsx,error.tsx,not-found.tsx,sitemap.ts, andtemplate.tsx, so the rule fires[ERROR]on every Write/Edit to any of those files. The reporter has a 44-page project where this fires constantly and cannot be suppressed without disabling the entire skill.Fix
Add a
skipIfFileContainsregex (the same shape used inskills/routing-middleware/SKILL.md) that suppresses the rule when the file shows strong signals of being an App Router file rather than a route handler:'use client'directiveexport const metadata|dynamic|revalidate|fetchCache|runtimeexport default function …(Page|Layout|Loading|Error|NotFound|Sitemap|Template|Default)(also lower-casesitemap/robots/opengraph/manifest)<[A-Z]…(capitalised JSX tag){ children }destructureMetadataRoute.from 'next/(font|image|link|navigation|headers|cookies)'Each of these is overwhelmingly common in App Router pages and overwhelmingly absent from route handlers. A buggy
export default function handlerinside aroute.tsstill fires the rule because none of the patterns match.Why
skipIfFileContainsand not a new fieldThe reporter suggested
onlyIfFilename/skipIfFilename. Adding a new schema field requires the downstream consumer (claude-code) to honor it, otherwise the field is inert and the false positive remains.skipIfFileContainsis already supported and already used byskills/routing-middleware/SKILL.md, so this PR fixes the bug today without coordinating new field support.Verification
Tested the regex against representative content for each affected file plus the buggy route handler case (Python regex used for portability):
Plugin-level checks still pass: