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,85 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
import rehypePrism from "@mapbox/rehype-prism";
|
||||
import nextMDX from "@next/mdx";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import createNextIntlPlugin from 'next-intl/plugin';
|
||||
|
||||
const withNextIntl = createNextIntlPlugin('./src/lib/i18n.ts');
|
||||
|
||||
const pnpmManagedPath = path.join(process.cwd(), "node_modules", ".pnpm");
|
||||
const snapshotManagedPaths = fs.existsSync(pnpmManagedPath) ? [pnpmManagedPath] : [];
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// Docker 部署使用 standalone 输出
|
||||
// 多主题构建:SITE_THEME=<id> NEXT_DIST_DIR=.next-<id> next build
|
||||
// 每个主题独立产物(一个构建 = 一个站点),由 next start 直接服务
|
||||
...(process.env.NEXT_DIST_DIR
|
||||
? { distDir: process.env.NEXT_DIST_DIR }
|
||||
: { output: "standalone" }),
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: "https",
|
||||
hostname: "i.pravatar.cc",
|
||||
},
|
||||
{
|
||||
protocol: "https",
|
||||
hostname: "images.unsplash.com",
|
||||
},
|
||||
{
|
||||
protocol: "https",
|
||||
hostname: "a.offerget.pro",
|
||||
},
|
||||
{
|
||||
protocol: "https",
|
||||
hostname: "lh3.googleusercontent.com",
|
||||
},
|
||||
// Google favicon 服务(种子数据 logo 来源之一)
|
||||
{
|
||||
protocol: "https",
|
||||
hostname: "www.google.com",
|
||||
},
|
||||
// R2/S3 公共访问域名(上传的 logo/封面)
|
||||
...(process.env.STORAGE_PUBLIC_URL
|
||||
? [
|
||||
{
|
||||
protocol: "https",
|
||||
hostname: new URL(process.env.STORAGE_PUBLIC_URL).hostname,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
// 工具 logo 指向各工具官网的 favicon,域名不可枚举,放开 https 通配
|
||||
{
|
||||
protocol: "https",
|
||||
hostname: "**",
|
||||
},
|
||||
],
|
||||
},
|
||||
pageExtensions: ["ts", "tsx", "mdx"],
|
||||
turbopack: {
|
||||
rules: {
|
||||
'*.mdx': {
|
||||
loaders: ['@mdx-js/loader'],
|
||||
as: '*.js',
|
||||
},
|
||||
},
|
||||
},
|
||||
webpack(config) {
|
||||
config.snapshot ??= {};
|
||||
config.snapshot.managedPaths = snapshotManagedPaths;
|
||||
return config;
|
||||
},
|
||||
};
|
||||
|
||||
const withMDX = nextMDX({
|
||||
extension: /\.mdx?$/,
|
||||
options: {
|
||||
remarkPlugins: [remarkGfm],
|
||||
rehypePlugins: [rehypePrism],
|
||||
},
|
||||
});
|
||||
|
||||
export default withNextIntl(withMDX(nextConfig));
|
||||
Reference in New Issue
Block a user