seo
This commit is contained in:
@@ -1,10 +1,30 @@
|
||||
import { setRequestLocale } from "next-intl/server";
|
||||
import type { Metadata } from "next";
|
||||
import { getTranslations, setRequestLocale } from "next-intl/server";
|
||||
import { Locale } from "@/i18n/config";
|
||||
import { createPageMetadata } from "@/lib/seo";
|
||||
import AboutHeroSection from "@/components/AboutHeroSection";
|
||||
import ParentCompanySection from "@/components/ParentCompanySection";
|
||||
import TeamSection from "@/components/TeamSection";
|
||||
import MilestonesSection from "@/components/MilestonesSection";
|
||||
import RecruitSection from "@/components/RecruitSection";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
const t = await getTranslations({ locale, namespace: "metadata" });
|
||||
|
||||
return createPageMetadata({
|
||||
locale: locale as Locale,
|
||||
pathname: "/about",
|
||||
title: t("aboutTitle"),
|
||||
description: t("aboutDescription"),
|
||||
siteName: t("title"),
|
||||
});
|
||||
}
|
||||
|
||||
export default async function AboutPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import type { Metadata } from "next";
|
||||
import { NextIntlClientProvider, useMessages } from "next-intl";
|
||||
import { NextIntlClientProvider } from "next-intl";
|
||||
import { getTranslations, setRequestLocale } from "next-intl/server";
|
||||
import { notFound } from "next/navigation";
|
||||
import { routing } from "@/i18n/routing";
|
||||
import { Locale } from "@/i18n/config";
|
||||
import { getBaseUrl, ogImage } from "@/lib/seo";
|
||||
import "../globals.css";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
@@ -25,10 +26,35 @@ export async function generateMetadata({
|
||||
}): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
const t = await getTranslations({ locale, namespace: "metadata" });
|
||||
const baseUrl = getBaseUrl();
|
||||
|
||||
return {
|
||||
title: t("title"),
|
||||
metadataBase: baseUrl,
|
||||
title: {
|
||||
default: t("title"),
|
||||
template: `%s | ${t("title")}`,
|
||||
},
|
||||
description: t("description"),
|
||||
keywords: t("keywords"),
|
||||
applicationName: t("title"),
|
||||
icons: { icon: "/LOGO_header.png" },
|
||||
openGraph: {
|
||||
title: t("title"),
|
||||
description: t("description"),
|
||||
siteName: t("title"),
|
||||
type: "website",
|
||||
images: [{ url: ogImage, alt: t("title") }],
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: t("title"),
|
||||
description: t("description"),
|
||||
images: [ogImage],
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,29 @@
|
||||
import { setRequestLocale } from "next-intl/server";
|
||||
import type { Metadata } from "next";
|
||||
import { getTranslations, setRequestLocale } from "next-intl/server";
|
||||
import { Locale } from "@/i18n/config";
|
||||
import { createPageMetadata } from "@/lib/seo";
|
||||
import HeroSection from "@/components/HeroSection";
|
||||
import FlywheelSection from "@/components/FlywheelSection";
|
||||
import MarketSection from "@/components/MarketSection";
|
||||
import CTASection from "@/components/CTASection";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
const t = await getTranslations({ locale, namespace: "metadata" });
|
||||
|
||||
return createPageMetadata({
|
||||
locale: locale as Locale,
|
||||
pathname: "/",
|
||||
title: t("homeTitle"),
|
||||
description: t("homeDescription"),
|
||||
siteName: t("title"),
|
||||
});
|
||||
}
|
||||
|
||||
export default async function Home({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
import type { Metadata } from "next";
|
||||
import { setRequestLocale, getTranslations } from "next-intl/server";
|
||||
import { Locale } from "@/i18n/config";
|
||||
import { createPageMetadata } from "@/lib/seo";
|
||||
import SolutionsHeroSection from "@/components/SolutionsHeroSection";
|
||||
import ScenarioSection from "@/components/ScenarioSection";
|
||||
import SolutionsCTASection from "@/components/SolutionsCTASection";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
const t = await getTranslations({ locale, namespace: "metadata" });
|
||||
|
||||
return createPageMetadata({
|
||||
locale: locale as Locale,
|
||||
pathname: "/solutions",
|
||||
title: t("solutionsTitle"),
|
||||
description: t("solutionsDescription"),
|
||||
siteName: t("title"),
|
||||
});
|
||||
}
|
||||
|
||||
export default async function SolutionsPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -1,10 +1,30 @@
|
||||
import { setRequestLocale } from "next-intl/server";
|
||||
import type { Metadata } from "next";
|
||||
import { getTranslations, setRequestLocale } from "next-intl/server";
|
||||
import { Locale } from "@/i18n/config";
|
||||
import { createPageMetadata } from "@/lib/seo";
|
||||
import TechHeroSection from "@/components/TechHeroSection";
|
||||
import ArchitectureSection from "@/components/ArchitectureSection";
|
||||
import AICapabilitiesSection from "@/components/AICapabilitiesSection";
|
||||
import Web3CapabilitiesSection from "@/components/Web3CapabilitiesSection";
|
||||
import TechCTASection from "@/components/TechCTASection";
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
const t = await getTranslations({ locale, namespace: "metadata" });
|
||||
|
||||
return createPageMetadata({
|
||||
locale: locale as Locale,
|
||||
pathname: "/tech",
|
||||
title: t("techTitle"),
|
||||
description: t("techDescription"),
|
||||
siteName: t("title"),
|
||||
});
|
||||
}
|
||||
|
||||
export default async function TechPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
15
src/app/robots.ts
Normal file
15
src/app/robots.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { MetadataRoute } from "next";
|
||||
import { siteUrl } from "@/lib/seo";
|
||||
|
||||
export default function robots(): MetadataRoute.Robots {
|
||||
return {
|
||||
rules: [
|
||||
{
|
||||
userAgent: "*",
|
||||
allow: "/",
|
||||
},
|
||||
],
|
||||
sitemap: `${siteUrl}/sitemap.xml`,
|
||||
host: siteUrl,
|
||||
};
|
||||
}
|
||||
19
src/app/sitemap.ts
Normal file
19
src/app/sitemap.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { MetadataRoute } from "next";
|
||||
import { routing } from "@/i18n/routing";
|
||||
import { Locale } from "@/i18n/config";
|
||||
import { buildUrl, getLocalePath } from "@/lib/seo";
|
||||
|
||||
const staticRoutes = ["/", "/tech", "/solutions", "/about"] as const;
|
||||
|
||||
export default function sitemap(): MetadataRoute.Sitemap {
|
||||
const lastModified = new Date();
|
||||
|
||||
return staticRoutes.flatMap((pathname) =>
|
||||
routing.locales.map((locale) => ({
|
||||
url: buildUrl(getLocalePath(locale as Locale, pathname)),
|
||||
lastModified,
|
||||
changeFrequency: pathname === "/" ? "weekly" : "monthly",
|
||||
priority: pathname === "/" ? 1 : 0.7,
|
||||
})),
|
||||
);
|
||||
}
|
||||
86
src/lib/seo.ts
Normal file
86
src/lib/seo.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import type { Metadata } from "next";
|
||||
import { routing } from "@/i18n/routing";
|
||||
import { defaultLocale, Locale } from "@/i18n/config";
|
||||
|
||||
const rawSiteUrl =
|
||||
process.env.NEXT_PUBLIC_SITE_URL ||
|
||||
process.env.SITE_URL ||
|
||||
"http://localhost:3000";
|
||||
|
||||
const normalizedSiteUrl = rawSiteUrl.match(/^https?:\/\//)
|
||||
? rawSiteUrl
|
||||
: `https://${rawSiteUrl}`;
|
||||
|
||||
export const siteUrl = normalizedSiteUrl.replace(/\/+$/, "");
|
||||
export const ogImage = "/LOGO_header.png";
|
||||
|
||||
const trimSlashes = (value: string) => value.replace(/^\/+|\/+$/g, "");
|
||||
|
||||
export const getBaseUrl = () => {
|
||||
try {
|
||||
return new URL(siteUrl);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export const getLocalePath = (locale: Locale, pathname: string) => {
|
||||
const cleaned = trimSlashes(pathname);
|
||||
const suffix = cleaned ? `/${cleaned}` : "";
|
||||
|
||||
if (locale === defaultLocale) {
|
||||
return suffix || "/";
|
||||
}
|
||||
|
||||
return `/${locale}${suffix}`;
|
||||
};
|
||||
|
||||
export const buildUrl = (pathname: string) => `${siteUrl}${pathname}`;
|
||||
|
||||
export const getAlternates = (pathname: string) =>
|
||||
Object.fromEntries(
|
||||
routing.locales.map((locale) => [
|
||||
locale,
|
||||
buildUrl(getLocalePath(locale as Locale, pathname)),
|
||||
]),
|
||||
) as Record<Locale, string>;
|
||||
|
||||
export const createPageMetadata = ({
|
||||
locale,
|
||||
pathname,
|
||||
title,
|
||||
description,
|
||||
siteName,
|
||||
}: {
|
||||
locale: Locale;
|
||||
pathname: string;
|
||||
title: string;
|
||||
description: string;
|
||||
siteName: string;
|
||||
}): Metadata => {
|
||||
const canonicalPath = getLocalePath(locale, pathname);
|
||||
const canonicalUrl = buildUrl(canonicalPath);
|
||||
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
alternates: {
|
||||
canonical: canonicalUrl,
|
||||
languages: getAlternates(pathname),
|
||||
},
|
||||
openGraph: {
|
||||
title,
|
||||
description,
|
||||
url: canonicalUrl,
|
||||
siteName,
|
||||
type: "website",
|
||||
images: [{ url: ogImage, alt: siteName }],
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title,
|
||||
description,
|
||||
images: [ogImage],
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,7 +1,16 @@
|
||||
{
|
||||
"metadata": {
|
||||
"title": "DESUN SINGULARITY",
|
||||
"description": "AI + Web3 Powered Full-Chain Asset Technology Platform"
|
||||
"description": "AI + Web3 Powered Full-Chain Asset Technology Platform",
|
||||
"homeTitle": "Reshaping Global Asset Value Networks",
|
||||
"homeDescription": "AI + Web3 Powered Full-Chain Asset Technology Platform",
|
||||
"techTitle": "Technology Stack",
|
||||
"techDescription": "Full-stack architecture combining AI, Web3, and asset operations for scalable real-world asset digitization.",
|
||||
"solutionsTitle": "Solutions",
|
||||
"solutionsDescription": "DeSpace smart space management, RWA services, and AI-driven quantitative management for asset value creation.",
|
||||
"aboutTitle": "About DESUN Singularity",
|
||||
"aboutDescription": "Technology-driven alternative asset management platform integrating AI, Web3, finance, and real estate operations.",
|
||||
"keywords": "AI, Web3, RWA, asset digitization, tokenization, quantitative management, smart space"
|
||||
},
|
||||
"header": {
|
||||
"home": "Home",
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
{
|
||||
"metadata": {
|
||||
"title": "DESUN SINGULARITY",
|
||||
"description": "AI + Web3 驅動的全鏈路資產科技平台"
|
||||
"description": "AI + Web3 驅動的全鏈路資產科技平台",
|
||||
"homeTitle": "重構全球資產價值網絡",
|
||||
"homeDescription": "AI + Web3 驅動的全鏈路資產科技平台",
|
||||
"techTitle": "技術體系",
|
||||
"techDescription": "AI 與 Web3 貫通的全棧技術架構,支撐實體資產數字化與規模化營運。",
|
||||
"solutionsTitle": "場景解決方案",
|
||||
"solutionsDescription": "DeSpace 空間管理、RWA 資產代幣化、量化資管等核心場景解決方案。",
|
||||
"aboutTitle": "關於德商奇點",
|
||||
"aboutDescription": "科技驅動的另類資產管理平台,融合 AI、Web3、金融與實體營運能力。",
|
||||
"keywords": "AI, Web3, RWA, 資產數字化, 資產代幣化, 量化資管, 空間管理"
|
||||
},
|
||||
"header": {
|
||||
"home": "首頁",
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
{
|
||||
"metadata": {
|
||||
"title": "DESUN SINGULARITY",
|
||||
"description": "AI + Web3 驱动的全链路资产科技平台"
|
||||
"description": "AI + Web3 驱动的全链路资产科技平台",
|
||||
"homeTitle": "重构全球资产价值网络",
|
||||
"homeDescription": "AI + Web3 驱动的全链路资产科技平台",
|
||||
"techTitle": "技术体系",
|
||||
"techDescription": "AI 与 Web3 贯通的全栈技术架构,支撑实体资产数字化与规模化运营。",
|
||||
"solutionsTitle": "场景解决方案",
|
||||
"solutionsDescription": "DeSpace 空间管理、RWA 资产代币化、量化资管等核心场景解决方案。",
|
||||
"aboutTitle": "关于德商奇点",
|
||||
"aboutDescription": "科技驱动的另类资产管理平台,融合 AI、Web3、金融与实体运营能力。",
|
||||
"keywords": "AI, Web3, RWA, 资产数字化, 资产代币化, 量化资管, 空间管理"
|
||||
},
|
||||
"header": {
|
||||
"home": "首页",
|
||||
|
||||
Reference in New Issue
Block a user