139 lines
8.5 KiB
Markdown
139 lines
8.5 KiB
Markdown
# آریا ایمن — لندینگ (Next.js)
|
|
|
|
لندینگ شرکت آریا ایمن، مهاجرتیافته از Vite/React به Next.js (App Router) با خروجی کاملاً استاتیک، بهینه برای سئو و سرعت.
|
|
|
|
## نصب
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
## اجرا در حالت توسعه
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
سپس آدرس `http://localhost:3000` را باز کنید.
|
|
|
|
## Build (تولید نسخه نهایی استاتیک)
|
|
|
|
```bash
|
|
npm run build
|
|
```
|
|
|
|
خروجی در پوشه `out/` ساخته میشود — مجموعهای از فایلهای HTML/CSS/JS کاملاً استاتیک که نیازی به سرور Node ندارند.
|
|
|
|
برای پیشنمایش محلی خروجی build:
|
|
|
|
```bash
|
|
npx serve out
|
|
```
|
|
|
|
## دیپلوی پروداکشن با Docker
|
|
|
|
بیلد روی ماشین توسعه انجام میشود؛ خروجی `out/` داخل گیت commit میشود و روی سرور فقط image ساخته و اجرا میشود (بدون `npm install` / `npm run build` در سرور).
|
|
|
|
### روی سیستم توسعه (قبل از push)
|
|
|
|
```bash
|
|
npm install
|
|
npm run build
|
|
git add out Dockerfile nginx.conf docker-compose.yml
|
|
git commit -m "build: ..."
|
|
git push
|
|
```
|
|
|
|
### روی سرور پروداکشن
|
|
|
|
```bash
|
|
git pull
|
|
docker compose build --no-cache
|
|
docker compose up -d
|
|
```
|
|
|
|
پیشفرض `docker-compose.yml` پورت **8080** را به کانتینر map میکند؛ در reverse proxy (مثلاً Traefik یا Nginx روی host) به `http://127.0.0.1:8080` اشاره کنید، یا پورت را در compose به `80:80` تغییر دهید.
|
|
|
|
بدون compose:
|
|
|
|
```bash
|
|
docker build -t aria-imen-landing .
|
|
docker run -d --name aria-imen-landing -p 8080:80 --restart unless-stopped aria-imen-landing
|
|
```
|
|
|
|
تنظیمات Nginx داخل image مطابق export استاتیک Next.js است (`try_files`، کش `/_next/static/`، صفحه `404.html`).
|
|
|
|
## آپلود روی هاست (Static Hosting)
|
|
|
|
این پروژه با `output: 'export'` پیکربندی شده، یعنی:
|
|
|
|
1. `npm run build` را اجرا کنید.
|
|
2. کل محتوای پوشه `out/` را (نه خود پوشه، بلکه فایلهای داخلش) در ریشه هاست (public_html، یا مشابه آن در cPanel/Nginx) آپلود کنید.
|
|
3. سایت بدون نیاز به Node.js یا هیچ سرور اختصاصی کار میکند.
|
|
|
|
### نکات مهم هاست استاتیک (cPanel / Nginx / هاست ایرانی)
|
|
|
|
- **ریدایرکتها و هدرها** در `next.config.ts` روی static export اجرا نمیشوند. اگر بعداً نیاز به ریدایرکت ۳۰۱ داشتید (مثلاً از `/index.html`)، باید در سطح هاست تنظیم شود:
|
|
|
|
**Apache (.htaccess):**
|
|
```apache
|
|
Redirect 301 /index.html /
|
|
<IfModule mod_expires.c>
|
|
ExpiresActive On
|
|
ExpiresByType text/css "access plus 1 year"
|
|
ExpiresByType application/javascript "access plus 1 year"
|
|
ExpiresByType image/webp "access plus 1 year"
|
|
ExpiresByType font/woff2 "access plus 1 year"
|
|
</IfModule>
|
|
ErrorDocument 404 /404.html
|
|
```
|
|
|
|
**Nginx:**
|
|
```nginx
|
|
location /_next/static/ { expires 1y; add_header Cache-Control "public, immutable"; }
|
|
location / { try_files $uri $uri.html $uri/index.html =404; }
|
|
error_page 404 /404.html;
|
|
gzip on; gzip_types text/css application/javascript image/svg+xml;
|
|
```
|
|
|
|
ریدایرکت `location = /index.html { return 301 /; }` را نگذارید؛ با `index index.html` حلقهٔ ۳۰۱ روی `/` میسازد.
|
|
|
|
## پیش از دیپلوی واقعی — کارهایی که باید انجام دهید
|
|
|
|
این پروژه فعلاً با دادههای تستی/placeholder برای موارد زیر ساخته شده و **باید قبل از انتشار واقعی بررسی و اصلاح شوند**:
|
|
|
|
1. **دامنه واقعی**: در فایل [`src/config/site.ts`](src/config/site.ts) مقدار `url: "https://ariaiman.ir"` باید با دامنه نهایی واقعی جایگزین شود (این مقدار روی canonical، Open Graph، sitemap و JSON-LD اثر مستقیم دارد).
|
|
2. **لوگوی رسمی**: در همان فایل، `logo` فعلاً به تصویر hero اشاره میکند؛ یک فایل PNG/SVG لوگوی واقعی جایگزین شود.
|
|
3. **آیکونهای PWA**: `src/app/manifest.ts` فعلاً بدون آیکون است. دو فایل `icon-192.png` و `icon-512.png` در `public/` قرار داده و در manifest معرفی شوند.
|
|
4. **تصویر Open Graph**: یک فایل `opengraph-image.png` با ابعاد ۱۲۰۰×۶۳۰ در `src/app/` قرار دهید (Next.js آن را بهصورت خودکار شناسایی میکند).
|
|
5. **شبکههای اجتماعی**: در `src/config/site.ts`، آرایه `socials` خالی است. لینکهای واقعی اینستاگرام/تلگرام/لینکدین را اضافه کنید تا در Schema.org (`sameAs`) درج شود.
|
|
6. **فرم تماس**: فرم بخش «تماس» فعلاً فقط یک شبیهسازی محلی است (بدون ارسال واقعی به سرور یا سرویس ایمیل) — دقیقاً همان رفتاری که در نسخه قبلی هم وجود داشت. برای فعالسازی واقعی باید به یک سرویس فرم (مثل فرماسپری، ایمیل، یا API اختصاصی) متصل شود.
|
|
7. **npm audit**: یک آسیبپذیری «high» در نسخه postcss داخلی Next.js 15.5 گزارش میشود (`npm audit`). این مربوط به مرحله build/dev است، نه کد سمت کاربر نهایی. رفع کامل آن نیازمند ارتقا به Next.js 16 (breaking change) است — در صورت تمایل بهروزرسانی جداگانه انجام شود.
|
|
|
|
## چکلیست سئوی پیادهسازیشده
|
|
|
|
| مورد | وضعیت | فایل |
|
|
|---|---|---|
|
|
| یک H1 با کلمه کلیدی اصلی | ✅ | `src/components/sections/Hero.tsx` |
|
|
| سلسلهمراتب H2/H3 منطقی، بدون پرش سطح | ✅ | `src/components/ui/SectionHead.tsx` و همه سکشنها |
|
|
| عنوان و توضیحات با طول مناسب | ✅ | `src/config/site.ts` |
|
|
| Canonical، metadataBase، Open Graph، Twitter Card | ✅ | `src/app/layout.tsx` |
|
|
| `lang="fa"` و `dir="rtl"` | ✅ | `src/app/layout.tsx` |
|
|
| JSON-LD (LocalBusiness + WebSite) | ✅ | `src/lib/seo/schema.ts`, `src/components/seo/JsonLd.tsx` |
|
|
| `sitemap.xml` | ✅ | `src/app/sitemap.ts` |
|
|
| `robots.txt` | ✅ | `src/app/robots.ts` |
|
|
| `manifest.webmanifest` | ✅ (بدون آیکون — نیاز به تکمیل) | `src/app/manifest.ts` |
|
|
| صفحه ۴۰۴ واقعی (بدون ریدایرکت به خانه) | ✅ | `src/app/not-found.tsx` |
|
|
| alt توصیفی روی همه تصاویر محتوایی | ✅ | همه کامپوننتهای سکشن |
|
|
| تمام متن در HTML بدون نیاز به اجرای JS | ✅ | تأیید شده با بررسی خروجی build |
|
|
| لینکهای داخلی سالم (`#anchor`) | ✅ | بدون تغییر نسبت به نسخه اصلی |
|
|
| فونت خودمیزبان (self-hosted) بدون CDN خارجی | ✅ | `public/fonts/`, `src/app/layout.tsx` |
|
|
| تصاویر بدون وابستگی به CDN خارجی | ✅ | تصاویر Industries از pexels دانلود و داخلی شدند |
|
|
|
|
## معماری فنی مهاجرت
|
|
|
|
- **Server Components برای محتوا**: تمام بخشهای بدون تعامل (Hero, About, Standards, TapeMarquee, Footer) بهصورت Server Component هستند و در HTML build نهایی کامل قابل مشاهدهاند.
|
|
- **Client Components فقط برای تعامل**: منو موبایل، فرم تماس، اسلایدر نظرات، پنلهای تعاملی محصولات/خدمات، شمارنده آمار، کرسر سفارشی و Preloader، هرکدام جداگانه `'use client'` هستند تا حجم JS اولیه صفحه کمینه بماند.
|
|
- **بدون بکاند**: هیچ `app/api`، دیتابیس یا server action اضافه نشده؛ طبق درخواست پروژه.
|
|
- **انیمیشن ورودی Hero با CSS خالص**: برخلاف نسخه اصلی (که H1 تا پایان انیمیشن Preloader با `opacity:0` مخفی بود)، اکنون محتوای Hero همیشه در HTML اولیه قابل مشاهده است و فقط با CSS keyframes (بدون وابستگی به اجرای JS) وارد صفحه میشود — این تغییر برای رفع مشکل LCP/SEO با تأیید شما انجام شد.
|