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