diff --git a/docs/website-api/AI_PROMPT.md b/docs/website-api/AI_PROMPT.md index 45ac86f..bd6ffa2 100644 --- a/docs/website-api/AI_PROMPT.md +++ b/docs/website-api/AI_PROMPT.md @@ -275,9 +275,12 @@ Minimal example: - Product: `/products/{id}/{nameFaSlug}` — build `nameFaSlug` from `nameFa` (fallback `title`); resolve page via `GET /tenants/{domain}/products/by-id/{id}` (slug segment is SEO-only; redirect to canonical if it drifts). - Product category: `/products/category/{categoryId}/{nameFaSlug}` — build slug from `nameFa` (fallback `name`); resolve via `GET /tenants/{domain}/categories/by-id/{id}`, then list products with `categoryId`. - User product (customer listing): `/user-products/{slug}` — use the listing’s `slug` from the API; resolve via `GET /tenants/{domain}/user-products/{slug}`. - - Blog: `/blog/{id}/{titleSlug}` — `GET /tenants/{domain}/blogs/by-id/{id}` - - Portfolio: `/portfolios/{id}/{titleFaSlug}` — `GET /tenants/{domain}/portfolios/by-id/{id}` -- When linking from lists/cards, use the same `{id}/{slug}` shape for details (slugify Farsi title: spaces → `-`, keep Persian letters). Category links use `/products/category/{id}/{nameFaSlug}`. User-product cards use `/user-products/{slug}`. + - Blog: `/blog/{slug}` — use the blog’s `slug` from the API; resolve via `GET /tenants/{domain}/blogs/{slug}` (or list + match). Prefer slug routes over id. + - Portfolio: `/portfolio/{slug}` — use the portfolio’s `slug` from the API; resolve via `GET /tenants/{domain}/portfolios/{slug}`. + - Instruction: `/instruction/{slug}` — use the instruction’s `slug` from the API; resolve via `GET /tenants/{domain}/instructions/{slug}`. + - Video: `/videos/{slug}` — use the video’s `slug` from the API. + - Workshop: `/workshops/{slug}` — use the workshop’s `slug` from the API. +- When linking from lists/cards, use the same slug-based detail paths. Category links use `/products/category/{id}/{nameFaSlug}`. User-product cards use `/user-products/{slug}`. - Omit `templates` in `sitemap-config.json` unless this site uses non-default paths. - **Sitemap files (proxied by nginx — do not ship local copies):** - `/sitemap.xml` — sitemap **index** (lists child sitemaps for enabled modules) diff --git a/docs/website-api/Meshkee-Website-API.postman_collection.json b/docs/website-api/Meshkee-Website-API.postman_collection.json index ae16f9a..79e7b04 100644 --- a/docs/website-api/Meshkee-Website-API.postman_collection.json +++ b/docs/website-api/Meshkee-Website-API.postman_collection.json @@ -957,7 +957,7 @@ "name": "Get published portfolio by id (website)", "request": { "method": "GET", - "description": "Preferred for /portfolios/{id}/{titleFaSlug} pages. Includes nullable `projectUrl`.", + "description": "Preferred for /portfolio/{slug} pages. Includes nullable `projectUrl`.", "url": "{{baseUrl}}/tenants/{{domain}}/portfolios/by-id/{{portfolioId}}" } }, diff --git a/docs/website-api/openapi.json b/docs/website-api/openapi.json index a502453..4450e7b 100644 --- a/docs/website-api/openapi.json +++ b/docs/website-api/openapi.json @@ -1606,7 +1606,7 @@ "tags": [ "Blogs" ], - "summary": "Blog by id (preferred for /blog/{id}/{titleSlug} pages)", + "summary": "Blog by id (legacy; prefer slug routes `/blog/{slug}`)", "parameters": [ { "$ref": "#/components/parameters/domain" @@ -1959,7 +1959,7 @@ "tags": [ "Portfolios" ], - "summary": "Portfolio by id (preferred for /portfolios/{id}/{titleFaSlug} pages)", + "summary": "Portfolio by id (legacy; prefer slug routes `/portfolio/{slug}`)", "parameters": [ { "$ref": "#/components/parameters/domain" diff --git a/src/sitemap/sitemap.constants.ts b/src/sitemap/sitemap.constants.ts index 243f540..a8cf3f0 100644 --- a/src/sitemap/sitemap.constants.ts +++ b/src/sitemap/sitemap.constants.ts @@ -6,10 +6,10 @@ export const SITEMAP_URLSET_NS = 'http://www.sitemaps.org/schemas/sitemap/0.9'; export const DEFAULT_SITEMAP_PATH_TEMPLATES = { product: '/products/{id}/{slug}', productCategory: '/products/category/{id}/{slug}', - blog: '/blog/{id}/{slug}', - portfolio: '/portfolios/{id}/{slug}', + blog: '/blog/{slug}', + portfolio: '/portfolio/{slug}', video: '/videos/{slug}', - instruction: '/instructions/{slug}', + instruction: '/instruction/{slug}', workshop: '/workshops/{slug}', userProduct: '/user-products/{slug}', } as const; diff --git a/src/sitemap/sitemap.service.ts b/src/sitemap/sitemap.service.ts index 8e63502..c56770b 100644 --- a/src/sitemap/sitemap.service.ts +++ b/src/sitemap/sitemap.service.ts @@ -344,7 +344,7 @@ export class SitemapService { }, select: { id: true, - title: true, + slug: true, updated_at: true, }, orderBy: [{ updated_at: 'desc' }, { id: 'desc' }], @@ -353,7 +353,7 @@ export class SitemapService { return rows.map((row) => this.toEntry(baseUrl, template, { id: row.id, - slug: slugifyForUrl(row.title, 'blog'), + slug: row.slug, updatedAt: row.updated_at, }), ); @@ -371,8 +371,7 @@ export class SitemapService { }, select: { id: true, - title: true, - title_fa: true, + slug: true, updated_at: true, }, orderBy: [{ updated_at: 'desc' }, { id: 'desc' }], @@ -381,7 +380,7 @@ export class SitemapService { return rows.map((row) => this.toEntry(baseUrl, template, { id: row.id, - slug: slugifyForUrl(row.title_fa || row.title, 'portfolio'), + slug: row.slug, updatedAt: row.updated_at, }), ); diff --git a/src/website-docs/static/AI_PROMPT.md b/src/website-docs/static/AI_PROMPT.md index 45ac86f..bd6ffa2 100644 --- a/src/website-docs/static/AI_PROMPT.md +++ b/src/website-docs/static/AI_PROMPT.md @@ -275,9 +275,12 @@ Minimal example: - Product: `/products/{id}/{nameFaSlug}` — build `nameFaSlug` from `nameFa` (fallback `title`); resolve page via `GET /tenants/{domain}/products/by-id/{id}` (slug segment is SEO-only; redirect to canonical if it drifts). - Product category: `/products/category/{categoryId}/{nameFaSlug}` — build slug from `nameFa` (fallback `name`); resolve via `GET /tenants/{domain}/categories/by-id/{id}`, then list products with `categoryId`. - User product (customer listing): `/user-products/{slug}` — use the listing’s `slug` from the API; resolve via `GET /tenants/{domain}/user-products/{slug}`. - - Blog: `/blog/{id}/{titleSlug}` — `GET /tenants/{domain}/blogs/by-id/{id}` - - Portfolio: `/portfolios/{id}/{titleFaSlug}` — `GET /tenants/{domain}/portfolios/by-id/{id}` -- When linking from lists/cards, use the same `{id}/{slug}` shape for details (slugify Farsi title: spaces → `-`, keep Persian letters). Category links use `/products/category/{id}/{nameFaSlug}`. User-product cards use `/user-products/{slug}`. + - Blog: `/blog/{slug}` — use the blog’s `slug` from the API; resolve via `GET /tenants/{domain}/blogs/{slug}` (or list + match). Prefer slug routes over id. + - Portfolio: `/portfolio/{slug}` — use the portfolio’s `slug` from the API; resolve via `GET /tenants/{domain}/portfolios/{slug}`. + - Instruction: `/instruction/{slug}` — use the instruction’s `slug` from the API; resolve via `GET /tenants/{domain}/instructions/{slug}`. + - Video: `/videos/{slug}` — use the video’s `slug` from the API. + - Workshop: `/workshops/{slug}` — use the workshop’s `slug` from the API. +- When linking from lists/cards, use the same slug-based detail paths. Category links use `/products/category/{id}/{nameFaSlug}`. User-product cards use `/user-products/{slug}`. - Omit `templates` in `sitemap-config.json` unless this site uses non-default paths. - **Sitemap files (proxied by nginx — do not ship local copies):** - `/sitemap.xml` — sitemap **index** (lists child sitemaps for enabled modules) diff --git a/src/website-docs/static/Meshkee-Website-API.postman_collection.json b/src/website-docs/static/Meshkee-Website-API.postman_collection.json index ae16f9a..79e7b04 100644 --- a/src/website-docs/static/Meshkee-Website-API.postman_collection.json +++ b/src/website-docs/static/Meshkee-Website-API.postman_collection.json @@ -957,7 +957,7 @@ "name": "Get published portfolio by id (website)", "request": { "method": "GET", - "description": "Preferred for /portfolios/{id}/{titleFaSlug} pages. Includes nullable `projectUrl`.", + "description": "Preferred for /portfolio/{slug} pages. Includes nullable `projectUrl`.", "url": "{{baseUrl}}/tenants/{{domain}}/portfolios/by-id/{{portfolioId}}" } }, diff --git a/src/website-docs/static/openapi.json b/src/website-docs/static/openapi.json index a502453..4450e7b 100644 --- a/src/website-docs/static/openapi.json +++ b/src/website-docs/static/openapi.json @@ -1606,7 +1606,7 @@ "tags": [ "Blogs" ], - "summary": "Blog by id (preferred for /blog/{id}/{titleSlug} pages)", + "summary": "Blog by id (legacy; prefer slug routes `/blog/{slug}`)", "parameters": [ { "$ref": "#/components/parameters/domain" @@ -1959,7 +1959,7 @@ "tags": [ "Portfolios" ], - "summary": "Portfolio by id (preferred for /portfolios/{id}/{titleFaSlug} pages)", + "summary": "Portfolio by id (legacy; prefer slug routes `/portfolio/{slug}`)", "parameters": [ { "$ref": "#/components/parameters/domain"