This commit is contained in:
sofio
2026-02-03 16:02:41 +08:00
parent e87c9006a8
commit 30e0d480c2
11 changed files with 261 additions and 8 deletions

View File

@@ -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,
}: {

View File

@@ -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 {
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"),
icons: { icon: "/LOGO_header.png" },
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,
},
};
}

View File

@@ -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,
}: {

View File

@@ -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,
}: {

View File

@@ -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
View 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
View 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
View 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],
},
};
};

View File

@@ -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",

View File

@@ -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": "首頁",

View File

@@ -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": "首页",