commit 7cd50654ed909fdf7b54b82582a3798f528a7cba Author: 砂糖 Date: Fri Nov 21 13:36:06 2025 +0800 init diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..f9c388d --- /dev/null +++ b/.env.example @@ -0,0 +1,42 @@ +# ----------------------------------------------------------------------------- +# Site info +# ----------------------------------------------------------------------------- +NEXT_PUBLIC_SITE_URL=http://localhost:3000 +NEXT_PUBLIC_LOCALE_DETECTION=false + +# ----------------------------------------------------------------------------- +# Discord +# ----------------------------------------------------------------------------- +NEXT_PUBLIC_DISCORD_INVITE_URL="https://discord.com/invite/R7bUxWKRqZ" + +# ----------------------------------------------------------------------------- +# Analytics +# Google Analytics: https://analytics.google.com/analytics/web/ +# Baidu Tongji: https://tongji.baidu.com/ +# Plausible: https://plausible.io/ +# ----------------------------------------------------------------------------- +NEXT_PUBLIC_GOOGLE_ID= +NEXT_PUBLIC_BAIDU_TONGJI= +NEXT_PUBLIC_PLAUSIBLE_DOMAIN= +NEXT_PUBLIC_PLAUSIBLE_SRC= + +#------------------------------------------------------------------------ +# Ads +# Google Adsense: https://www.google.com/adsense/ +#------------------------------------------------------------------------ +NEXT_PUBLIC_GOOGLE_ADSENSE_ID= + +#------------------------------------------------------------------------ +# Resend: https://resend.com/ +#------------------------------------------------------------------------ +RESEND_API_KEY= +ADMIN_EMAIL= +RESEND_AUDIENCE_ID= + +#------------------------------------------------------------------------ +# Upstash: https://upstash.com/ +#------------------------------------------------------------------------ +UPSTASH_REDIS_REST_URL= +UPSTASH_REDIS_REST_TOKEN= +UPSTASH_REDIS_NEWSLETTER_RATE_LIMIT_KEY=newsletter-rate-limit +DAY_MAX_SUBMISSIONS= \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..bffb357 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cfcdb3e --- /dev/null +++ b/.gitignore @@ -0,0 +1,133 @@ +### Node template +.idea +.DS_Store +dist + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.temp +yarn.lock + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.local +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the assets line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# assets + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# pnpm +.pnpm-store/ + +/.vuepress/dist/ + +# sitemap +*/sitemap*.xml +*/robots.txt \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..86efa26 --- /dev/null +++ b/.npmrc @@ -0,0 +1,4 @@ +# if use pnpm +enable-pre-post-scripts=true +public-hoist-pattern[]=*@nextui-org/* +registry=https://registry.npmmirror.com/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f8210cf --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,18 @@ +{ + "css.validate": false, + "editor.formatOnSave": true, + "editor.tabSize": 2, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit", + "source.organizeImports": "explicit" + }, + "headwind.runOnSave": false, + "typescript.preferences.importModuleSpecifier": "non-relative", + "eslint.validate": ["javascript", "javascriptreact", "typescript"], + "typescript.tsdk": "node_modules/typescript/lib", + "commentTranslate.source": "Bing", + "cSpell.words": [ + "contentlayer", + "lemonsqueezy" + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..a688f02 --- /dev/null +++ b/README.md @@ -0,0 +1,293 @@ +--- +Ship your SaaS faster with Nexty + +Nexty.dev is a comprehensive Next.js SaaS boilerplate that provides everything developers need to rapidly build and launch modern AI web applications + +Try [Nexty.dev today](https://nexty.dev?utm_source=github-nextjs-starter) +--- + +[](https://nexty.dev?utm_source=github-nextjs-starter) + + +🌍 *[English](README.md) ∙ [简体中文](README_zh.md) ∙ [日本語](README_ja.md)* + +# Next Forge - Multilingual Next.js 16 Starter + +A feature-rich Next.js 16 multilingual starter template to help you quickly build globally-ready websites. + +- [👉 Source Code](https://github.com/weijunext/nextjs-starter) +- [👉 Live Demo](https://nextforge.dev/) + +**🚀 Looking for a full-featured SaaS Starter Template? [Check out the complete version](https://nexty.dev)** + +## ✨ Features + +- 🌐 Built-in i18n support (English, Chinese, Japanese) +- 🎨 Modern UI design with Tailwind CSS +- 🌙 Dark/Light theme toggle +- 📱 Responsive layout +- 📝 MDX blog system +- 🔍 SEO optimization +- 📊 Integrated analytics tools + - Google Analytics + - Baidu Analytics + - Google Adsense + - Vercel Analytics + +## 🚀 Quick Start + +### Prerequisites + +- Node.js 20.9 or higher +- pnpm 9.0 or higher (recommended) + +> **Note**: The project has configured `packageManager` field, we recommend using pnpm for the best experience. + +### Installation + +1. Clone the repository: +```bash +git clone https://github.com/weijunext/nextjs-starter.git +cd nextjs-starter +``` + +2. Enable Corepack (recommended): +```bash +corepack enable +``` + +3. Install dependencies: +```bash +pnpm install +# or use other package managers +npm install +yarn +``` + +4. Copy environment variables: +```bash +cp .env.example .env +``` + +5. Start the development server: +```bash +pnpm dev +# or npm run dev +``` + +Visit http://localhost:3000 to view your application. + +## ⚙️ Configuration + +1. Basic Setup + - Edit `config/site.ts` for website information + - Update icons and logo in `public/` + - Configure `app/sitemap.ts` for sitemap + - Update `app/robots.ts` for robots.txt + +2. i18n Setup + - Add/modify language files in `i18n/messages/` + - Configure supported languages in `i18n/routing.ts` + - Set up i18n routing in `middleware.ts` + - Create pages under `app/[locale]/` + - Use the `Link` component from `i18n/routing.ts` instead of Next.js default + +## 📝 Content Management + +### Blog Posts +Create MDX files in `blog/[locale]` with the following format: + +```markdown +--- +title: Post Title +description: Post Description +image: /image.png +slug: /url-path +tags: tag1,tag2 +date: 2025-02-20 +visible: published +pin: true +--- + +Post content... +``` + +Reference `types/blog.ts` for supported fields. + +### Static Pages +Manage static page content in `content/[page]/[locale].mdx`. + +## 🔍 SEO Optimization + +Built-in comprehensive SEO features: + - Server-side rendering and static generation + - Automatic sitemap.xml generation + - robots.txt configuration + - Optimized metadata + - Open Graph support + - Multilingual SEO support + +## 📊 Analytics + +Enable analytics by adding IDs in `.env`: +``` +NEXT_PUBLIC_GOOGLE_ANALYTICS= +NEXT_PUBLIC_BAIDU_TONGJI= +NEXT_PUBLIC_GOOGLE_ADSENSE= +``` + +## 📁 Project Structure + +``` +nextjs-starter/ +├── app/ # App directory +│ ├── [locale]/ # Internationalized routes +│ │ ├── about/ # About page +│ │ ├── blog/ # Blog pages +│ │ └── ... # Other pages +│ ├── api/ # API routes +│ └── globals/ # Global components +├── blog/ # Blog content (MDX) +│ ├── en/ # English blog +│ ├── ja/ # Japanese blog +│ └── zh/ # Chinese blog +├── components/ # Reusable components +│ ├── ui/ # Base UI components +│ ├── header/ # Header components +│ ├── footer/ # Footer components +│ └── ... # Other components +├── config/ # Configuration files +├── content/ # Static content (MDX) +├── i18n/ # Internationalization +│ ├── messages/ # Translation files +│ ├── routing.ts # Routing configuration +│ └── request.ts # Request configuration +├── lib/ # Utility functions +├── public/ # Static assets +└── types/ # Type definitions +``` + +## 🛠️ Tech Stack + +- **Framework**: Next.js 16 (App Router) +- **Language**: TypeScript +- **Styling**: Tailwind CSS + Shadcn/ui +- **Internationalization**: next-intl +- **Content**: MDX +- **State Management**: Zustand +- **Deployment**: Vercel +- **Package Manager**: pnpm (recommended) + +## 🚀 Deployment + +### One-Click Deploy + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/weijunext/nextjs-starter&project-name=&repository-name=nextjs-starter&demo-title=NextjsStarter&demo-description=Nextjs%2015%20starter.&demo-url=https://nextforge.dev&demo-image=https://nextforge.dev/og.png) + +### Manual Deployment to Vercel + +1. Push your code to GitHub +2. Import project in Vercel +3. Configure environment variables +4. Deploy + +### Other Platforms + +```bash +# Build for production +pnpm build + +# Start production server +pnpm start +``` + +## 💡 Development Best Practices + +### Package Manager + +- Project configured with `packageManager: "pnpm@10.12.4"` +- Enable Corepack: `corepack enable` +- Team members should use the same pnpm version + +### Code Quality + +```bash +# Lint code +pnpm lint + +# Type checking +pnpm type-check +``` + +### Internationalization Development + +1. Adding new language support: + - Add new language files in `i18n/messages/` + - Update `i18n/routing.ts` configuration + - Create corresponding language directories in `blog/` and `content/` + +2. Using translations: +```tsx +import { useTranslations } from 'next-intl'; + +export default function MyComponent() { + const t = useTranslations('namespace'); + return

{t('title')}

; +} +``` + +## 🔧 Troubleshooting + +### Common Issues + +**1. Package manager version mismatch** +```bash +# Remove node_modules and lockfile +rm -rf node_modules pnpm-lock.yaml +# Reinstall +pnpm install +``` + +**2. MDX files not displaying** +- Check file path is correct +- Verify frontmatter format +- Ensure `visible` field is set to `published` + +**3. Internationalization routing issues** +- Use `Link` component from `i18n/routing.ts` +- Check `middleware.ts` configuration + +**4. Styles not working** +- Verify Tailwind CSS class names are correct +- Try restarting development server + +### Environment Variables + +Ensure `.env` file contains necessary configuration: +```bash +# Copy example config +cp .env.example .env +# Modify as needed +``` + +## 📄 License + +MIT + +## 🤝 Contributing + +Issues and Pull Requests are welcome! + +## About the Author + +Next.js full-stack specialist providing expert services in project development, performance optimization, and SEO improvement. + +For consulting and training opportunities, reach out at weijunext@gmail.com + +- [Github](https://github.com/weijunext) +- [Bento](https://bento.me/weijunext) +- [Twitter/X](https://twitter.com/judewei_dev) + +Buy Me A Coffee + +[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/G2G6TWWMG) diff --git a/README_ja.md b/README_ja.md new file mode 100644 index 0000000..181d6ab --- /dev/null +++ b/README_ja.md @@ -0,0 +1,290 @@ +--- +Nexty で SaaS を迅速に立ち上げよう - ビジュアル料金ダッシュボード、AI プレイグラウンド、エンタープライズレベル CMS を備えた唯一の Next.js ボイラープレート。多言語対応、認証、決済、メール機能、SEO 最適化も完備。 + +[Nexty.dev を今すぐ試す](https://nexty.dev?utm_source=github-nextjs-starter) +--- + +[](https://nexty.dev?utm_source=github-nextjs-starter) + +🌍 *[English](README.md) ∙ [简体中文](README_zh.md) ∙ [日本語](README_ja.md)* + +# Next Forge - 多言語対応 Next.js 16 スターター + +グローバル対応のウェブサイトを素早く構築するための、機能豊富なNext.js 15多言語スターターテンプレートです。 + +- [👉 ソースコード](https://github.com/weijunext/nextjs-starter) +- [👉 デモサイト](https://nextforge.dev/) + +**🚀 多機能で使いやすいフルスタックの起動テンプレートをお探しですか? ぜひ、当社の[アドバンス版](https://nexty.dev)をお試しください。** + +## ✨ 主な機能 + +- 🌐 多言語対応(英語・中国語・日本語) +- 🎨 Tailwind CSSによるモダンなUI +- 🌙 ダーク/ライトテーマ切り替え +- 📱 レスポンシブデザイン +- 📝 MDXブログシステム +- 🔍 SEO最適化 +- 📊 アナリティクスツール統合 + - Google Analytics + - Baidu Analytics + - Google Adsense + - Vercel Analytics + +## 🚀 クイックスタート + +### 必要な環境 + +- Node.js 20.9 以上 +- pnpm 9.0 以上(推奨) + +> **注意**: プロジェクトには `packageManager` フィールドが設定されており、最適な体験のために pnpm の使用を推奨しています。 + +### インストール手順 + +1. リポジトリのクローン: +```bash +git clone https://github.com/weijunext/nextjs-starter.git +cd nextjs-starter +``` + +2. Corepack の有効化(推奨): +```bash +corepack enable +``` + +3. 依存関係のインストール: +```bash +pnpm install +# または他のパッケージマネージャーを使用 +npm install +yarn +``` + +4. 環境変数の設定: +```bash +cp .env.example .env +``` + +5. 開発サーバーの起動: +```bash +pnpm dev +# または npm run dev +``` + +http://localhost:3000 にアクセスして確認できます。 + +## ⚙️ 設定方法 + +1. 基本設定 + - `config/site.ts`でウェブサイト情報を編集 + - `public/`内のアイコンとロゴを更新 + - `app/sitemap.ts`でサイトマップを設定 + - `app/robots.ts`でrobots.txtを更新 + +2. 多言語設定 + - `i18n/messages/`内の言語ファイルを追加/編集 + - `i18n/routing.ts`でサポートする言語を設定 + - `middleware.ts`で多言語ルーティングを設定 + - `app/[locale]/`配下にページを作成 + - Next.jsデフォルトの代わりに`i18n/routing.ts`の`Link`コンポーネントを使用 + +## 📝 コンテンツ管理 + +### ブログ投稿 +`blog/[locale]`にMDXファイルを以下のフォーマットで作成: + +```markdown +--- +title: 投稿タイトル +description: 投稿の説明 +image: /image.png +slug: /url-path +tags: tag1,tag2 +date: 2025-02-20 +visible: published +pin: true +--- + +投稿内容... +``` + +対応フィールドについては`types/blog.ts`を参照してください。 + +### 静的ページ +`content/[page]/[locale].mdx`で静的ページのコンテンツを管理します。 + +## 🔍 SEO最適化 + +包括的なSEO機能を搭載: + - サーバーサイドレンダリングと静的生成 + - sitemap.xml自動生成 + - robots.txt設定 + - 最適化されたメタデータ + - OGP対応 + - 多言語SEOサポート + +## 📊 アナリティクス + +`.env`にIDを追加して有効化: +``` +NEXT_PUBLIC_GOOGLE_ANALYTICS= +NEXT_PUBLIC_BAIDU_TONGJI= +NEXT_PUBLIC_GOOGLE_ADSENSE= +``` + +## 📁 プロジェクト構成 + +``` +nextjs-starter/ +├── app/ # アプリディレクトリ +│ ├── [locale]/ # 多言語ルート +│ │ ├── about/ # Aboutページ +│ │ ├── blog/ # ブログページ +│ │ └── ... # その他のページ +│ ├── api/ # APIルート +│ └── globals/ # グローバルコンポーネント +├── blog/ # ブログコンテンツ(MDX) +│ ├── en/ # 英語ブログ +│ ├── ja/ # 日本語ブログ +│ └── zh/ # 中国語ブログ +├── components/ # 再利用可能なコンポーネント +│ ├── ui/ # ベースUIコンポーネント +│ ├── header/ # ヘッダーコンポーネント +│ ├── footer/ # フッターコンポーネント +│ └── ... # その他のコンポーネント +├── config/ # 設定ファイル +├── content/ # 静的コンテンツ(MDX) +├── i18n/ # 国際化設定 +│ ├── messages/ # 翻訳ファイル +│ ├── routing.ts # ルーティング設定 +│ └── request.ts # リクエスト設定 +├── lib/ # ユーティリティ関数 +├── public/ # 静的アセット +└── types/ # 型定義 +``` + +## 🛠️ 技術スタック + +- **フレームワーク**: Next.js 16 (App Router) +- **言語**: TypeScript +- **スタイリング**: Tailwind CSS + Shadcn/ui +- **国際化**: next-intl +- **コンテンツ**: MDX +- **状態管理**: Zustand +- **デプロイ**: Vercel +- **パッケージマネージャー**: pnpm(推奨) + +## 🚀 デプロイ + +### ワンクリックデプロイ + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/weijunext/nextjs-starter&project-name=&repository-name=nextjs-starter&demo-title=NextjsStarter&demo-description=Nextjs%2015%20starter.&demo-url=https://nextforge.dev&demo-image=https://nextforge.dev/og.png) + +### Vercelへの手動デプロイ + +1. GitHubにコードをプッシュ +2. Vercelでプロジェクトをインポート +3. 環境変数を設定 +4. デプロイ + +### その他のプラットフォーム + +```bash +# プロダクション用ビルド +pnpm build + +# プロダクションサーバーを起動 +pnpm start +``` + +## 💡 開発のベストプラクティス + +### パッケージマネージャー使用 + +- プロジェクトは `packageManager: "pnpm@10.12.4"` で設定済み +- Corepack を有効化: `corepack enable` +- チームメンバーは同じ pnpm バージョンを使用すべき + +### コード品質 + +```bash +# コードリント +pnpm lint + +# 型チェック +pnpm type-check +``` + +### 多言語開発 + +1. 新しい言語サポートの追加: + - `i18n/messages/` に新しい言語ファイルを追加 + - `i18n/routing.ts` 設定を更新 + - `blog/` と `content/` に対応する言語ディレクトリを作成 + +2. 翻訳の使用: +```tsx +import { useTranslations } from 'next-intl'; + +export default function MyComponent() { + const t = useTranslations('namespace'); + return

{t('title')}

; +} +``` + +## 🔧 トラブルシューティング + +### よくある問題 + +**1. パッケージマネージャーのバージョン不一致** +```bash +# node_modules と lockfile を削除 +rm -rf node_modules pnpm-lock.yaml +# 再インストール +pnpm install +``` + +**2. MDXファイルが表示されない** +- ファイルパスが正しいか確認 +- frontmatter のフォーマットが正しいか確認 +- `visible` フィールドが `published` に設定されているか確認 + +**3. 多言語ルーティングの問題** +- `i18n/routing.ts` の `Link` コンポーネントを使用 +- `middleware.ts` の設定を確認 + +**4. スタイルが効かない** +- Tailwind CSS のクラス名が正しいか確認 +- 開発サーバーの再起動を試す + +### 環境変数の問題 + +`.env` ファイルに必要な設定が含まれていることを確認: +```bash +# サンプル設定をコピー +cp .env.example .env +# 必要に応じて設定を変更 +``` + +## 📄 ライセンス + +MIT + +## 🤝 コントリビューション + +Issue、PRは大歓迎です! + +## 作者について + +Next.jsのフルスタックスペシャリストとして、プロジェクト開発、パフォーマンス最適化、SEO改善のエキスパートサービスを提供しています。 + +コンサルティングやトレーニングについては、 weijunext@gmail.com までご連絡ください。 + +- [Github](https://github.com/weijunext) +- [Bento](https://bento.me/weijunext) +- [Twitter/X](https://twitter.com/judewei_dev) + +Buy Me A Coffee + +[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/G2G6TWWMG) \ No newline at end of file diff --git a/README_zh.md b/README_zh.md new file mode 100644 index 0000000..ab50fb4 --- /dev/null +++ b/README_zh.md @@ -0,0 +1,297 @@ +--- +使用 Nexty 加速 SaaS 开发 - 唯一一个集成可视化定价面板、AI 开发环境和企业级 CMS 的 Next.js 模板,还包含多语言支持、身份验证、支付系统、电子邮件功能和 SEO 优化。 + +立即体验 [Nexty.dev](https://nexty.dev/?utm_source=github-nextjs-starter) +--- + +[](https://nexty.dev/?utm_source=github-nextjs-starter) + +🌍 *[English](README.md) ∙ [简体中文](README_zh.md) ∙ [日本语](README_ja.md)* + +# Next Forge - 多语言 Next.js 16 启动模板 + +一个轻量的 Next.js 16 多语言启动模板,帮助你快速构建面向全球的网站。 + +- [👉 源码地址](https://github.com/weijunext/nextjs-starter) +- [👉 在线预览](https://nextforge.dev/) + +**🚀 如果你正在寻找功能完备的全栈启动模板,请了解我们的[高级版](https://nexty.dev/?utm_source=github-nextjs-starter)** + +## ✨ 特性 + +- 🌐 内置多语言支持 (中文、英文、日语) +- 🎨 基于 Tailwind CSS 的现代 UI 设计 +- 🌙 深色/浅色主题切换 +- 📱 响应式布局 +- 📝 MDX 博客系统 +- 🔍 SEO 优化 +- 📊 集成多个统计分析工具 + - Google Analytics + - Baidu Analytics + - Google Adsense + - Vercel Analytics + +## 🚀 快速开始 + +### 环境要求 + +- Node.js 20.9 或更高版本 +- pnpm 9.0 或更高版本(推荐) + +> **注意**: 项目已配置 `packageManager` 字段,推荐使用 pnpm 以获得最佳体验。 + +### 安装步骤 + +1. 克隆项目: +```bash +git clone https://github.com/weijunext/nextjs-starter.git +cd nextjs-starter +``` + +2. 启用 Corepack (推荐): +```bash +corepack enable +``` + +3. 安装依赖: +```bash +pnpm install +# 或使用其他包管理器 +npm install +yarn +``` + +4. 复制环境变量文件: +```bash +cp .env.example .env +``` + +5. 启动开发服务器: +```bash +pnpm dev +# 或 npm run dev +``` + +访问 http://localhost:3000 查看你的应用。 + +## ⚙️ 配置 + +1. 基础配置 + - 修改 `config/site.ts` 配置网站信息 + - 修改 `public/` 下的图标和 logo + - 更新 `app/sitemap.ts` 配置站点地图 + - 更新 `app/robots.ts` 配置 robots.txt + +2. 多语言配置 + - 在 `i18n/messages/` 下添加或修改语言文件 + - 在 `i18n/routing.ts` 中配置支持的语言 + - 在 `middleware.ts` 中配置多语言路由 + - 在 `app/[locale]/` 目录下创建页面 + - 多语言页面使用 `i18n/routing.ts` 导出的 `Link` 组件替代 next.js 的 + +## 📝 内容管理 + +### 博客文章 +在 `blog/[locale]` 目录下创建 MDX 文件,支持以下格式: + +```markdown +--- +title: 文章标题 +description: 文章描述 +image: /image.png +slug: /url-path +tags: tag1,tag2 +date: 2025-02-20 +visible: published +pin: true +--- + +文章内容... +``` + +可参考类型定义 `types/blog.ts` 确认支持的字段。 + +### 静态页面 +在 `content/[page]/[locale].mdx` 下管理静态页面内容。 + +## 🔍 SEO 优化 + +模板内置了完整的 SEO 优化方案: + - 服务端渲染和静态生成 + - 自动生成 sitemap.xml + - 配置 robots.txt + - 优化的 metadata + - 支持 Open Graph + - 多语言 SEO 支持 + +## 📊 统计分析 + +在 `.env` 文件中配置相应的 ID 即可启用: +``` +NEXT_PUBLIC_GOOGLE_ANALYTICS= +NEXT_PUBLIC_BAIDU_TONGJI= +NEXT_PUBLIC_GOOGLE_ADSENSE= +``` + +## 📁 项目结构 + +``` +nextjs-starter/ +├── app/ # 应用路由目录 +│ ├── [locale]/ # 多语言路由 +│ │ ├── about/ # 关于页面 +│ │ ├── blog/ # 博客页面 +│ │ └── ... # 其他页面 +│ ├── api/ # API 路由 +│ └── globals/ # 全局组件 +├── blog/ # 博客内容 (MDX) +│ ├── en/ # 英文博客 +│ ├── ja/ # 日文博客 +│ └── zh/ # 中文博客 +├── components/ # 可复用组件 +│ ├── ui/ # 基础 UI 组件 +│ ├── header/ # 头部组件 +│ ├── footer/ # 底部组件 +│ └── ... # 其他组件 +├── config/ # 配置文件 +├── content/ # 静态内容 (MDX) +├── i18n/ # 国际化配置 +│ ├── messages/ # 翻译文件 +│ ├── routing.ts # 路由配置 +│ └── request.ts # 请求配置 +├── lib/ # 工具函数 +├── public/ # 静态资源 +└── types/ # 类型定义 +``` + +## 🛠️ 技术栈 + +- **框架**: Next.js 16 (App Router) +- **语言**: TypeScript +- **样式**: Tailwind CSS + Shadcn/ui +- **国际化**: next-intl +- **内容**: MDX +- **状态管理**: Zustand +- **部署**: Vercel +- **包管理器**: pnpm (推荐) + + +## 🚀 部署 + +### 一键部署 + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/weijunext/nextjs-starter&project-name=&repository-name=nextjs-starter&demo-title=NextjsStarter&demo-description=Nextjs%2015%20starter.&demo-url=https://nextforge.dev&demo-image=https://nextforge.dev/og.png) + +### 手动部署到 Vercel + +1. 推送代码到 GitHub +2. 在 Vercel 中导入项目 +3. 配置环境变量 +4. 部署 + +### 其他平台部署 + +```bash +# 构建生产版本 +pnpm build + +# 启动生产服务器 +pnpm start +``` + +## 💡 开发最佳实践 + +### 包管理器使用 + +- 项目已配置 `packageManager: "pnpm@10.12.4"` +- 建议启用 Corepack: `corepack enable` +- 团队成员应使用相同版本的 pnpm + +### 代码规范 + +```bash +# 代码检查 +pnpm lint + +# 类型检查 +pnpm type-check +``` + +### 多语言开发 + +1. 新增语言支持: + - 在 `i18n/messages/` 添加新的语言文件 + - 更新 `i18n/routing.ts` 配置 + - 在 `blog/` 和 `content/` 下创建对应语言目录 + +2. 使用翻译: +```tsx +import { useTranslations } from 'next-intl'; + +export default function MyComponent() { + const t = useTranslations('namespace'); + return

{t('title')}

; +} +``` + +## 🔧 故障排除 + +### 常见问题 + +**1. 包管理器版本不一致** +```bash +# 删除 node_modules 和 lockfile +rm -rf node_modules pnpm-lock.yaml +# 重新安装 +pnpm install +``` + +**2. MDX 文件不显示** +- 检查文件路径是否正确 +- 确认 frontmatter 格式正确 +- 检查 `visible` 字段是否设置为 `published` + +**3. 多语言路由问题** +- 确保使用 `i18n/routing.ts` 中的 `Link` 组件 +- 检查 `middleware.ts` 配置 + +**4. 样式不生效** +- 确认 Tailwind CSS 类名拼写正确 +- 检查是否需要重启开发服务器 + +### 环境变量问题 + +确保 `.env` 文件包含必要的配置: +```bash +# 复制示例配置 +cp .env.example .env +# 根据需要修改配置 +``` + + +## 📄 许可证 + +MIT + +## 🤝 贡献 + +欢迎提交 Issue 和 Pull Request! + +## 关于作者 + +专注于 Next.js 全栈开发,欢迎探讨开发、咨询与培训等合作机会,联系微信:bigye_chengpu + +- [Github](https://github.com/weijunext) +- [Twitter/X](https://twitter.com/weijunext) +- [博客 - J实验室](https://weijunext.com) +- [Medium](https://medium.com/@weijunext) +- [掘金](https://juejin.cn/user/26044008768029) +- [知乎](https://www.zhihu.com/people/mo-mo-mo-89-12-11) + +Buy Me A Coffee + +[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/G2G6TWWMG) + +赞赏作者 + + diff --git a/actions/newsletter.ts b/actions/newsletter.ts new file mode 100644 index 0000000..a14b4ec --- /dev/null +++ b/actions/newsletter.ts @@ -0,0 +1,125 @@ +import { normalizeEmail, validateEmail } from '@/lib/email'; +import { Ratelimit } from '@upstash/ratelimit'; +import { Redis } from '@upstash/redis'; +import { headers } from 'next/headers'; +import { Resend } from 'resend'; + +// initialize resend +const resend = new Resend(process.env.RESEND_API_KEY); + +// Resend Audience ID +const AUDIENCE_ID = process.env.RESEND_AUDIENCE_ID!; + +// initialize Redis +const redis = new Redis({ + url: process.env.UPSTASH_REDIS_REST_URL!, + token: process.env.UPSTASH_REDIS_REST_TOKEN!, +}); + +const REDIS_RATE_LIMIT_KEY = process.env.UPSTASH_REDIS_NEWSLETTER_RATE_LIMIT_KEY!; +const DAY_MAX_SUBMISSIONS = parseInt(process.env.DAY_MAX_SUBMISSIONS || '10'); + +// create rate limiter +const limiter = new Ratelimit({ + redis, + limiter: Ratelimit.slidingWindow(DAY_MAX_SUBMISSIONS, '1d'), + prefix: REDIS_RATE_LIMIT_KEY, +}); + +// Shared rate limit check +async function checkRateLimit() { + const headersList = await headers(); + const ip = headersList.get('x-real-ip') || + headersList.get('x-forwarded-for') || + 'unknown'; + + const { success } = await limiter.limit(ip); + if (!success) { + throw new Error('Too many submissions, please try again later'); + } +} + +export async function subscribeToNewsletter(email: string) { + try { + await checkRateLimit(); + + const normalizedEmail = normalizeEmail(email); + const { isValid, error } = validateEmail(normalizedEmail); + + if (!isValid) { + throw new Error(error || 'Invalid email address'); + } + + // Check if already subscribed + // const list = await resend.contacts.list({ audienceId: AUDIENCE_ID }); + // const user = list.data?.data.find((item) => item.email === normalizedEmail); + // if (user) { + // return { success: true, alreadySubscribed: true }; + // } + + // Add to audience + await resend.contacts.create({ + audienceId: AUDIENCE_ID, + email: normalizedEmail, + }); + + // Send welcome email + const unsubscribeToken = Buffer.from(normalizedEmail).toString('base64'); + const unsubscribeLink = `${process.env.NEXT_PUBLIC_SITE_URL}/unsubscribe?token=${unsubscribeToken}`; + + await resend.emails.send({ + from: 'NextForge <' + process.env.ADMIN_EMAIL! + '>', + to: normalizedEmail, + subject: 'Welcome to Next Forge', + html: ` +

Welcome to Next Forge

+

Thank you for subscribing to the newsletter. You will receive the latest updates and news.

+

+ If you wish to unsubscribe, please click here +

+ `, + headers: { + "List-Unsubscribe": `<${unsubscribeLink}>`, + "List-Unsubscribe-Post": "List-Unsubscribe=One-Click" + } + }); + + return { success: true }; + } catch (error) { + console.error('Newsletter subscription failed:', error); + throw error; + } +} + +export async function unsubscribeFromNewsletter(token: string) { + try { + await checkRateLimit(); + + const email = Buffer.from(token, 'base64').toString(); + const normalizedEmail = normalizeEmail(email); + const { isValid, error } = validateEmail(normalizedEmail); + + if (!isValid) { + throw new Error(error || 'Invalid email address'); + } + + // Check if subscribed + const list = await resend.contacts.list({ audienceId: AUDIENCE_ID }); + const user = list.data?.data.find((item) => item.email === normalizedEmail); + + if (!user) { + throw new Error('This email is not subscribed to our notifications'); + } + + // Remove from audience + await resend.contacts.remove({ + audienceId: AUDIENCE_ID, + email: normalizedEmail, + }); + + return { success: true, email: normalizedEmail }; + } catch (error) { + console.error('Newsletter unsubscribe failed:', error); + throw error; + } +} \ No newline at end of file diff --git a/app/BaiDuAnalytics.tsx b/app/BaiDuAnalytics.tsx new file mode 100644 index 0000000..1f96f04 --- /dev/null +++ b/app/BaiDuAnalytics.tsx @@ -0,0 +1,33 @@ +"use client"; + +import Script from "next/script"; + +const BaiDuAnalytics = () => { + return ( + <> + {process.env.NEXT_PUBLIC_BAIDU_TONGJI ? ( + <> +