Files
nobat724_front/.claude/prompt/seo-post-deploy-verification.md
hamedandClaude Opus 4.8 21f5f07bc6 chore(prompt): record SEO audit and split remaining work
P1-P11 of the live SEO audit are implemented and verified against a local
production build, so the audit file becomes a reference rather than a
task list: it now records what shipped, the root causes that differed
from the original hypotheses, and the deliberate trade-offs.

Remaining work is split into smaller prompts, ordered by dependency:

- seo-post-deploy-verification: the acceptance criteria were "curl on
  production" but were only run against a local build
- blog-city-scoping-activate: blocked on the backend blog city column
- sitemap-simplify-with-city: drops the 35-sweep workaround once the
  doctors list exposes city

Each names its blocking dependency and carries reference numbers so a
regression is visible.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 08:09:21 +03:30

149 lines
8.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div dir="rtl" markdown="1">
# تأیید زندهٔ فیکس‌های SEO بعد از deploy
## پروژه
`nobat724_front`
## زمینه
فیکس‌های ممیزی SEO (P1–P11 از `seo-critical-fixes-live-audit.md`) پیاده و تست شده‌اند، اما تأیید روی **build محلی production** انجام شد، نه روی دامنه‌های واقعی:
```
NEXT_PUBLIC_API_URL=https://clinic-pro.ir DEV_MODE=FALSE npm run build
NODE_TLS_REJECT_UNAUTHORIZED=0 npx next start -p 3111
# سپس curl با هدر Host برای شبیه‌سازی دامنه‌های شهری
```
معیارهای پذیرش اصلی «curl روی production» بودند. این پرامپت همان‌ها را روی دامنه‌های واقعی اجرا می‌کند.
**دو نکتهٔ حیاتی قبل از تفسیر هر خروجی:**
۱. **`DEV_MODE` باید `FALSE` باشد.** با `DEV_MODE=TRUE` کل سایت `noindex, nofollow, nocache` می‌گیرد و همهٔ تست‌های robots بی‌معنی می‌شوند. این مقدار در `next.config.js` از طریق `env` در **زمان build** درون کد جاسازی می‌شود — تغییر آن در runtime بی‌اثر است و نیاز به build مجدد دارد.
۲. **تغییرات هنوز commit نشده‌اند** (وضعیت کاری). قبل از deploy باید commit و push شوند.
## هدف
اجرای کامل معیارهای پذیرش روی production و ثبت خروجی واقعی؛ و در صورت اختلاف با نتایج محلی، ریشه‌یابی.
## وظایف
### ۱. پیش از deploy
- `git status` را بررسی کن؛ تغییرات SEO را commit کن.
- تأیید کن build با `DEV_MODE=FALSE` انجام می‌شود.
- تأیید کن `NEXT_PUBLIC_API_URL` در محیط production درست است (نه `clinic-pro.ddev.site` که مقدار فعلی `.env` محلی است).
### ۲. اجرای معیارهای پذیرش روی production
بعد از deploy، این‌ها را اجرا کن و **خروجی واقعی هر کدام را در گزارش نقل کن**:
```bash
# P3 — noindex سیستمیک لیست‌ها (باید خالی باشد)
for h in yasuj-nobat.ir tehran-nobat.ir yazd-nobat.ir nobat724.com; do
for p in doctors clinics; do
printf "%s/%s: " "$h" "$p"
curl -s "https://$h/$p" | grep -o '<meta name="robots"[^>]*>' | head -1; echo
done
done
# P3 — فیلتر واقعی باید noindex بماند
curl -s "https://yasuj-nobat.ir/doctors?name=x" | grep -o 'content="noindex[^"]*"'
curl -s "https://yasuj-nobat.ir/doctors?specialty=پوست%20و%20مو&gender=woman" | grep -o 'content="noindex[^"]*"'
# P4 — C1-a self-canonical
for h in yazd-nobat.ir nobat724.com yasuj-nobat.ir; do
for p in "" doctors clinics specialties blogs; do
printf "%s/%s -> " "$h" "$p"
curl -s "https://$h/$p" | grep -o 'rel="canonical" href="[^"]*"'; echo
done
done
# P4 — C1-c استاتیک مشترک → دامنهٔ اصلی
curl -s https://yasuj-nobat.ir/about-us | grep -o 'rel="canonical" href="[^"]*"'
curl -s https://yasuj-nobat.ir/contact-us | grep -o 'rel="canonical" href="[^"]*"'
# P4 — C1-b موجودیت → دامنهٔ شهر خودش
D=beaca548-816f-4613-937d-360db01bd7c8 # شهر: یاسوج
C=9c163d69-0051-4745-a423-c830135b1c01 # شهر: یاسوج
curl -s "https://nobat724.com/doctor/$D" | grep -o 'rel="canonical" href="[^"]*"' # → yasuj-nobat.ir
curl -s "https://yazd-nobat.ir/doctor/$D" | grep -o 'rel="canonical" href="[^"]*"' # → yasuj-nobat.ir
curl -s "https://nobat724.com/clinic/$C" | grep -o 'rel="canonical" href="[^"]*"' # → yasuj-nobat.ir
# P4 — هماهنگی JSON-LD با canonical (تناقض زندهٔ قبلی)
curl -s "https://nobat724.com/clinic/$C" | grep -o '"url":"[^"]*"'
# M3-B — pagination
curl -s "https://yasuj-nobat.ir/doctors?page=2" | grep -o 'rel="canonical" href="[^"]*"' # → ?page=2
curl -s "https://yasuj-nobat.ir/doctors?page=1" | grep -o 'rel="canonical" href="[^"]*"' # → بدون page
# P6 — Soft-404 (هر چهار باید 404 بدهند)
for p in doctor/invalid-xxx clinic/invalid-xxx blog/invalid-xxx specialties/invalid-slug; do
printf "%s -> " "$p"; curl -o /dev/null -s -w "%{http_code}\n" "https://nobat724.com/$p"
done
# و موجودیت معتبر باید 200 بماند
curl -o /dev/null -s -w "valid doctor: %{http_code}\n" "https://nobat724.com/doctor/$D"
# P7 — دقیقاً یک h1 و شهرمحور
for p in doctors clinics specialties; do
printf "%s h1count=" "$p"; curl -s "https://yasuj-nobat.ir/$p" | grep -c "<h1"
curl -s "https://yasuj-nobat.ir/$p" | grep -o "<h1[^>]*>[^<]*"
done
curl -s "https://yasuj-nobat.ir/clinic/$C" | grep -c "<h1" # → 1 (قبلاً 4)
curl -s "https://nobat724.com/doctors" | grep -o "<title>[^<]*" # → بدون «نوبت 724» به‌جای شهر
# P8 — breadcrumb
curl -s https://yasuj-nobat.ir/clinics | grep -c 'aria-label="breadcrumb"'
curl -s https://yasuj-nobat.ir/clinics | grep -c 'BreadcrumbList'
curl -s "https://yasuj-nobat.ir/clinic/$C" | grep -c 'aria-label="breadcrumb"'
# P9 — صفحات فرود تخصص
curl -o /dev/null -s -w "%{http_code}\n" https://tehran-nobat.ir/specialties/dermatology # → 200
curl -o /dev/null -s -w "%{http_code}\n" https://tehran-nobat.ir/specialties/invalid-slug # → 404
curl -s "https://tehran-nobat.ir/doctors?specialty=پوست%20و%20مو" | grep -o 'rel="canonical" href="[^"]*"'
curl -s https://yasuj-nobat.ir/specialties | grep -c "doctors?specialty=" # → 0
# P5 — sitemap
curl -s https://nobat724.com/sitemap.xml | grep -c "<loc>"
curl -s https://yasuj-nobat.ir/sitemap.xml | grep -c "<loc>"
curl -s https://yasuj-nobat.ir/sitemap.xml | grep -c "$D" # → 1
curl -s https://nobat724.com/sitemap.xml | grep -c "$D" # → 0
curl -s https://yasuj-nobat.ir/sitemap.xml | grep -c "9c163d69" # → 0 (کلینیک بی‌محتوا)
# P11 — FAQPage بدون شکستن اسکیماهای موجود
curl -s https://tehran-nobat.ir/specialties/dermatology | grep -c FAQPage
curl -s "https://yasuj-nobat.ir/doctor/$D" | grep -c FAQPage
curl -s "https://yasuj-nobat.ir/doctor/$D" | grep -c Physician # باید سالم بماند
```
### ۳. اعتبارسنجی ساختاریافته
- **Rich Results Test گوگل** روی یک صفحهٔ پزشک و یک صفحهٔ تخصص: تأیید کن `Physician` / `MedicalClinic` / `Review` / `BreadcrumbList` قبلی سالم‌اند و `FAQPage` معتبر است.
- تأیید کن همهٔ بلوک‌های JSON-LD پارس می‌شوند (در تست محلی: ۰ خطای پارس، انواع `Organization, WebSite, Physician, FAQPage, BreadcrumbList`).
### ۴. بازبینی بصری
صفحات تغییریافته را با نسخهٔ قبل مقایسه کن. تغییر تگ‌ها باید بدون اثر بصری باشد:
| صفحه | تغییر | انتظار |
|------|-------|--------|
| `/` | خط برند `h1``p`؛ شعار `h2``h1` | ظاهر یکسان |
| `/doctors` | متن دکمهٔ موقعیت `h1``span` + h1 جدید و پاراگراف مقدمه | دکمه بدون تغییر؛ عنوان و متن جدید بالای لیست |
| `/clinics` | عنوان پویا + پاراگراف مقدمه + breadcrumb با «خانه» | «خانه >» به breadcrumb اضافه شده |
| `/clinic/[id]` | ۳ عنوان بخش `h1``h2`؛ breadcrumb بصری جدید | تایپوگرافی یکسان |
### ۵. Search Console
برای هر دامنهٔ درگیر: URL Inspection روی صفحات کلیدی (`/`، `/doctors`، `/clinics`، یک صفحهٔ پزشک، یک صفحهٔ تخصص) و ثبت sitemap. re-index چند هفته طول می‌کشد.
## نکات مهم
- **رگرسیون احتمالی که باید مشخصاً چک شود:** حذف `loading.js` از سه مسیر `doctor/[slug]`، `clinic/[slug]`، `blog/[slug]`. این کار برای رفع Soft-404 لازم بود (Suspense باعث می‌شد پاسخ با ۲۰۰ استریم شود و `notFound()` دیگر نتواند status را عوض کند). هزینه‌اش نبودِ اسکلت لودینگ هنگام ناوبری کلاینتی است — تجربهٔ کاربری این سه مسیر را عملاً بررسی کن.
- اگر `robots` روی همهٔ صفحات `noindex, nofollow, nocache` بود، تقریباً قطعاً `DEV_MODE=TRUE` در build بوده — کد را دنبال نکن، اول build را بررسی کن.
- ArvanCloud ممکن است روی دامنهٔ اصلی bot-challenge داشته باشد؛ اگر curl خروجی غیرمنتظره داد، قبل از دیباگ کد این را رد کن. (خارج از دامنهٔ اپ — DevOps)
- sitemap دامنهٔ اصلی ~۱۳ ثانیه طول می‌کشد (۳۵ sweep برای تفکیک شهر). اگر timeout خورد، این انتظار است نه باگ — رفعش در `sitemap-simplify-with-city.md`.
</div>