feat: 服务器迁移后的全量演进(依赖升级/安全审计/设计统一/截图/SEO 底座化)

在原仓库历史之上同步本服务器上的全部演进:

- 迁移至新服务器并重建 PG 数据库 + ddnc 开发域名绑定
- 全部依赖升级至最新(Next 16.3.5 / React 19.3 / better-auth 1.7.5 / Drizzle 0.45 / TS 7),
  overrides 消除已知 CVE,安全审计 19 项发现全部修复闭环
- 设计统一:各站宽度 token(--container + site-container)、classic hero 重设计、
  头部换行修复、页面过渡与 View Transitions
- 截图功能:api.adx9.com 截图服务接入(ow=800 本地化 webp、cf=1、去重/限流/占位图)
- SEO 底座化:canonical/hreflang/sitemap/JSON-LD/robots 全部收进 core,新站自动继承
- 加载体验:五站五形态路由骨架(data-theme 切换、shimmer 微光、延迟淡入)+
  过滤 useTransition 交叉淡入淡出(card-enter 错峰入场)
- 构建:experimental.cpus 限流防 PG 连接打满;清理死组件链
This commit is contained in:
bigcode
2026-09-15 18:19:53 +08:00
parent 0eed5183b2
commit 05440ffb5b
144 changed files with 3055 additions and 12937 deletions
+24 -23
View File
@@ -110,7 +110,7 @@
"items": [
{
"name": "Sarah Chen",
"quote": "Toolso.AI helped me find the perfect AI writing assistant. The categorization makes discovery so easy!",
"quote": "LaunchAI helped me find the perfect AI writing assistant. The categorization makes discovery so easy!",
"designation": "Content Creator"
},
{
@@ -120,7 +120,7 @@
},
{
"name": "Emily Rodriguez",
"quote": "I discover new AI tools every week on Toolso.AI. It's become my go-to resource for AI exploration.",
"quote": "I discover new AI tools every week on LaunchAI. It's become my go-to resource for AI exploration.",
"designation": "Startup Founder"
},
{
@@ -669,48 +669,49 @@
},
"clearFilters": "Clear search & filters",
"useCasesTitle": "Use cases",
"goodForTitle": "Good for"
"goodForTitle": "Good for",
"preview": "Website preview"
},
"seo": {
"home": {
"title": "LaunchAI — Discover and Upvote Today's AI Products",
"description": "A daily launch feed for AI products. Upvote the best AI tools, follow makers and climb the leaderboard.",
"ogImage": "https://toolso.ai/banner.png"
"ogImage": "/banner.png"
},
"blog": {
"title": "Blog - Toolso.AI",
"title": "Blog - LaunchAI",
"description": "Latest insights, tutorials and updates about AI tools. Stay informed about the best AI tools and industry trends.",
"ogImage": "https://toolso.ai/banner.png"
"ogImage": "/banner.png"
},
"contact": {
"title": "Contact Us - Toolso.AI",
"title": "Contact Us - LaunchAI",
"description": "Get in touch with us. We'd love to hear your feedback and tool suggestions.",
"ogImage": "https://toolso.ai/banner.png"
"ogImage": "/banner.png"
},
"login": {
"title": "Login - Toolso.AI",
"title": "Login - LaunchAI",
"description": "Sign in to your account to submit tools, save favorites, and contribute to our AI tools directory.",
"ogImage": "https://toolso.ai/banner.png"
"ogImage": "/banner.png"
},
"signup": {
"title": "Sign Up - Toolso.AI",
"title": "Sign Up - LaunchAI",
"description": "Create your account and start contributing to our AI tools directory. Submit tools and join our community.",
"ogImage": "https://toolso.ai/banner.png"
"ogImage": "/banner.png"
},
"terms": {
"title": "Terms of Service - Toolso.AI",
"description": "Read our terms of service to understand the rules and guidelines for using Toolso.AI.",
"ogImage": "https://toolso.ai/banner.png"
"title": "Terms of Service - LaunchAI",
"description": "Read our terms of service to understand the rules and guidelines for using LaunchAI.",
"ogImage": "/banner.png"
},
"privacy": {
"title": "Privacy Policy - Toolso.AI",
"description": "Learn how we collect, use, and protect your personal information and data on Toolso.AI.",
"ogImage": "https://toolso.ai/banner.png"
"title": "Privacy Policy - LaunchAI",
"description": "Learn how we collect, use, and protect your personal information and data on LaunchAI.",
"ogImage": "/banner.png"
},
"cookies": {
"title": "Cookie Policy - Toolso.AI",
"description": "Understand how we use cookies and similar tracking technologies on Toolso.AI.",
"ogImage": "https://toolso.ai/banner.png"
"title": "Cookie Policy - LaunchAI",
"description": "Understand how we use cookies and similar tracking technologies on LaunchAI.",
"ogImage": "/banner.png"
},
"tools": {
"title": "AI Tools Directory - Discover the Best AI Tools",
@@ -949,7 +950,7 @@
"launchButton": "Launch your product",
"featuredLabel": "Featured story",
"featuredRead": "Read the story",
"picksEditorialLabel": "EDITOR'S PICKS",
"picksEditorialLabel": "Editor's picks",
"guidesTitle": "Buying guides",
"guidesSubtitle": "Deep dives that help you choose",
"guidesViewAll": "All guides",
@@ -1092,4 +1093,4 @@
"siteHeader": {
"searchPlaceholder": "Search AI products..."
}
}
}
+25 -24
View File
@@ -105,11 +105,11 @@
},
"testimonials": {
"title": "用户评价",
"subtitle": "来自使用 Toolso.AI 发现优质 AI 工具的真实用户反馈。",
"subtitle": "来自使用 LaunchAI 发现优质 AI 工具的真实用户反馈。",
"items": [
{
"name": "张伟",
"quote": "Toolso.AI 帮我找到了完美的 AI 写作助手,分类清晰让发现变得非常简单!",
"quote": "LaunchAI 帮我找到了完美的 AI 写作助手,分类清晰让发现变得非常简单!",
"designation": "内容创作者"
},
{
@@ -119,7 +119,7 @@
},
{
"name": "李娜",
"quote": "每周都能在 Toolso.AI 上发现新的 AI 工具,已经成为我探索 AI 的首选资源。",
"quote": "每周都能在 LaunchAI 上发现新的 AI 工具,已经成为我探索 AI 的首选资源。",
"designation": "创业者"
},
{
@@ -523,7 +523,7 @@
"description": "请联系我们,我们会尽快回复。",
"testimonial": {
"title": "帮助用户发现最佳 AI 工具",
"description": "Toolso.AI 致力于为用户提供精选的 AI 工具目录,帮助大家找到最适合的 AI 助手。"
"description": "LaunchAI 致力于为用户提供精选的 AI 工具目录,帮助大家找到最适合的 AI 助手。"
},
"form": {
"nameLabel": "姓名",
@@ -676,48 +676,49 @@
},
"clearFilters": "清除搜索与筛选",
"useCasesTitle": "使用场景",
"goodForTitle": "适合人群"
"goodForTitle": "适合人群",
"preview": "网站预览"
},
"seo": {
"home": {
"title": "LaunchAI — 发现并投票今日 AI 新品",
"description": "AI 产品每日发布社区:为最好的 AI 工具投票,登上社区排行榜。",
"ogImage": "https://toolso.ai/banner.png"
"ogImage": "/banner.png"
},
"blog": {
"title": "博客 - Toolso.AI",
"title": "博客 - LaunchAI",
"description": "关于 AI 工具的最新资讯、教程和更新。了解最佳 AI 工具和行业趋势。",
"ogImage": "https://toolso.ai/banner.png"
"ogImage": "/banner.png"
},
"contact": {
"title": "联系我们 - Toolso.AI",
"title": "联系我们 - LaunchAI",
"description": "与我们取得联系。我们期待听到您的反馈和工具推荐建议。",
"ogImage": "https://toolso.ai/banner.png"
"ogImage": "/banner.png"
},
"login": {
"title": "登录 - Toolso.AI",
"title": "登录 - LaunchAI",
"description": "登录您的账户,提交工具、收藏喜爱的工具,为 AI 工具目录做贡献。",
"ogImage": "https://toolso.ai/banner.png"
"ogImage": "/banner.png"
},
"signup": {
"title": "注册 - Toolso.AI",
"title": "注册 - LaunchAI",
"description": "创建您的账户,开始为 AI 工具目录做贡献。提交工具、加入我们的社区。",
"ogImage": "https://toolso.ai/banner.png"
"ogImage": "/banner.png"
},
"terms": {
"title": "服务条款 - Toolso.AI",
"description": "阅读我们的服务条款,了解使用 Toolso.AI 的规则和指南。",
"ogImage": "https://toolso.ai/banner.png"
"title": "服务条款 - LaunchAI",
"description": "阅读我们的服务条款,了解使用 LaunchAI 的规则和指南。",
"ogImage": "/banner.png"
},
"privacy": {
"title": "隐私政策 - Toolso.AI",
"description": "了解我们如何在 Toolso.AI 上收集、使用和保护您的个人信息和数据。",
"ogImage": "https://toolso.ai/banner.png"
"title": "隐私政策 - LaunchAI",
"description": "了解我们如何在 LaunchAI 上收集、使用和保护您的个人信息和数据。",
"ogImage": "/banner.png"
},
"cookies": {
"title": "Cookie 政策 - Toolso.AI",
"description": "了解我们如何在 Toolso.AI 上使用 cookies 和类似的跟踪技术。",
"ogImage": "https://toolso.ai/banner.png"
"title": "Cookie 政策 - LaunchAI",
"description": "了解我们如何在 LaunchAI 上使用 cookies 和类似的跟踪技术。",
"ogImage": "/banner.png"
},
"tools": {
"title": "AI 工具库 - 发现最好的 AI 工具",
@@ -1099,4 +1100,4 @@
"siteHeader": {
"searchPlaceholder": "搜索 AI 产品..."
}
}
}
+16 -16
View File
@@ -11,24 +11,24 @@
},
"dependencies": {
"@aidir/core": "workspace:*",
"next": "16.1.1",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"next-intl": "^4.7.0",
"next": "^16.3.5",
"react": "^19.3.0",
"react-dom": "^19.3.0",
"next-intl": "^4.14.5",
"next-themes": "^0.4.6",
"next-view-transitions": "^0.3.5",
"sonner": "^2.0.7",
"geist": "^1.3.0",
"lucide-react": "^0.562.0",
"framer-motion": "^12.43.0"
"sonner": "^2.0.8",
"geist": "^1.7.2",
"lucide-react": "^1.46.0",
"framer-motion": "^13.3.0"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@types/mdx": "^2.0.13",
"typescript": "^5",
"tailwindcss": "^3.4.1",
"postcss": "^8"
"@types/node": "^26.5.1",
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
"@types/mdx": "^2.0.14",
"typescript": "^7.0.2",
"tailwindcss": "^3.4.19",
"postcss": "^8.5.28"
}
}
}
-24
View File
@@ -1,24 +0,0 @@
# robots.txt for Toolso.AI - AI Tools Directory
# https://toolso.ai
User-agent: *
Allow: /
# Disallow admin and API pages
Disallow: /admin/
Disallow: /api/
# Disallow authentication pages
Disallow: /*/signup
Disallow: /*/login
Disallow: /*/check-email
Disallow: /*/verify-email
Disallow: /*/forgot-password
Disallow: /*/reset-password
# Disallow protected user pages
Disallow: /*/dashboard
Disallow: /*/profile
# Sitemap location
Sitemap: https://toolso.ai/sitemap.xml
@@ -1,2 +1,2 @@
// 自动生成:[locale]/(admin)/layout.tsx 的薄路由
export { default } from "@aidir/core/pages/[locale]/(admin)/layout";
export { default, metadata } from "@aidir/core/pages/[locale]/(admin)/layout";
@@ -1,2 +1,2 @@
// 自动生成:[locale]/(auth)/layout.tsx 的薄路由
export { default } from "@aidir/core/pages/[locale]/(auth)/layout";
export { default, metadata } from "@aidir/core/pages/[locale]/(auth)/layout";
@@ -1,2 +1,2 @@
// 自动生成:[locale]/(protected)/layout.tsx 的薄路由
export { default } from "@aidir/core/pages/[locale]/(protected)/layout";
export { default, metadata } from "@aidir/core/pages/[locale]/(protected)/layout";
+1 -1
View File
@@ -1,2 +1,2 @@
// 自动生成:[locale]/layout.tsx 的薄路由
export { default, generateStaticParams } from "@aidir/core/pages/[locale]/layout";
export { default, generateMetadata, generateStaticParams } from "@aidir/core/pages/[locale]/layout";
@@ -0,0 +1,2 @@
// 自动生成:api/screenshots/[slug]/route.ts 的薄路由
export { GET } from "@aidir/core/pages/api/screenshots/[slug]/route";
+2
View File
@@ -0,0 +1,2 @@
// 自动生成:robots.ts 的薄路由
export { default } from "@aidir/core/pages/robots";
+12 -54
View File
@@ -1,6 +1,6 @@
// 自动生成:站点首页组件(源自底座 product 形态,品牌来自 @/site/brand)
import { siteConfig } from "@/site/brand";
import { Flame, Trophy, Rocket, ChevronRight, MessageSquare } from "lucide-react";
import { Rocket, ChevronRight, MessageSquare } from "lucide-react";
import { getTranslations } from "next-intl/server";
import { VoteButton } from "@/features/voting/components/vote-button";
import { LocaleLink } from "@/components/locale-link";
@@ -8,45 +8,6 @@ import { ToolLogo } from "@/components/tool-logo";
import { SectionHeader } from "@/kit/section";
import { getHomeDataSafe } from "@/kit/home-data";
/** Product:AI 产品社区(Daily Launch / Upvote / Maker) */
const navItems = [
{ label: "Today", href: "/" },
{ label: "Leaderboard", href: "/rankings" },
{ label: "Categories", href: "/tools" },
{ label: "Collections", href: "/best" },
{ label: "Blog", href: "/blog" },
{ label: "Submit", href: "/submit" },
];
const footerGroups = [
{
title: "Community",
links: [
{ label: "Submit a Product", href: "/submit" },
{ label: "Leaderboard", href: "/rankings" },
{ label: "Dashboard", href: "/dashboard" },
],
},
{
title: "Explore",
links: [
{ label: "All Products", href: "/tools" },
{ label: "Use Cases", href: "/ai-tools-for" },
{ label: "Collections", href: "/best" },
],
},
{
title: "About",
links: [
{ label: "Blog", href: "/blog" },
{ label: "Terms", href: "/terms" },
{ label: "Privacy", href: "/privacy" },
],
},
];
/** 单条 Launch 卡片:PH 风格(大投票块 + 产品信息 + 互动) */
function LaunchRow({
tool,
@@ -110,18 +71,18 @@ async function SiteHome({ locale }: { locale: string }) {
return (
<div className="min-h-screen bg-background">
{/* Hero:今日发布 */}
<section className="hero-launch border-b border-border bg-gradient-to-b from-primary/5 to-background">
<div className="mx-auto max-w-5xl px-4 py-12 text-center sm:px-6 md:py-16">
<h1 className="text-2xl font-extrabold tracking-tight text-foreground sm:text-4xl">
{/* Hero:亮底排版,橙色只留给主按钮 */}
<section className="border-b border-border">
<div className="site-container px-4 py-12 text-center sm:px-6 md:py-16">
<h1 className="text-balance text-2xl font-extrabold tracking-tight text-foreground sm:text-4xl">
{th("title")}
</h1>
<p className="mt-3 text-sm text-muted-foreground sm:text-base">
<p className="mx-auto mt-3 max-w-xl text-sm leading-relaxed text-muted-foreground sm:text-base">
{th("description")}
</p>
<LocaleLink
href="/submit"
className="mt-6 inline-flex items-center gap-1.5 rounded-full bg-primary px-6 py-2.5 text-sm font-semibold text-primary-foreground shadow transition-all hover:opacity-90"
className="mt-6 inline-flex items-center gap-1.5 rounded-lg bg-primary px-6 py-2.5 text-sm font-semibold text-primary-foreground transition-opacity hover:opacity-90"
>
<Rocket className="h-4 w-4" />
{t("launchButton")}
@@ -129,14 +90,13 @@ async function SiteHome({ locale }: { locale: string }) {
</div>
</section>
<div className="mx-auto grid max-w-5xl gap-8 px-4 py-10 sm:px-6 lg:grid-cols-[1fr_280px]">
<div className="site-container grid gap-8 px-4 py-10 sm:px-6 lg:grid-cols-[1fr_280px]">
{/* 产品 Feed */}
<div>
<div className="overflow-hidden rounded-2xl border border-border bg-background">
<div className="flex items-center gap-2 border-b border-border bg-secondary/30 px-4 py-3 sm:px-6">
<Flame className="h-4 w-4 text-primary" />
<h2 className="text-sm font-bold text-foreground">Today's feed</h2>
</div>
<div className="flex items-center justify-between border-b border-border px-4 py-3 sm:px-6">
<h2 className="text-sm font-bold text-foreground">Today's feed</h2>
</div>
{data.trending.length > 0 ? (
data.trending.map((tool, i) => (
<LaunchRow key={tool.id} tool={tool} locale={locale} rank={i + 1} />
@@ -172,8 +132,7 @@ async function SiteHome({ locale }: { locale: string }) {
<aside className="space-y-6">
{data.popular.length > 0 && (
<div className="rounded-2xl border border-border bg-background p-5">
<div className="flex items-center gap-2">
<Trophy className="h-4 w-4 text-primary" />
<div className="flex items-center justify-between">
<h3 className="text-sm font-bold text-foreground">Leaderboard</h3>
</div>
<ol className="mt-4 space-y-3">
@@ -255,5 +214,4 @@ async function SiteHome({ locale }: { locale: string }) {
</div>
);
}
export { SiteHome };