refactor: 主题系统 → monorepo 五个独立网站
- packages/core: @aidir/core 底座库(src/pages 页面组件体 1:1 镜像路由树 / kit 站点外壳工厂 / content/blog / scripts) - sites/: 5 个独立 Next.js 网站(ai-stack / launchai / the-ai-ledger / devai-tools / findai) - 每站独立 package.json / next.config / tailwind / messages / .env / 构建 - src/app 约 56 个薄路由文件(re-export 底座页面 + 内联路由段配置 revalidate/dynamic) - src/site/brand.tsx 站点配置 + src/site/home.tsx 站点首页(createMarketingLayout / createHomePage 工厂) - generate-site.mjs: 站点生成器(新增网站 = SITES 加条目,零 Core 修改) - start-all-sites.sh: 一键启动 3001-3005 - next-config.mjs: 底座统一 Next 配置工厂(next-intl + MDX + standalone) - 五站共享同一套 PostgreSQL / Better Auth / Admin(设计文档 §42) - 验证: 5 站 build OK / typecheck OK / 55 路由冒烟 200 / 品牌-内容-截图 差异确认 / 登录-投票-重复检测 e2e PASS
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import type { SiteConfig } from "@/kit/types";
|
||||
|
||||
// findai —— 独立站点的全部品牌/导航/页脚配置
|
||||
export const siteConfig: SiteConfig = {
|
||||
"port": 3005,
|
||||
"brand": {
|
||||
"name": "findai",
|
||||
"tagline": "The minimal AI tool search engine.",
|
||||
"headline": "What are you trying to do?",
|
||||
"subheadline": ""
|
||||
},
|
||||
"navItems": [
|
||||
{
|
||||
"label": "Search",
|
||||
"href": "/tools"
|
||||
},
|
||||
{
|
||||
"label": "Use Cases",
|
||||
"href": "/ai-tools-for"
|
||||
},
|
||||
{
|
||||
"label": "Rankings",
|
||||
"href": "/rankings"
|
||||
},
|
||||
{
|
||||
"label": "Submit",
|
||||
"href": "/submit"
|
||||
}
|
||||
],
|
||||
"footerGroups": [
|
||||
{
|
||||
"title": "Search",
|
||||
"links": [
|
||||
{
|
||||
"label": "All Tools",
|
||||
"href": "/tools"
|
||||
},
|
||||
{
|
||||
"label": "Use Cases",
|
||||
"href": "/ai-tools-for"
|
||||
},
|
||||
{
|
||||
"label": "Rankings",
|
||||
"href": "/rankings"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "About",
|
||||
"links": [
|
||||
{
|
||||
"label": "Submit a Tool",
|
||||
"href": "/submit"
|
||||
},
|
||||
{
|
||||
"label": "Privacy",
|
||||
"href": "/privacy"
|
||||
},
|
||||
{
|
||||
"label": "Terms",
|
||||
"href": "/terms"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"searchPlaceholder": "What do you need?",
|
||||
"seo": {
|
||||
"en": {
|
||||
"title": "findai — The Minimal AI Tool Search Engine",
|
||||
"description": "One search box, every AI tool. Describe what you're trying to do and find the right AI tool, ranked by the community."
|
||||
},
|
||||
"zh": {
|
||||
"title": "findai — 极简 AI 工具搜索引擎",
|
||||
"description": "一个搜索框,找遍全部 AI 工具。说出你想做的事,社区排名替你选。"
|
||||
}
|
||||
},
|
||||
"id": "findai"
|
||||
};
|
||||
@@ -0,0 +1,107 @@
|
||||
// 自动生成:站点首页组件(源自底座 minimal 形态,品牌来自 @/site/brand)
|
||||
import { siteConfig } from "@/site/brand";
|
||||
import { Search } from "lucide-react";
|
||||
import { ToolCardGrid } from "@/components/tool-card";
|
||||
import { LocaleLink } from "@/components/locale-link";
|
||||
import { getHomeDataSafe } from "@/kit/home-data";
|
||||
|
||||
/** Minimal:极简 AI 搜索引擎(一个框,一个任务) */
|
||||
|
||||
|
||||
const navItems = [
|
||||
{ label: "Search", href: "/tools" },
|
||||
{ label: "Use Cases", href: "/ai-tools-for" },
|
||||
{ label: "Rankings", href: "/rankings" },
|
||||
{ label: "Submit", href: "/submit" },
|
||||
];
|
||||
|
||||
const footerGroups = [
|
||||
{
|
||||
title: "Search",
|
||||
links: [
|
||||
{ label: "All Tools", href: "/tools" },
|
||||
{ label: "Use Cases", href: "/ai-tools-for" },
|
||||
{ label: "Rankings", href: "/rankings" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "About",
|
||||
links: [
|
||||
{ label: "Submit a Tool", href: "/submit" },
|
||||
{ label: "Privacy", href: "/privacy" },
|
||||
{ label: "Terms", href: "/terms" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const popularSearches = [
|
||||
"write a blog post",
|
||||
"generate video",
|
||||
"code assistant",
|
||||
"make a logo",
|
||||
"edit photos",
|
||||
"transcribe meetings",
|
||||
];
|
||||
|
||||
async function SiteHome({ locale }: { locale: string }) {
|
||||
const data = await getHomeDataSafe(6);
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col bg-background">
|
||||
{/* 极简搜索首屏 */}
|
||||
<section className="flex flex-1 flex-col items-center justify-center px-4 pb-16 pt-24 text-center">
|
||||
<LocaleLink href="/" className="text-3xl font-bold tracking-tight text-foreground">
|
||||
{siteConfig.brand.name}
|
||||
</LocaleLink>
|
||||
<p className="mt-1 text-xs uppercase tracking-[0.35em] text-muted-foreground">
|
||||
AI tool search
|
||||
</p>
|
||||
|
||||
<form action={`/${locale}/tools`} className="mt-10 w-full max-w-xl">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-5 top-1/2 h-5 w-5 -translate-y-1/2 text-muted-foreground" />
|
||||
<input
|
||||
name="search"
|
||||
autoFocus
|
||||
placeholder="I need to create marketing videos..."
|
||||
className="h-14 w-full rounded-full border border-border bg-background pl-14 pr-6 text-base text-foreground shadow-lg shadow-black/[0.03] placeholder:text-muted-foreground focus:border-primary/50 focus:outline-none focus:ring-4 focus:ring-primary/10"
|
||||
aria-label="Search AI tools"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div className="mt-6 flex flex-wrap items-center justify-center gap-2">
|
||||
{popularSearches.map((q) => (
|
||||
<LocaleLink
|
||||
key={q}
|
||||
href={`/tools?search=${encodeURIComponent(q)}`}
|
||||
className="rounded-full px-3 py-1.5 text-xs text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground"
|
||||
>
|
||||
{q}
|
||||
</LocaleLink>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 搜索之下:Trending */}
|
||||
{data.trending.length > 0 && (
|
||||
<section className="mx-auto w-full max-w-3xl px-4 pb-20 sm:px-6">
|
||||
<h2 className="mb-4 text-center text-xs font-medium uppercase tracking-[0.25em] text-muted-foreground">
|
||||
Trending now
|
||||
</h2>
|
||||
<ToolCardGrid tools={data.trending.slice(0, 4)} locale={locale} />
|
||||
<div className="mt-6 text-center">
|
||||
<LocaleLink
|
||||
href="/rankings"
|
||||
className="text-xs font-medium text-muted-foreground hover:text-primary"
|
||||
>
|
||||
See full rankings
|
||||
</LocaleLink>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { SiteHome };
|
||||
Reference in New Issue
Block a user