Expand website AI prompt with on-page SEO requirements for every public page.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
2e8d7c1cfd
commit
24ce75c2e6
@@ -85,35 +85,69 @@ Use `slot.key` in the placeholder. Match `pageKey` to the website page. For a si
|
|||||||
|
|
||||||
`kind` is `single` (one image) or `list` (duplicatable). For a fixed row, set `itemCount` (e.g. `2`). Leave `itemCount` null for an unbounded slider. `aspectRatio` must look like `16:9`. Do not invent CMS/upload APIs.
|
`kind` is `single` (one image) or `list` (duplicatable). For a fixed row, set `itemCount` (e.g. `2`). Leave `itemCount` null for an unbounded slider. `aspectRatio` must look like `16:9`. Do not invent CMS/upload APIs.
|
||||||
|
|
||||||
### Sitemap (SEO)
|
### Sitemap + robots.txt (SEO)
|
||||||
|
|
||||||
Meshkee generates `https://<WEBSITE_DOMAIN>/sitemap.xml` on the API from published CMS content plus a manifest your site publishes. Nginx on the storefront proxies `/sitemap.xml` and `/robots.txt` to the API — do not hardcode a static sitemap file in the repo unless you know nginx is not proxying yet.
|
Meshkee generates both files on the API. Nginx on the storefront proxies them — **do not** ship `public/sitemap.xml` or `public/robots.txt` (and do not add Next.js `app/sitemap.ts` / `app/robots.ts` that override these paths).
|
||||||
|
|
||||||
**Publish route manifest** so the business dashboard can sync static pages and URL templates:
|
| URL on this site | Served by |
|
||||||
|
|------------------|-----------|
|
||||||
|
| `https://<WEBSITE_DOMAIN>/sitemap.xml` | Meshkee API (proxied) |
|
||||||
|
| `https://<WEBSITE_DOMAIN>/robots.txt` | Meshkee API (proxied) — includes `Sitemap: https://<WEBSITE_DOMAIN>/sitemap.xml` |
|
||||||
|
|
||||||
|
**What the website must publish** (for static pages only):
|
||||||
|
|
||||||
`GET https://<WEBSITE_DOMAIN>/meshkee/sitemap-config.json`
|
`GET https://<WEBSITE_DOMAIN>/meshkee/sitemap-config.json`
|
||||||
|
|
||||||
|
Prefer generating this **at build time from app routes** (scan public static pages). Do not hand-maintain long lists in prompts.
|
||||||
|
|
||||||
|
Minimal example:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"baseUrl": "https://sanihome.ir",
|
"baseUrl": "https://<WEBSITE_DOMAIN>",
|
||||||
"staticPages": [
|
"staticPages": [
|
||||||
{ "path": "/", "changefreq": "daily", "priority": 1.0 },
|
{ "path": "/", "changefreq": "daily", "priority": 1.0 },
|
||||||
{ "path": "/about", "priority": 0.6 },
|
{ "path": "/about", "priority": 0.6 },
|
||||||
{ "path": "/contact", "priority": 0.5 },
|
{ "path": "/contact", "priority": 0.5 }
|
||||||
{ "path": "/blog", "priority": 0.7 }
|
]
|
||||||
],
|
|
||||||
"templates": {
|
|
||||||
"product": "/products/{slug}",
|
|
||||||
"blog": "/blog/{slug}",
|
|
||||||
"portfolio": "/portfolios/{slug}"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- `path` must start with `/`. Do not include checkout, login, or customer-dashboard URLs.
|
- Include public static routes automatically; exclude login, checkout, cart, account, and admin paths.
|
||||||
- Each `templates` value must include `{slug}` and match how this site routes detail pages.
|
- Omit `templates` unless this site uses non-default detail URLs (Meshkee defaults: `/products/{slug}`, `/blog/{slug}`, `/portfolios/{slug}`).
|
||||||
- After deploy, the business owner syncs from **Website → Settings** in the dashboard.
|
- After deploy, business owner: **Website → Settings → Sync sitemap config** (imports the manifest once; does not rebuild XML by itself).
|
||||||
- Dynamic URLs (products, blogs, portfolios) come from the CMS; only paths/templates are declared here.
|
- Dynamic URLs (products, blogs, portfolios, …) come from the CMS automatically. Hitting `/sitemap.xml` serves a Redis-cached XML that regenerates after CMS publish/update/delete (or when cache expires).
|
||||||
|
|
||||||
|
### On-page SEO (every public page)
|
||||||
|
|
||||||
|
These are **required on every crawlable page** (home, listing, product/blog/portfolio detail, about, contact, etc.). Auth/checkout may be noindex.
|
||||||
|
|
||||||
|
**Document title (`<title>`)**
|
||||||
|
- Unique per page; include the primary topic + business name when space allows.
|
||||||
|
- Prefer CMS fields when present (`title`, `nameFa`/`nameEn`, product title, blog title). Never leave the Next.js default title.
|
||||||
|
|
||||||
|
**Meta description**
|
||||||
|
- Unique `<meta name="description" content="…">` on every public page (roughly 120–160 characters).
|
||||||
|
- Prefer CMS summary/excerpt/description when available; otherwise write a short page-specific sentence. Never empty, never identical across all pages.
|
||||||
|
|
||||||
|
**Headings**
|
||||||
|
- Exactly **one** `<h1>` per page — the main topic (product name, blog title, page title). Do not hide it with CSS-only “fake” headings.
|
||||||
|
- Use `<h2>` (then `<h3>`…) for real section structure under the H1. Do not skip levels for styling (don’t use H4 as a visual label without H2/H3).
|
||||||
|
- Do not use headings for nav logos, button labels, or decorative text.
|
||||||
|
|
||||||
|
**Images**
|
||||||
|
- Every meaningful `<img>` / Next.js `Image` must have a non-empty **`alt`** describing the image (product name, slide title, banner purpose).
|
||||||
|
- Prefer CMS title / `titleFa` / `titleEn` / media alt when available; for decorative icons use `alt=""` only when the image adds no information.
|
||||||
|
- Never leave missing `alt` on content images (hero, product gallery, blog cover, static-image slots, sliders).
|
||||||
|
|
||||||
|
**Open Graph (recommended)**
|
||||||
|
- Set `og:title`, `og:description`, and `og:image` on important pages (home + detail pages) from CMS media when available.
|
||||||
|
|
||||||
|
**Checklist before shipping a page**
|
||||||
|
1. Unique `<title>` and meta description
|
||||||
|
2. One clear H1 + sensible H2 sections
|
||||||
|
3. All content images have alt text
|
||||||
|
4. Public URL is included via CMS sitemap and/or `sitemap-config.json` static pages
|
||||||
|
|
||||||
If OpenAPI and this brief conflict, **OpenAPI wins**.
|
If OpenAPI and this brief conflict, **OpenAPI wins**.
|
||||||
|
|
||||||
|
|||||||
@@ -85,35 +85,69 @@ Use `slot.key` in the placeholder. Match `pageKey` to the website page. For a si
|
|||||||
|
|
||||||
`kind` is `single` (one image) or `list` (duplicatable). For a fixed row, set `itemCount` (e.g. `2`). Leave `itemCount` null for an unbounded slider. `aspectRatio` must look like `16:9`. Do not invent CMS/upload APIs.
|
`kind` is `single` (one image) or `list` (duplicatable). For a fixed row, set `itemCount` (e.g. `2`). Leave `itemCount` null for an unbounded slider. `aspectRatio` must look like `16:9`. Do not invent CMS/upload APIs.
|
||||||
|
|
||||||
### Sitemap (SEO)
|
### Sitemap + robots.txt (SEO)
|
||||||
|
|
||||||
Meshkee generates `https://<WEBSITE_DOMAIN>/sitemap.xml` on the API from published CMS content plus a manifest your site publishes. Nginx on the storefront proxies `/sitemap.xml` and `/robots.txt` to the API — do not hardcode a static sitemap file in the repo unless you know nginx is not proxying yet.
|
Meshkee generates both files on the API. Nginx on the storefront proxies them — **do not** ship `public/sitemap.xml` or `public/robots.txt` (and do not add Next.js `app/sitemap.ts` / `app/robots.ts` that override these paths).
|
||||||
|
|
||||||
**Publish route manifest** so the business dashboard can sync static pages and URL templates:
|
| URL on this site | Served by |
|
||||||
|
|------------------|-----------|
|
||||||
|
| `https://<WEBSITE_DOMAIN>/sitemap.xml` | Meshkee API (proxied) |
|
||||||
|
| `https://<WEBSITE_DOMAIN>/robots.txt` | Meshkee API (proxied) — includes `Sitemap: https://<WEBSITE_DOMAIN>/sitemap.xml` |
|
||||||
|
|
||||||
|
**What the website must publish** (for static pages only):
|
||||||
|
|
||||||
`GET https://<WEBSITE_DOMAIN>/meshkee/sitemap-config.json`
|
`GET https://<WEBSITE_DOMAIN>/meshkee/sitemap-config.json`
|
||||||
|
|
||||||
|
Prefer generating this **at build time from app routes** (scan public static pages). Do not hand-maintain long lists in prompts.
|
||||||
|
|
||||||
|
Minimal example:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"baseUrl": "https://sanihome.ir",
|
"baseUrl": "https://<WEBSITE_DOMAIN>",
|
||||||
"staticPages": [
|
"staticPages": [
|
||||||
{ "path": "/", "changefreq": "daily", "priority": 1.0 },
|
{ "path": "/", "changefreq": "daily", "priority": 1.0 },
|
||||||
{ "path": "/about", "priority": 0.6 },
|
{ "path": "/about", "priority": 0.6 },
|
||||||
{ "path": "/contact", "priority": 0.5 },
|
{ "path": "/contact", "priority": 0.5 }
|
||||||
{ "path": "/blog", "priority": 0.7 }
|
]
|
||||||
],
|
|
||||||
"templates": {
|
|
||||||
"product": "/products/{slug}",
|
|
||||||
"blog": "/blog/{slug}",
|
|
||||||
"portfolio": "/portfolios/{slug}"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- `path` must start with `/`. Do not include checkout, login, or customer-dashboard URLs.
|
- Include public static routes automatically; exclude login, checkout, cart, account, and admin paths.
|
||||||
- Each `templates` value must include `{slug}` and match how this site routes detail pages.
|
- Omit `templates` unless this site uses non-default detail URLs (Meshkee defaults: `/products/{slug}`, `/blog/{slug}`, `/portfolios/{slug}`).
|
||||||
- After deploy, the business owner syncs from **Website → Settings** in the dashboard.
|
- After deploy, business owner: **Website → Settings → Sync sitemap config** (imports the manifest once; does not rebuild XML by itself).
|
||||||
- Dynamic URLs (products, blogs, portfolios) come from the CMS; only paths/templates are declared here.
|
- Dynamic URLs (products, blogs, portfolios, …) come from the CMS automatically. Hitting `/sitemap.xml` serves a Redis-cached XML that regenerates after CMS publish/update/delete (or when cache expires).
|
||||||
|
|
||||||
|
### On-page SEO (every public page)
|
||||||
|
|
||||||
|
These are **required on every crawlable page** (home, listing, product/blog/portfolio detail, about, contact, etc.). Auth/checkout may be noindex.
|
||||||
|
|
||||||
|
**Document title (`<title>`)**
|
||||||
|
- Unique per page; include the primary topic + business name when space allows.
|
||||||
|
- Prefer CMS fields when present (`title`, `nameFa`/`nameEn`, product title, blog title). Never leave the Next.js default title.
|
||||||
|
|
||||||
|
**Meta description**
|
||||||
|
- Unique `<meta name="description" content="…">` on every public page (roughly 120–160 characters).
|
||||||
|
- Prefer CMS summary/excerpt/description when available; otherwise write a short page-specific sentence. Never empty, never identical across all pages.
|
||||||
|
|
||||||
|
**Headings**
|
||||||
|
- Exactly **one** `<h1>` per page — the main topic (product name, blog title, page title). Do not hide it with CSS-only “fake” headings.
|
||||||
|
- Use `<h2>` (then `<h3>`…) for real section structure under the H1. Do not skip levels for styling (don’t use H4 as a visual label without H2/H3).
|
||||||
|
- Do not use headings for nav logos, button labels, or decorative text.
|
||||||
|
|
||||||
|
**Images**
|
||||||
|
- Every meaningful `<img>` / Next.js `Image` must have a non-empty **`alt`** describing the image (product name, slide title, banner purpose).
|
||||||
|
- Prefer CMS title / `titleFa` / `titleEn` / media alt when available; for decorative icons use `alt=""` only when the image adds no information.
|
||||||
|
- Never leave missing `alt` on content images (hero, product gallery, blog cover, static-image slots, sliders).
|
||||||
|
|
||||||
|
**Open Graph (recommended)**
|
||||||
|
- Set `og:title`, `og:description`, and `og:image` on important pages (home + detail pages) from CMS media when available.
|
||||||
|
|
||||||
|
**Checklist before shipping a page**
|
||||||
|
1. Unique `<title>` and meta description
|
||||||
|
2. One clear H1 + sensible H2 sections
|
||||||
|
3. All content images have alt text
|
||||||
|
4. Public URL is included via CMS sitemap and/or `sitemap-config.json` static pages
|
||||||
|
|
||||||
If OpenAPI and this brief conflict, **OpenAPI wins**.
|
If OpenAPI and this brief conflict, **OpenAPI wins**.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user