16 Commits
Author SHA1 Message Date
Amirmahdi ed8994aaca fix: site url 2026-08-02 11:55:00 +03:30
AmirmahdiandClaude Opus 4.8 21302f59ec seo: add blog sitemap to robots.txt
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 09:06:59 +03:30
AmirmahdiandClaude Opus 4.8 ee81da8f70 seo: unify domain to aramejan.com; real logo, favicon, og-image; assetlinks; fix canonical/sitemap/robots
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 09:00:18 +03:30
Amirmahdi bf7706fb2d feat: change logo and og 2026-06-29 11:22:56 +03:30
Amirmahdi dae31e9e83 feat: add assetlinks.json 2026-06-21 20:21:33 +03:30
Amirmahdi fc30597835 feat: logo 2026-06-21 19:04:29 +03:30
Amirmahdi 3c6a9c79df feat: add enemad to footer 2025-12-09 20:45:47 +03:30
Amirmahdi 23767a713a feat: add blogs 2025-12-05 18:41:17 +03:30
Amirmahdi bece9a2171 fix: link is fixed 2025-12-03 15:18:26 +03:30
Amirmahdi c40356568f feat: rebrans 2025-11-28 17:53:12 +03:30
Amirmahdi abc3f89195 feat: change sitemap 2025-11-19 01:27:24 +03:30
Amirmahdi b6108a04d8 feat: add favicon.ico 2025-11-19 00:53:22 +03:30
Amirmahdi 18da3984ae feat: add sitemap, tag for SEO 2025-11-12 00:25:51 +03:30
Amirmahdi e95983d9b0 feat: drawer in mobile view 2025-11-07 16:31:45 +03:30
Amirmahdi 5b5d1cfa69 feat: add download links 2025-11-07 15:48:54 +03:30
Amirmahdi 3ceec02356 feat: better fotter 2025-11-07 15:43:46 +03:30
32 changed files with 1096 additions and 127 deletions
+22
View File
@@ -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
+34 -8
View File
@@ -5,29 +5,55 @@ import Features from './components/Features';
import WhatYouCanDo from './components/WhatYouCanDo';
import WhyAramland from './components/WhyAramland';
import FreeTrial from './components/FreeTrial';
import BlogSection from './components/BlogSection';
// import ScientificBenefits from './components/ScientificBenefits';
import CallToAction from './components/CallToAction';
import Footer from './components/Footer';
import { SEOHead } from './components/SEOHead';
function App() {
return (
<>
<SEOHead
title="آرام جان - تمرین تنفسی و مدیتیشن"
description="اپلیکیشن آرام جان - همراه شما برای رسیدن به آرامش درونی با مدیتیشن‌های فارسی، تمرین‌های تنفسی و موسیقی آرامش‌بخش"
canonical="/" />
<div className="min-h-screen bg-gradient-to-b from-blue-50 via-white to-green-50" dir="rtl">
<Header />
<main className="max-w-5xl mx-auto px-6 sm:px-8 lg:px-10 py-24 space-y-32">
<div id="download">
<Hero />
<DownloadSection />
<Features />
<WhatYouCanDo />
<WhyAramland />
<FreeTrial />
{/* <ScientificBenefits /> */}
<CallToAction />
</main>
</div>
<div id="features">
<Features />
</div>
<div id="what-you-can-do">
<WhatYouCanDo />
</div>
<div id="why-aramland">
<WhyAramland />
</div>
<BlogSection />
<div id="free-trial">
<FreeTrial />
</div>
<div id="call-to-action">
<CallToAction />
</div>
</main>
<div id='footer'>
<Footer />
</div>
</div>
</>
);
}
+127
View File
@@ -0,0 +1,127 @@
// components/BlogSection.jsx
"use client";
import { Calendar, Clock, ArrowLeft } from 'lucide-react';
import Link from 'next/link';
function BlogSection() {
const blogs = [
{
title: "تمرین تنفسی برای کاهش استرس",
subtitle: "تکنیک‌های ساده تنفسی برای کاهش فوری استرس و اضطراب",
link: "https://aramejan.com/blog/tmryn-tnfsy-bry-khhsh-strs.html",
readTime: "۵ دقیقه",
date: "۱۴۰۴/۱/۱۵",
category: "سلامت روان",
gradient: "from-primary-500/10 to-primary-600/10",
border: "border-primary-500/20"
},
{
title: "مدیتیشن چیست و چگونه شروع کنیم؟",
subtitle: "راهنمای کامل برای شناخت مدیتیشن و شروع این سفر زیبا",
link: "https://aramejan.com/blog/mdytyshn-chyh.html",
readTime: "۷ دقیقه",
date: "۱۴۰۴/۱۰/۱۰",
category: "آموزش",
gradient: "from-primary-500/10 to-primary-600/10",
border: "border-primary-500/20"
},
{
title: "مدیتیشن چیست و چگونه زندگی‌ات را متحول می‌کند؟",
subtitle: "راهنمای کامل برای شناخت انواع مدیتیشن",
link: "https://aramejan.com/blog/khls-shdn-z-strs-b-arm-lnd.html",
readTime: "۸ دقیقه",
date: "۱۴۰۴/۱۰/۰۵",
category: "تحول شخصی",
gradient: "from-primary-500/10 to-primary-600/10",
border: "border-primary-500/20"
}
];
return (
<section className="my-24">
{/* Header */}
<div className="text-center mb-16">
<div className="inline-flex items-center gap-2 bg-primary-500/10 text-primary-600 px-4 py-2 rounded-full text-sm font-medium mb-4">
<span className="text-lg">📝</span>
مقالات آموزشی
</div>
<h2 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
آخرین <span className="text-primary-500">مقالات</span> آرامش
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
یادگیری عمیقتر درباره تکنیکهای آرامش، مدیتیشن و سلامت روان
</p>
</div>
{/* Blog Cards Grid */}
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8 mb-12">
{blogs.map((blog, index) => (
<article
key={index}
className={`bg-gradient-to-br ${blog.gradient} border ${blog.border} rounded-3xl overflow-hidden group hover:shadow-2xl transition-all duration-500 hover:-translate-y-2 animate-fadeInUp`}
style={{ animationDelay: `${index * 100}ms` }}
>
{/* Card Header */}
<div className="p-8">
{/* Category Badge */}
<div className="inline-block bg-primary-500/20 text-primary-600 px-3 py-1 rounded-full text-xs font-medium mb-4">
{blog.category}
</div>
{/* Title */}
<h3 className="text-xl font-bold text-gray-900 mb-3 group-hover:text-primary-600 transition-colors duration-300 line-clamp-2">
{blog.title}
</h3>
{/* Subtitle */}
<p className="text-gray-600 leading-relaxed mb-6 line-clamp-2">
{blog.subtitle}
</p>
{/* Meta Info */}
<div className="flex items-center justify-between text-sm text-gray-500">
<div className="flex items-center gap-4">
<div className="flex items-center gap-1">
<Calendar className="w-4 h-4" />
<span>{blog.date}</span>
</div>
<div className="flex items-center gap-1">
<Clock className="w-4 h-4" />
<span>{blog.readTime} مطالعه</span>
</div>
</div>
</div>
</div>
{/* Read More Button */}
<div className="border-t border-primary-500/10 p-6">
<a
href={blog.link}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 text-primary-600 hover:text-primary-700 font-medium group/link transition-colors duration-300"
>
<span>مطالعه مقاله</span>
<ArrowLeft className="w-4 h-4 group-hover/link:-translate-x-1 transition-transform duration-300" />
</a>
</div>
</article>
))}
</div>
{/* View All Button */}
<div className="text-center">
<Link
href="https://aramejan.com/blog/"
className="inline-flex items-center gap-2 bg-gradient-to-r from-primary-500 to-primary-600 text-white font-medium py-3 px-8 rounded-2xl hover:shadow-lg transition-all duration-300 transform hover:scale-105 group"
>
<span>مشاهده همه مقالات</span>
<ArrowLeft className="w-5 h-5 group-hover:-translate-x-1 transition-transform duration-300" />
</Link>
</div>
</section>
);
}
export default BlogSection;
+6 -3
View File
@@ -1,4 +1,7 @@
"use client";
import { useScroll } from '../hooks/useScroll';
function CallToAction() {
const { scrollToSectionWithHeader } = useScroll();
return (
<div className="relative text-center rounded-3xl p-16 animate-fadeInUp overflow-hidden">
{/* Background with gradient */}
@@ -12,15 +15,15 @@ function CallToAction() {
آماده برای <span className="text-primary-500">تغییر</span> زندگی؟
</h2>
<p className="text-xl text-gray-700 mb-8 max-w-2xl mx-auto leading-relaxed">
امروز اولین قدم رو بردار و ببین چطور آراملند میتونه کیفیت زندگیات رو متحول کنه
امروز اولین قدم رو بردار و ببین چطور آرام جان میتونه کیفیت زندگیات رو متحول کنه
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center">
<button className="bg-gradient-to-r from-primary-500 to-primary-600 text-white font-bold py-4 px-8 rounded-2xl hover:shadow-2xl transition-all duration-300 transform hover:scale-105 text-lg shadow-lg hover:shadow-primary-500/40 relative overflow-hidden group">
<button onClick={() => scrollToSectionWithHeader('download')} className="bg-gradient-to-r from-primary-500 to-primary-600 text-white font-bold py-4 px-8 rounded-2xl hover:shadow-2xl transition-all duration-300 transform hover:scale-105 text-lg shadow-lg hover:shadow-primary-500/40 relative overflow-hidden group">
<div className="absolute inset-0 bg-white/20 -translate-x-full group-hover:translate-x-full transition-transform duration-700"></div>
<span className="relative">شروع سفر آرامش</span>
</button>
<button className="border-2 border-gray-300 text-gray-700 font-bold py-4 px-8 rounded-2xl hover:border-primary-500 hover:text-primary-500 transition-all duration-300">
<button onClick={() => scrollToSectionWithHeader('features')} className="border-2 border-gray-300 text-gray-700 font-bold py-4 px-8 rounded-2xl hover:border-primary-500 hover:text-primary-500 transition-all duration-300">
بیشتر بدانید
</button>
</div>
+31 -23
View File
@@ -1,70 +1,78 @@
import { li } from 'framer-motion/client';
import { Download, Globe, PlayCircle } from 'lucide-react';
function DownloadSection() {
const downloadOptions = [
{
icon: Download,
icon: './images/cafe.png',
title: "کافه بازار",
description: "دانلود برای اندروید",
badge: "پرطرفدار",
gradient: "from-primary-500 to-primary-600",
link: "https://cafebazaar.ir/app/com.approagency.meditation",
// badge: "پرطرفدار",
gradient: "from-primary-500/10 to-primary-600/10",
border: "border-primary-500/20",
animation: "animate-slideInLeft delay-100"
},
{
icon: PlayCircle,
icon: './images/myket.png',
title: "مایکت",
link: "https://myket.ir/app/com.approagency.meditation",
description: "دانلود برای اندروید",
gradient: "from-primary-500 to-primary-600",
gradient: "from-primary-500/10 to-primary-600/10",
border: "border-primary-500/20",
animation: "animate-fadeInUp delay-200"
},
{
icon: Globe,
icon: './images/appstore.png',
title: "وب سایت",
description: "نسخه وب برای تمام دستگاه‌ها",
badge: "جدید",
gradient: "from-primary-500 to-primary-600",
animation: "animate-slideInRight delay-300"
link: 'https://app.aramejan.com',
badge: "",
gradient: "from-primary-500/10 to-primary-600/10",
animation: "animate-slideInRight delay-300",
border: "border-primary-500/20",
}
];
return (
<div className="relative bg-white rounded-3xl shadow-2xl p-12 mb-20 animate-fadeInUp overflow-hidden">
<div className="relative rounded-3xl p-1 mb-10 animate-fadeInUp overflow-hidden">
{/* Background pattern */}
<div className="absolute inset-0 opacity-5">
<div className="absolute inset-0 bg-gradient-to-r from-primary-500 to-primary-600"></div>
<div className="absolute inset-0 opacity-4">
<div className="absolute inset-0"></div>
</div>
<div className="relative">
<div className="text-center mb-12">
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4 mt-8">
همین حالا <span className="text-primary-500">شروع کنید</span>
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
آراملند را روی دستگاه مورد علاقهتان نصب کنید
آرام جان را روی دستگاه مورد علاقهتان نصب کنید
</p>
</div>
<div className="grid md:grid-cols-3 gap-6 max-w-4xl mx-auto">
<div className="grid md:grid-cols-3 gap-6 max-w-4xl mx-auto ">
{downloadOptions.map((option, index) => (
<a
key={index}
href="#"
className={`relative flex flex-col items-center justify-center p-8 bg-gradient-to-br ${option.gradient} rounded-3xl shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 text-white group ${option.animation} overflow-hidden`}
href={option.link}
className={`relative flex flex-col items-center justify-center p-8 bg-gradient-to-br ${option.gradient} rounded-3xl hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2 group ${option.animation} overflow-hidden border ${option.border}`}
>
{/* Shine effect */}
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent -translate-x-full group-hover:translate-x-full transition-transform duration-1000"></div>
{/* <div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent -translate-x-full group-hover:translate-x-full transition-transform duration-1000"></div> */}
{option.badge && (
<div className="absolute -top-2 -right-2 bg-white text-primary-500 px-3 py-1 rounded-full text-xs font-bold shadow-lg">
<div className="absolute -top-0 right-0 bg-primary-200 px-2 py-2 rounded text-xs font-bold">
{option.badge}
</div>
)}
<div className="bg-white/20 p-4 rounded-2xl mb-4 group-hover:scale-110 transition-transform duration-300">
<option.icon className="w-8 h-8" />
<div className="bg-white p-4 rounded-2xl mb-4 group-hover:scale-110 transition-transform duration-300">
<img src={option.icon} alt="Download" className="w-20 h-20 border border-transparent rounded-xl " />
{/* <option.icon className="w-8 h-8" /> */}
</div>
<h3 className="text-xl font-bold mb-2">{option.title}</h3>
<p className="text-white/90 text-sm">{option.description}</p>
<h3 className="text-xl text-black font-bold mb-2">{option.title}</h3>
<p className="text-sm text-black">{option.description}</p>
</a>
))}
</div>
+1 -1
View File
@@ -27,7 +27,7 @@ function Features() {
];
return (
<div className="my-24">
<div className="my-12">
<div className="text-center mb-16">
<div className="inline-flex items-center gap-2 bg-primary-500/10 text-primary-500 px-4 py-2 rounded-full text-sm font-medium mb-4">
<span></span>
+163 -3
View File
@@ -1,8 +1,168 @@
"use client";
import { useScroll } from '../hooks/useScroll';
import LotusLogo from './LotusLogo';
function Footer() {
const { scrollToSectionWithHeader } = useScroll();
return (
<footer className="py-12 text-center text-gray-500 border-t border-gray-200">
<p className="mb-4">© ۱۴۰۳ آراملند - همراه تو برای یک زندگی آرامتر</p>
<p className="text-sm">ساخته شده با عشق برای مردم ایران</p>
<footer className="bg-white border-t border-gray-100">
{/* Main Footer Content */}
<div className="max-w-5xl mx-auto px-6 sm:px-8 lg:px-10 py-16">
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8 mb-12">
{/* Brand Column */}
<div className="lg:col-span-2">
<div className="flex items-center gap-3 mb-6">
<LotusLogo className="w-11 h-11 drop-shadow-sm" />
<div className="text-2xl font-bold bg-gradient-to-r from-primary-500 to-primary-600 bg-clip-text text-transparent">
آرام جان
</div>
</div>
<p className="text-gray-600 leading-relaxed mb-6 max-w-md">
همراه شما در مسیر رسیدن به آرامش درونی. با ابزارهای علمی و تخصصی
برای زندگی بهتر و ذهنی آرامتر.
</p>
<div className="flex gap-4">
{/* Social Media Icons - You can add actual links later */}
<div className="w-10 h-10 bg-primary-500/10 rounded-xl flex items-center justify-center cursor-pointer hover:bg-primary-500/20 transition-colors">
<span className="text-primary-500">📱</span>
</div>
<div className="w-10 h-10 bg-primary-500/10 rounded-xl flex items-center justify-center cursor-pointer hover:bg-primary-500/20 transition-colors">
<span className="text-primary-500">💬</span>
</div>
<div className="w-10 h-10 bg-primary-500/10 rounded-xl flex items-center justify-center cursor-pointer hover:bg-primary-500/20 transition-colors">
<span className="text-primary-500">📸</span>
</div>
</div>
</div>
{/* Quick Links */}
<div>
<h3 className="font-bold text-gray-900 mb-6 text-lg">لینکهای سریع</h3>
<ul className="space-y-3">
{[
{ name: 'ویژگی‌ها', section: 'features' },
{ name: 'امکانات', section: 'what-you-can-do' },
{ name: 'چرا آرام جان', section: 'why-aramland' },
{ name: 'ارتباط با تیم', href: 'https://approagency.ir/' }
].map((link) => (
<li key={link.name}>
<a
href={link.href}
onClick={() => scrollToSectionWithHeader(link.section)}
target="_blank"
className="text-gray-600 hover:text-primary-500 transition-colors duration-200"
>
{link.name}
</a>
</li>
))}
</ul>
</div>
{/* Agency Contact */}
<div>
<h3 className="font-bold text-gray-900 mb-6 text-lg">توسعهدهنده</h3>
<div className="space-y-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-gradient-to-r from-primary-500 to-primary-600 rounded-xl flex items-center justify-center">
<span className="text-white text-sm">AP</span>
</div>
<div>
<p className="font-medium text-gray-900">اپرواجنسی</p>
<p className="text-sm text-gray-500">Approagency</p>
</div>
</div>
<div className="space-y-3">
<a
href="mailto:approagency@gmail.com"
className="flex items-center gap-2 text-gray-600 hover:text-primary-500 transition-colors group"
>
<div className="w-8 h-8 bg-primary-500/10 rounded-lg flex items-center justify-center group-hover:bg-primary-500/20 transition-colors">
<span className="text-primary-500 text-sm"></span>
</div>
<span className="text-sm">approagency@gmail.com</span>
</a>
<a
href="tel:+989362957108"
className="flex items-center gap-2 text-gray-600 hover:text-primary-500 transition-colors group"
>
<div className="w-8 h-8 bg-primary-500/10 rounded-lg flex items-center justify-center group-hover:bg-primary-500/20 transition-colors">
<span className="text-primary-500 text-sm">📞</span>
</div>
<span className="text-sm">۰۹۳۶۲۹۵۷۱۰۸</span>
</a>
</div>
</div>
</div>
</div>
{/* Divider */}
<div className="h-px bg-gradient-to-r from-transparent via-gray-200 to-transparent mb-8"></div>
{/* Bottom Section */}
<div className="flex flex-col md:flex-row justify-between items-center gap-4">
<div className="text-center md:text-right">
<p className="text-gray-600 mb-2">
© 1404 آرام جان - همراه تو برای یک زندگی آرامتر
</p>
<p className="text-gray-500 text-sm">
ساخته شده با عشق برای مردم ایران
</p>
</div>
<div className="flex flex-col md:flex-row items-center gap-6">
{/* Enamad Badge */}
<div className="mt-4 md:mt-0">
<a
referrerPolicy='origin'
target='_blank'
href='https://trustseal.enamad.ir/?id=684477&Code=O0VD9spjoV48pvyakFsJgoY361OXvszk'
className="inline-block"
>
<img
referrerPolicy='origin'
src='https://trustseal.enamad.ir/logo.aspx?id=684477&Code=O0VD9spjoV48pvyakFsJgoY361OXvszk'
alt='Enamad Trust Seal'
style={{cursor: 'pointer'}}
code='O0VD9spjoV48pvyakFsJgoY361OXvszk'
className="h-12 w-auto"
/>
</a>
</div>
{/* Additional Links */}
<div className="flex gap-6 text-sm">
<a href="#" className="text-gray-500 hover:text-primary-500 transition-colors">
حریم خصوصی
</a>
<a href="#" className="text-gray-500 hover:text-primary-500 transition-colors">
شرایط استفاده
</a>
<a href="#" className="text-gray-500 hover:text-primary-500 transition-colors">
پشتیبانی
</a>
</div>
</div>
</div>
</div>
{/* Floating CTA */}
<div className="bg-gradient-to-r from-primary-500/5 to-primary-600/5 border-t border-primary-500/10">
<div className="max-w-5xl mx-auto px-6 sm:px-8 lg:px-10 py-6">
<div className="flex flex-col md:flex-row justify-between items-center gap-4">
<div>
<p className="font-medium text-gray-900">آماده شروع سفر آرامش؟</p>
<p className="text-gray-600 text-sm">همین حالا رایگان شروع کنید</p>
</div>
<button onClick={() => scrollToSectionWithHeader('download')} className="bg-gradient-to-r from-primary-500 to-primary-600 text-white font-medium py-3 px-8 rounded-2xl hover:shadow-lg transition-all duration-300 transform hover:scale-105 whitespace-nowrap">
دانلود اپلیکیشن
</button>
</div>
</div>
</div>
</footer>
);
}
+12 -6
View File
@@ -1,4 +1,7 @@
"use client";
import { useScroll } from '../hooks/useScroll';
function FreeTrial() {
const { scrollToSectionWithHeader } = useScroll();
return (
<div className="relative bg-gradient-to-r from-primary-500 via-primary-600 to-primary-500 rounded-3xl p-12 text-white text-center mb-20 animate-fadeInUp overflow-hidden">
{/* Background Pattern */}
@@ -26,8 +29,8 @@ function FreeTrial() {
{/* Description */}
<p className="text-lg md:text-xl text-white/90 mb-8 max-w-2xl mx-auto leading-relaxed animate-fadeInUp delay-300">
تمام ویژگیهای پریمیوم رو برای یک هفته کامل تجربه کن،
<span className="font-bold text-yellow-300"> بدون نیاز به کارت اعتباری</span>
تمام ویژگیهای پریمیوم رو میتونی به طور محدود تجربه کنی
<span className="font-bold text-yellow-300"></span>
</p>
{/* Features */}
@@ -35,7 +38,10 @@ function FreeTrial() {
{[
"تمامی مدیتیشن‌ها",
"موسیقی‌های انحصاری",
"مشاوره هوش مصنوعی"
"مشاوره هوش مصنوعی",
"تمرین تنفسی دلخواه",
"اطلاعات آموزشی",
"رابط کاربری ساده",
].map((feature, index) => (
<div key={index} className="flex items-center justify-center gap-2 bg-white/10 backdrop-blur-sm py-3 px-4 rounded-xl">
<svg className="w-4 h-4 text-yellow-300" fill="currentColor" viewBox="0 0 20 20">
@@ -47,14 +53,14 @@ function FreeTrial() {
</div>
{/* CTA Button */}
<button className="bg-white text-primary-500 font-bold py-4 px-12 rounded-2xl hover:shadow-2xl transition-all duration-300 transform hover:scale-105 animate-fadeInUp delay-500 relative overflow-hidden group">
<button onClick={() => scrollToSectionWithHeader('download')} className="bg-white text-primary-500 font-bold py-4 px-12 rounded-2xl hover:shadow-2xl transition-all duration-300 transform hover:scale-105 animate-fadeInUp delay-500 relative overflow-hidden group">
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent -translate-x-full group-hover:translate-x-full transition-transform duration-700"></div>
<span className="relative">شروع دوره آزمایشی رایگان</span>
<span className="relative">شروع سفر آرامش</span>
</button>
{/* Footer Note */}
<p className="text-white/70 text-sm mt-6 animate-fadeInUp delay-600">
هیچ تعهدی ندارد هر زمان میتوانی لغو کنی
میتونی روی گوشیت همیشه داشته باشی
</p>
</div>
</div>
+95 -18
View File
@@ -1,36 +1,113 @@
"use client";
import { useScroll } from '../hooks/useScroll';
import { useState } from 'react';
import { Menu, X } from 'lucide-react';
import LotusLogo from './LotusLogo';
function Header() {
const { scrollToSectionWithHeader } = useScroll();
const [isMenuOpen, setIsMenuOpen] = useState(false);
const navigationItems = [
{ name: 'ویژگی‌ها', id: 'features' },
{ name: 'امکانات', id: 'what-you-can-do' },
{ name: 'چرا ما', id: 'why-aramland' },
{ name: 'دانلود', id: 'download' },
{ name: 'ارتباط با ما', id: 'footer' },
{ name: 'بلاگ', id: 'blog' },
];
const handleNavClick = (sectionId) => {
scrollToSectionWithHeader(sectionId);
setIsMenuOpen(false);
};
return (
<nav className="py-6 px-8 sticky top-0 bg-white/80 backdrop-blur-md z-50 border-b border-gray-100">
<nav className="py-4 px-6 sm:px-8 sticky top-0 bg-white/80 backdrop-blur-md z-50 border-b border-gray-100">
<div className="max-w-6xl mx-auto flex justify-between items-center">
{/* Logo */}
<div className="flex items-center gap-3">
<div className="bg-gradient-to-r from-primary-500 to-primary-600 w-8 h-8 rounded-xl flex items-center justify-center">
<span className="text-white font-bold text-sm">آ</span>
</div>
<div className="text-2xl font-bold bg-gradient-to-r from-primary-500 to-primary-600 bg-clip-text text-transparent">
آراملند
<LotusLogo className="w-9 h-9 drop-shadow-sm" />
<div className="text-xl sm:text-2xl font-bold bg-gradient-to-r from-primary-500 to-primary-600 bg-clip-text text-transparent">
آرام جان
</div>
</div>
{/* Navigation */}
<div className="hidden md:flex items-center gap-8">
{['ویژگی‌ها', 'دانلود', 'قیمت‌ها', 'درباره ما'].map((item) => (
<a
key={item}
href="#"
className="text-gray-600 hover:text-primary-500 font-medium transition-colors duration-200 relative group"
{/* Desktop Navigation */}
<div className="hidden md:flex items-center gap-6 lg:gap-8">
{navigationItems.map((item) => (
<button
key={item.id}
onClick={() => {
if (item.id === 'blog') {
window.open('https://aramejan.com/blog/', '_self');
} else {
handleNavClick(item.id);
}
}}
className="text-gray-600 hover:text-primary-500 font-medium transition-colors duration-200 relative group text-sm lg:text-base"
>
{item}
{item.name}
<span className="absolute bottom-0 left-0 w-0 h-0.5 bg-primary-500 group-hover:w-full transition-all duration-300"></span>
</a>
</button>
))}
</div>
{/* CTA Button */}
<button className="bg-gradient-to-r from-primary-500 to-primary-600 text-white font-medium py-2 px-6 rounded-xl hover:shadow-lg transition-all duration-300 transform hover:scale-105">
شروع رایگان
{/* Desktop CTA Button */}
<div className="hidden md:block">
<button
onClick={() => handleNavClick('download')}
className="bg-gradient-to-r from-primary-500 to-primary-600 text-white font-medium py-2 px-4 lg:py-2 lg:px-6 rounded-xl hover:shadow-lg transition-all duration-300 transform hover:scale-105 text-sm lg:text-base"
>
شروع سفر آرامش
</button>
</div>
{/* Mobile Menu Button */}
<button
className="md:hidden p-2 rounded-lg hover:bg-gray-100 transition-colors"
onClick={() => setIsMenuOpen(!isMenuOpen)}
>
{isMenuOpen ? (
<X className="w-6 h-6 text-gray-600" />
) : (
<Menu className="w-6 h-6 text-gray-600" />
)}
</button>
</div>
{/* Mobile Menu */}
{isMenuOpen && (
<div className="md:hidden absolute top-full left-0 right-0 bg-white/95 backdrop-blur-md border-b border-gray-200 shadow-lg">
<div className="px-6 py-4 space-y-4">
{navigationItems.map((item) => (
<button
key={item.id}
onClick={() => {
if (item.id === 'blog') {
window.open('https://aramejan.com/blog/', '_self');
} else {
handleNavClick(item.id);
}
}}
className="block w-full text-right py-3 px-4 text-gray-700 hover:text-primary-500 hover:bg-primary-50 rounded-lg transition-all duration-200 font-medium border-b border-gray-100 last:border-b-0"
>
{item.name}
</button>
))}
{/* Mobile CTA Button */}
<div className="pt-4 border-t border-gray-200">
<button
onClick={() => handleNavClick('download')}
className="w-full bg-gradient-to-r from-primary-500 to-primary-600 text-white font-medium py-3 px-4 rounded-xl hover:shadow-lg transition-all duration-300 transform hover:scale-105 text-center"
>
شروع سفر آرامش
</button>
</div>
</div>
</div>
)}
</nav>
);
}
+32 -24
View File
@@ -1,37 +1,45 @@
import { motion } from "framer-motion";
"use client";
import DownloadSection from "./DownloadSection";
import { useScroll } from '../hooks/useScroll';
import LotusLogo from "./LotusLogo";
function Hero() {
const { scrollToSectionWithHeader } = useScroll();
return (
<div className="text-center mb-20 relative">
<div className="text-center mb-10 relative">
{/* Background decoration */}
<div className="absolute inset-0 overflow-hidden pointer-events-none">
<div className="absolute inset-0 overflow-hidden pointer-events-none rounded-3xl">
<div className="absolute -top-20 -right-20 w-72 h-72 bg-primary-500 opacity-10 rounded-full blur-3xl"></div>
<div className="absolute -bottom-20 -left-20 w-72 h-72 bg-primary-500 opacity-10 rounded-full blur-3xl"></div>
<div className="absolute -bottom-20 -left-20 w-72 h-72 bg-primary-400 opacity-10 rounded-full blur-3xl"></div>
</div>
<div className="relative">
<div className="mb-8 animate-float">
<div className="relative inline-block">
<span className="text-6xl"></span>
<div className="absolute inset-0 bg-gradient-to-r from-primary-500 to-primary-600 opacity-20 blur-xl rounded-full"></div>
{/* App logo */}
<div className="mb-6 flex justify-center">
<div className="relative inline-block animate-float">
<div className="absolute inset-0 bg-gradient-to-r from-primary-500 to-primary-600 blur-2xl rounded-full animate-pulseGlow"></div>
<div className="relative w-24 h-24 sm:w-28 sm:h-28 rounded-[26px] overflow-hidden shadow-2xl shadow-primary-500/40">
<LotusLogo className="w-full h-full" />
</div>
</div>
</div>
<h1 className="text-5xl md:text-7xl font-bold text-gray-900 mb-6 leading-tight animate-fadeInUp">
{/* Badge */}
<div className="inline-flex items-center gap-2 bg-primary-500/10 text-primary-600 px-4 py-2 rounded-full text-sm font-medium mb-6 animate-fadeInUp">
<span>🌿</span>
مدیتیشن، تمرین تنفسی و آرامش فارسی
</div>
<h1 className="text-5xl md:text-7xl font-bold text-gray-900 mb-4 leading-tight animate-fadeInUp">
آرامش را در
<span className="bg-gradient-to-r from-primary-500 to-primary-600 bg-clip-text text-transparent"> هر لحظه </span>
تجربه کنید
</h1>
<p className="text-xl md:text-2xl text-gray-600 max-w-3xl mx-auto leading-relaxed mb-6 animate-fadeInUp delay-100">
آراملند دستیار شخصی شما برای یافتن آرامش درونی. با مدیتیشنهای اختصاصی،
موسیقی آرامشبخش و راهنماییهای حرفهای.
<p className="text-lg md:text-xl text-gray-600 max-w-2xl mx-auto animate-fadeInUp delay-100">
با آرام جان هر روز چند دقیقه برای خودت وقت بگذار؛ ذهنی آرامتر، خوابی عمیقتر و انرژیای تازه.
</p>
<DownloadSection />
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center animate-fadeInUp delay-200">
<button className="bg-gradient-to-r from-primary-500 to-primary-600 text-white font-bold py-4 px-8 rounded-2xl hover:shadow-2xl transition-all duration-300 transform hover:scale-105 text-lg shadow-lg hover:shadow-primary-500/25">
شروع کنید رایگان
</button>
<button className="border-2 border-gray-300 text-gray-700 font-bold py-4 px-8 rounded-2xl hover:border-primary-500 hover:text-primary-500 transition-all duration-300">
<button onClick={() => scrollToSectionWithHeader('what-you-can-do')} className="bg-gradient-to-r from-primary-500 to-primary-600 border-2 border-transparent text-white font-bold py-4 px-8 rounded-2xl hover:shadow-2xl hover:shadow-primary-500/30 transition-all duration-300 transform hover:scale-105">
مشاهده ویژگیها
</button>
</div>
@@ -39,12 +47,12 @@ function Hero() {
{/* Trust indicators */}
<div className="mt-12 animate-fadeInUp delay-300">
<p className="text-gray-500 text-sm mb-4">مورد اعتماد هزاران کاربر</p>
<div className="flex justify-center items-center gap-8 opacity-60">
<div className="text-2xl font-bold text-gray-400"> ۴</div>
<div className="h-4 w-px bg-gray-300"></div>
<div className="text-gray-500">+۱۰۰۰ دانلود</div>
<div className="h-4 w-px bg-gray-300"></div>
<div className="text-gray-500">۹۸٪ رضایت</div>
<div className="flex justify-center items-center gap-8 opacity-80">
<div className="text-2xl font-bold text-primary-500"> ۴</div>
<div className="h-4 w-px bg-primary-300"></div>
<div className="text-primary-500 font-bold">+۱۰۰۰ دانلود</div>
<div className="h-4 w-px bg-primary-300"></div>
<div className="text-primary-500 font-bold ">۹۸٪ رضایت</div>
</div>
</div>
</div>
+17
View File
@@ -0,0 +1,17 @@
// Brand mark for آرام جان — the real app icon (blue→indigo lotus) served as a
// vector from /logo.svg, so it stays crisp at any size and matches the store
// icon exactly. Size it with `className` (e.g. "w-9 h-9"); corners are rounded
// like an app icon.
function LotusLogo({ className = "w-9 h-9", title = "آرام جان" }) {
return (
<span className={`inline-block overflow-hidden rounded-[22%] ${className}`}>
<img
src="/logo.svg"
alt={title}
className="w-full h-full object-cover"
/>
</span>
);
}
export default LotusLogo;
+33
View File
@@ -0,0 +1,33 @@
// components/SEOHead.jsx
export function SEOHead({
title,
description,
canonical,
ogImage = ''
}) {
const siteUrl = 'https://aramejan.com';
return (
<>
<title>{title}</title>
<meta name="description" content={description} />
{/* Canonical URL */}
<link rel="canonical" href={`${siteUrl}${canonical}`} />
{/* Open Graph */}
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:url" content={`${siteUrl}${canonical}`} />
<meta property="og:image" content={ogImage || `${siteUrl}/og-image.jpg`} />
<meta property="og:type" content="website" />
<meta property="og:locale" content="fa_IR" />
{/* Twitter */}
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={ogImage || `${siteUrl}/og-image.jpg`} />
<meta name="twitter:card" content="summary_large_image" />
</>
);
}
+2 -2
View File
@@ -2,7 +2,7 @@
// const benefits = [
// {
// title: "تکنیک‌های مبتنی بر علم اعصاب",
// description: "آراملند از روش‌های اثبات‌شده علمی برای کاهش استرس و افزایش آرامش استفاده می‌کند",
// description: "آرام لند از روش‌های اثبات‌شده علمی برای کاهش استرس و افزایش آرامش استفاده می‌کند",
// icon: "🧠",
// items: [
// "بهبود خلق و خو در کمتر از ۵ دقیقه",
@@ -124,7 +124,7 @@
// 📊 پشتیبانی شده توسط تحقیقات
// </h4>
// <p className="text-gray-700 leading-relaxed">
// تمام تکنیک‌های استفاده شده در آراملند بر اساس مطالعات علمی معتبر در زمینه‌های
// تمام تکنیک‌های استفاده شده در آرام لند بر اساس مطالعات علمی معتبر در زمینه‌های
// روانشناسی، علوم اعصاب و پزشکی رفتاری طراحی شده‌اند.
// </p>
// </div>
+4 -4
View File
@@ -49,7 +49,7 @@ function WhatYouCanDo() {
];
return (
<div className="my-24">
<div className="my-12">
{/* Section Header */}
<div className="text-center mb-16">
<div className="inline-flex items-center gap-2 bg-primary-500/10 text-primary-500 px-4 py-2 rounded-full text-sm font-medium mb-4">
@@ -57,7 +57,7 @@ function WhatYouCanDo() {
قابلیتهای اصلی
</div>
<h2 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
هر آنچه برای <span className="text-primary-500">آرامش</span> نیاز داری
اینجا زندگی <span className="text-primary-500">آسون تر</span> میشه
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
ابزارهای متنوع و تخصصی برای رسیدن به آرامش در هر شرایطی
@@ -109,14 +109,14 @@ function WhatYouCanDo() {
</div>
{/* Bottom CTA */}
<div className="text-center">
{/* <div className="text-center">
<p className="text-gray-600 text-lg mb-6">
بیش از <span className="text-primary-500 font-bold">۱۰۰۰</span> کاربر از این ویژگی‌ها استفاده می‌کنند
</p>
<button className="bg-gradient-to-r from-primary-500 to-primary-600 text-white font-bold py-3 px-6 rounded-2xl hover:shadow-lg transition-all duration-300 transform hover:scale-105">
کشف همه قابلیت‌ها
</button>
</div>
</div> */}
</div>
);
}
+3 -3
View File
@@ -60,10 +60,10 @@ function WhyAramland() {
<div className="text-center mb-16">
<div className="inline-flex items-center gap-2 bg-primary-500/10 text-primary-500 px-4 py-2 rounded-full text-sm font-medium mb-4">
<span className="text-lg">🚀</span>
برتری آراملند
برتری آرام جان
</div>
<h2 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
چرا <span className="text-primary-500">هزاران نفر</span> آراملند را انتخاب میکنند؟
چرا <span className="text-primary-500">هزاران نفر</span> آرام جان را انتخاب میکنند؟
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
تجربهای متفاوت از آرامش، طراحی شده مخصوص فارسیزبانان
@@ -129,7 +129,7 @@ function WhyAramland() {
<div className="flex flex-col md:flex-row items-center justify-between gap-6">
<div className="flex-1">
<h4 className="text-2xl font-bold text-gray-900 mb-3">
👥 عضو جامعه هزاران نفری آراملند شوید
👥 عضو جامعه هزاران نفری آرام جان شوید
</h4>
<p className="text-gray-700 leading-relaxed">
به خانوادهای از کاربران خوشحال بپیوندید که هر روز قدمی به سمت آرامش برمیدارند
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

+46
View File
@@ -69,3 +69,49 @@ body {
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;
}
}
+40
View File
@@ -0,0 +1,40 @@
// hooks/useScroll.js
import { useCallback } from 'react';
export const useScroll = () => {
const scrollToSection = useCallback((sectionId, offset = 0) => {
if (typeof window === 'undefined') return;
const element = document.getElementById(sectionId);
if (element) {
const elementPosition = element.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.pageYOffset - offset;
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
});
}
}, []);
const scrollToSectionWithHeader = useCallback((sectionId) => {
const headerOffset = 80; // Adjust based on your header height
scrollToSection(sectionId, headerOffset);
}, [scrollToSection]);
const scrollToTop = useCallback(() => {
if (typeof window === 'undefined') return;
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}, []);
return {
scrollToSection,
scrollToSectionWithHeader,
scrollToTop
};
};
+90
View File
@@ -0,0 +1,90 @@
<svg width="600" height="600" viewBox="0 0 600 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2449_11924)">
<rect width="600" height="600" fill="white"/>
<rect width="600" height="600" fill="url(#paint0_linear_2449_11924)"/>
<mask id="mask0_2449_11924" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="67" y="127" width="307" height="307">
<circle cx="220.588" cy="280.488" r="152.894" fill="url(#paint1_linear_2449_11924)"/>
</mask>
<g mask="url(#mask0_2449_11924)">
<circle cx="379.598" cy="280.488" r="152.894" fill="url(#paint2_linear_2449_11924)"/>
</g>
<mask id="mask1_2449_11924" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="9" y="185" width="307" height="306">
<circle cx="162.544" cy="337.995" r="152.894" transform="rotate(-30 162.544 337.995)" fill="url(#paint3_linear_2449_11924)"/>
</mask>
<g mask="url(#mask1_2449_11924)">
<circle cx="300.25" cy="258.49" r="152.894" transform="rotate(-30 300.25 258.49)" fill="url(#paint4_linear_2449_11924)"/>
</g>
<mask id="mask2_2449_11924" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="145" y="105" width="307" height="307">
<circle cx="298.619" cy="258.491" r="152.894" transform="rotate(30 298.619 258.491)" fill="url(#paint5_linear_2449_11924)"/>
</mask>
<g mask="url(#mask2_2449_11924)">
<circle cx="436.325" cy="337.996" r="152.894" transform="rotate(30 436.325 337.996)" fill="url(#paint6_linear_2449_11924)"/>
</g>
<mask id="mask3_2449_11924" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="226" y="124" width="306" height="307">
<circle cx="379.004" cy="277.486" r="152.894" transform="rotate(60 379.004 277.486)" fill="url(#paint7_linear_2449_11924)"/>
</mask>
<g mask="url(#mask3_2449_11924)">
<circle cx="458.509" cy="415.192" r="152.894" transform="rotate(60 458.509 415.192)" fill="url(#paint8_linear_2449_11924)"/>
</g>
<mask id="mask4_2449_11924" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="-13" y="262" width="307" height="307">
<circle cx="140.491" cy="415.192" r="152.894" transform="rotate(-60 140.491 415.192)" fill="url(#paint9_linear_2449_11924)"/>
</mask>
<g mask="url(#mask4_2449_11924)">
<circle cx="219.996" cy="277.486" r="152.894" transform="rotate(-60 219.996 277.486)" fill="url(#paint10_linear_2449_11924)"/>
</g>
<ellipse cx="300.093" cy="434.911" rx="29.0498" ry="33.6366" fill="url(#paint11_linear_2449_11924)"/>
</g>
<defs>
<linearGradient id="paint0_linear_2449_11924" x1="300" y1="0" x2="300" y2="600" gradientUnits="userSpaceOnUse">
<stop stop-color="#3ABDEB"/>
<stop offset="1" stop-color="#553AEB"/>
</linearGradient>
<linearGradient id="paint1_linear_2449_11924" x1="220.588" y1="127.595" x2="220.588" y2="433.382" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint2_linear_2449_11924" x1="379.598" y1="127.595" x2="379.598" y2="433.382" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
</linearGradient>
<linearGradient id="paint3_linear_2449_11924" x1="162.544" y1="185.102" x2="162.544" y2="490.889" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint4_linear_2449_11924" x1="300.25" y1="105.597" x2="300.25" y2="411.384" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
</linearGradient>
<linearGradient id="paint5_linear_2449_11924" x1="298.619" y1="105.597" x2="298.619" y2="411.384" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint6_linear_2449_11924" x1="436.325" y1="185.102" x2="436.325" y2="490.889" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
</linearGradient>
<linearGradient id="paint7_linear_2449_11924" x1="379.004" y1="124.592" x2="379.004" y2="430.38" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint8_linear_2449_11924" x1="458.509" y1="262.298" x2="458.509" y2="568.086" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
</linearGradient>
<linearGradient id="paint9_linear_2449_11924" x1="140.491" y1="262.298" x2="140.491" y2="568.085" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint10_linear_2449_11924" x1="219.996" y1="124.593" x2="219.996" y2="430.38" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
</linearGradient>
<linearGradient id="paint11_linear_2449_11924" x1="300.093" y1="401.274" x2="300.093" y2="420.805" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0.4"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<clipPath id="clip0_2449_11924">
<rect width="600" height="600" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

+103 -8
View File
@@ -2,15 +2,70 @@ import type { Metadata } from 'next';
import './globals.css';
export const metadata: Metadata = {
title: 'آرام‌لند | تمرین تنفسی و مدیتیشن',
title: 'آرام جان | تمرین تنفسی و مدیتیشن',
description: 'لحظه‌ای آرام بگیر، زندگی را حس کن',
keywords: ['مدیتیشن فارسی', 'آرامش', 'تمرین تنفسی', 'کاهش استرس', 'ذهن‌آگاهی', 'مدیتیشن هدایت شده', 'سلامت روان', 'آرام جان'],
authors: [{ name: 'آرام جان' }],
creator: 'آرام جان',
publisher: 'آرام جان',
metadataBase: new URL('https://aramejan.com'),
formatDetection: {
email: false,
address: false,
telephone: false,
},
icons: {
icon: '/icon.svg',
},
alternates: {
canonical: '/',
languages: {
'fa-IR': '/',
},
},
openGraph: {
title: 'آرام جان - دستیار آرامش و مدیتیشن فارسی',
description: 'اپلیکیشن آرام جان - همراه شما برای رسیدن به آرامش درونی با مدیتیشن‌های فارسی و تمرین‌های تنفسی',
url: '/',
siteName: 'آرام جان',
images: [
{
url: '/og-image.jpg',
width: 1067,
height: 600,
alt: ' آرام جان - اپلیکیشن مدیتیشن و آرامش - تمرین تنفسی',
},
],
locale: 'fa_IR',
type: 'website',
},
twitter: {
card: 'summary_large_image',
title: 'آرام جان - تمرین تنفسی و مدیتیشن',
description: 'اپلیکیشن آرام جان - همراه شما برای رسیدن به آرامش درونی',
images: ['/og-image.jpg'],
creator: '@aramland', // Replace with your Twitter handle
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
verification: {
// Add your verification codes here
google: 'google-site-verification=HIKgdf_siYdPxbJ2P1792opMprpxci_QjE-quk9kyi8', // From Google Search Console
// yandex: 'your-yandex-verification-code', // If targeting Iran/Russia
},
};
<link
rel="icon"
href="/favicon.png"
type="image/<generated>"
sizes="<generated>"
/>
export default function RootLayout({
children,
}: {
@@ -19,7 +74,47 @@ export default function RootLayout({
return (
<html lang="fa" dir="rtl">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="google-site-verification"
content="HIKgdf_siYdPxbJ2P1792opMprpxci_QjE-quk9kyi8"
/>
{/* Favicon — lotus mark (آرام جان) */}
<link rel="icon" href="/icon.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="/logo-aram.png" />
{/* Preload critical resources */}
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
{/* Structured Data for SEO */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "WebApplication",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.5",
"ratingCount": "1000"
},
"name": "آرام جان",
"description": "اپلیکیشن آرام جان - همراه شما برای رسیدن به آرامش درونی با مدیتیشن‌های فارسی و تمرین‌های تنفسی",
"url": "https://aramejan.com/",
"applicationCategory": "HealthApplication",
"operatingSystem": "Android, iOS, Web",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "IRR"
},
"author": {
"@type": "Organization",
"name": "آرام جان"
}
})
}}
/>
</head>
<body className="antialiased">
{children}
+16
View File
@@ -0,0 +1,16 @@
// app/robots.txt
User-agent: *
Allow: /
Disallow: /api/
Disallow: /_next/
Disallow: /private/
Sitemap: https://aramejan.com/sitemap.xml
Sitemap: https://aramejan.com/blog/sitemap.xml
# Iranian search engines
User-agent: YoozBot
Allow: /
User-agent: Parsijoo
Allow: /
+44
View File
@@ -0,0 +1,44 @@
// app/sitemap.js
// Required for `output: 'export'` so Next emits a static /sitemap.xml.
export const dynamic = 'force-static';
export default function sitemap() {
const baseUrl = 'https://aramejan.com/';
return [
{
url: baseUrl,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 1,
},
// ⬇️ مقالات بلاگ — بعد از اینکه بلاگ روی aramejan.com/blog/ منتشر شد،
// این‌ها را از کامنت خارج کن. تا وقتی بلاگ بالا نیامده، در سایت‌مپ نباشند
// تا در سرچ کنسول خطای «صفحه یافت نشد / 404» نگیری.
// {
// url: `${baseUrl}blog/`,
// lastModified: new Date(),
// changeFrequency: 'weekly',
// priority: 0.9,
// },
// {
// url: `${baseUrl}blog/tmryn-tnfsy-bry-khhsh-strs.html`,
// lastModified: new Date(),
// changeFrequency: 'monthly',
// priority: 0.8,
// },
// {
// url: `${baseUrl}blog/mdytyshn-chyh.html`,
// lastModified: new Date(),
// changeFrequency: 'monthly',
// priority: 0.7,
// },
// {
// url: `${baseUrl}blog/khls-shdn-z-strs-b-arm-lnd.html`,
// lastModified: new Date(),
// changeFrequency: 'monthly',
// priority: 0.6,
// },
];
}
+1 -2
View File
@@ -1,7 +1,6 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
output: 'export',
};
export default nextConfig;
+2 -1
View File
@@ -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",
+12
View File
@@ -0,0 +1,12 @@
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.approagency.meditation",
"sha256_cert_fingerprints": [
"7B:43:79:DE:71:EB:86:4B:60:FF:8D:CC:49:7C:D3:F7:91:7B:86:EB:30:B7:2C:1A:CD:98:44:AC:34:9E:E4:DA"
]
}
}
]

Before

Width:  |  Height:  |  Size: 676 KiB

After

Width:  |  Height:  |  Size: 676 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

+90
View File
@@ -0,0 +1,90 @@
<svg width="600" height="600" viewBox="0 0 600 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2449_11924)">
<rect width="600" height="600" fill="white"/>
<rect width="600" height="600" fill="url(#paint0_linear_2449_11924)"/>
<mask id="mask0_2449_11924" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="67" y="127" width="307" height="307">
<circle cx="220.588" cy="280.488" r="152.894" fill="url(#paint1_linear_2449_11924)"/>
</mask>
<g mask="url(#mask0_2449_11924)">
<circle cx="379.598" cy="280.488" r="152.894" fill="url(#paint2_linear_2449_11924)"/>
</g>
<mask id="mask1_2449_11924" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="9" y="185" width="307" height="306">
<circle cx="162.544" cy="337.995" r="152.894" transform="rotate(-30 162.544 337.995)" fill="url(#paint3_linear_2449_11924)"/>
</mask>
<g mask="url(#mask1_2449_11924)">
<circle cx="300.25" cy="258.49" r="152.894" transform="rotate(-30 300.25 258.49)" fill="url(#paint4_linear_2449_11924)"/>
</g>
<mask id="mask2_2449_11924" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="145" y="105" width="307" height="307">
<circle cx="298.619" cy="258.491" r="152.894" transform="rotate(30 298.619 258.491)" fill="url(#paint5_linear_2449_11924)"/>
</mask>
<g mask="url(#mask2_2449_11924)">
<circle cx="436.325" cy="337.996" r="152.894" transform="rotate(30 436.325 337.996)" fill="url(#paint6_linear_2449_11924)"/>
</g>
<mask id="mask3_2449_11924" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="226" y="124" width="306" height="307">
<circle cx="379.004" cy="277.486" r="152.894" transform="rotate(60 379.004 277.486)" fill="url(#paint7_linear_2449_11924)"/>
</mask>
<g mask="url(#mask3_2449_11924)">
<circle cx="458.509" cy="415.192" r="152.894" transform="rotate(60 458.509 415.192)" fill="url(#paint8_linear_2449_11924)"/>
</g>
<mask id="mask4_2449_11924" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="-13" y="262" width="307" height="307">
<circle cx="140.491" cy="415.192" r="152.894" transform="rotate(-60 140.491 415.192)" fill="url(#paint9_linear_2449_11924)"/>
</mask>
<g mask="url(#mask4_2449_11924)">
<circle cx="219.996" cy="277.486" r="152.894" transform="rotate(-60 219.996 277.486)" fill="url(#paint10_linear_2449_11924)"/>
</g>
<ellipse cx="300.093" cy="434.911" rx="29.0498" ry="33.6366" fill="url(#paint11_linear_2449_11924)"/>
</g>
<defs>
<linearGradient id="paint0_linear_2449_11924" x1="300" y1="0" x2="300" y2="600" gradientUnits="userSpaceOnUse">
<stop stop-color="#3ABDEB"/>
<stop offset="1" stop-color="#553AEB"/>
</linearGradient>
<linearGradient id="paint1_linear_2449_11924" x1="220.588" y1="127.595" x2="220.588" y2="433.382" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint2_linear_2449_11924" x1="379.598" y1="127.595" x2="379.598" y2="433.382" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
</linearGradient>
<linearGradient id="paint3_linear_2449_11924" x1="162.544" y1="185.102" x2="162.544" y2="490.889" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint4_linear_2449_11924" x1="300.25" y1="105.597" x2="300.25" y2="411.384" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
</linearGradient>
<linearGradient id="paint5_linear_2449_11924" x1="298.619" y1="105.597" x2="298.619" y2="411.384" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint6_linear_2449_11924" x1="436.325" y1="185.102" x2="436.325" y2="490.889" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
</linearGradient>
<linearGradient id="paint7_linear_2449_11924" x1="379.004" y1="124.592" x2="379.004" y2="430.38" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint8_linear_2449_11924" x1="458.509" y1="262.298" x2="458.509" y2="568.086" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
</linearGradient>
<linearGradient id="paint9_linear_2449_11924" x1="140.491" y1="262.298" x2="140.491" y2="568.085" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint10_linear_2449_11924" x1="219.996" y1="124.593" x2="219.996" y2="430.38" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="white" stop-opacity="0.1"/>
</linearGradient>
<linearGradient id="paint11_linear_2449_11924" x1="300.093" y1="401.274" x2="300.093" y2="420.805" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0.4"/>
<stop offset="1" stop-color="white" stop-opacity="0"/>
</linearGradient>
<clipPath id="clip0_2449_11924">
<rect width="600" height="600" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

+49
View File
@@ -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"