From 303339747ff0d8d95558f40ad02f33749afc55cf Mon Sep 17 00:00:00 2001 From: ymk Date: Wed, 30 Jul 2025 20:18:02 +0800 Subject: [PATCH] first commit --- .gitignore | 41 + .roo/rules-code/rules.md | 4 + LICENSE | 21 + README.md | 268 + components.json | 21 + dictionary/en.json | 105 + dictionary/zh.json | 105 + eslint.config.mjs | 23 + global.d.ts | 8 + next.config.ts | 7 + package.json | 46 + pnpm-lock.yaml | 5849 +++++++++++++++++ postcss.config.mjs | 5 + public/file.svg | 1 + public/fonts/LICENSE | 13 + public/fonts/gentilis_bold.typeface.json | 1 + public/fonts/gentilis_regular.typeface.json | 1 + public/fonts/helvetiker_bold.typeface.json | 1 + public/fonts/helvetiker_regular.typeface.json | 1 + public/fonts/optimer_bold.typeface.json | 1 + public/fonts/optimer_regular.typeface.json | 1 + public/globe.svg | 1 + public/next.svg | 1 + public/og-image-black-screen.png | Bin 0 -> 74388 bytes public/og-image-do-not-write-on-this-page.png | Bin 0 -> 328193 bytes public/og-image-white-screen.png | Bin 0 -> 77904 bytes public/og-image.png | Bin 0 -> 471477 bytes public/vercel.svg | 1 + public/window.svg | 1 + src/app/[locale]/[...rest]/page.tsx | 5 + .../do-not-write-on-this-page/page.tsx | 140 + src/app/[locale]/layout.tsx | 84 + src/app/[locale]/not-found.tsx | 43 + src/app/[locale]/page.tsx | 206 + src/app/error.tsx | 47 + src/app/favicon.ico | Bin 0 -> 25931 bytes src/app/globals.css | 123 + src/app/robots.txt | 4 + src/app/sitemap.ts | 59 + src/components/Editor.tsx | 42 + src/components/Footer.tsx | 36 + src/components/Header.tsx | 42 + src/components/LanguageSwitcher.tsx | 75 + src/components/ModeToggle.tsx | 25 + src/components/OmmitRlt.tsx | 16 + src/components/common/BackgroundSelector.tsx | 124 + src/components/common/PreviewToolbar.tsx | 175 + src/components/common/TextSetting.tsx | 88 + src/components/common/ThreeTools.ts | 201 + src/i18n/config.ts | 1 + src/i18n/navigation.ts | 7 + src/i18n/request.ts | 16 + src/i18n/routing.ts | 13 + src/lib/utils.ts | 6 + src/middleware.ts | 11 + tsconfig.json | 41 + 56 files changed, 8157 insertions(+) create mode 100644 .gitignore create mode 100644 .roo/rules-code/rules.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 components.json create mode 100644 dictionary/en.json create mode 100644 dictionary/zh.json create mode 100644 eslint.config.mjs create mode 100644 global.d.ts create mode 100644 next.config.ts create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 postcss.config.mjs create mode 100644 public/file.svg create mode 100644 public/fonts/LICENSE create mode 100644 public/fonts/gentilis_bold.typeface.json create mode 100644 public/fonts/gentilis_regular.typeface.json create mode 100644 public/fonts/helvetiker_bold.typeface.json create mode 100644 public/fonts/helvetiker_regular.typeface.json create mode 100644 public/fonts/optimer_bold.typeface.json create mode 100644 public/fonts/optimer_regular.typeface.json create mode 100644 public/globe.svg create mode 100644 public/next.svg create mode 100644 public/og-image-black-screen.png create mode 100644 public/og-image-do-not-write-on-this-page.png create mode 100644 public/og-image-white-screen.png create mode 100644 public/og-image.png create mode 100644 public/vercel.svg create mode 100644 public/window.svg create mode 100644 src/app/[locale]/[...rest]/page.tsx create mode 100644 src/app/[locale]/do-not-write-on-this-page/page.tsx create mode 100644 src/app/[locale]/layout.tsx create mode 100644 src/app/[locale]/not-found.tsx create mode 100644 src/app/[locale]/page.tsx create mode 100644 src/app/error.tsx create mode 100644 src/app/favicon.ico create mode 100644 src/app/globals.css create mode 100644 src/app/robots.txt create mode 100644 src/app/sitemap.ts create mode 100644 src/components/Editor.tsx create mode 100644 src/components/Footer.tsx create mode 100644 src/components/Header.tsx create mode 100644 src/components/LanguageSwitcher.tsx create mode 100644 src/components/ModeToggle.tsx create mode 100644 src/components/OmmitRlt.tsx create mode 100644 src/components/common/BackgroundSelector.tsx create mode 100644 src/components/common/PreviewToolbar.tsx create mode 100644 src/components/common/TextSetting.tsx create mode 100644 src/components/common/ThreeTools.ts create mode 100644 src/i18n/config.ts create mode 100644 src/i18n/navigation.ts create mode 100644 src/i18n/request.ts create mode 100644 src/i18n/routing.ts create mode 100644 src/lib/utils.ts create mode 100644 src/middleware.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/.roo/rules-code/rules.md b/.roo/rules-code/rules.md new file mode 100644 index 0000000..2899be1 --- /dev/null +++ b/.roo/rules-code/rules.md @@ -0,0 +1,4 @@ +- 始终使用中文进行提示,使用英文进行代码输出 +- 始终使用 @radix-ui/themes 里面的组件,禁止自定义基础组件 +- 禁止修改 package.json +- 始终考虑多语言 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2b7a85e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Sovers Tonmoy Pandey + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7d96391 --- /dev/null +++ b/README.md @@ -0,0 +1,268 @@ +# Next.js 15 Template with i18n and Shadcn UI + +A modern, SEO-optimized template for Next.js 15 applications featuring server components, internationalization support, shadcn UI components, and theme switching capabilities. Perfect for building performant, accessible, and multilingual web applications. + +## ✨ Features + +- **Next.js 15**: Built on the latest [Next.js 15](https://nextjs.org/) React framework with App Router and Server Components for optimal performance +- **SEO Optimization**: Includes metadata API, structured data, and optimized page loading strategies +- **Internationalization**: Full i18n support using middleware-based routing with [next-intl](https://next-intl-docs.vercel.app/) +- **Shadcn UI**: Pre-configured [shadcn UI](https://ui.shadcn.com/) components using the new React Server Components pattern +- **Theme System**: CSS Variables-based theme system with light/dark mode toggle and system preference detection +- **Language Switching**: Seamless switching between languages (including RTL support for Arabic and other RTL languages) +- **OmitRTL Utility**: Helper component to control elements that should maintain LTR (left-to-right) rendering in RTL contexts +- **TypeScript**: Type-safe codebase with TypeScript configuration optimized for Next.js 15 +- **Metadata API**: Built-in SEO metadata management using Next.js 15's metadata API + +## 🚀 Getting Started + +Clone the repository: + +```bash +git clone https://github.com/S0vers/next-app-i18n-starter.git +``` + +Install dependencies: + +```bash +npm install +# or +yarn +# or +pnpm install +# or +bun install +``` + +Start the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) in your browser to see the result. + +## 📋 Project Structure + +The project follows Next.js 15's recommended App Router structure with additions for internationalization: + +``` +├── .next # Next.js build output +├── dictionary # i18n translation files +│ ├── ar.json # Arabic translations +│ └── en.json # English translations +├── node_modules # Dependencies +├── public # Static assets +├── src # Source code +│ ├── app # Next.js App Router +│ │ ├── [locale] # Dynamic locale routing +│ │ │ ├── page.tsx # Home page +│ │ │ ├── error.tsx # Error handling +│ │ │ ├── favicon.ico # Favicon +│ │ │ ├── globals.css # Global styles +│ │ │ ├── robots.txt # SEO robots file +│ │ │ └── sitemap.ts # Dynamic sitemap generation +│ │ └── components # Application components +│ │ ├── ui # shadcn UI components +│ │ ├── LanguageSwitcher.tsx # Language toggle component +│ │ ├── ModeToggle.tsx # Theme toggle component +│ │ ├── OmitRTL.tsx # RTL handling utility +│ │ └── theme-provider.tsx # Theme context provider +│ ├── i18n # Internationalization utilities +│ │ ├── navigation.ts # Localized navigation helpers +│ │ ├── requests.ts # i18n-aware API request helpers +│ │ └── routing.ts # Locale routing utilities +│ ├── lib # Utility functions and shared code +│ │ └── middleware.ts # i18n middleware for route handling +│ └── components.json # shadcn UI component configuration +├── .eslintrc.json # ESLint configuration +├── global.d.ts # Global TypeScript declarations +├── LICENSE # Project license +├── next-env.d.ts # Next.js TypeScript declarations +├── next.config.js # Next.js configuration +├── package.json # Project dependencies and scripts +├── bun.lock # Bun lock file +├── postcss.config.js # PostCSS configuration +├── README.md # Project documentation +└── tsconfig.json # TypeScript configuration +``` + +## 🌐 Internationalization + +This template uses middleware-based i18n routing with Next.js 15. Language files are stored in the `dictionary/` directory. + +### Adding a New Language + +1. Create a new JSON file in the `dictionary/` directory (e.g., `fr.json`) +2. Add the language to the supported locales in `middleware.ts` and `lib/i18n.ts` +3. Add language option to the `LanguageSwitcher` component + +## 🎨 Shadcn UI Components + +Shadcn UI components are configured to work with Next.js 15 Server Components. Import them from the `components/ui/` directory: + +```jsx +import { Button } from "@/components/ui/button"; + +export default function Home() { + return ; +} +``` + +## 🔄 OmitRTL Utility + +The `OmitRTL` utility helps you control which elements should maintain LTR direction even when the site is in RTL mode. + +### How to use the function: + +```jsx +import { OmitRTL } from "@/components/OmitRTL"; + +function MyComponent() { + return ( +
+

This text will follow the website's direction.

+ + Logo +
+

This heading and content will always be LTR

+

Regardless of the website's direction.

+
+
+
+ ); +} +``` + +### NPM Package + +If you just need the OmitRTL function, it's also available as an npm package: + +```bash +npm i react-omit-rtl +``` + +```jsx +import React from "react"; +import OmitRTL from "react-omit-rtl"; + +function App() { + return ( + +

This text will not have RTL direction.

+
+ ); +} +export default App; +``` + +## 🔍 SEO Optimization + +The template provides comprehensive SEO features with the Next.js 15 Metadata API: + +```jsx +export async function generateMetadata({ + params, +}: { + params: { locale: string }, +}): Promise { + const { locale } = await params; + const t = await getTranslations({ locale, namespace: "Metadata" }); + + return { + title: t("title"), + description: t("description"), + other: { + "google-site-verification": "********", + }, + openGraph: { + title: t("title"), + description: t("description"), + url: `next-app-i18n-starter.vercel.app`, + siteName: "Next.js i18n Template", + images: [ + { + url: "next-app-i18n-starter.vercel.app/og-image.png", + width: 1200, + height: 630, + }, + ], + locale: locale, + type: "website", + }, + twitter: { + card: "summary_large_image", + title: t("title"), + description: t("description"), + images: ["next-app-i18n-starter.vercel.app/og-image.png"], + }, + alternates: { + canonical: `next-app-i18n-starter.vercel.app`, + languages: { + en: "next-app-i18n-starter.vercel.app", + ar: "next-app-i18n-starter.vercel.app", + }, + }, + robots: { + index: true, + follow: true, + googleBot: { + index: true, + follow: true, + "max-video-preview": -1, + "max-image-preview": "large", + "max-snippet": -1, + }, + }, + }; +} +``` + +Additionally, structured data is implemented using react-schemaorg for better search engine understanding: + +```jsx +