Full 1:1 migration preserving all visuals, animations and behavior: - Nuxt 4 + Vue 3 (script setup, TypeScript strict) with SSG output - Tailwind CSS v4 with @tailwindcss/vite - Ant Design Vue 4 (dark theme, RTL, Persian locale) for design system - Pinia for state management (ui + contact stores) - motion-v (framer-motion port) for all animations - lucide-vue-next for icons - SEO improvements: og:image, canonical fix, real 404 page, JSON-LD services - JS bundle reduced from 302KB to 239KB gzip - Docker/nginx deployment preserved (out/ -> nginx) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
150 lines
8.5 KiB
Markdown
150 lines
8.5 KiB
Markdown
# آریا ایمن — لندینگ (Nuxt)
|
|
|
|
لندینگ شرکت آریا ایمن، مهاجرتیافته از Next.js به **Nuxt 4 (Vue 3)** با خروجی کاملاً استاتیک (SSG)، بهینه برای سئو و سرعت.
|
|
ظاهر و رفتار صفحه دقیقاً همان نسخه Next.js است.
|
|
|
|
| لایه | ابزار |
|
|
|---|---|
|
|
| فریمورک | Nuxt 4 + Vue 3 (`<script setup>`, TypeScript strict) |
|
|
| استایل | Tailwind CSS v4 (`@tailwindcss/vite`) — توکنها در `app/assets/css/main.css` |
|
|
| Design system | Ant Design Vue 4 — تم تیره با پالت پروژه در `app/design/theme.ts`، RTL و لوکال فارسی |
|
|
| State management | Pinia (`app/stores/`) |
|
|
| انیمیشن | motion-v (پورت Motion/framer-motion برای Vue) |
|
|
| آیکن | lucide-vue-next |
|
|
|
|
## نصب و اجرا
|
|
|
|
```bash
|
|
npm install
|
|
npm run dev # http://localhost:3000
|
|
npm run typecheck # بررسی TypeScript
|
|
```
|
|
|
|
## Build (تولید نسخه نهایی استاتیک)
|
|
|
|
```bash
|
|
npm run build # = nuxt generate
|
|
```
|
|
|
|
خروجی در پوشه `out/` ساخته میشود — فایلهای HTML/CSS/JS کاملاً استاتیک که نیازی به سرور Node ندارند
|
|
(`index.html`، `404.html`، `robots.txt`، `sitemap.xml`، `manifest.webmanifest`، `_nuxt/`).
|
|
|
|
پیشنمایش محلی خروجی:
|
|
|
|
```bash
|
|
npm run preview # = npx serve out
|
|
```
|
|
|
|
## ساختار پروژه
|
|
|
|
```
|
|
app/
|
|
app.vue ConfigProvider (antd) + سئوی سراسری + JSON-LD سازمان/وبسایت
|
|
error.vue صفحه ۴۰۴ / خطا (noindex) — در build بهصورت out/404.html پیشرندر میشود
|
|
pages/index.vue صفحه اصلی (AppShell → ۱۰ سکشن + Footer)، canonical
|
|
components/layout/ AppShell, Header, Footer, Preloader, Cursor, BackToTop
|
|
components/sections/ Hero, TapeMarquee, Stats, CountUp, Products, About, Services, Standards, Industries, Testimonials, Contact
|
|
components/ui/ Logo, Reveal, SectionHead
|
|
composables/ useSiteSeo, useJsonLd, useTehranClock, useScrolledPast
|
|
stores/ ui (Preloader/منوی موبایل)، contact (فرم تماس)
|
|
design/theme.ts توکنهای Ant Design (همگام با @theme در main.css)
|
|
assets/css/ main.css (Tailwind + فونتها)، antd-overrides.css
|
|
plugins/antd-style.ts استخراج CSS-in-JS آنتدیزاین در SSR (بدون FOUC)
|
|
shared/ config/site.ts و seo/schema.ts (مشترک بین app و server)
|
|
server/routes/ robots.txt، sitemap.xml، manifest.webmanifest
|
|
public/ فونتها، تصاویر، favicon.svg
|
|
```
|
|
|
|
### نکات Ant Design + Tailwind
|
|
- استایلهای Tailwind v4 داخل cascade layer هستند و CSS-in-JS آنتدیزاین بیرون از layer؛ بنابراین روی کامپوننتهای antd کلاس ظاهری Tailwind نگذارید. ظاهر کامپوننتهای antd از توکنها (`app/design/theme.ts`) و `app/assets/css/antd-overrides.css` میآید.
|
|
- پالت رنگ در دو جا تعریف شده (`@theme` در `main.css` برای Tailwind و `palette` در `theme.ts` برای antd)؛ هنگام تغییر، هر دو را همگام کنید.
|
|
|
|
## دیپلوی پروداکشن با 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 مطابق خروجی استاتیک Nuxt است (`try_files`، کش immutable برای `/_nuxt/`، صفحه `404.html`).
|
|
|
|
## آپلود روی هاست (Static Hosting)
|
|
|
|
1. `npm run build` را اجرا کنید.
|
|
2. کل محتوای پوشه `out/` را (نه خود پوشه، بلکه فایلهای داخلش) در ریشه هاست (public_html، یا مشابه آن در cPanel/Nginx) آپلود کنید.
|
|
3. سایت بدون نیاز به Node.js یا هیچ سرور اختصاصی کار میکند.
|
|
|
|
### نکات مهم هاست استاتیک (cPanel / Nginx / هاست ایرانی)
|
|
|
|
**Apache (.htaccess):**
|
|
```apache
|
|
<IfModule mod_expires.c>
|
|
ExpiresActive On
|
|
ExpiresByType text/css "access plus 1 year"
|
|
ExpiresByType application/javascript "access plus 1 year"
|
|
ExpiresByType font/woff2 "access plus 1 year"
|
|
</IfModule>
|
|
ErrorDocument 404 /404.html
|
|
```
|
|
|
|
**Nginx:**
|
|
```nginx
|
|
location /_nuxt/ { 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 application/json image/svg+xml;
|
|
```
|
|
|
|
ریدایرکت `location = /index.html { return 301 /; }` را نگذارید؛ با `index index.html` حلقهٔ ۳۰۱ روی `/` میسازد.
|
|
|
|
## پیش از دیپلوی واقعی — کارهایی که باید انجام دهید
|
|
|
|
1. **دامنه واقعی**: در [`shared/config/site.ts`](shared/config/site.ts) مقدار `url: "https://ariaiman.ir"` را با دامنه نهایی جایگزین کنید (روی canonical، Open Graph، sitemap، robots و JSON-LD اثر مستقیم دارد).
|
|
2. **لوگوی رسمی**: در همان فایل، `logo` فعلاً به تصویر hero اشاره میکند؛ یک فایل PNG/SVG لوگوی واقعی جایگزین شود.
|
|
3. **تصویر Open Graph**: `ogImage` فعلاً `hero.jpg` است؛ یک تصویر اختصاصی ۱۲۰۰×۶۳۰ در `public/` قرار دهید و مسیر/ابعاد را در `site.ts` بهروز کنید.
|
|
4. **آیکونهای PWA**: manifest فعلاً از `favicon.svg` استفاده میکند؛ برای سازگاری کامل، `icon-192.png`، `icon-512.png` و `apple-touch-icon.png` اضافه شوند.
|
|
5. **شبکههای اجتماعی**: آرایه `socials` در `site.ts` خالی است؛ لینکهای واقعی را اضافه کنید تا در Schema.org (`sameAs`) درج شوند.
|
|
6. **فرم تماس**: اکشن `submit` در [`app/stores/contact.ts`](app/stores/contact.ts) فعلاً فقط ارسال را شبیهسازی میکند (مثل نسخه قبلی)؛ برای فعالسازی واقعی به API/سرویس فرم متصل شود.
|
|
|
|
## چکلیست سئو
|
|
|
|
| مورد | وضعیت | فایل |
|
|
|---|---|---|
|
|
| یک H1 با کلمه کلیدی اصلی | ✅ | `app/components/sections/Hero.vue` |
|
|
| سلسلهمراتب H2/H3 منطقی، بدون پرش سطح | ✅ | `app/components/ui/SectionHead.vue` و همه سکشنها |
|
|
| عنوان، title template و توضیحات | ✅ | `shared/config/site.ts`, `app/composables/useSiteSeo.ts` |
|
|
| Canonical یکسان با sitemap (`https://ariaiman.ir/`) | ✅ | `app/pages/index.vue` |
|
|
| Open Graph و Twitter Card **همراه با تصویر** (og:image/twitter:image) | ✅ | `app/composables/useSiteSeo.ts` |
|
|
| `lang="fa"` و `dir="rtl"` | ✅ | `nuxt.config.ts` |
|
|
| JSON-LD: LocalBusiness (+ ساعات کاری، سال تأسیس، منطقه خدمات)، WebSite، Service ×۴ | ✅ | `shared/seo/schema.ts`, `app/composables/useJsonLd.ts` |
|
|
| `sitemap.xml` / `robots.txt` / `manifest.webmanifest` (با آیکون) | ✅ | `server/routes/` |
|
|
| صفحه ۴۰۴ واقعی پیشرندرشده، `noindex` و بدون canonical | ✅ | `app/error.vue`, `nuxt.config.ts` |
|
|
| preload تصویر hero و فونتها | ✅ | `app/pages/index.vue`, `nuxt.config.ts` |
|
|
| alt توصیفی روی همه تصاویر محتوایی | ✅ | همه سکشنها |
|
|
| تمام متن در HTML بدون نیاز به اجرای JS | ✅ | خروجی `out/index.html` |
|
|
| فونت و تصاویر خودمیزبان (بدون CDN) | ✅ | `public/` |
|