Files
aramesh-backend/frontend/index.html
T
aramesh-site deploy 1d0c1ae53d feat(seo): ایندکس‌پذیری کامل، محتوای سمت سرور برای خزنده‌های AI و رفع باگ ایندکس
سئوی سمت سرور (backend/app/seo_pages.py)
- متا/canonical/hreflang/JSON-LD برای همهٔ صفحات عمومی (شش صفحهٔ استاتیک فارسی که قبلاً پوستهٔ خالی بودند)
- canonical سمت سرور (قبلاً فقط با JS ست می‌شد)، ۴۰۴ واقعی برای مسیرهای ناموجود
- اسکیما: Organization با لوگوی ImageObject، FAQPage، LocalBusiness، BreadcrumbList،
  CreativeWork پروژه با همهٔ تصاویر به‌صورت ImageObject (نام/توضیح + موقعیت پروژه)
- hreflang فقط وقتی ترجمهٔ انگلیسی واقعاً وجود دارد؛ sitemap با URLهای درصد‌گذاری‌شده
- llms.txt و robots.txt تازه‌ساز از دیتابیس؛ سیاست صریح خزنده‌های AI + Allow: /api/site
- _site_content_html: محتوای واقعی سایت به‌صورت HTML خوانا در <noscript> —
  خزنده‌های بدون جاوااسکریپت (GPTBot/OAI-SearchBot/ClaudeBot/PerplexityBot) از ۲۴۰ نویسه
  به ۸٬۵۰۰+ نویسه محتوای معنایی می‌رسند
- Cache-Control: no-store روی HTML و llms.txt (جلوگیری از کش کهنهٔ CDN)، max-age روی sitemap

فرانت‌اند
- api.tsx: خواندن دادهٔ تزریق‌شدهٔ سرور (window.__SITE__) به‌عنوان حالت اولیه — رندر بدون XHR
- App.tsx: اسکلت بارگذاری به‌جای DOM خالی (رفع Soft 404 گوگل)
- index.html: فاوآیکون واقعی برند (قبلاً به vite.svg ناموجود اشاره می‌کرد) + preload فونت

زیرساخت
- Dockerfile: آینهٔ PyPI (Tsinghua/Aliyun) — PyPI برای IP ایران بلاک است
- Caddyfile: هر مسیر پسوند‌دار بدون فایل واقعی ۴۰۴ می‌گیرد (قبلاً HTML اسپا برمی‌گرداند)
- docker-compose.prod.yml: مسیرهای seo برای صفحات استاتیک + llms.txt + کلیدهای IndexNow

داده
- seed_data*.py: حذف دفاتر و معرفی‌های دمو (که در هر استقرار برمی‌گشتند)؛
  تنها دفتر واقعی: اصفهان، ملاصدرا شمالی

دارایی‌ها
- فاوآیکون/آیکون‌های برند از لوگوی رسمی + کلیدهای IndexNow
2026-10-09 23:29:26 +00:00

48 lines
2.9 KiB
HTML

<!doctype html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8" />
<!-- آیکون‌های سایت از لوگوی رسمی برند (قبلاً به vite.svg پیش‌فرض اشاره می‌کرد که وجود نداشت) -->
<link rel="icon" href="/favicon.ico" sizes="any" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />
<link rel="icon" type="image/png" sizes="192x192" href="/icon-192.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- پیش‌بارگذاری فونت‌های اصلی — بدون این، swap فونت با تأخیر می‌آید (LCP) -->
<link rel="preload" href="/fonts/pinar/Pinar-Light.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/fonts/pinar/Pinar-Regular.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/fonts/pinar/Pinar-Bold.woff2" as="font" type="font/woff2" crossorigin />
<title>گروه ساختمانی آرامش</title>
<meta name="description" content="گروه ساختمانی آرامش — طراحی، اجرا و مدیریت پروژه‌های ساختمانی؛ خدمات مهندسی، پیمانکاری و سرمایه‌گذاری ساخت‌وساز." />
<meta property="og:site_name" content="گروه ساختمانی آرامش" />
<meta property="og:type" content="website" />
<meta property="og:locale" content="fa_IR" />
<meta name="twitter:card" content="summary_large_image" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"Organization","name":"گروه ساختمانی آرامش","inLanguage":"fa"}
</script>
</head>
<body>
<div id="root"></div>
<script>
// زبان و جهت سند پیش از اولین رندر، از خود مسیر — /en/... انگلیسی و LTR است
// تا جهت صفحه از نخستین فریم درست باشد (نسخه انگلیسی سمت سرور هم همین را تزریق می‌کند)
if (location.pathname === '/en' || location.pathname.startsWith('/en/')) {
document.documentElement.setAttribute('lang', 'en');
document.documentElement.setAttribute('dir', 'ltr');
}
</script>
<script type="module">
// تحلیل رفتار (Umami) — در زمان بیلد تزریق می‌شود؛ VITE_UMAMI_SRC خالی یعنی خاموش
if (import.meta.env.VITE_UMAMI_SRC) {
const s = document.createElement('script');
s.defer = true;
s.src = import.meta.env.VITE_UMAMI_SRC;
s.setAttribute('data-website-id', import.meta.env.VITE_UMAMI_WEBSITE_ID ?? '');
document.head.appendChild(s);
}
</script>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>