Files
mercadodevida/work/artifacts/F-015/architect.md
2026-08-17 22:23:10 +02:00

3.1 KiB

Architect — F-015 SEO core: structured data, sitemap, redirects

Feature

F-015 adds SEO crawlability and structured data to the existing F-014 storefront catalog pages.

Design

Storefront SEO module

Create a small storefront SEO module under project/storefront/src/lib/seo/:

  • json-ld.ts builds typed JSON-LD objects for Organization, BreadcrumbList and Product.
  • redirects.ts defines a RedirectRepository interface and an env-backed implementation.
  • Keep public URL generation centralized through existing absoluteUrl() / SITE_URL.

No new runtime dependency is required.

Structured data

  • Root layout embeds Organization JSON-LD once.
  • Product pages embed:
    • Product JSON-LD using product name, description, canonical URL and main image when available.
    • BreadcrumbList JSON-LD for Home → Product.
  • Category and brand pages embed BreadcrumbList JSON-LD.
  • JSON-LD is rendered as application/ld+json with JSON serialization, not string concatenation.

Sitemap and robots

Use Next.js metadata routes:

  • src/app/sitemap.ts returns MetadataRoute.Sitemap.
  • src/app/robots.ts returns MetadataRoute.Robots.

Sitemap source:

  • Static public URLs: /, /products/search.
  • Product URLs from searchProducts({ limit: 100, offset }), which returns active products only through backend SearchProducts.activeOnly = true; page through results to avoid silently truncating the first page.
  • Category URLs from listCategoryTree() flattened recursively.
  • Brand URLs from a new public GET /brands backend endpoint and storefront listBrands() client helper.
  • On API failure, sitemap degrades to static URLs rather than failing the build.

Redirect management

  • Add src/middleware.ts using an env-backed redirect store.
  • RedirectRepository.findBySourcePath(pathname) returns a redirect target when configured.
  • Configure redirects with REDIRECTS_JSON, an array of { "from": "/old", "to": "/new" } entries.
  • Middleware returns permanent 301 redirects only for same-origin local paths. External targets are rejected by the parser to avoid open redirects.
  • Redirect source and target paths must start with /; source cannot equal target.

Backend brand listing

Extend the brands module minimally:

  • Add BrandRepository.list().
  • Add ListBrands use case.
  • Add public GET /brands returning { items: [...] } in stable name ASC, id ASC order.

Acceptance trace

  • Product JSON-LD: product page embeds Product schema script.
  • Sitemap: lists active product URLs via search API, category URLs, brand URLs and static pages; draft products excluded by backend active search.
  • Redirect: middleware redirects stored old path with HTTP 301 to same-origin local target.
  • Canonical URLs: existing F-014 canonical metadata remains on product/category/brand/search and root layout gains canonical metadata.
  • verify.sh: must pass after gates.

Risks / constraints

  • No hreflang and no external SEO tooling by scope.
  • Lighthouse/Google validator may be unavailable locally; validate structurally and through build output.
  • Env redirects are enough for this slice; a database-backed admin UI is intentionally deferred.