25d895d 🐛 fix(gitea_workflow): clean up temp repos after job steps 2bc3b11 🐛 fix(gitea_workflow): clean up temporary repo dirs in workflows 98c3f30 📝 docs(agent_rules): allow plan execution on current branch 16c7230 📝 docs(prompts): define custom verify layering 8efc4dd 🐛 fix(skills): quote commit-message description bc8498f 🐛 fix(ci): install tomli for gitea tests 55cda3b 🐛 fix(tests): report missing toml parser clearly c0729c7 🐛 fix(playbook): import Optional for cli compatibility 63e24bf 📦 deps(skills): sync thirdparty skills d2f9356 🐛 fix(ci): isolate gitea workflow repos 588b81d 🐛 fix(ci): inline gitea workflow bootstrap e0b1c3a ♻️ refactor(skills): standardize first-party skill contracts 2c5050d ♻️ refactor(skills): rename repo skills source dir f049dfb 📦 deps(skills): drop duplicate first-party superpowers skills 234b335 ✨ feat(workflow): add superpowers planning and execution state tracking c1702a6 📝 docs(markdown): format tracked markdown and drop stale templates 2325409 📝 docs(markdown): clarify optional markdownlint usage 214c44e 🔧 chore(markdown): add markdownlint baseline and lint fixes a22b324 📝 docs(templates): add execution and memory-bank prompt templates 223a797 📝 docs(templates): update README for Claude Code and current features 4ac8672 📝 docs: simplify README + platform-agnostic tools + auto-create local rules 2431c9d 📝 docs: add claude_md config and use cross-platform paths d64b248 📝 docs: fix README.md inaccuracies and add Claude Code info c8d6bf2 🐛 fix(playbook): use relative paths in CLAUDE.md when not at project root 6518f0f ✨ feat(playbook): auto-create CLAUDE.md with path discovery 6ec9a45 ✨ feat(skills): add skill_link symlink support + platform-agnostic prompt 9f8b6b5 📝 docs: update README and config example for Claude Code support 79cff6c 📝 docs(skills): add Claude Code platform support 452c6f5 ✨ feat(playbook): auto-inject AGENTS.md into CLAUDE.md e1dbf3c 🐛 fix(skills): remove dual-path from commit-message skill f3a7259 🔧 chore(ci): use prepare_repo.sh in both workflows da08212 🔧 chore(ci): extract prepare_repo.sh and clean up workflows 7ade85e 🗑️ remove(tsl): drop syntax_book/, data/ source and build script f94dba0 ♻️ refactor(skills): update playbook.py and tests for thirdparty/ layout b3df412 ♻️ refactor(skills): separate thirdparty skills into thirdparty/ subdirectory 64950e7 📦 deps(skills): sync thirdparty skills a2e3cb0 ✨ feat(playbook): add no_backup deploy controls 8609d59 🐛 fix(docs): repair reference catalog source links 956da11 🐛 fix(playbook): publish hidden ci test fixes 3f67754 📦 deps(skills): sync thirdparty skills 08ca87b 📦 deps(skills): add karpathy thirdparty sync 96b705b 📝 docs(tsl): rebuild canonical syntax and routing manual 3ed5052 📦 deps(skills): sync thirdparty skills 60108dd 📦 deps(skills): sync thirdparty skills da85d4e 🐛 fix(thirdparty): prune nested project snapshots a2a697e 📦 deps(skills): sync thirdparty skills 9df610a 🐛 fix(thirdparty): exclude duplicated superpowers skills 33dd5bb 🐛 fix(thirdparty): preserve optional manifest fields 91b0ea7 🐛 fix(thirdparty): preserve manifest during snapshot update 2e26f98 🔧 chore(thirdparty): generalize skills sync pipeline 5b9c1e3 📦 deps(skills): sync superpowers 2f2d34a 📝 docs(readme): normalize subtree command spacing 62db7db 🐛 fix(ci): serialize superpowers update and sync 3463223 🐛 fix(ci): use literal superpowers sync paths 48f6de8 📦 deps(skills): sync superpowers 4b23529 🔧 chore(ci): merge superpowers update and sync workflow a56d75b 📦 deps(skills): sync superpowers 84bcefa 🔧 chore(ci): use ci[bot] commit author name 00a07e5 📦 deps(skills): sync superpowers 7b84daf 🐛 fix(templates): enforce main loop progress tracking 51373d7 🔧 chore(ci): automate superpowers sync workflow eaaa39c 🐛 fix(ci): prevent stale superpowers sync from restoring skills block 79755c6 📦 deps(skills): sync superpowers 836d878 📦 deps(skills): sync superpowers 8216c9f 📦 deps(skills): sync superpowers 9439505 🐛 fix(playbook): address reported repo issues git-subtree-dir: docs/standards/playbook git-subtree-split: 25d895d8b3f56624ccfe99ad7289e9eb49e0f316
12 KiB
12 KiB
| 1 | No | Category | Guideline | Description | Do | Don't | Code Good | Code Bad | Severity | Docs URL |
|---|---|---|---|---|---|---|---|---|---|---|
| 2 | 1 | Routing | Use App Router for new projects | App Router is the recommended approach in Next.js 14+ | app/ directory with page.tsx | pages/ for new projects | app/dashboard/page.tsx | pages/dashboard.tsx | Medium | https://nextjs.org/docs/app |
| 3 | 2 | Routing | Use file-based routing | Create routes by adding files in app directory | page.tsx for routes layout.tsx for layouts | Manual route configuration | app/blog/[slug]/page.tsx | Custom router setup | Medium | https://nextjs.org/docs/app/building-your-application/routing |
| 4 | 3 | Routing | Colocate related files | Keep components styles tests with their routes | Component files alongside page.tsx | Separate components folder | app/dashboard/_components/ | components/dashboard/ | Low | |
| 5 | 4 | Routing | Use route groups for organization | Group routes without affecting URL | Parentheses for route groups | Nested folders affecting URL | (marketing)/about/page.tsx | marketing/about/page.tsx | Low | https://nextjs.org/docs/app/building-your-application/routing/route-groups |
| 6 | 5 | Routing | Handle loading states | Use loading.tsx for route loading UI | loading.tsx alongside page.tsx | Manual loading state management | app/dashboard/loading.tsx | useState for loading in page | Medium | https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming |
| 7 | 6 | Routing | Handle errors with error.tsx | Catch errors at route level | error.tsx with reset function | try/catch in every component | app/dashboard/error.tsx | try/catch in page component | High | https://nextjs.org/docs/app/building-your-application/routing/error-handling |
| 8 | 7 | Rendering | Use Server Components by default | Server Components reduce client JS bundle | Keep components server by default | Add 'use client' unnecessarily | export default function Page() | ('use client') for static content | High | https://nextjs.org/docs/app/building-your-application/rendering/server-components |
| 9 | 8 | Rendering | Mark Client Components explicitly | 'use client' for interactive components | Add 'use client' only when needed | Server Component with hooks/events | ('use client') for onClick useState | No directive with useState | High | https://nextjs.org/docs/app/building-your-application/rendering/client-components |
| 10 | 9 | Rendering | Push Client Components down | Keep Client Components as leaf nodes | Client wrapper for interactive parts only | Mark page as Client Component | <InteractiveButton/> in Server Page | ('use client') on page.tsx | High | |
| 11 | 10 | Rendering | Use streaming for better UX | Stream content with Suspense boundaries | Suspense for slow data fetches | Wait for all data before render | <Suspense><SlowComponent/></Suspense> | await allData then render | Medium | https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming |
| 12 | 11 | Rendering | Choose correct rendering strategy | SSG for static SSR for dynamic ISR for semi-static | generateStaticParams for known paths | SSR for static content | export const revalidate = 3600 | fetch without cache config | Medium | |
| 13 | 12 | DataFetching | Fetch data in Server Components | Fetch directly in async Server Components | async function Page() { const data = await fetch() } | useEffect for initial data | const data = await fetch(url) | useEffect(() => fetch(url)) | High | https://nextjs.org/docs/app/building-your-application/data-fetching |
| 14 | 13 | DataFetching | Configure caching explicitly (Next.js 15+) | Next.js 15 changed defaults to uncached for fetch | Explicitly set cache: 'force-cache' for static data | Assume default is cached (it's not in Next.js 15) | fetch(url { cache: 'force-cache' }) | fetch(url) // Uncached in v15 | High | https://nextjs.org/docs/app/building-your-application/upgrading/version-15 |
| 15 | 14 | DataFetching | Deduplicate fetch requests | React and Next.js dedupe same requests | Same fetch call in multiple components | Manual request deduplication | Multiple components fetch same URL | Custom cache layer | Low | |
| 16 | 15 | DataFetching | Use Server Actions for mutations | Server Actions for form submissions | action={serverAction} in forms | API route for every mutation | <form action={createPost}> | <form onSubmit={callApiRoute}> | Medium | https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations |
| 17 | 16 | DataFetching | Revalidate data appropriately | Use revalidatePath/revalidateTag after mutations | Revalidate after Server Action | 'use client' with manual refetch | revalidatePath('/posts') | router.refresh() everywhere | Medium | https://nextjs.org/docs/app/building-your-application/caching#revalidating |
| 18 | 17 | Images | Use next/image for optimization | Automatic image optimization and lazy loading | <Image> component for all images | <img> tags directly | <Image src={} alt={} width={} height={}> | <img src={}/> | High | https://nextjs.org/docs/app/building-your-application/optimizing/images |
| 19 | 18 | Images | Provide width and height | Prevent layout shift with dimensions | width and height props or fill | Missing dimensions | <Image width={400} height={300}/> | <Image src={url}/> | High | |
| 20 | 19 | Images | Use fill for responsive images | Fill container with object-fit | fill prop with relative parent | Fixed dimensions for responsive | <Image fill className="object-cover"/> | <Image width={window.width}/> | Medium | |
| 21 | 20 | Images | Configure remote image domains | Whitelist external image sources | remotePatterns in next.config.js | Allow all domains | remotePatterns: [{ hostname: 'cdn.example.com' }] | domains: ['*'] | High | https://nextjs.org/docs/app/api-reference/components/image#remotepatterns |
| 22 | 21 | Images | Use priority for LCP images | Mark above-fold images as priority | priority prop on hero images | All images with priority | <Image priority src={hero}/> | <Image priority/> on every image | Medium | |
| 23 | 22 | Fonts | Use next/font for fonts | Self-hosted fonts with zero layout shift | next/font/google or next/font/local | External font links | import { Inter } from 'next/font/google' | <link href="fonts.googleapis.com"/> | Medium | https://nextjs.org/docs/app/building-your-application/optimizing/fonts |
| 24 | 23 | Fonts | Apply font to layout | Set font in root layout for consistency | className on body in layout.tsx | Font in individual pages | <body className={inter.className}> | Each page imports font | Low | |
| 25 | 24 | Fonts | Use variable fonts | Variable fonts reduce bundle size | Single variable font file | Multiple font weights as files | Inter({ subsets: ['latin'] }) | Inter_400 Inter_500 Inter_700 | Low | |
| 26 | 25 | Metadata | Use generateMetadata for dynamic | Generate metadata based on params | export async function generateMetadata() | Hardcoded metadata everywhere | generateMetadata({ params }) | export const metadata = {} | Medium | https://nextjs.org/docs/app/building-your-application/optimizing/metadata |
| 27 | 26 | Metadata | Include OpenGraph images | Add OG images for social sharing | opengraph-image.tsx or og property | Missing social preview images | opengraph: { images: ['/og.png'] } | No OG configuration | Medium | |
| 28 | 27 | Metadata | Use metadata API | Export metadata object for static metadata | export const metadata = {} | Manual head tags | export const metadata = { title: 'Page' } | <head><title>Page</title></head> | Medium | |
| 29 | 28 | API | Use Route Handlers for APIs | app/api routes for API endpoints | app/api/users/route.ts | pages/api for new projects | export async function GET(request) | export default function handler | Medium | https://nextjs.org/docs/app/building-your-application/routing/route-handlers |
| 30 | 29 | API | Return proper Response objects | Use NextResponse for API responses | NextResponse.json() for JSON | Plain objects or res.json() | return NextResponse.json({ data }) | return { data } | Medium | |
| 31 | 30 | API | Handle HTTP methods explicitly | Export named functions for methods | Export GET POST PUT DELETE | Single handler for all methods | export async function POST() | switch(req.method) | Low | |
| 32 | 31 | API | Validate request body | Validate input before processing | Zod or similar for validation | Trust client input | const body = schema.parse(await req.json()) | const body = await req.json() | High | |
| 33 | 32 | Middleware | Use middleware for auth | Protect routes with middleware.ts | middleware.ts at root | Auth check in every page | export function middleware(request) | if (!session) redirect in page | Medium | https://nextjs.org/docs/app/building-your-application/routing/middleware |
| 34 | 33 | Middleware | Match specific paths | Configure middleware matcher | config.matcher for specific routes | Run middleware on all routes | matcher: ['/dashboard/:path*'] | No matcher config | Medium | |
| 35 | 34 | Middleware | Keep middleware edge-compatible | Middleware runs on Edge runtime | Edge-compatible code only | Node.js APIs in middleware | Edge-compatible auth check | fs.readFile in middleware | High | |
| 36 | 35 | Environment | Use NEXT_PUBLIC prefix | Client-accessible env vars need prefix | NEXT_PUBLIC_ for client vars | Server vars exposed to client | NEXT_PUBLIC_API_URL | API_SECRET in client code | High | https://nextjs.org/docs/app/building-your-application/configuring/environment-variables |
| 37 | 36 | Environment | Validate env vars | Check required env vars exist | Validate on startup | Undefined env at runtime | if (!process.env.DATABASE_URL) throw | process.env.DATABASE_URL (might be undefined) | High | |
| 38 | 37 | Environment | Use .env.local for secrets | Local env file for development secrets | .env.local gitignored | Secrets in .env committed | .env.local with secrets | .env with DATABASE_PASSWORD | High | |
| 39 | 38 | Performance | Analyze bundle size | Use @next/bundle-analyzer | Bundle analyzer in dev | Ship large bundles blindly | ANALYZE=true npm run build | No bundle analysis | Medium | https://nextjs.org/docs/app/building-your-application/optimizing/bundle-analyzer |
| 40 | 39 | Performance | Use dynamic imports | Code split with next/dynamic | dynamic() for heavy components | Import everything statically | const Chart = dynamic(() => import('./Chart')) | import Chart from './Chart' | Medium | https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading |
| 41 | 40 | Performance | Avoid layout shifts | Reserve space for dynamic content | Skeleton loaders aspect ratios | Content popping in | <Skeleton className="h-48"/> | No placeholder for async content | High | |
| 42 | 41 | Performance | Use Partial Prerendering | Combine static and dynamic in one route | Static shell with Suspense holes | Full dynamic or static pages | Static header + dynamic content | Entire page SSR | Low | https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering |
| 43 | 42 | Link | Use next/link for navigation | Client-side navigation with prefetching | <Link href=""> for internal links | <a> for internal navigation | <Link href="/about">About</Link> | <a href="/about">About</a> | High | https://nextjs.org/docs/app/api-reference/components/link |
| 44 | 43 | Link | Prefetch strategically | Control prefetching behavior | prefetch={false} for low-priority | Prefetch all links | <Link prefetch={false}> | Default prefetch on every link | Low | |
| 45 | 44 | Link | Use scroll option appropriately | Control scroll behavior on navigation | scroll={false} for tabs pagination | Always scroll to top | <Link scroll={false}> | Manual scroll management | Low | |
| 46 | 45 | Config | Use next.config.js correctly | Configure Next.js behavior | Proper config options | Deprecated or wrong options | images: { remotePatterns: [] } | images: { domains: [] } | Medium | https://nextjs.org/docs/app/api-reference/next-config-js |
| 47 | 46 | Config | Enable strict mode | Catch potential issues early | reactStrictMode: true | Strict mode disabled | reactStrictMode: true | reactStrictMode: false | Medium | |
| 48 | 47 | Config | Configure redirects and rewrites | Use config for URL management | redirects() rewrites() in config | Manual redirect handling | redirects: async () => [...] | res.redirect in pages | Medium | https://nextjs.org/docs/app/api-reference/next-config-js/redirects |
| 49 | 48 | Deployment | Use Vercel for easiest deploy | Vercel optimized for Next.js | Deploy to Vercel | Self-host without knowledge | vercel deploy | Complex Docker setup for simple app | Low | https://nextjs.org/docs/app/building-your-application/deploying |
| 50 | 49 | Deployment | Configure output for self-hosting | Set output option for deployment target | output: 'standalone' for Docker | Default output for containers | output: 'standalone' | No output config for Docker | Medium | https://nextjs.org/docs/app/building-your-application/deploying#self-hosting |
| 51 | 50 | Security | Sanitize user input | Never trust user input | Escape sanitize validate all input | Direct interpolation of user data | DOMPurify.sanitize(userInput) | dangerouslySetInnerHTML={{ __html: userInput }} | High | |
| 52 | 51 | Security | Use CSP headers | Content Security Policy for XSS protection | Configure CSP in next.config.js | No security headers | headers() with CSP | No CSP configuration | High | https://nextjs.org/docs/app/building-your-application/configuring/content-security-policy |
| 53 | 52 | Security | Validate Server Action input | Server Actions are public endpoints | Validate and authorize in Server Action | Trust Server Action input | Auth check + validation in action | Direct database call without check | High |