feat(website): Next.js 16 marketing website with RTL/Farsi
Marketing website for Meezi platform: - Server-side rendered pages: home, demo, blog, pricing - RTL/Farsi layout with Vazirmatn font - SEO metadata and Open Graph tags - proxy.ts for Next.js 16 middleware convention - MEEZI_API_URL internal Docker network routing Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
type JsonLdType = "SoftwareApplication" | "Organization" | "BlogPosting" | "WebSite" | "FAQPage";
|
||||
|
||||
interface JsonLdProps {
|
||||
type: JsonLdType;
|
||||
locale: string;
|
||||
data?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
const BASE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "https://meezi.ir";
|
||||
|
||||
function buildSoftwareApplication(locale: string) {
|
||||
return {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "SoftwareApplication",
|
||||
name: "Meezi",
|
||||
alternateName: "میزی",
|
||||
applicationCategory: "BusinessApplication",
|
||||
operatingSystem: "Web, Android, iOS",
|
||||
url: BASE_URL,
|
||||
description:
|
||||
locale === "fa"
|
||||
? "پلتفرم هوشمند مدیریت کافه و رستوران — منوی QR، سیستم POS، تحلیل فروش و مدیریت کارکنان"
|
||||
: "Smart cafe & restaurant management — QR menu, POS system, sales analytics and staff management",
|
||||
offers: {
|
||||
"@type": "Offer",
|
||||
price: "0",
|
||||
priceCurrency: "IRR",
|
||||
name: locale === "fa" ? "پلن رایگان" : "Free Plan",
|
||||
},
|
||||
publisher: {
|
||||
"@type": "Organization",
|
||||
name: "Meezi",
|
||||
url: BASE_URL,
|
||||
},
|
||||
inLanguage: locale === "fa" ? "fa-IR" : "en",
|
||||
};
|
||||
}
|
||||
|
||||
function buildOrganization(locale: string) {
|
||||
return {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
name: "Meezi",
|
||||
alternateName: "میزی",
|
||||
url: BASE_URL,
|
||||
logo: `${BASE_URL}/logo.png`,
|
||||
description:
|
||||
locale === "fa"
|
||||
? "پلتفرم هوشمند مدیریت کافه و رستوران ایران"
|
||||
: "Smart cafe & restaurant management platform for Iran",
|
||||
foundingDate: "2022",
|
||||
foundingLocation: "Tehran, Iran",
|
||||
contactPoint: {
|
||||
"@type": "ContactPoint",
|
||||
contactType: locale === "fa" ? "پشتیبانی" : "Customer Support",
|
||||
availableLanguage: ["Persian", "English"],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function buildFAQPage(locale: string) {
|
||||
const faqs =
|
||||
locale === "fa"
|
||||
? [
|
||||
{ q: "آیا برای استفاده از میزی به دانش فنی نیاز است؟", a: "خیر. میزی برای استفاده توسط افراد غیرفنی طراحی شده. راهاندازی اولیه توسط تیم پشتیبانی انجام میشود." },
|
||||
{ q: "آیا دادههایم امن هستند؟", a: "بله. تمام دادههای شما روی سرورهای ایرانی با رمزگذاری TLS ذخیره میشوند. پشتیبانگیری خودکار روزانه انجام میشود." },
|
||||
{ q: "آیا میتوانم پلن را تغییر دهم؟", a: "بله. میتوانید هر زمان پلنتان را ارتقا یا تغییر دهید. هزینه بهصورت پرو-ریت محاسبه میشود." },
|
||||
{ q: "آیا میزی با دستگاههای موجودم کار میکند؟", a: "بله. میزی یک وباپلیکیشن است و روی هر دستگاهی با مرورگر مدرن کار میکند — ویندوز، مک، تبلت و موبایل." },
|
||||
{ q: "پشتیبانی چگونه است؟", a: "پلن استارتر پشتیبانی ایمیلی دارد. پلن کسبوکار پشتیبانی تلفنی و چت دارد. پلن سازمانی پشتیبانی ۲۴/۷ با مدیر حساب اختصاصی." },
|
||||
]
|
||||
: [
|
||||
{ q: "Do I need technical knowledge to use Meezi?", a: "No. Meezi is designed for non-technical users. Initial setup is handled by our support team." },
|
||||
{ q: "Is my data secure?", a: "Yes. All data is stored on Iranian servers with TLS encryption. Automatic daily backups are performed." },
|
||||
{ q: "Can I change my plan?", a: "Yes. You can upgrade or change your plan at any time. Upgrades are pro-rated." },
|
||||
{ q: "Does Meezi work with my existing devices?", a: "Yes. Meezi is a web application that works on any modern browser — Windows, Mac, tablet, and mobile." },
|
||||
{ q: "What's your support like?", a: "Starter has email support. Business has phone and chat support. Enterprise has 24/7 support with a dedicated account manager." },
|
||||
];
|
||||
return {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "FAQPage",
|
||||
mainEntity: faqs.map(({ q, a }) => ({
|
||||
"@type": "Question",
|
||||
name: q,
|
||||
acceptedAnswer: { "@type": "Answer", text: a },
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
function buildWebSite(locale: string) {
|
||||
return {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebSite",
|
||||
name: "Meezi",
|
||||
alternateName: "میزی",
|
||||
url: BASE_URL,
|
||||
inLanguage: locale === "fa" ? "fa-IR" : "en",
|
||||
potentialAction: {
|
||||
"@type": "SearchAction",
|
||||
target: {
|
||||
"@type": "EntryPoint",
|
||||
urlTemplate: `${BASE_URL}/${locale}/blog?q={search_term_string}`,
|
||||
},
|
||||
"query-input": "required name=search_term_string",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function JsonLd({ type, locale, data }: JsonLdProps) {
|
||||
let schema: Record<string, unknown>;
|
||||
|
||||
switch (type) {
|
||||
case "SoftwareApplication":
|
||||
schema = buildSoftwareApplication(locale);
|
||||
break;
|
||||
case "Organization":
|
||||
schema = buildOrganization(locale);
|
||||
break;
|
||||
case "WebSite":
|
||||
schema = buildWebSite(locale);
|
||||
break;
|
||||
case "FAQPage":
|
||||
schema = buildFAQPage(locale);
|
||||
break;
|
||||
case "BlogPosting":
|
||||
schema = { "@context": "https://schema.org", "@type": "BlogPosting", ...data };
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema, null, 0) }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user