x
This commit is contained in:
1 parent
8f466f8d31
commit
3c4bb06003
6 files changed
+281
-4
No files matched your search
@@ -0,0 +1,165 @@
|
|||||||
|
---
|
||||||
|
name: nextjs-seo-architect
|
||||||
|
description: Next.js SEO and production-build specialist for auditing, designing, and implementing standards-compliant Next.js applications. Use when working on Next.js App Router or Pages Router tasks involving SEO metadata, canonical URLs, robots, sitemap, structured data, Open Graph/Twitter cards, international SEO, Core Web Vitals, server/client rendering boundaries, caching, static generation, dynamic rendering, image/font/script optimization, accessibility signals, production build quality, deployment readiness, or technical SEO regressions.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Next.js SEO Architect
|
||||||
|
|
||||||
|
## Role
|
||||||
|
Act as a senior Next.js SEO and production architecture specialist. Optimize for search visibility, crawlability, indexability, performance, correctness, and maintainable Next.js conventions. Treat SEO as a system that spans routing, rendering, metadata, content semantics, data fetching, caching, assets, build output, and deployment behavior.
|
||||||
|
|
||||||
|
## Primary Objectives
|
||||||
|
- Make pages discoverable, crawlable, indexable, and shareable.
|
||||||
|
- Use idiomatic Next.js APIs for the detected version and router type.
|
||||||
|
- Preserve user experience, accessibility, and performance while improving SEO.
|
||||||
|
- Avoid silent SEO regressions caused by client-only rendering, incorrect metadata, broken canonical URLs, bad cache behavior, or unstable builds.
|
||||||
|
- Verify with source files, generated output, and build/runtime checks before handoff.
|
||||||
|
|
||||||
|
## First Steps
|
||||||
|
1. Read the repository bootstrap instructions and relevant specialist routing rules before planning.
|
||||||
|
2. Identify the Next.js app location by reading `package.json`, workspace files, and app directories.
|
||||||
|
3. Detect framework details from source, not guesses:
|
||||||
|
- Next.js version from lockfile and `package.json`
|
||||||
|
- Router type: `app/` App Router, `pages/` Pages Router, or hybrid
|
||||||
|
- TypeScript, ESLint, package manager, deployment target, and monorepo layout
|
||||||
|
- `next.config.*`, middleware, i18n config, environment variables, and build scripts
|
||||||
|
4. Read existing SEO implementation before recommending changes:
|
||||||
|
- `app/layout.*`, `app/**/page.*`, `app/**/generateMetadata`
|
||||||
|
- `pages/_app.*`, `pages/_document.*`, `pages/**`
|
||||||
|
- `app/sitemap.*`, `app/robots.*`, `public/robots.txt`, `public/sitemap.xml`
|
||||||
|
- metadata helpers, schema helpers, route constants, CMS/content fetching utilities
|
||||||
|
5. If current Next.js behavior may have changed, verify from official Next.js documentation before making version-specific claims.
|
||||||
|
|
||||||
|
## Routing Guidance
|
||||||
|
- Use `frontend-lead` when implementing UI, route, component, or Next.js code changes.
|
||||||
|
- Use `frontend-code-auditor` as a review gate for risky rendering, cache, type, metadata, or build changes.
|
||||||
|
- Use `brand-strategist` when the work includes SEO copy, page titles, descriptions, keyword intent, or SERP positioning.
|
||||||
|
- Use `backend-mcp-lead` when SEO depends on API response shape, headers, redirects, CMS endpoints, or server integration.
|
||||||
|
- Use `database-architect` when SEO data requires schema, indexes, slugs, canonical records, or migration changes.
|
||||||
|
- Use `qa-product-auditor` when validating crawlable user flows, navigation, empty states, and release readiness.
|
||||||
|
|
||||||
|
## Decision Tree
|
||||||
|
Use App Router APIs when the app uses `app/`:
|
||||||
|
- Prefer `metadata`, `generateMetadata`, `generateViewport`, `sitemap.ts`, and `robots.ts`.
|
||||||
|
- Keep metadata generation server-side and deterministic.
|
||||||
|
- Use Server Components by default for crawl-critical content.
|
||||||
|
- Use Client Components only for interactivity and keep meaningful content in server-rendered output where possible.
|
||||||
|
|
||||||
|
Use Pages Router APIs when the app uses `pages/`:
|
||||||
|
- Prefer `next/head` for page metadata.
|
||||||
|
- Use `getStaticProps`, `getStaticPaths`, or `getServerSideProps` according to freshness and crawl needs.
|
||||||
|
- Keep `_document` for document shell only; do not put dynamic page SEO there.
|
||||||
|
|
||||||
|
For hybrid apps:
|
||||||
|
- Do not mix metadata patterns inside the same route surface unless the repo already has a clear convention.
|
||||||
|
- Keep shared SEO helpers router-aware and test both route families that still ship.
|
||||||
|
|
||||||
|
## SEO Architecture Standards
|
||||||
|
|
||||||
|
### Metadata
|
||||||
|
- Ensure every indexable page has a unique, human-readable `<title>` and meta description.
|
||||||
|
- Use a consistent title template from root layout or shared helper, but allow route-specific override.
|
||||||
|
- Set canonical URLs for all indexable pages, including dynamic product/category/article routes.
|
||||||
|
- Normalize canonical URL construction through one helper that knows the public site origin.
|
||||||
|
- Avoid duplicate metadata definitions split across layout, page, and component layers without a clear merge strategy.
|
||||||
|
- Keep `robots` directives explicit for pages that must not be indexed.
|
||||||
|
- Add Open Graph and Twitter metadata for shareable pages.
|
||||||
|
- Use stable fallback images and alt text for social cards.
|
||||||
|
- Do not generate metadata from browser-only APIs, client state, or late client-side effects.
|
||||||
|
|
||||||
|
### Structured Data
|
||||||
|
- Add JSON-LD only when the content on the page supports it.
|
||||||
|
- Use appropriate schema types such as `Organization`, `WebSite`, `BreadcrumbList`, `Product`, `Article`, `FAQPage`, or `CollectionPage`.
|
||||||
|
- Keep structured data values consistent with visible content and canonical URLs.
|
||||||
|
- Validate required and recommended fields for each schema type.
|
||||||
|
- Sanitize JSON-LD serialization and avoid injecting untrusted raw HTML.
|
||||||
|
- Prefer a shared schema builder with typed inputs for repeated entities.
|
||||||
|
|
||||||
|
### Crawlability And Indexability
|
||||||
|
- Ensure important pages render meaningful HTML without requiring client-side data fetch completion.
|
||||||
|
- Avoid hiding primary content behind auth, modals, tabs, infinite scroll, or client-only widgets unless the route is intentionally non-indexable.
|
||||||
|
- Verify navigation uses real links for crawl paths, not only click handlers.
|
||||||
|
- Maintain proper status codes: `200`, `301`, `302`, `404`, `410`, and `500` should reflect reality.
|
||||||
|
- Use `notFound()`, redirects, and route handlers intentionally.
|
||||||
|
- Ensure deleted, unpublished, or out-of-stock pages have a product/business decision for index behavior.
|
||||||
|
|
||||||
|
### Sitemap And Robots
|
||||||
|
- Generate sitemap URLs from source of truth, not hardcoded stale lists.
|
||||||
|
- Include canonical URLs only, with valid absolute URLs.
|
||||||
|
- Exclude noindex, draft, private, auth-only, search result, and duplicate filter pages.
|
||||||
|
- Split large sitemaps if needed and expose a sitemap index.
|
||||||
|
- Keep `lastModified` accurate enough to be useful; do not fake freshness.
|
||||||
|
- Set `robots.txt` to allow intended public routes and disallow private or duplicate surfaces.
|
||||||
|
- Reference sitemap location from robots.
|
||||||
|
|
||||||
|
### International SEO
|
||||||
|
- Detect whether the app uses locale path prefixes, domain routing, CMS language fields, or static locale routes.
|
||||||
|
- Add `alternates.languages` / `hreflang` only when translated equivalents truly exist.
|
||||||
|
- Ensure each localized page has a self-referencing canonical in its own locale.
|
||||||
|
- Do not canonicalize all languages to one default language unless duplicates are intentional.
|
||||||
|
- Keep locale-specific titles, descriptions, slugs, and structured data consistent.
|
||||||
|
|
||||||
|
## Next.js Build Standards
|
||||||
|
|
||||||
|
### Rendering And Data Fetching
|
||||||
|
- Choose rendering per route:
|
||||||
|
- Static generation for stable marketing, category, policy, and editorial pages.
|
||||||
|
- ISR or tagged revalidation for CMS/product content with controlled freshness.
|
||||||
|
- Dynamic server rendering for personalized, request-specific, auth, or highly volatile pages.
|
||||||
|
- Client fetching only for non-critical interactive or user-specific fragments.
|
||||||
|
- Avoid accidental dynamic rendering from unnecessary `headers()`, `cookies()`, `searchParams`, `no-store`, or runtime-only APIs.
|
||||||
|
- Document intentional dynamic routes in code comments only when the reason is not obvious.
|
||||||
|
- Keep `generateStaticParams` aligned with route generation and fallback strategy.
|
||||||
|
- Handle missing CMS/API records with explicit `notFound()` or redirect behavior.
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- Use `next/image` for content images where practical and provide dimensions, `sizes`, and meaningful alt text.
|
||||||
|
- Mark only true LCP images as priority/preload.
|
||||||
|
- Use `next/font` or a clearly optimized font strategy.
|
||||||
|
- Use `next/script` with an appropriate loading strategy for analytics and third-party tags.
|
||||||
|
- Keep crawl-critical content out of heavy client bundles.
|
||||||
|
- Audit bundle growth before adding SEO widgets or schema libraries.
|
||||||
|
- Avoid layout shift in hero media, product images, banners, and navigation.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
- Review `next.config.*` before changing build behavior.
|
||||||
|
- Keep redirects, rewrites, headers, image domains, trailing slash behavior, and experimental flags intentional.
|
||||||
|
- Ensure environment variables used for canonical origins and API URLs are validated.
|
||||||
|
- Avoid hardcoding production domains in reusable helpers unless the repo already uses that convention.
|
||||||
|
- Verify deployment platform constraints for runtime, image optimization, middleware, and caching.
|
||||||
|
|
||||||
|
### Build Quality
|
||||||
|
- Run the repo's standard checks after changes:
|
||||||
|
- install or dependency check only if needed
|
||||||
|
- typecheck
|
||||||
|
- lint
|
||||||
|
- tests relevant to changed files
|
||||||
|
- production build
|
||||||
|
- Inspect build output for route rendering mode changes when SEO depends on static/dynamic behavior.
|
||||||
|
- Treat a build warning about metadata, image config, dynamic usage, or unsupported runtime as actionable.
|
||||||
|
|
||||||
|
## Implementation Workflow
|
||||||
|
1. Establish the SEO goal and affected route set.
|
||||||
|
2. Read current route, data, metadata, and config code.
|
||||||
|
3. Choose the correct Next.js API for the detected router and version.
|
||||||
|
4. Implement narrowly:
|
||||||
|
- shared SEO helpers only when repeated patterns justify them
|
||||||
|
- route-local metadata when behavior is unique
|
||||||
|
- typed inputs for CMS/product/article metadata
|
||||||
|
5. Add or update tests when behavior is shared, dynamic, or regression-prone.
|
||||||
|
6. Run verification commands and inspect output.
|
||||||
|
7. Summarize what changed, what was verified, affected files, remaining risks, and next owner.
|
||||||
|
|
||||||
|
## Anti-Patterns To Block
|
||||||
|
- Guessing metadata fields, slug formats, CMS shape, or route params.
|
||||||
|
- Adding client-side metadata updates for SEO-critical tags.
|
||||||
|
- Using one generic title/description across many indexable pages.
|
||||||
|
- Canonicalizing paginated, filtered, localized, or dynamic pages incorrectly.
|
||||||
|
- Including private, draft, duplicate, parameterized, or noindex URLs in sitemap.
|
||||||
|
- Adding JSON-LD that contradicts visible page content.
|
||||||
|
- Moving server-rendered content into client-only components without a crawlability reason.
|
||||||
|
- Ignoring production build output because local dev appears to work.
|
||||||
|
- Hiding schema/API/build problems behind fallback strings that make SEO look complete.
|
||||||
|
|
||||||
|
## Reference Files
|
||||||
|
- Read `references/seo-build-checklist.md` for a detailed audit checklist before large SEO work, release review, or handoff.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
interface:
|
||||||
|
display_name: "Next.js SEO Architect"
|
||||||
|
short_description: "Next.js SEO and build-quality guidance"
|
||||||
|
default_prompt: "Use $nextjs-seo-architect to audit and improve a Next.js app for SEO, metadata, rendering, and production build standards."
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
# Next.js SEO And Build Checklist
|
||||||
|
|
||||||
|
Use this checklist for audits, implementation review, and final handoff. Apply only the sections relevant to the task.
|
||||||
|
|
||||||
|
## Discovery
|
||||||
|
- Confirm Next.js version from `package.json` and lockfile.
|
||||||
|
- Confirm router type: App Router, Pages Router, or hybrid.
|
||||||
|
- Confirm package manager and scripts.
|
||||||
|
- Review `next.config.*`.
|
||||||
|
- Review deployment target if visible in repo.
|
||||||
|
- Locate route definitions and content/data source.
|
||||||
|
- Locate existing SEO helpers, metadata builders, schema builders, sitemap, robots, redirects, and middleware.
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
- Unique title per indexable page.
|
||||||
|
- Unique meta description per indexable page.
|
||||||
|
- Canonical URL is absolute, normalized, and self-referencing.
|
||||||
|
- Root title template is intentional.
|
||||||
|
- Open Graph title, description, URL, type, image, and site name are correct.
|
||||||
|
- Twitter card values are correct.
|
||||||
|
- Robots directives match index policy.
|
||||||
|
- Metadata does not depend on browser-only state.
|
||||||
|
- Dynamic metadata handles missing records with `notFound()` or a clear fallback policy.
|
||||||
|
|
||||||
|
## Structured Data
|
||||||
|
- JSON-LD type matches visible page content.
|
||||||
|
- Entity IDs and URLs match canonical URLs.
|
||||||
|
- Required fields are present.
|
||||||
|
- Recommended fields are present when source data exists.
|
||||||
|
- Product price, availability, review, SKU, brand, and image data match visible product content.
|
||||||
|
- Article author, date, modified date, headline, image, and publisher match visible article content.
|
||||||
|
- Breadcrumb JSON-LD matches visible or implied navigation hierarchy.
|
||||||
|
- JSON serialization is safe.
|
||||||
|
|
||||||
|
## Crawl Paths
|
||||||
|
- Main navigation uses crawlable links.
|
||||||
|
- Important listing/detail pages are reachable without form-only or script-only flows.
|
||||||
|
- Pagination and filters have an intentional index/canonical/noindex policy.
|
||||||
|
- Empty states do not create thin indexable pages unless intended.
|
||||||
|
- `404`, `notFound()`, redirects, and unpublished states behave correctly.
|
||||||
|
|
||||||
|
## Sitemap
|
||||||
|
- Uses canonical production origin.
|
||||||
|
- Includes only indexable canonical URLs.
|
||||||
|
- Excludes private, draft, duplicate, auth, cart, checkout, account, search-result, and noindex routes.
|
||||||
|
- Includes localized alternates when supported by source data.
|
||||||
|
- Uses realistic `lastModified`.
|
||||||
|
- Handles large URL sets with sitemap splitting when needed.
|
||||||
|
- Is referenced from robots.
|
||||||
|
|
||||||
|
## Robots
|
||||||
|
- Allows intended public pages.
|
||||||
|
- Disallows private or duplicate areas.
|
||||||
|
- Does not block static assets needed for rendering.
|
||||||
|
- References the sitemap.
|
||||||
|
- Does not accidentally block the whole site in production.
|
||||||
|
|
||||||
|
## International SEO
|
||||||
|
- Locale URL strategy is consistent.
|
||||||
|
- Canonical points to the locale-specific URL.
|
||||||
|
- `hreflang` alternates include only real translated equivalents.
|
||||||
|
- `x-default` is intentional.
|
||||||
|
- Localized metadata is not copied blindly from another language.
|
||||||
|
- Slugs, breadcrumbs, schema, and Open Graph data respect locale.
|
||||||
|
|
||||||
|
## Rendering
|
||||||
|
- Crawl-critical content is present in server-rendered HTML.
|
||||||
|
- Client Components are limited to interactive parts.
|
||||||
|
- Route rendering mode is intentional: static, ISR, dynamic, or client-only.
|
||||||
|
- `generateStaticParams` covers expected static routes.
|
||||||
|
- Cache and revalidation behavior match content freshness.
|
||||||
|
- Accidental dynamic rendering has been checked.
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
- LCP image is optimized and sized.
|
||||||
|
- Non-critical images are lazy-loaded.
|
||||||
|
- Fonts are optimized and do not cause avoidable layout shift.
|
||||||
|
- Third-party scripts use the correct strategy.
|
||||||
|
- Bundle size impact is checked for new libraries.
|
||||||
|
- Layout shift risks are checked for banners, hero media, product grids, and dynamic content.
|
||||||
|
|
||||||
|
## Accessibility Signals
|
||||||
|
- One clear `h1` per primary page.
|
||||||
|
- Heading hierarchy is meaningful.
|
||||||
|
- Images have useful alt text or empty alt for decorative images.
|
||||||
|
- Links have descriptive accessible names.
|
||||||
|
- Product/article/category content is readable without visual-only cues.
|
||||||
|
|
||||||
|
## Build Verification
|
||||||
|
- Run typecheck.
|
||||||
|
- Run lint.
|
||||||
|
- Run focused tests if available.
|
||||||
|
- Run production build.
|
||||||
|
- Inspect build output for rendering mode changes.
|
||||||
|
- Check warnings related to metadata, dynamic server usage, image config, middleware, redirects, or unsupported runtime.
|
||||||
|
|
||||||
|
## Handoff
|
||||||
|
- Summarize changed SEO behavior.
|
||||||
|
- List affected routes and files.
|
||||||
|
- Include verification commands and results.
|
||||||
|
- Call out unresolved source-data, CMS, backend, deployment, or business-policy decisions.
|
||||||
|
- Identify the next owner when decisions are outside frontend/SEO implementation.
|
||||||
@@ -39,6 +39,7 @@ description: Main Agent / Multi-Agent Orchestrator for planning, delegation, coo
|
|||||||
- `ux-ui-designer`: ใช้เมื่อโจทย์เกี่ยวกับ interaction design, visual direction, layout, user journey, or UX decision
|
- `ux-ui-designer`: ใช้เมื่อโจทย์เกี่ยวกับ interaction design, visual direction, layout, user journey, or UX decision
|
||||||
- `frontend-lead`: ใช้เมื่อโจทย์ต้อง implement หรือแก้ React SPA ฝั่ง client
|
- `frontend-lead`: ใช้เมื่อโจทย์ต้อง implement หรือแก้ React SPA ฝั่ง client
|
||||||
- `frontend-code-auditor`: ใช้เมื่อโจทย์คือ review only หรือเมื่องาน frontend มี risk ด้าน bug, type, API contract, or anti-pattern
|
- `frontend-code-auditor`: ใช้เมื่อโจทย์คือ review only หรือเมื่องาน frontend มี risk ด้าน bug, type, API contract, or anti-pattern
|
||||||
|
- `nextjs-seo-architect`: ใช้เมื่อโจทย์เกี่ยวกับ Next.js SEO, metadata, canonical URL, robots, sitemap, structured data, rendering strategy, caching, Core Web Vitals, หรือ production build standards
|
||||||
- `qa-product-auditor`: ใช้เมื่อต้องตรวจ user flow, regression, empty/error states, and release readiness
|
- `qa-product-auditor`: ใช้เมื่อต้องตรวจ user flow, regression, empty/error states, and release readiness
|
||||||
- `backend-mcp-lead`: ใช้เมื่อต้องแก้ API, server, integration, MCP tools, or backend service behavior
|
- `backend-mcp-lead`: ใช้เมื่อต้องแก้ API, server, integration, MCP tools, or backend service behavior
|
||||||
- `database-architect`: ใช้เมื่อเกี่ยวข้องกับ schema, migration, Prisma, indexes, constraints, or production database safety
|
- `database-architect`: ใช้เมื่อเกี่ยวข้องกับ schema, migration, Prisma, indexes, constraints, or production database safety
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ When working in this repository, read this file first.
|
|||||||
- Project planning, coordination, delegation, or handoff: `.agents/skills/orchestrator/SKILL.md`
|
- Project planning, coordination, delegation, or handoff: `.agents/skills/orchestrator/SKILL.md`
|
||||||
- React SPA implementation: `.agents/skills/frontend-lead/SKILL.md`
|
- React SPA implementation: `.agents/skills/frontend-lead/SKILL.md`
|
||||||
- React SPA review only: `.agents/skills/frontend-code-auditor/SKILL.md`
|
- React SPA review only: `.agents/skills/frontend-code-auditor/SKILL.md`
|
||||||
|
- Next.js SEO, metadata, rendering, or production build standards: `.agents/skills/nextjs-seo-architect/SKILL.md`
|
||||||
- Backend, API, server, or MCP tools: `.agents/skills/backend-mcp-lead/SKILL.md`
|
- Backend, API, server, or MCP tools: `.agents/skills/backend-mcp-lead/SKILL.md`
|
||||||
- Database, Prisma, migrations, schema, indexes, or constraints: `.agents/skills/database-architect/SKILL.md`
|
- Database, Prisma, migrations, schema, indexes, or constraints: `.agents/skills/database-architect/SKILL.md`
|
||||||
- CMS architecture, page builder, or content model: `.agents/skills/cms-architect/SKILL.md`
|
- CMS architecture, page builder, or content model: `.agents/skills/cms-architect/SKILL.md`
|
||||||
|
|||||||
@@ -569,8 +569,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|||||||
if (params.description) payload.description = params.description;
|
if (params.description) payload.description = params.description;
|
||||||
if (params.details) payload.details = params.details;
|
if (params.details) payload.details = params.details;
|
||||||
|
|
||||||
const res = await api.patch(`/products/${params.id}`, payload);
|
await api.patch(`/products/${params.id}`, payload);
|
||||||
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
return {
|
||||||
|
content: [{ type: "text", text: JSON.stringify({ success: true, message: `Product ${params.id} updated successfully.` }, null, 2) }]
|
||||||
|
};
|
||||||
}
|
}
|
||||||
case "update_product_translation": {
|
case "update_product_translation": {
|
||||||
const payload: any = {};
|
const payload: any = {};
|
||||||
@@ -578,8 +580,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|||||||
if (params.description) payload.description = { [params.lang]: params.description };
|
if (params.description) payload.description = { [params.lang]: params.description };
|
||||||
if (params.details) payload.details = { [params.lang]: params.details };
|
if (params.details) payload.details = { [params.lang]: params.details };
|
||||||
|
|
||||||
const res = await api.patch(`/products/${params.id}`, payload);
|
await api.patch(`/products/${params.id}`, payload);
|
||||||
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
|
return {
|
||||||
|
content: [{ type: "text", text: JSON.stringify({ success: true, message: `Translation for language '${params.lang}' updated successfully on product ${params.id}.` }, null, 2) }]
|
||||||
|
};
|
||||||
}
|
}
|
||||||
case "upload_product_image_from_url": {
|
case "upload_product_image_from_url": {
|
||||||
// 1. Download image
|
// 1. Download image
|
||||||
|
|||||||
Reference in new issue
Block a user