diff --git a/.agents/skills/nextjs-seo-architect/SKILL.md b/.agents/skills/nextjs-seo-architect/SKILL.md new file mode 100644 index 0000000..3c04234 --- /dev/null +++ b/.agents/skills/nextjs-seo-architect/SKILL.md @@ -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 `` 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. diff --git a/.agents/skills/nextjs-seo-architect/agents/openai.yaml b/.agents/skills/nextjs-seo-architect/agents/openai.yaml new file mode 100644 index 0000000..d565b71 --- /dev/null +++ b/.agents/skills/nextjs-seo-architect/agents/openai.yaml @@ -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." diff --git a/.agents/skills/nextjs-seo-architect/references/seo-build-checklist.md b/.agents/skills/nextjs-seo-architect/references/seo-build-checklist.md new file mode 100644 index 0000000..4071392 --- /dev/null +++ b/.agents/skills/nextjs-seo-architect/references/seo-build-checklist.md @@ -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. diff --git a/.agents/skills/orchestrator/SKILL.md b/.agents/skills/orchestrator/SKILL.md index 932c06d..a769f84 100644 --- a/.agents/skills/orchestrator/SKILL.md +++ b/.agents/skills/orchestrator/SKILL.md @@ -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 - `frontend-lead`: ใช้เมื่อโจทย์ต้อง implement หรือแก้ React SPA ฝั่ง client - `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 - `backend-mcp-lead`: ใช้เมื่อต้องแก้ API, server, integration, MCP tools, or backend service behavior - `database-architect`: ใช้เมื่อเกี่ยวข้องกับ schema, migration, Prisma, indexes, constraints, or production database safety diff --git a/AGENTS.md b/AGENTS.md index 5d7cb43..48cb1ea 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,6 +11,7 @@ When working in this repository, read this file first. - Project planning, coordination, delegation, or handoff: `.agents/skills/orchestrator/SKILL.md` - React SPA implementation: `.agents/skills/frontend-lead/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` - 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` diff --git a/apps/mcp-server/index.ts b/apps/mcp-server/index.ts index 6f99e32..4314731 100644 --- a/apps/mcp-server/index.ts +++ b/apps/mcp-server/index.ts @@ -569,8 +569,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { if (params.description) payload.description = params.description; if (params.details) payload.details = params.details; - const res = await api.patch(`/products/${params.id}`, payload); - return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] }; + await api.patch(`/products/${params.id}`, payload); + return { + content: [{ type: "text", text: JSON.stringify({ success: true, message: `Product ${params.id} updated successfully.` }, null, 2) }] + }; } case "update_product_translation": { const payload: any = {}; @@ -578,8 +580,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { if (params.description) payload.description = { [params.lang]: params.description }; if (params.details) payload.details = { [params.lang]: params.details }; - const res = await api.patch(`/products/${params.id}`, payload); - return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] }; + await api.patch(`/products/${params.id}`, payload); + 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": { // 1. Download image