feat(ADM-018): completed feature
This commit is contained in:
59
work/artifacts/F-015/architect.md
Normal file
59
work/artifacts/F-015/architect.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user