Co-authored-by: Cursor <cursoragent@cursor.com>
آریا ایمن — لندینگ (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 |
نصب و اجرا
npm install
npm run dev # http://localhost:3000
npm run typecheck # بررسی TypeScript
Build (تولید نسخه نهایی استاتیک)
npm run build # = nuxt generate
خروجی در پوشه out/ ساخته میشود — فایلهای HTML/CSS/JS کاملاً استاتیک که نیازی به سرور Node ندارند
(index.html، 404.html، robots.txt، sitemap.xml، manifest.webmanifest، _nuxt/).
پیشنمایش محلی خروجی:
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)
npm install
npm run build
git add out Dockerfile nginx.conf docker-compose.yml
git commit -m "build: ..."
git push
روی سرور پروداکشن
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:
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)
npm run buildرا اجرا کنید.- کل محتوای پوشه
out/را (نه خود پوشه، بلکه فایلهای داخلش) در ریشه هاست (public_html، یا مشابه آن در cPanel/Nginx) آپلود کنید. - سایت بدون نیاز به Node.js یا هیچ سرور اختصاصی کار میکند.
نکات مهم هاست استاتیک (cPanel / Nginx / هاست ایرانی)
Apache (.htaccess):
<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:
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 حلقهٔ ۳۰۱ روی / میسازد.
پیش از دیپلوی واقعی — کارهایی که باید انجام دهید
- دامنه واقعی: در
shared/config/site.tsمقدارurl: "https://ariaiman.ir"را با دامنه نهایی جایگزین کنید (روی canonical، Open Graph، sitemap، robots و JSON-LD اثر مستقیم دارد). - لوگوی رسمی: در همان فایل،
logoفعلاً به تصویر hero اشاره میکند؛ یک فایل PNG/SVG لوگوی واقعی جایگزین شود. - تصویر Open Graph:
ogImageفعلاًhero.jpgاست؛ یک تصویر اختصاصی ۱۲۰۰×۶۳۰ درpublic/قرار دهید و مسیر/ابعاد را درsite.tsبهروز کنید. - آیکونهای PWA: manifest فعلاً از
favicon.svgاستفاده میکند؛ برای سازگاری کامل،icon-192.png،icon-512.pngوapple-touch-icon.pngاضافه شوند. - شبکههای اجتماعی: آرایه
socialsدرsite.tsخالی است؛ لینکهای واقعی را اضافه کنید تا در Schema.org (sameAs) درج شوند. - فرم تماس: اکشن
submitدر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/ |