diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100644 index 0000000..4b4b1ef --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Runs on `git push`. If a tag ref is among what's being pushed, build locally +# and deploy to the server. Normal branch pushes are untouched. +set -euo pipefail + +deploy=0 +tag="" +while read -r local_ref _local_sha _remote_ref _remote_sha; do + case "$local_ref" in + refs/tags/*) + deploy=1 + tag="${local_ref#refs/tags/}" + ;; + esac +done + +if [ "$deploy" = "1" ]; then + echo "→ Tag '$tag' is being pushed — building locally and deploying to the server…" + exec "$(git rev-parse --show-toplevel)/scripts/deploy.sh" +fi + +exit 0 diff --git a/app/app.tsx b/app/app.tsx index a143b1f..5e796c8 100644 --- a/app/app.tsx +++ b/app/app.tsx @@ -16,8 +16,8 @@ function App() { <>
diff --git a/app/components/CallToAction.jsx b/app/components/CallToAction.jsx index 92fe6f7..3f889e8 100644 --- a/app/components/CallToAction.jsx +++ b/app/components/CallToAction.jsx @@ -15,7 +15,7 @@ function CallToAction() { آماده برای تغییر زندگی؟

- امروز اولین قدم رو بردار و ببین چطور آرام لند می‌تونه کیفیت زندگی‌ات رو متحول کنه + امروز اولین قدم رو بردار و ببین چطور آرام جان می‌تونه کیفیت زندگی‌ات رو متحول کنه

diff --git a/app/components/DownloadSection.jsx b/app/components/DownloadSection.jsx index 2d466c5..7709d0e 100644 --- a/app/components/DownloadSection.jsx +++ b/app/components/DownloadSection.jsx @@ -47,7 +47,7 @@ function DownloadSection() { همین حالا شروع کنید

- آرام لند را روی دستگاه مورد علاقه‌تان نصب کنید + آرام جان را روی دستگاه مورد علاقه‌تان نصب کنید

diff --git a/app/components/Footer.jsx b/app/components/Footer.jsx index 2c82529..76e0a0e 100644 --- a/app/components/Footer.jsx +++ b/app/components/Footer.jsx @@ -1,5 +1,6 @@ "use client"; import { useScroll } from '../hooks/useScroll'; +import LotusLogo from './LotusLogo'; function Footer() { const { scrollToSectionWithHeader } = useScroll(); @@ -12,11 +13,9 @@ function Footer() { {/* Brand Column */}
-
- آ -
+
- آرام لند + آرام جان

@@ -44,7 +43,7 @@ function Footer() { {[ { name: 'ویژگی‌ها', section: 'features' }, { name: 'امکانات', section: 'what-you-can-do' }, - { name: 'چرا آرام لند', section: 'why-aramland' }, + { name: 'چرا آرام جان', section: 'why-aramland' }, { name: 'ارتباط با تیم', href: 'https://approagency.ir/' } ].map((link) => (

  • @@ -107,7 +106,7 @@ function Footer() {

    - © 1404 آرام لند - همراه تو برای یک زندگی آرام‌تر + © 1404 آرام جان - همراه تو برای یک زندگی آرام‌تر

    ساخته شده با عشق برای مردم ایران diff --git a/app/components/Header.jsx b/app/components/Header.jsx index 314a31f..e515583 100644 --- a/app/components/Header.jsx +++ b/app/components/Header.jsx @@ -2,6 +2,7 @@ import { useScroll } from '../hooks/useScroll'; import { useState } from 'react'; import { Menu, X } from 'lucide-react'; +import LotusLogo from './LotusLogo'; function Header() { const { scrollToSectionWithHeader } = useScroll(); @@ -26,11 +27,9 @@ function Header() {

    {/* Logo */}
    -
    - آ -
    +
    - آرام لند + آرام جان
    diff --git a/app/components/Hero.jsx b/app/components/Hero.jsx index a151307..31caa58 100644 --- a/app/components/Hero.jsx +++ b/app/components/Hero.jsx @@ -1,6 +1,7 @@ "use client"; import DownloadSection from "./DownloadSection"; import { useScroll } from '../hooks/useScroll'; +import LotusLogo from "./LotusLogo"; function Hero() { const { scrollToSectionWithHeader } = useScroll(); return ( @@ -8,28 +9,37 @@ function Hero() { {/* Background decoration */}
    -
    +
    - +
    -
    -
    - -
    + {/* App logo */} +
    +
    +
    +
    + +
    - -

    - آرامش را در + + {/* Badge */} +
    + 🌿 + مدیتیشن، تمرین تنفسی و آرامش فارسی +
    + +

    + آرامش را در هر لحظه تجربه کنید

    +

    + با آرام جان هر روز چند دقیقه برای خودت وقت بگذار؛ ذهنی آرام‌تر، خوابی عمیق‌تر و انرژی‌ای تازه. +

    - {/* */} -
    @@ -37,11 +47,11 @@ function Hero() { {/* Trust indicators */}

    مورد اعتماد هزاران کاربر

    -
    +
    ★ ۴.۹
    -
    +
    +۱۰۰۰ دانلود
    -
    +
    ۹۸٪ رضایت
    diff --git a/app/components/LotusLogo.jsx b/app/components/LotusLogo.jsx new file mode 100644 index 0000000..0d29e12 --- /dev/null +++ b/app/components/LotusLogo.jsx @@ -0,0 +1,43 @@ +// Brand mark for آرام جان — a layered translucent lotus on a blue→indigo +// gradient, matching the app icon. Self-contained SVG so it stays crisp at any +// size and needs no image asset. Size it with `className` (e.g. "w-9 h-9"). +function LotusLogo({ className = "w-9 h-9", title = "آرام جان" }) { + const petal = "M50 72 C42 56 42 34 50 22 C58 34 58 56 50 72 Z"; + const angles = [-50, -25, 0, 25, 50]; + + const opacityFor = (a) => { + if (a === 0) return 0.95; + if (Math.abs(a) === 25) return 0.72; + return 0.5; + }; + + return ( + + + + + + + + + + {angles.map((a) => ( + + ))} + + + ); +} + +export default LotusLogo; diff --git a/app/components/WhyAramland.jsx b/app/components/WhyAramland.jsx index ac2db39..b7c66b5 100644 --- a/app/components/WhyAramland.jsx +++ b/app/components/WhyAramland.jsx @@ -60,10 +60,10 @@ function WhyAramland() {
    🚀 - برتری آرام لند + برتری آرام جان

    - چرا هزاران نفر آرام لند را انتخاب می‌کنند؟ + چرا هزاران نفر آرام جان را انتخاب می‌کنند؟

    تجربه‌ای متفاوت از آرامش، طراحی شده مخصوص فارسی‌زبانان @@ -129,7 +129,7 @@ function WhyAramland() {

    - 👥 عضو جامعه هزاران نفری آرام لند شوید + 👥 عضو جامعه هزاران نفری آرام جان شوید

    به خانواده‌ای از کاربران خوشحال بپیوندید که هر روز قدمی به سمت آرامش برمی‌دارند diff --git a/app/globals.css b/app/globals.css index 3d17cd9..f0245b9 100644 --- a/app/globals.css +++ b/app/globals.css @@ -68,4 +68,50 @@ body { color: var(--foreground); font-family: 'Dana', 'Inter', Arial, Helvetica, sans-serif; font-weight: 400; +} + +/* ===== Brand motion ===== + The markup already references these animation classes; define them here so + the landing page feels alive (entrance reveals, floating logo, soft glow). */ +@keyframes fadeInUp { + from { opacity: 0; transform: translateY(30px); } + to { opacity: 1; transform: translateY(0); } +} +@keyframes slideInLeft { + from { opacity: 0; transform: translateX(-40px); } + to { opacity: 1; transform: translateX(0); } +} +@keyframes slideInRight { + from { opacity: 0; transform: translateX(40px); } + to { opacity: 1; transform: translateX(0); } +} +@keyframes floatY { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-14px); } +} +@keyframes pulseGlow { + 0%, 100% { opacity: .3; transform: scale(1); } + 50% { opacity: .6; transform: scale(1.08); } +} + +.animate-fadeInUp { animation: fadeInUp 0.7s ease-out both; } +.animate-slideInLeft { animation: slideInLeft 0.7s ease-out both; } +.animate-slideInRight { animation: slideInRight 0.7s ease-out both; } +.animate-float { animation: floatY 5s ease-in-out infinite; } +.animate-pulseGlow { animation: pulseGlow 4s ease-in-out infinite; } + +/* Stagger helpers — apply animation-delay on top of the entrance animations */ +.delay-100 { animation-delay: .1s; } +.delay-200 { animation-delay: .2s; } +.delay-300 { animation-delay: .3s; } +.delay-400 { animation-delay: .4s; } + +@media (prefers-reduced-motion: reduce) { + .animate-fadeInUp, + .animate-slideInLeft, + .animate-slideInRight, + .animate-float, + .animate-pulseGlow { + animation: none; + } } \ No newline at end of file diff --git a/app/icon.svg b/app/icon.svg new file mode 100644 index 0000000..e012ed2 --- /dev/null +++ b/app/icon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/app/layout.tsx b/app/layout.tsx index a9a6561..6984e03 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -2,12 +2,12 @@ import type { Metadata } from 'next'; import './globals.css'; export const metadata: Metadata = { - title: 'آرام لند | تمرین تنفسی و مدیتیشن', + title: 'آرام جان | تمرین تنفسی و مدیتیشن', description: 'لحظه‌ای آرام بگیر، زندگی را حس کن', - keywords: ['مدیتیشن فارسی', 'آرامش', 'تمرین تنفسی', 'کاهش استرس', 'ذهن‌آگاهی', 'مدیتیشن هدایت شده', 'سلامت روان', 'آرام لند'], - authors: [{ name: 'آرام لند' }], - creator: 'آرام لند', - publisher: 'آرام لند', + keywords: ['مدیتیشن فارسی', 'آرامش', 'تمرین تنفسی', 'کاهش استرس', 'ذهن‌آگاهی', 'مدیتیشن هدایت شده', 'سلامت روان', 'آرام جان'], + authors: [{ name: 'آرام جان' }], + creator: 'آرام جان', + publisher: 'آرام جان', metadataBase: new URL('https://aramland.approagency.ir/'), formatDetection: { email: false, @@ -15,7 +15,7 @@ export const metadata: Metadata = { telephone: false, }, icons: { - icon: '/favicon.png', + icon: '/icon.svg', }, alternates: { canonical: '/', @@ -24,16 +24,16 @@ export const metadata: Metadata = { }, }, openGraph: { - title: 'آرام لند - دستیار آرامش و مدیتیشن فارسی', - description: 'اپلیکیشن آرام لند - همراه شما برای رسیدن به آرامش درونی با مدیتیشن‌های فارسی و تمرین‌های تنفسی', + title: 'آرام جان - دستیار آرامش و مدیتیشن فارسی', + description: 'اپلیکیشن آرام جان - همراه شما برای رسیدن به آرامش درونی با مدیتیشن‌های فارسی و تمرین‌های تنفسی', url: 'https://aramland.approagency.ir/', - siteName: 'آرام لند', + siteName: 'آرام جان', images: [ { url: '/og-image.png', // Create this image (1200x630px) width: 1200, height: 630, - alt: ' آرام لند - اپلیکیشن مدیتیشن و آرامش - تمرین تنفسی', + alt: ' آرام جان - اپلیکیشن مدیتیشن و آرامش - تمرین تنفسی', }, ], @@ -43,8 +43,8 @@ export const metadata: Metadata = { twitter: { card: 'summary_large_image', - title: 'آرام لند - تمرین تنفسی و مدیتیشن', - description: 'اپلیکیشن آرام لند - همراه شما برای رسیدن به آرامش درونی', + title: 'آرام جان - تمرین تنفسی و مدیتیشن', + description: 'اپلیکیشن آرام جان - همراه شما برای رسیدن به آرامش درونی', images: ['/og-image.png'], creator: '@aramland', // Replace with your Twitter handle }, @@ -78,10 +78,9 @@ export default function RootLayout({ name="google-site-verification" content="HIKgdf_siYdPxbJ2P1792opMprpxci_QjE-quk9kyi8" /> - {/* Favicon */} - - - + {/* Favicon — lotus mark (آرام جان) */} + + {/* Preload critical resources */} @@ -99,8 +98,8 @@ export default function RootLayout({ "ratingValue": "4.5", "ratingCount": "1000" }, - "name": "آرام لند", - "description": "اپلیکیشن آرام لند - همراه شما برای رسیدن به آرامش درونی با مدیتیشن‌های فارسی و تمرین‌های تنفسی", + "name": "آرام جان", + "description": "اپلیکیشن آرام جان - همراه شما برای رسیدن به آرامش درونی با مدیتیشن‌های فارسی و تمرین‌های تنفسی", "url": "https://aramland.approagency.ir/", "applicationCategory": "HealthApplication", "operatingSystem": "Android, iOS, Web", @@ -111,7 +110,7 @@ export default function RootLayout({ }, "author": { "@type": "Organization", - "name": "آرام لند" + "name": "آرام جان" } }) }} diff --git a/out.zip b/out.zip deleted file mode 100644 index 125e31e..0000000 Binary files a/out.zip and /dev/null differ diff --git a/package.json b/package.json index 7a2776b..678fab6 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "eslint" + "lint": "eslint", + "deploy": "bash scripts/deploy.sh" }, "dependencies": { "framer-motion": "^12.23.24", diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100644 index 0000000..f1a9c81 --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Build the static site locally, then replace the server directory with it. +# +# - Builds on THIS machine (npm run build -> ./out). +# - Streams out/ over a single SSH connection (tar pipe) and swaps the +# contents of the target dir on the server. No rsync/sshpass required. +# +# Password handling: +# - If `sshpass` is installed AND DEPLOY_PASSWORD is set (env or .env.deploy), +# the deploy is fully unattended. +# - Otherwise SSH prompts for the password once (interactive). +# +# Config (override via env or .env.deploy): +set -euo pipefail +cd "$(git rev-parse --show-toplevel 2>/dev/null || dirname "$(dirname "$0")")" + +# Optional local secrets file (gitignored). +[ -f .env.deploy ] && . ./.env.deploy + +DEPLOY_HOST="${DEPLOY_HOST:-185.226.116.88}" +DEPLOY_USER="${DEPLOY_USER:-ubuntu}" +DEPLOY_PATH="${DEPLOY_PATH:-/var/www/aramland-front}" +DEPLOY_PASSWORD="${DEPLOY_PASSWORD:-}" + +echo "▸ Building locally (clean)…" +# Remove caches so the production build never type-checks a stale `.next/dev` +# validator (tsconfig includes .next/dev/types) and never ships stale out/ files. +rm -rf .next out +npm run build + +if [ ! -d out ]; then + echo "✗ Build did not produce ./out" >&2 + exit 1 +fi + +# Pick the SSH command: unattended with sshpass, else interactive prompt. +ssh_cmd=(ssh -o StrictHostKeyChecking=no "$DEPLOY_USER@$DEPLOY_HOST") +if command -v sshpass >/dev/null 2>&1 && [ -n "$DEPLOY_PASSWORD" ]; then + ssh_cmd=(sshpass -p "$DEPLOY_PASSWORD" "${ssh_cmd[@]}") +else + echo "ℹ sshpass/password not available — SSH will prompt for the password." +fi + +echo "▸ Uploading to $DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH …" +# Replace the directory contents (incl. dotfiles) then extract the new build. +tar -C out -czf - . | "${ssh_cmd[@]}" \ + "set -e; mkdir -p '$DEPLOY_PATH'; find '$DEPLOY_PATH' -mindepth 1 -delete; tar -C '$DEPLOY_PATH' -xzf -" + +echo "✓ Deployed to $DEPLOY_HOST:$DEPLOY_PATH"