Use /{id}/{fa-slug} detail URLs in sitemaps and add public by-id lookups.

Default sitemap templates now emit SEO-friendly Farsi path segments with stable CMS ids; storefronts resolve content via new by-id public endpoints.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-22 23:43:25 +03:30
co-authored by Cursor
parent 1b16e79d3f
commit 7cef24336a
16 changed files with 495 additions and 25 deletions
+131 -1
View File
@@ -195,7 +195,7 @@
"SEO"
],
"summary": "XML sitemap for search engines",
"description": "Published products, blogs, and portfolios for this tenant (respects enabled modules), plus static pages and URL templates from the synced website manifest (`GET https://{domain}/meshkee/sitemap-config.json`). Default paths when not synced: `/`, `/products/{slug}`, `/blog/{slug}`, `/portfolios/{slug}`. Proxied from `https://{domain}/sitemap.xml` on the storefront. Cached in Redis; refreshed after CMS writes and manifest sync.",
"description": "Published products, blogs, and portfolios for this tenant (respects enabled modules), plus static pages and URL templates from the synced website manifest (`GET https://{domain}/meshkee/sitemap-config.json`). Default detail paths: `/products/{id}/{nameFaSlug}`, `/blog/{id}/{titleSlug}`, `/portfolios/{id}/{titleFaSlug}`. Proxied from `https://{domain}/sitemap.xml` on the storefront. Cached in Redis; refreshed after CMS writes and manifest sync.",
"parameters": [
{
"$ref": "#/components/parameters/domain"
@@ -514,6 +514,84 @@
}
}
},
"/tenants/{domain}/products/by-id/{productId}": {
"get": {
"tags": [
"Products"
],
"summary": "Product by id (preferred for /products/{id}/{nameFaSlug} pages)",
"parameters": [
{
"$ref": "#/components/parameters/domain"
},
{
"name": "productId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "{ product, relatedProducts } — same shape as product-by-slug"
}
}
}
},
"/tenants/{domain}/products/by-id/{productId}/variations": {
"get": {
"tags": [
"Products"
],
"summary": "Product variations by id",
"parameters": [
{
"$ref": "#/components/parameters/domain"
},
{
"name": "productId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Variation tree for the product"
}
}
}
},
"/tenants/{domain}/products/by-id/{productId}/technical-info": {
"get": {
"tags": [
"Products"
],
"summary": "Product technical info by id",
"parameters": [
{
"$ref": "#/components/parameters/domain"
},
{
"name": "productId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Technical form + values"
}
}
}
},
"/tenants/{domain}/products/{slug}": {
"get": {
"tags": [
@@ -950,6 +1028,32 @@
}
}
},
"/tenants/{domain}/blogs/by-id/{blogId}": {
"get": {
"tags": [
"Blogs"
],
"summary": "Blog by id (preferred for /blog/{id}/{titleSlug} pages)",
"parameters": [
{
"$ref": "#/components/parameters/domain"
},
{
"name": "blogId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "{ blog }"
}
}
}
},
"/tenants/{domain}/blogs/{slug}": {
"get": {
"tags": [
@@ -1277,6 +1381,32 @@
}
}
},
"/tenants/{domain}/portfolios/by-id/{portfolioId}": {
"get": {
"tags": [
"Portfolios"
],
"summary": "Portfolio by id (preferred for /portfolios/{id}/{titleFaSlug} pages)",
"parameters": [
{
"$ref": "#/components/parameters/domain"
},
{
"name": "portfolioId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "{ portfolio }"
}
}
}
},
"/tenants/{domain}/portfolios/{slug}": {
"get": {
"tags": [