fix: update site_name for city record to remove redundancy
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
# بهینهسازی SEO تکتک شهرها در city.json (سطح حرفهای)
|
||||
|
||||
## پروژه
|
||||
|
||||
`nobat724_front` (سایت عمومی نوبتدهی، چند-دامنهای — هر شهر یک دامنه)
|
||||
|
||||
## نقش
|
||||
|
||||
تو یک **متخصص حرفهای SEO فارسی/محلی (Local SEO)** هستی. خروجی باید در سطح یک آژانس سئوی حرفهای باشد: یکتا، کلیدواژهمحور بدون stuffing، با رعایت طول بهینه، CTR-optimized.
|
||||
|
||||
## زمینه
|
||||
|
||||
`data/city.json` منبع واحد SEO هر دامنهی شهری است. `app/layout.js` → `generateMetadata()` مقادیر این فایل را مستقیم به تگهای متا تبدیل میکند. یعنی کیفیت SEO هر شهر = کیفیت فیلدهای متنی همان رکورد در این فایل.
|
||||
|
||||
۳۴ رکورد وجود دارد (۳۳ شهر + رکورد اصلی `id:600` دامنه `nobat724.com`). محتوای فعلی با یک **قالب یکسان کلون** شده — جملات تقریباً تکراری بین شهرها (خطر duplicate content) و ضعیف.
|
||||
|
||||
## مشکل / هدف
|
||||
|
||||
دو مشکل بحرانی:
|
||||
|
||||
1. **فیلد `title` در هیچکدام از ۳۴ رکورد وجود ندارد.** `layout.js` اول `matchedCity?.title` را میخواند؛ چون نیست، همه شهرها به یک قالب یکسان fallback میکنند → تایتلهای تقریباً تکراری. **باید به هر رکورد فیلد `title` یکتا و بهینه اضافه شود.**
|
||||
2. `description` / `keywords` / `slogan` / `footer_description` قالبی و تکراریاند → باید هرکدام برای هر شهر **بازنویسی یکتا و بهینه** شوند.
|
||||
|
||||
هدف: هر ۳۴ رکورد، ۵ فیلد متنی SEO در بالاترین کیفیت، **بدون تکرار جمله بین شهرها**.
|
||||
|
||||
## فایلهای مرتبط
|
||||
|
||||
| فایل | نقش |
|
||||
|------|-----|
|
||||
| `data/city.json` | تنها فایلی که ویرایش میشود — رکورد هر شهر |
|
||||
| `app/layout.js` | مصرفکننده فیلدها (فقط برای درک، ویرایش نشود مگر task ۶) |
|
||||
|
||||
## وضعیت فعلی
|
||||
|
||||
مصرف فیلدها در `app/layout.js`:
|
||||
|
||||
```js
|
||||
const title =
|
||||
matchedCity?.title || // ← این فیلد وجود ندارد!
|
||||
(matchedCity?.name
|
||||
? `نوبتدهی آنلاین پزشکان ${matchedCity.name} | نوبت 724`
|
||||
: "نوبت 724 | سیستم نوبتدهی آنلاین پزشکی");
|
||||
const description = matchedCity?.description || "...";
|
||||
// keywords: matchedCity.keywords
|
||||
// openGraph.siteName: matchedCity.site_name
|
||||
```
|
||||
|
||||
نمونه رکورد فعلی (تکراری/قالبی):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 113, "name": "اهواز", "site_name": "اهواز نوبت",
|
||||
"province_name": "خوزستان",
|
||||
"description": "اهواز نوبت، سامانه نوبتدهی آنلاین در اهواز و استان خوزستان. امکان جستجو و رزرو نوبت در مراکز درمانی. اهواز نوبت بهترین راه دسترسی به پزشکان متخصص است.",
|
||||
"slogan": "سامانه هوشمند نوبتدهی پزشکان اهواز",
|
||||
"keywords": "رزرو نوبت اهواز, پزشکان خوزستان, کلینیکهای اهواز, بیمارستانهای اهواز, متخصصین پزشکی اهواز",
|
||||
"footer_description": "اهواز نوبت، سامانه جامع نوبتدهی پزشکی در استان خوزستان. رزرو نوبت از پزشکان و مراکز درمانی اهواز بدون نیاز به مراجعه حضوری."
|
||||
}
|
||||
```
|
||||
|
||||
## فهرست ۳۴ رکورد (همه باید پردازش شوند)
|
||||
|
||||
| id | شهر | استان | دامنه |
|
||||
|----|-----|-------|-------|
|
||||
| 129 | اراک | مرکزی | arak-nobat.ir |
|
||||
| 103 | اردبیل | اردبیل | ardabil-nobat.ir |
|
||||
| 102 | ارومیه | آذربایجان غربی | urmia-nobat.ir |
|
||||
| 104 | اصفهان | اصفهان | esf-nobat.ir |
|
||||
| 113 | اهواز | خوزستان | ahvaz-nobat.ir |
|
||||
| 106 | ایلام | ایلام | ilam-nobat.ir |
|
||||
| 112 | بجنورد | خراسان شمالی | bojnord-nobat.ir |
|
||||
| 130 | بندرعباس | هرمزگان | bandar-nobat.ir |
|
||||
| 107 | بوشهر | بوشهر | bushehr-nobat.ir |
|
||||
| 110 | بیرجند | خراسان جنوبی | birjand-nobat.ir |
|
||||
| 101 | تبریز | آذربایجان شرقی | tabriz-nobat.ir |
|
||||
| 108 | تهران | تهران | tehran-nobat.ir |
|
||||
| 127 | خرمآباد | لرستان | lorestan-nobat.ir |
|
||||
| 126 | رشت | گیلان | rasht-nobat.ir |
|
||||
| 116 | زاهدان | سیستان و بلوچستان | zahedan-nobat.ir |
|
||||
| 114 | زنجان | زنجان | zanjan-nobat.ir |
|
||||
| 128 | ساری | مازندران | sari-nobat.ir |
|
||||
| 115 | سمنان | سمنان | semnan-nobat.ir |
|
||||
| 120 | سنندج | کردستان | sanandaj-nobat.ir |
|
||||
| 109 | شهرکرد | چهارمحال و بختیاری | shkord-nobat.ir |
|
||||
| 117 | شیراز | فارس | shiraz-nobat.ir |
|
||||
| 118 | قزوین | قزوین | qazvin-nobat.ir |
|
||||
| 119 | قم | قم | qom-nobat.ir |
|
||||
| 105 | کرج | البرز | karaj-nobat.ir |
|
||||
| 121 | کرمان | کرمان | kerman-nobat.ir |
|
||||
| 122 | کرمانشاه | کرمانشاه | kermanshah-nobat.ir |
|
||||
| 125 | گرگان | گلستان | golestan-nobat.ir |
|
||||
| 111 | مشهد | خراسان رضوی | mashhad-nobat.ir |
|
||||
| 131 | همدان | همدان | hamadan-nobat.ir |
|
||||
| 123 | یاسوج | کهگیلویه و بویراحمد | yasuj-nobat.ir |
|
||||
| 132 | یزد | یزد | yazd-nobat.ir |
|
||||
| 133 | دهدشت | کهگیلویه و بویراحمد | dehdasht-nobat.ir |
|
||||
| 134 | بهبهان | خوزستان | behbahan-nobat.ir |
|
||||
| 600 | نوبت 724 (برند اصلی) | — | nobat724.com |
|
||||
|
||||
## وظایف
|
||||
|
||||
### ۱. افزودن فیلد `title` یکتا به هر رکورد (مهمترین)
|
||||
|
||||
بعد از `site_name` در هر رکورد، فیلد `title` اضافه کن.
|
||||
|
||||
**قواعد `title`:**
|
||||
- طول: **۵۰–۶۰ کاراکتر** (حداکثر ~۶۰ برای عدم truncate در گوگل).
|
||||
- کلیدواژه اصلی **اول** جمله: «نوبتدهی آنلاین پزشکان {شهر}» یا واریانت.
|
||||
- برند در انتها با جداکننده `|`: `... | نوبت ۷۲۴`.
|
||||
- **یکتا بین شهرها** — فقط جایگذاری اسم شهر کافی نیست؛ ساختار/کلمات را بین گروهها متنوع کن (مثلاً برخی «رزرو نوبت پزشک {شهر}»، برخی «نوبت اینترنتی دکتر {شهر}»).
|
||||
- بدون stuffing، خوانا، طبیعی.
|
||||
|
||||
مثال طلایی:
|
||||
|
||||
```json
|
||||
"title": "نوبتدهی آنلاین پزشکان اهواز | رزرو نوبت دکتر | نوبت ۷۲۴"
|
||||
```
|
||||
|
||||
### ۲. بازنویسی `description` (متا دیسکریپشن)
|
||||
|
||||
**قواعد:**
|
||||
- طول: **۱۵۰–۱۶۰ کاراکتر** (نه کمتر از ۱۲۰، نه بیشتر از ۱۶۵).
|
||||
- کلیدواژه اصلی front-load شده در ابتدای جمله.
|
||||
- شامل: نام شهر + استان + اشاره به تخصصها/مراکز درمانی + **CTA** («همین حالا رزرو کنید» / «آنلاین نوبت بگیرید»).
|
||||
- **یکتا** — هیچ دو شهری جملهی یکسان نداشته باشند. زاویهی متن را متنوع کن (یکی روی سرعت، یکی روی تنوع پزشکان، یکی روی ۲۴ساعتهبودن).
|
||||
- بدون تکرار بیش از حد اسم شهر (حداکثر ۲ بار).
|
||||
|
||||
مثال طلایی:
|
||||
|
||||
```json
|
||||
"description": "با نوبت اهواز، آنلاین از پزشکان متخصص و عمومی خوزستان نوبت بگیرید. جستجوی دکتر بر اساس تخصص، بیمه و منطقه در اهواز؛ رزرو نوبت ۲۴ساعته بدون مراجعه حضوری. همین حالا نوبت خود را ثبت کنید."
|
||||
```
|
||||
|
||||
### ۳. بهینهسازی `keywords`
|
||||
|
||||
- ۶–۹ عبارت هدفمند، جدا با `, `.
|
||||
- ترکیب: `نوبت {شهر}`، `دکتر {شهر}`، `پزشک متخصص {شهر}`، `رزرو نوبت اینترنتی {شهر}`، `کلینیک {شهر}`، `بهترین پزشک {استان}`، عبارات intent-محور («نوبت آنلاین دکتر»).
|
||||
- بدون تکرار عینبهعین عبارات بین شهرها (اسم شهر متفاوت کافی نیست برای long-tailها).
|
||||
|
||||
### ۴. بازنویسی `slogan` یکتا
|
||||
|
||||
- کوتاه (۴–۸ کلمه)، جذاب، دارای کلیدواژه شهر، متمایز بین شهرها.
|
||||
- نمونه: `"در اهواز، نوبت دکتر فقط با چند کلیک"`.
|
||||
|
||||
### ۵. بازنویسی `footer_description` یکتا
|
||||
|
||||
- ۱–۲ جمله، محلی، دارای شهر+استان، متفاوت از `description` (نه کپی).
|
||||
- برای فوتر — لحن معرفی برند محلی.
|
||||
|
||||
### ۶. (اختیاری، اگر کاربر خواست) بهبود فنی در `layout.js`
|
||||
|
||||
اگر زمان بود، اینها را هم پیشنهاد بده (اما JSON اولویت است):
|
||||
- `openGraph.images` و `twitter.images` الان هاردکد `nobat724.com/assets/images/logo.png` است — میتوان per-city کرد.
|
||||
- JSON-LD فعلی فقط `Organization` + `WebSite` با `siteUrl` ثابت `nobat724.com` است؛ افزودن `MedicalBusiness`/`LocalBusiness` per-city با دامنه و نام شهر، سیگنال Local SEO قوی میدهد.
|
||||
|
||||
### ۷. رکورد برند اصلی (`id: 600`)
|
||||
|
||||
این رکورد شهر نیست (دامنهی مادر `nobat724.com`, `province_name: null`). برایش `title`/`description`/`keywords` سراسری و برندمحور بنویس (نه شهرمحور): تمرکز روی «سامانه سراسری نوبتدهی آنلاین پزشکی ایران».
|
||||
|
||||
## نکات مهم
|
||||
|
||||
- **فقط `data/city.json` ویرایش شود** (بهجز task ۶ اختیاری). ساختار JSON، ترتیب رکوردها، و فیلدهای `id`, `uuid`, `status`, `weight`, `province_id`, `province_name`, `representation_id`, `contact_phone`, `email`, `domain`, `social_media`, `logo_url` **دستنخورده** بمانند.
|
||||
- فیلد `title` جدید را بعد از `site_name` قرار بده (سازگاری با ترتیب منطقی).
|
||||
- **اعداد در `title` فارسی** باشند (`۷۲۴` نه `724`) برای هماهنگی با UI فارسی — مگر اینکه در برند لاتین لازم باشد.
|
||||
- **یکتایی سراسری**: بعد از اتمام، هیچ دو رکوردی نباید `title` یا `description` با ساختار جملهی یکسان (فقط تغییر اسم شهر) داشته باشند. حداقل ۳–۴ الگوی متنی متفاوت بین ۳۴ رکورد بچرخان.
|
||||
- **صحت جغرافیایی**: `province_name` هر رکورد را بهعنوان واقعیت بپذیر (قبلاً بهبهان=خوزستان، دهدشت=کهگیلویه اصلاح شده). محتوای استان را با همین مقدار بنویس.
|
||||
- بعد از ویرایش، **اعتبار JSON را تأیید کن**:
|
||||
```bash
|
||||
python3 -c "import json; d=json.load(open('data/city.json')); print('valid', len(d)); \
|
||||
t=[c.get('title') for c in d]; assert all(t), 'missing title'; \
|
||||
print('unique titles:', len(set(t))==len(t)); \
|
||||
print('unique descriptions:', len(set(c['description'] for c in d))==len(d))"
|
||||
```
|
||||
باید: valid، همه title دارند، titleها و descriptionها یکتا.
|
||||
- زبان فارسی رسمی و روان، RTL، بدون غلط املایی. اسامی شهر/استان دقیقاً مطابق فایل.
|
||||
- این تغییر داده است، نه endpoint API → نیازی به بهروزرسانی `docs/api/` نیست.
|
||||
- بعد از ویرایش، یک build سریع بزن که فایل درست پارس میشود: `npm run build` (یا حداقل import شدن JSON).
|
||||
```
|
||||
Reference in New Issue
Block a user