commit 400b1177c02f915e4e0e623f7a9c106ddc746da2 Author: “dongming” <“lidongming@aituringflow.com”> Date: Fri Dec 19 12:19:14 2025 +0800 first commit diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..4041b5e --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,154 @@ +name: Deploy to Cloudflare Pages + +on: + push: + tags: + - 'deploy-*' # 只在推送 deploy-* 标签时触发 + +jobs: + deploy: + runs-on: ubuntu-latest + container: + image: swr.cn-south-1.myhuaweicloud.com/bws/node:20.19.6-bookworm-slim-ci + + steps: + # 1. 拉取代码 + - name: Checkout + uses: actions/checkout@v4 + + # 2. 设置 pnpm(使用 corepack,避免从 GitHub 拉取 action) + - name: Setup pnpm + run: | + corepack enable + corepack prepare pnpm@10.23.0 --activate + pnpm --version + + - name: Parse tag to env + shell: bash + run: | + # 获取 tag 名称(Gitea Actions 使用 GITHUB_REF_NAME) + TAG_NAME="${GITHUB_REF_NAME}" + echo "TAG_NAME=$TAG_NAME" + + # Tag 格式: deploy-{project_name}-{deploymentId_no_dashes} + # 例如: deploy-b7ea026a-cf09-4e31-9f29-b55d7c652b71-123e4567e89b12d3a456426614174000 + + # 去掉 "deploy-" 前缀 + PREFIX="deploy-" + REST="${TAG_NAME#$PREFIX}" + + # deploymentId(无破折号)固定是最后32个字符 + DEPLOYMENT_ID="${REST: -32}" + + # project_name 是剩余部分(去掉最后的 "-" 和 deploymentId) + PROJECT_NAME="${REST%-${DEPLOYMENT_ID}}" + + echo "PROJECT_NAME=$PROJECT_NAME" >> "$GITHUB_ENV" + echo "DEPLOYMENT_ID=$DEPLOYMENT_ID" >> "$GITHUB_ENV" + #echo "DOMAIN=${PROJECT_NAME}-preview.turingflowai.com" >> "$GITHUB_ENV" + + # 调试输出 + echo "Parsed PROJECT_NAME: $PROJECT_NAME" + echo "Parsed DEPLOYMENT_ID: $DEPLOYMENT_ID" + + - name: Check toolchain (debug only, 可选) + run: | + node -v || echo "node not found" + pnpm -v || echo "pnpm not found" + curl --version || echo "curl not found" + + - name: Use CN npm registry + run: | + pnpm config set registry http://repo.myhuaweicloud.com/repository/npm/ + + - name: Install dependencies + run: | + pnpm install --frozen-lockfile + + - name: Build + run: pnpm run build + + - name: Deploy to Cloudflare Pages + shell: bash + env: + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} + CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }} + PROJECT_NAME: ${{ env.PROJECT_NAME }} + DOMAIN: ${{ env.DOMAIN }} + run: | + set -euo pipefail + echo "[deploy] project: $PROJECT_NAME" + #echo "[deploy] domain: $DOMAIN" + + # 部署到 Cloudflare Pages (假定构建产物在 dist/) + # 使用项目本地安装的 wrangler + npx wrangler pages deploy dist \ + --project-name "$PROJECT_NAME" \ + --branch main + + # 绑定自定义域名:-preview.turingflowai.com + #echo "[deploy] 正在绑定自定义域名..." + #DOMAIN_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \ + # "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/pages/projects/${PROJECT_NAME}/domains" \ + # -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \ + # -H "Content-Type: application/json" \ + # -d '{"name":"'"${DOMAIN}"'"}') + + #HTTP_CODE=$(echo "$DOMAIN_RESPONSE" | tail -n1) + #RESPONSE_BODY=$(echo "$DOMAIN_RESPONSE" | sed '$d') + + #if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "409" ]; then + # echo "[deploy] 域名绑定成功或已存在 (HTTP $HTTP_CODE)" + #else + # echo "[deploy] 警告: 域名绑定失败 (HTTP $HTTP_CODE)" + # echo "[deploy] 响应: $RESPONSE_BODY" + # echo "[deploy] 继续执行,但域名可能未绑定成功" + #fi + + - name: Notify Deploy Service (success) + if: success() + shell: bash + env: + DEPLOY_SERVICE_CALLBACK_URL: ${{ secrets.DEPLOY_SERVICE_CALLBACK_URL }} + DEPLOY_SERVICE_TOKEN: ${{ secrets.DEPLOY_SERVICE_TOKEN }} + DEPLOYMENT_ID: ${{ env.DEPLOYMENT_ID }} + run: | + set -euo pipefail + + # 获取当前 commit SHA (Gitea Actions 使用 GITHUB_SHA) + COMMIT_SHA="${GITHUB_SHA}" + + curl -X POST "$DEPLOY_SERVICE_CALLBACK_URL" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $DEPLOY_SERVICE_TOKEN" \ + -d '{ + "deploymentId": "'"${DEPLOYMENT_ID}"'", + "status": "deployed", + "commitSha": "'"${COMMIT_SHA}"'", + "cfDeploymentId": "", + "errorMessage": null + }' + + - name: Notify Deploy Service (failure) + if: failure() + shell: bash + env: + DEPLOY_SERVICE_CALLBACK_URL: ${{ secrets.DEPLOY_SERVICE_CALLBACK_URL }} + DEPLOY_SERVICE_TOKEN: ${{ secrets.DEPLOY_SERVICE_TOKEN }} + DEPLOYMENT_ID: ${{ env.DEPLOYMENT_ID }} + run: | + set -euo pipefail + + # 获取当前 commit SHA + COMMIT_SHA="${GITHUB_SHA}" + + curl -X POST "$DEPLOY_SERVICE_CALLBACK_URL" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $DEPLOY_SERVICE_TOKEN" \ + -d '{ + "deploymentId": "'"${DEPLOYMENT_ID}"'", + "status": "failed", + "commitSha": "'"${COMMIT_SHA}"'", + "cfDeploymentId": "", + "errorMessage": "see Gitea Actions logs" + }' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..28b7580 --- /dev/null +++ b/.gitignore @@ -0,0 +1,157 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# =================== +# Dependencies +# =================== +node_modules/ +/.pnp +.pnp.js +.yarn/install-state.gz +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +package-lock.json +yarn.lock +pnpm-lock.yaml +bun.lockb + +# =================== +# Next.js +# =================== +/.next/ +/out/ +/build/ +.next +out + +# =================== +# Production +# =================== +/dist/ +*.min.js +*.min.css + +# =================== +# Testing +# =================== +/coverage/ +.nyc_output +*.lcov +jest-results.json + +# =================== +# TypeScript +# =================== +*.tsbuildinfo +next-env.d.ts +tsconfig.tsbuildinfo + +# =================== +# Environment Variables +# =================== +.env +.env.* +.env.local +.env.development.local +.env.test.local +.env.production.local +!.env.example + +# =================== +# IDE & Editors +# =================== +.idea/ +.vscode/ +*.swp +*.swo +*.sublime-workspace +*.sublime-project +.project +.classpath +.c9/ +*.launch +.settings/ +*.code-workspace + +# =================== +# OS Generated Files +# =================== +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db +Desktop.ini + +# =================== +# Logs +# =================== +logs/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# =================== +# Cache +# =================== +.cache/ +.parcel-cache/ +.eslintcache +.stylelintcache +*.cache +.turbo/ +.pnpm-store/ + +# =================== +# Vercel +# =================== +.vercel + +# =================== +# Debug +# =================== +*.pem +*.key +*.crt +*.p12 + +# =================== +# Misc +# =================== +*.pid +*.seed +*.pid.lock +*.orig +.temp/ +.tmp/ +tmp/ +temp/ + +# =================== +# Storybook +# =================== +storybook-static/ + +# =================== +# PWA +# =================== +public/sw.js +public/workbox-*.js +public/sw.js.map +public/workbox-*.js.map + +# =================== +# Sentry +# =================== +.sentryclirc + +# =================== +# Docker +# =================== +docker-compose.override.yml diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..e9ee3cb --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +legacy-peer-deps=true \ No newline at end of file diff --git a/NotFound/index.tsx b/NotFound/index.tsx new file mode 100644 index 0000000..cc27aca --- /dev/null +++ b/NotFound/index.tsx @@ -0,0 +1,78 @@ +import React from "react"; +import Image from "next/image"; +import Link from "next/link"; + +const NotFound = () => { + return ( +
+
+
+
+
+ image +
+
+
+
+
+ + + + + + + + +
+

+ We Can't Seem to Find The Page You're Looking For. +

+

+ Oops! The page you are looking for does not exist. It might have + been moved or deleted. +

+ + Go To Home + +
+
+
+
+
+ ); +}; + +export default NotFound; \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..2b506f4 --- /dev/null +++ b/README.md @@ -0,0 +1,264 @@ +# venus-nextjs + +个人作品集/博客网站模板,适用于设计师、开发者、自由职业者展示作品和服务。 + +## 技术栈 + +- Next.js 15.5.9 (已锁定版本,App Router) +- React 19.2.3 (已锁定版本,修复 CVE-2025-55182 漏洞) +- TypeScript 5 +- Tailwind CSS 4 +- next-auth (身份认证) +- next-themes (深色/浅色主题切换) +- AOS (滚动动画) +- react-slick (轮播组件) +- Markdown/MDX (博客内容) + +## 快速开始 + +```bash +npm install +npm run dev +``` + +## 目录结构 + +```text +src/ +├── app/ # Next.js App Router 入口 +│ ├── layout.tsx # 根布局 (Header + Footer + 主题Provider) +│ ├── page.tsx # 首页 +│ ├── not-found.tsx # 404 页面 +│ ├── globals.css # 全局样式 +│ ├── context/ # React Context +│ │ └── AuthDialogContext.tsx # 认证对话框状态管理 +│ ├── api/ # API 路由和数据 +│ │ ├── auth/[...nextauth]/route.ts # NextAuth 认证 API +│ │ ├── data.tsx # 静态数据 (菜单、计数器、服务、作品集) +│ │ └── contex/ToasetContex.tsx # Toast 通知 Context +│ └── (site)/ # 路由分组 (共享布局) +│ ├── about/page.tsx # 关于页面 +│ ├── blog/page.tsx # 博客列表 +│ ├── contact/page.tsx # 联系页面 +│ ├── documentation/page.tsx # 文档页面 +│ ├── portfolio/page.tsx # 作品集列表 +│ └── services/page.tsx # 服务页面 +├── components/ # 可复用组件 +│ ├── Layout/ # 布局组件 +│ │ ├── Header/index.tsx # 导航栏 (Logo + 菜单 + 主题切换) +│ │ └── Footer/index.tsx # 页脚 +│ ├── Home/ # 首页专用组件 +│ │ ├── Hero/index.tsx # Hero 区域 +│ │ ├── Services/index.tsx # 服务展示 +│ │ ├── Counter/index.tsx # 数据统计 +│ │ ├── WorkProgress/index.tsx # 工作进度 +│ │ └── Contact/index.tsx # 联系表单 +│ ├── Auth/ # 认证相关 +│ │ ├── SignIn/index.tsx # 登录组件 +│ │ ├── SignUp/index.tsx # 注册组件 +│ │ ├── SocialSignIn.tsx # 社交登录 +│ │ └── AuthDialog/ # 认证对话框 +│ ├── Blog/ # 博客组件 +│ ├── Contact/ # 联系页组件 +│ │ ├── Form/index.tsx # 联系表单 +│ │ ├── ContactInfo/index.tsx # 联系信息 +│ │ └── OfficeLocation/index.tsx # 办公地点 +│ ├── Documentation/ # 文档组件 +│ ├── portfolio/ # 作品集组件 +│ ├── Common/ # 通用组件 +│ ├── SharedComponent/ # 共享组件 +│ ├── Breadcrumb/ # 面包屑 +│ ├── ScrollToTop/ # 回到顶部按钮 +│ ├── NotFound/ # 404 组件 +│ └── nextauth/ # NextAuth Provider +├── types/ # TypeScript 类型定义 +│ ├── blog.ts # 博客类型 +│ ├── menu.ts # 菜单类型 +│ └── breadcrumb.ts # 面包屑类型 +├── utils/ # 工具函数 +│ ├── image.ts # 图片路径处理 +│ ├── aos.tsx # AOS 动画初始化 +│ ├── markdown.ts # Markdown 解析 +│ ├── markdownToHtml.ts # Markdown 转 HTML +│ ├── validateEmail.ts # 邮箱验证 +│ └── extendedConfig.ts # 扩展配置 +└── Style/ # 样式文件 + └── style.css # 组件样式 + +markdown/ # 博客内容 (MDX 格式) +└── Blog/ + ├── Blog_1.mdx + ├── Blog_2.mdx + └── ... + +public/ # 静态资源 +└── images/ + ├── logo/ # Logo 图片 + ├── hero/ # Hero 区域图片 + ├── blog/ # 博客封面图 + ├── portfolio/ # 作品集图片 + ├── services/ # 服务图标 + ├── contact/ # 联系页图片 + ├── counter/ # 计数器图标 + ├── testimonial/ # 评价图片 + ├── footer/ # 页脚图标 + └── documentation/ # 文档图片 +``` + +## 路由配置 + +| 路径 | 页面 | 说明 | +|------|------|------| +| `/` | Home | 首页 (Hero + 服务 + 作品集 + 评价 + 联系) | +| `/about` | About | 关于我 | +| `/services` | Services | 服务介绍 | +| `/portfolio` | Portfolio | 作品集列表 | +| `/blog` | Blog | 博客列表 | +| `/contact` | Contact | 联系方式 | +| `/documentation` | Documentation | 模板文档 | + +## 数据结构 + +### 菜单数据 (src/app/api/data.tsx) + +```typescript +export const menuItems = [ + { name: "Home", href: "#home" }, + { name: "About", href: "#about" }, + { name: "Services", href: "#services" }, + { name: "Portfolio", href: "#portfolio" }, + { name: "Testimonials", href: "#testimonials" }, + { name: "Blog", href: "/#blog" }, +]; +``` + +### 服务数据 (src/app/api/data.tsx) + +```typescript +export const Servicebox = [ + { + icon: '/images/services/ux-design-product_1.svg', + title: 'UX & Product Design', + description: '服务描述...', + }, + // ... +]; +``` + +### 作品集数据 (src/app/api/data.tsx) + +```typescript +export const portfolioinfo = [ + { + image: '/images/portfolio/cozycasa.png', + alt: 'Portfolio', + title: 'Cozycasa', + slug: 'Cozycasa', + info: 'Designation', + Class: 'md:mt-0' // 布局样式 + }, + // ... +]; +``` + +### 博客类型 (src/types/blog.ts) + +```typescript +export type Blog = { + id?: number; + title?: string; + slug?: string; + excerpt?: string; + coverImage?: string; + date: string; +}; +``` + +## 核心组件说明 + +### 布局系统 + +- `RootLayout` (src/app/layout.tsx): 根布局,包含主题Provider、认证Provider、Header和Footer +- 使用 `next-themes` 实现深色/浅色模式切换 +- 使用 `next-auth` 实现用户认证 + +### 主题切换 + +主题通过 `next-themes` 的 `ThemeProvider` 管理,支持: + +- `light` - 浅色主题 +- `dark` - 深色主题 +- `system` - 跟随系统 + +### 动画效果 + +使用 AOS (Animate On Scroll) 库,在 `src/utils/aos.tsx` 初始化 + +### 认证系统 + +使用 `next-auth` v4,配置文件位于 `src/app/api/auth/[...nextauth]/route.ts`。 + +启用社交登录需要: + +1. 在 `.env.local` 中配置环境变量: + +```bash +NEXTAUTH_SECRET=your-secret-key +NEXTAUTH_URL=http://localhost:3000 + +# Google 登录 +GOOGLE_CLIENT_ID=your-google-client-id +GOOGLE_CLIENT_SECRET=your-google-client-secret + +# GitHub 登录 +GITHUB_ID=your-github-id +GITHUB_SECRET=your-github-secret +``` + +1. 在 `route.ts` 中取消对应 provider 的注释 + +## 常见修改任务 + +### 修改网站信息 + +1. 修改 `src/components/Layout/Header/index.tsx` 中的 Logo +2. 修改 `src/components/Layout/Footer/index.tsx` 中的版权信息 +3. 修改 `src/app/layout.tsx` 中的 metadata + +### 修改导航菜单 + +编辑 `src/app/api/data.tsx` 中的 `menuItems` 数组 + +### 添加新页面 + +1. 在 `src/app/(site)/` 目录下创建新文件夹和 `page.tsx` +2. 在 `menuItems` 中添加导航项 + +### 添加博客文章 + +1. 在 `markdown/Blog/` 目录下创建新的 `.mdx` 文件 +2. 使用 frontmatter 定义标题、日期、封面图等 + +### 修改样式主题 + +1. 编辑 `src/app/globals.css` 中的 CSS 变量 +2. 或修改 `tailwind.config.ts` 中的主题配置 + +### 修改服务/作品集数据 + +编辑 `src/app/api/data.tsx` 中对应的数据数组 + +## 图片资源 + +- 存放在 `public/images/` 目录 +- 使用 `getImgPath()` 工具函数获取路径 (src/utils/image.ts) +- 引用路径:`/images/xxx.jpg` + +## 安全说明 + +以下依赖版本已锁定以修复安全漏洞: + +- **Next.js 15.5.9** - 锁定版本,修复漏洞编号为:CVE-2025-66478 +- **React 19.2.3** - 修复 React Server Components 远程代码执行漏洞 (CVE-2025-55182) + +请勿使用 `^` 或 `~` 前缀以避免自动升级到有漏洞的版本。 diff --git a/markdown/Blog/Blog_1.mdx b/markdown/Blog/Blog_1.mdx new file mode 100644 index 0000000..c421ae3 --- /dev/null +++ b/markdown/Blog/Blog_1.mdx @@ -0,0 +1,50 @@ +--- +title: Business from the brink of ruin by optimizing our website.... +excerpt: Business from the brink of ruin by optimizing our website.... +date: 2025-11-08 +coverImage: /images/blog/blog_1.png +author: silicaman +authorImage: /images/blogdetail-page/silicaman.png +--- + +# Main Heading & Points + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +- Vivamus eu lacus scelerisque, placerat commodo lectus. +- Etiam et ante at ex porta fringilla. +- Nullam dignissim sem eu magna aliquet, sit amet volutpat tellus + +![Blog Details](/images/blogdetail-1.jpg) + +Unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +--- + +We are a dedicated team of passionate product managers, developers, UX/UI designers, QA engineers experts helping businesses from new startups + +--- + +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable making this the first true generator on the Internet. It uses a dictionary + +--- + +## Tags + +- Trends +- Design +- Research + +--- + +## Share + +- [Facebook](#) +- [Twitter](#) +- [Linkedin](#) + +--- + +## Join our newsletter + +Email address: [Subscribe](#) \ No newline at end of file diff --git a/markdown/Blog/Blog_2.mdx b/markdown/Blog/Blog_2.mdx new file mode 100644 index 0000000..d3ee0bb --- /dev/null +++ b/markdown/Blog/Blog_2.mdx @@ -0,0 +1,50 @@ +--- +title: The work is top-notch and I consistently outrank all my... +excerpt: The work is top-notch and I consistently outrank all my... +date: 2025-11-08 +coverImage: /images/blog/blog_2.jpg +author: silicaman +authorImage: /images/blogdetail-page/silicaman.png +--- + +# Main Heading & Points + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +- Vivamus eu lacus scelerisque, placerat commodo lectus. +- Etiam et ante at ex porta fringilla. +- Nullam dignissim sem eu magna aliquet, sit amet volutpat tellus + +![Blog Details](/images/blogdetail-1.jpg) + +Unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +--- + +We are a dedicated team of passionate product managers, developers, UX/UI designers, QA engineers experts helping businesses from new startups + +--- + +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable making this the first true generator on the Internet. It uses a dictionary + +--- + +## Tags + +- Trends +- Design +- Research + +--- + +## Share + +- [Facebook](#) +- [Twitter](#) +- [Linkedin](#) + +--- + +## Join our newsletter + +Email address: [Subscribe](#) \ No newline at end of file diff --git a/markdown/Blog/Blog_3.mdx b/markdown/Blog/Blog_3.mdx new file mode 100644 index 0000000..1e13e25 --- /dev/null +++ b/markdown/Blog/Blog_3.mdx @@ -0,0 +1,50 @@ +--- +title: Grow my business through organic search and marketing... +excerpt: Grow my business through organic search and marketing... +date: 2025-11-08 +coverImage: /images/blog/blog_3.png +author: silicaman +authorImage: /images/blogdetail-page/silicaman.png +--- + +# Main Heading & Points + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +- Vivamus eu lacus scelerisque, placerat commodo lectus. +- Etiam et ante at ex porta fringilla. +- Nullam dignissim sem eu magna aliquet, sit amet volutpat tellus + +![Blog Details](/images/blogdetail-1.jpg) + +Unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +--- + +We are a dedicated team of passionate product managers, developers, UX/UI designers, QA engineers experts helping businesses from new startups + +--- + +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable making this the first true generator on the Internet. It uses a dictionary + +--- + +## Tags + +- Trends +- Design +- Research + +--- + +## Share + +- [Facebook](#) +- [Twitter](#) +- [Linkedin](#) + +--- + +## Join our newsletter + +Email address: [Subscribe](#) \ No newline at end of file diff --git a/markdown/Blog/Blog_4.mdx b/markdown/Blog/Blog_4.mdx new file mode 100644 index 0000000..0555abf --- /dev/null +++ b/markdown/Blog/Blog_4.mdx @@ -0,0 +1,50 @@ +--- +title: Tailored to your audience to enhance brand awareness... +excerpt: Tailored to your audience to enhance brand awareness... +date: 2025-11-08 +coverImage: /images/blog/blog_4.jpg +author: silicaman +authorImage: /images/blogdetail-page/silicaman.png +--- + +# Main Heading & Points + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +- Vivamus eu lacus scelerisque, placerat commodo lectus. +- Etiam et ante at ex porta fringilla. +- Nullam dignissim sem eu magna aliquet, sit amet volutpat tellus + +![Blog Details](/images/blogdetail-1.jpg) + +Unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +--- + +We are a dedicated team of passionate product managers, developers, UX/UI designers, QA engineers experts helping businesses from new startups + +--- + +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable making this the first true generator on the Internet. It uses a dictionary + +--- + +## Tags + +- Trends +- Design +- Research + +--- + +## Share + +- [Facebook](#) +- [Twitter](#) +- [Linkedin](#) + +--- + +## Join our newsletter + +Email address: [Subscribe](#) \ No newline at end of file diff --git a/markdown/Blog/Blog_5.mdx b/markdown/Blog/Blog_5.mdx new file mode 100644 index 0000000..9b334e7 --- /dev/null +++ b/markdown/Blog/Blog_5.mdx @@ -0,0 +1,50 @@ +--- +title: Uncover valuable insights for strategic business decisions... +excerpt: Uncover valuable insights for strategic business decisions... +date: 2025-11-08 +coverImage: /images/blog/blog_5.jpg +author: silicaman +authorImage: /images/blogdetail-page/silicaman.png +--- + +# Main Heading & Points + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +- Vivamus eu lacus scelerisque, placerat commodo lectus. +- Etiam et ante at ex porta fringilla. +- Nullam dignissim sem eu magna aliquet, sit amet volutpat tellus + +![Blog Details](/images/blogdetail-1.jpg) + +Unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +--- + +We are a dedicated team of passionate product managers, developers, UX/UI designers, QA engineers experts helping businesses from new startups + +--- + +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable making this the first true generator on the Internet. It uses a dictionary + +--- + +## Tags + +- Trends +- Design +- Research + +--- + +## Share + +- [Facebook](#) +- [Twitter](#) +- [Linkedin](#) + +--- + +## Join our newsletter + +Email address: [Subscribe](#) \ No newline at end of file diff --git a/markdown/Blog/Blog_6.mdx b/markdown/Blog/Blog_6.mdx new file mode 100644 index 0000000..4df5087 --- /dev/null +++ b/markdown/Blog/Blog_6.mdx @@ -0,0 +1,50 @@ +--- +title: Drive growth and achieve your business objectives effectively... +excerpt: Drive growth and achieve your business objectives effectively... +date: 2025-11-08 +coverImage: /images/blog/blog_6.jpg +author: silicaman +authorImage: /images/blogdetail-page/silicaman.png +--- + +# Main Heading & Points + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +- Vivamus eu lacus scelerisque, placerat commodo lectus. +- Etiam et ante at ex porta fringilla. +- Nullam dignissim sem eu magna aliquet, sit amet volutpat tellus + +![Blog Details](/images/blogdetail-1.jpg) + +Unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +--- + +We are a dedicated team of passionate product managers, developers, UX/UI designers, QA engineers experts helping businesses from new startups + +--- + +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable making this the first true generator on the Internet. It uses a dictionary + +--- + +## Tags + +- Trends +- Design +- Research + +--- + +## Share + +- [Facebook](#) +- [Twitter](#) +- [Linkedin](#) + +--- + +## Join our newsletter + +Email address: [Subscribe](#) \ No newline at end of file diff --git a/markdown/Blog/Blog_7.mdx b/markdown/Blog/Blog_7.mdx new file mode 100644 index 0000000..38125e5 --- /dev/null +++ b/markdown/Blog/Blog_7.mdx @@ -0,0 +1,50 @@ +--- +title: Free access to our global partner network and marketplace... +excerpt: Free access to our global partner network and marketplace... +date: 2025-11-08 +coverImage: /images/blog/blog_7.jpg +author: silicaman +authorImage: /images/blogdetail-page/silicaman.png +--- + +# Main Heading & Points + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +- Vivamus eu lacus scelerisque, placerat commodo lectus. +- Etiam et ante at ex porta fringilla. +- Nullam dignissim sem eu magna aliquet, sit amet volutpat tellus + +![Blog Details](/images/blogdetail-1.jpg) + +Unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +--- + +We are a dedicated team of passionate product managers, developers, UX/UI designers, QA engineers experts helping businesses from new startups + +--- + +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable making this the first true generator on the Internet. It uses a dictionary + +--- + +## Tags + +- Trends +- Design +- Research + +--- + +## Share + +- [Facebook](#) +- [Twitter](#) +- [Linkedin](#) + +--- + +## Join our newsletter + +Email address: [Subscribe](#) \ No newline at end of file diff --git a/markdown/Blog/Blog_8.mdx b/markdown/Blog/Blog_8.mdx new file mode 100644 index 0000000..507d266 --- /dev/null +++ b/markdown/Blog/Blog_8.mdx @@ -0,0 +1,50 @@ +--- +title: Define each stage of work to see whats important for you... +excerpt: Define each stage of work to see whats important for you... +date: 2025-11-08 +coverImage: /images/blog/blog_8.jpg +author: silicaman +authorImage: /images/blogdetail-page/silicaman.png +--- + +# Main Heading & Points + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +- Vivamus eu lacus scelerisque, placerat commodo lectus. +- Etiam et ante at ex porta fringilla. +- Nullam dignissim sem eu magna aliquet, sit amet volutpat tellus + +![Blog Details](/images/blogdetail-1.jpg) + +Unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +--- + +We are a dedicated team of passionate product managers, developers, UX/UI designers, QA engineers experts helping businesses from new startups + +--- + +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable making this the first true generator on the Internet. It uses a dictionary + +--- + +## Tags + +- Trends +- Design +- Research + +--- + +## Share + +- [Facebook](#) +- [Twitter](#) +- [Linkedin](#) + +--- + +## Join our newsletter + +Email address: [Subscribe](#) \ No newline at end of file diff --git a/markdown/Blog/Blog_9.mdx b/markdown/Blog/Blog_9.mdx new file mode 100644 index 0000000..259e684 --- /dev/null +++ b/markdown/Blog/Blog_9.mdx @@ -0,0 +1,50 @@ +--- +title: We have a plan that aligns perfectly with your goal... +excerpt: We have a plan that aligns perfectly with your goal... +date: 2025-11-08 +coverImage: /images/blog/blog_9.jpg +author: silicaman +authorImage: /images/blogdetail-page/silicaman.png +--- + +# Main Heading & Points + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +- Vivamus eu lacus scelerisque, placerat commodo lectus. +- Etiam et ante at ex porta fringilla. +- Nullam dignissim sem eu magna aliquet, sit amet volutpat tellus + +![Blog Details](/images/blogdetail-1.jpg) + +Unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the + +--- + +We are a dedicated team of passionate product managers, developers, UX/UI designers, QA engineers experts helping businesses from new startups + +--- + +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable making this the first true generator on the Internet. It uses a dictionary + +--- + +## Tags + +- Trends +- Design +- Research + +--- + +## Share + +- [Facebook](#) +- [Twitter](#) +- [Linkedin](#) + +--- + +## Join our newsletter + +Email address: [Subscribe](#) \ No newline at end of file diff --git a/next.config.mjs b/next.config.mjs new file mode 100644 index 0000000..2578e43 --- /dev/null +++ b/next.config.mjs @@ -0,0 +1,20 @@ +/** @type {import('next').NextConfig} */ + +// 如需部署到子路径(如 GitHub Pages),设置 basePath +// 例如:const basePath = "/your-repo-name"; +const basePath = ""; + +const nextConfig = { + // output: "export", // 静态导出模式,部署时取消注释 + basePath, + assetPrefix: basePath, + images: { + unoptimized: true, + }, + trailingSlash: true, + env: { + NEXT_PUBLIC_BASE_PATH: basePath, + }, +}; + +export default nextConfig; diff --git a/package.json b/package.json new file mode 100644 index 0000000..334b405 --- /dev/null +++ b/package.json @@ -0,0 +1,42 @@ +{ + "name": "venus_project", + "version": "1.0.1", + "private": true, + "scripts": { + "dev": "next dev -H 0.0.0.0 -p 3000", + "build": "next build", + "export": "next build", + "start": "next start -H 0.0.0.0 -p 3000", + "lint": "next lint" + }, + "dependencies": { + "@iconify/icons-ion": "^1.2.10", + "@iconify/react": "^5.0.1", + "aos": "^2.3.4", + "axios": "^1.7.2", + "date-fns": "^3.4.0", + "gray-matter": "^4.0.3", + "next": "15.5.9", + "next-auth": "^4.24.11", + "next-themes": "^0.3.0", + "nextjs-toploader": "^3.7.15", + "react": "19.2.3", + "react-dom": "19.2.3", + "react-hot-toast": "^2.4.1", + "react-slick": "^0.30.2", + "remark": "^15.0.1", + "remark-html": "^16.0.1", + "slick-carousel": "^1.8.1" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4.0.0", + "@types/aos": "^3.0.7", + "@types/node": "^20", + "@types/react": "^18", + "@types/react-dom": "^18", + "@types/react-slick": "^0.23.13", + "postcss": "^8", + "tailwindcss": "^4.0.0", + "typescript": "^5" + } +} \ No newline at end of file diff --git a/page.tsx b/page.tsx new file mode 100644 index 0000000..a4b6a53 --- /dev/null +++ b/page.tsx @@ -0,0 +1,35 @@ +// This is a mock data source. In a real app, you might fetch this +// from a headless CMS, a database, or a local JSON file. +const portfolioItems = [ + { slug: "project-alpha", title: "Project Alpha", content: "Details about project Alpha..." }, + { slug: "project-beta", title: "Project Beta", content: "Details about project Beta..." }, + { slug: "venus-nextjs", title: "Venus Next.js Theme", content: "Details about the Venus theme..." }, +]; + +// This function tells Next.js which slugs to pre-render at build time. +export async function generateStaticParams() { + // We return an array of objects, where each object has a `slug` property + // matching the dynamic segment `[slug]`. + return portfolioItems.map((item) => ({ + slug: item.slug, + })); +} + +// This is your page component. +export default function PortfolioPage({ params }: { params: { slug: string } }) { + // Find the specific portfolio item based on the slug from the URL. + const item = portfolioItems.find((p) => p.slug === params.slug); + + if (!item) { + // Optionally, handle cases where the slug doesn't match any item. + // In a static export, this would typically lead to a 404. + return
Project not found.
; + } + + return ( +
+

{item.title}

+

{item.content}

+
+ ); +} diff --git a/postcss.config.mjs b/postcss.config.mjs new file mode 100644 index 0000000..5d6d845 --- /dev/null +++ b/postcss.config.mjs @@ -0,0 +1,8 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + '@tailwindcss/postcss': {}, + }, +}; + +export default config; diff --git a/public/images/blog/blog_1.png b/public/images/blog/blog_1.png new file mode 100644 index 0000000..dd42b08 Binary files /dev/null and b/public/images/blog/blog_1.png differ diff --git a/public/images/blog/blog_2.jpg b/public/images/blog/blog_2.jpg new file mode 100644 index 0000000..fb2739c Binary files /dev/null and b/public/images/blog/blog_2.jpg differ diff --git a/public/images/blog/blog_3.png b/public/images/blog/blog_3.png new file mode 100644 index 0000000..0cbd810 Binary files /dev/null and b/public/images/blog/blog_3.png differ diff --git a/public/images/blog/blog_4.jpg b/public/images/blog/blog_4.jpg new file mode 100644 index 0000000..25a7073 Binary files /dev/null and b/public/images/blog/blog_4.jpg differ diff --git a/public/images/blog/blog_5.jpg b/public/images/blog/blog_5.jpg new file mode 100644 index 0000000..ba6e269 Binary files /dev/null and b/public/images/blog/blog_5.jpg differ diff --git a/public/images/blog/blog_6.jpg b/public/images/blog/blog_6.jpg new file mode 100644 index 0000000..0d06f18 Binary files /dev/null and b/public/images/blog/blog_6.jpg differ diff --git a/public/images/blog/blog_7.jpg b/public/images/blog/blog_7.jpg new file mode 100644 index 0000000..b003516 Binary files /dev/null and b/public/images/blog/blog_7.jpg differ diff --git a/public/images/blog/blog_8.jpg b/public/images/blog/blog_8.jpg new file mode 100644 index 0000000..e9b63b4 Binary files /dev/null and b/public/images/blog/blog_8.jpg differ diff --git a/public/images/blog/blog_9.jpg b/public/images/blog/blog_9.jpg new file mode 100644 index 0000000..30c106e Binary files /dev/null and b/public/images/blog/blog_9.jpg differ diff --git a/public/images/blogdetail-page/silicaman.png b/public/images/blogdetail-page/silicaman.png new file mode 100644 index 0000000..e18129a Binary files /dev/null and b/public/images/blogdetail-page/silicaman.png differ diff --git a/public/images/contact-page/Career.svg b/public/images/contact-page/Career.svg new file mode 100644 index 0000000..e0e7b86 --- /dev/null +++ b/public/images/contact-page/Career.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/images/contact-page/contact.jpg b/public/images/contact-page/contact.jpg new file mode 100644 index 0000000..69f4127 Binary files /dev/null and b/public/images/contact-page/contact.jpg differ diff --git a/public/images/contact-page/email.svg b/public/images/contact-page/email.svg new file mode 100644 index 0000000..2ef59a4 --- /dev/null +++ b/public/images/contact-page/email.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/public/images/contact/form-line.png b/public/images/contact/form-line.png new file mode 100644 index 0000000..63b54bf Binary files /dev/null and b/public/images/contact/form-line.png differ diff --git a/public/images/contact/from-round-line.png b/public/images/contact/from-round-line.png new file mode 100644 index 0000000..b09e08d Binary files /dev/null and b/public/images/contact/from-round-line.png differ diff --git a/public/images/contact/google-pay.png b/public/images/contact/google-pay.png new file mode 100644 index 0000000..5dabb27 Binary files /dev/null and b/public/images/contact/google-pay.png differ diff --git a/public/images/contact/play-juction.png b/public/images/contact/play-juction.png new file mode 100644 index 0000000..a85ba62 Binary files /dev/null and b/public/images/contact/play-juction.png differ diff --git a/public/images/contact/stripe.png b/public/images/contact/stripe.png new file mode 100644 index 0000000..9c99bd5 Binary files /dev/null and b/public/images/contact/stripe.png differ diff --git a/public/images/contact/wise.png b/public/images/contact/wise.png new file mode 100644 index 0000000..110a8bd Binary files /dev/null and b/public/images/contact/wise.png differ diff --git a/public/images/counter/admin.svg b/public/images/counter/admin.svg new file mode 100644 index 0000000..d034f5d --- /dev/null +++ b/public/images/counter/admin.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/counter/bag.svg b/public/images/counter/bag.svg new file mode 100644 index 0000000..196d717 --- /dev/null +++ b/public/images/counter/bag.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/counter/star.svg b/public/images/counter/star.svg new file mode 100644 index 0000000..5952455 --- /dev/null +++ b/public/images/counter/star.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/documentation/Categories=Nextjs.svg b/public/images/documentation/Categories=Nextjs.svg new file mode 100644 index 0000000..f4663d0 --- /dev/null +++ b/public/images/documentation/Categories=Nextjs.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/documentation/Categories=React.svg b/public/images/documentation/Categories=React.svg new file mode 100644 index 0000000..aa9430c --- /dev/null +++ b/public/images/documentation/Categories=React.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/documentation/Categories=Tailwind.svg b/public/images/documentation/Categories=Tailwind.svg new file mode 100644 index 0000000..6e3334f --- /dev/null +++ b/public/images/documentation/Categories=Tailwind.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/documentation/Categories=Typescript.svg b/public/images/documentation/Categories=Typescript.svg new file mode 100644 index 0000000..3b31b02 --- /dev/null +++ b/public/images/documentation/Categories=Typescript.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/images/documentation/axios.svg b/public/images/documentation/axios.svg new file mode 100644 index 0000000..67369ea --- /dev/null +++ b/public/images/documentation/axios.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/images/documentation/nextauth.png b/public/images/documentation/nextauth.png new file mode 100644 index 0000000..67c21ae Binary files /dev/null and b/public/images/documentation/nextauth.png differ diff --git a/public/images/footer/facebook.svg b/public/images/footer/facebook.svg new file mode 100644 index 0000000..81047b1 --- /dev/null +++ b/public/images/footer/facebook.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/footer/linkedin.svg b/public/images/footer/linkedin.svg new file mode 100644 index 0000000..3e5e37f --- /dev/null +++ b/public/images/footer/linkedin.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/footer/twitter.svg b/public/images/footer/twitter.svg new file mode 100644 index 0000000..91ef886 --- /dev/null +++ b/public/images/footer/twitter.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/hero/hero-image.png b/public/images/hero/hero-image.png new file mode 100644 index 0000000..f34caee Binary files /dev/null and b/public/images/hero/hero-image.png differ diff --git a/public/images/hero/hero-profile-1.jpg b/public/images/hero/hero-profile-1.jpg new file mode 100644 index 0000000..5c17819 Binary files /dev/null and b/public/images/hero/hero-profile-1.jpg differ diff --git a/public/images/hero/hero-profile-2.jpg b/public/images/hero/hero-profile-2.jpg new file mode 100644 index 0000000..3dba7a7 Binary files /dev/null and b/public/images/hero/hero-profile-2.jpg differ diff --git a/public/images/hero/hero-profile-3.jpg b/public/images/hero/hero-profile-3.jpg new file mode 100644 index 0000000..cb75eae Binary files /dev/null and b/public/images/hero/hero-profile-3.jpg differ diff --git a/public/images/hero/line-leyar.svg b/public/images/hero/line-leyar.svg new file mode 100644 index 0000000..ff3e3fd --- /dev/null +++ b/public/images/hero/line-leyar.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/hero/round-leyar.svg b/public/images/hero/round-leyar.svg new file mode 100644 index 0000000..27eadef --- /dev/null +++ b/public/images/hero/round-leyar.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/logo/logo-white.svg b/public/images/logo/logo-white.svg new file mode 100644 index 0000000..567faaf --- /dev/null +++ b/public/images/logo/logo-white.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/logo/logo.svg b/public/images/logo/logo.svg new file mode 100644 index 0000000..e3e268a --- /dev/null +++ b/public/images/logo/logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/portfolio/cozycasa.png b/public/images/portfolio/cozycasa.png new file mode 100644 index 0000000..708d2c7 Binary files /dev/null and b/public/images/portfolio/cozycasa.png differ diff --git a/public/images/portfolio/humans.png b/public/images/portfolio/humans.png new file mode 100644 index 0000000..d5a21f0 Binary files /dev/null and b/public/images/portfolio/humans.png differ diff --git a/public/images/portfolio/mars.png b/public/images/portfolio/mars.png new file mode 100644 index 0000000..2abc0b4 Binary files /dev/null and b/public/images/portfolio/mars.png differ diff --git a/public/images/portfolio/panda-logo.png b/public/images/portfolio/panda-logo.png new file mode 100644 index 0000000..03afe1e Binary files /dev/null and b/public/images/portfolio/panda-logo.png differ diff --git a/public/images/portfolio/roket-squred.png b/public/images/portfolio/roket-squred.png new file mode 100644 index 0000000..7c73d36 Binary files /dev/null and b/public/images/portfolio/roket-squred.png differ diff --git a/public/images/services/perfomance-optimization.svg b/public/images/services/perfomance-optimization.svg new file mode 100644 index 0000000..8277da8 --- /dev/null +++ b/public/images/services/perfomance-optimization.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/services/ux-design-product_1.svg b/public/images/services/ux-design-product_1.svg new file mode 100644 index 0000000..5b426ed --- /dev/null +++ b/public/images/services/ux-design-product_1.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/services/ux-design-product_2.svg b/public/images/services/ux-design-product_2.svg new file mode 100644 index 0000000..5e82979 --- /dev/null +++ b/public/images/services/ux-design-product_2.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/svgs/404.svg b/public/images/svgs/404.svg new file mode 100644 index 0000000..0897b07 --- /dev/null +++ b/public/images/svgs/404.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/testimonial/vector-smart.png b/public/images/testimonial/vector-smart.png new file mode 100644 index 0000000..bbcae5e Binary files /dev/null and b/public/images/testimonial/vector-smart.png differ diff --git a/public/images/work-progress/progress-work.png b/public/images/work-progress/progress-work.png new file mode 100644 index 0000000..605c591 Binary files /dev/null and b/public/images/work-progress/progress-work.png differ diff --git a/src/Style/style.css b/src/Style/style.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/(site)/about/page.tsx b/src/app/(site)/about/page.tsx new file mode 100644 index 0000000..6341ae5 --- /dev/null +++ b/src/app/(site)/about/page.tsx @@ -0,0 +1,29 @@ + +import React from "react"; +import HeroSub from "@/components/SharedComponent/HeroSub"; +import { Metadata } from "next"; +import Counter from "@/components/Home/Counter"; +import Progresswork from "@/components/Home/WorkProgress"; +export const metadata: Metadata = { + title: "About | Venus", +}; + +const page = () => { + const breadcrumbLinks = [ + { href: "/", text: "Home" }, + { href: "/about", text: "About" }, + ]; + return ( + <> + + + + + ); +}; + +export default page; diff --git a/src/app/(site)/blog/page.tsx b/src/app/(site)/blog/page.tsx new file mode 100644 index 0000000..4469856 --- /dev/null +++ b/src/app/(site)/blog/page.tsx @@ -0,0 +1,22 @@ +import React from 'react' +import BlogList from '@/components/Blog/BlogList' +import HeroSub from '@/components/SharedComponent/HeroSub' + +const BlogPage = () => { + const breadcrumbLinks = [ + { href: '/', text: 'Home' }, + { href: '/blog', text: 'Blog' }, + ] + return ( + <> + + + + ) +} + +export default BlogPage diff --git a/src/app/(site)/contact/page.tsx b/src/app/(site)/contact/page.tsx new file mode 100644 index 0000000..06950bd --- /dev/null +++ b/src/app/(site)/contact/page.tsx @@ -0,0 +1,30 @@ +import ContactForm from "@/components/Contact/Form"; +import ContactInfo from "@/components/Contact/ContactInfo"; +import Location from "@/components/Contact/OfficeLocation"; +import React from "react"; +import HeroSub from "@/components/SharedComponent/HeroSub"; +import { Metadata } from "next"; +export const metadata: Metadata = { + title: "Contact | Venus", +}; + +const page = () => { + const breadcrumbLinks = [ + { href: "/", text: "Home" }, + { href: "/contact", text: "Contact" }, + ]; + return ( + <> + + + + + + ); +}; + +export default page; diff --git a/src/app/(site)/documentation/page.tsx b/src/app/(site)/documentation/page.tsx new file mode 100644 index 0000000..2f0ef90 --- /dev/null +++ b/src/app/(site)/documentation/page.tsx @@ -0,0 +1,14 @@ + +import { Documentation } from "@/components/Documentation/Documentation"; +import { Metadata } from "next"; +export const metadata: Metadata = { + title: "Documentation | Venus", +}; + +export default function Page() { + return ( + <> + + + ); +}; diff --git a/src/app/(site)/portfolio/page.tsx b/src/app/(site)/portfolio/page.tsx new file mode 100644 index 0000000..06fff56 --- /dev/null +++ b/src/app/(site)/portfolio/page.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import Portfolio from "@/components/portfolio/PortfolioList"; +import HeroSub from "@/components/SharedComponent/HeroSub"; +import { Metadata } from "next"; +export const metadata: Metadata = { + title: "Portfolio | Venus", +}; + +const PortfolioList = () => { + const breadcrumbLinks = [ + { href: "/", text: "Home" }, + { href: "/portfolio", text: "Portfolio" }, + ]; + return ( + <> + + + + ); +}; + +export default PortfolioList; \ No newline at end of file diff --git a/src/app/(site)/services/page.tsx b/src/app/(site)/services/page.tsx new file mode 100644 index 0000000..93ab480 --- /dev/null +++ b/src/app/(site)/services/page.tsx @@ -0,0 +1,29 @@ + +import React from "react"; +import HeroSub from "@/components/SharedComponent/HeroSub"; +import { Metadata } from "next"; +import Counter from "@/components/Home/Counter"; +import Progresswork from "@/components/Home/WorkProgress"; +import Services from "@/components/Home/Services"; +export const metadata: Metadata = { + title: "Services | Venus", +}; + +const page = () => { + const breadcrumbLinks = [ + { href: "/", text: "Home" }, + { href: "/services", text: "Services" }, + ]; + return ( + <> + + + + ); +}; + +export default page; diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts new file mode 100644 index 0000000..7edbb04 --- /dev/null +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -0,0 +1,24 @@ +import NextAuth from "next-auth" +import type { NextAuthOptions } from "next-auth" + +// 基础配置,如需启用社交登录请配置对应的 providers +// 参考: https://next-auth.js.org/providers/ +export const authOptions: NextAuthOptions = { + providers: [ + // 示例:启用 Google 登录 + // GoogleProvider({ + // clientId: process.env.GOOGLE_CLIENT_ID!, + // clientSecret: process.env.GOOGLE_CLIENT_SECRET!, + // }), + // 示例:启用 GitHub 登录 + // GithubProvider({ + // clientId: process.env.GITHUB_ID!, + // clientSecret: process.env.GITHUB_SECRET!, + // }), + ], + secret: process.env.NEXTAUTH_SECRET || "development-secret-change-in-production", +} + +const handler = NextAuth(authOptions) + +export { handler as GET, handler as POST } diff --git a/src/app/api/contex/ToasetContex.tsx b/src/app/api/contex/ToasetContex.tsx new file mode 100644 index 0000000..629dccf --- /dev/null +++ b/src/app/api/contex/ToasetContex.tsx @@ -0,0 +1,13 @@ +"use client"; + +import { Toaster } from "react-hot-toast"; + +const ToasterContext = () => { + return ( +
+ +
+ ); +}; + +export default ToasterContext; diff --git a/src/app/api/data.tsx b/src/app/api/data.tsx new file mode 100644 index 0000000..3008716 --- /dev/null +++ b/src/app/api/data.tsx @@ -0,0 +1,136 @@ +import { getImgPath } from "@/utils/image"; + +export const menuItems = [ + { name: "Home", href: "#home" }, + { name: "About", href: "#about" }, + { name: "Services", href: "#services" }, + { name: "Portfolio", href: "#portfolio" }, + { name: "Testimonials", href: "#testimonials" }, + { name: "Blog", href: "/#blog" }, +]; + +export const count = [ + { + icon: getImgPath("/images/counter/star.svg"), + value: "4.86", + description: "Out of 5 stars from 3896 reviews on Google platform", + }, + { + icon: getImgPath("/images/counter/admin.svg"), + value: "364", + description: "Client testimonials received in the year 2021", + }, + { + icon: getImgPath("/images/counter/bag.svg"), + value: "45M+", + description: "Revenue generated through new projects & marketing", + }, +]; + +export const Progress = [ + { title: 'UX Research and Testing', Progress: 95 }, + { title: 'Product Management', Progress: 84 }, + { title: 'UI & Visual Design', Progress: 90 } +]; + +export const Servicebox = [ + { + icon: getImgPath('/images/services/ux-design-product_1.svg'), + title: 'UX & Product Design', + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', + }, + { + icon: getImgPath('/images/services/perfomance-optimization.svg'), + title: 'Performance Optimization', + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', + }, + { + icon: getImgPath('/images/services/ux-design-product_2.svg'), + title: 'UX & Products Design', + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', + }, +] + +export const portfolioinfo = [ + { + image: getImgPath('/images/portfolio/cozycasa.png'), + alt: 'Portfolio', + title: 'Cozycasa', + slug: 'Cozycasa', + info: 'Designation', + Class: 'md:mt-0' + }, + { + image: getImgPath('/images/portfolio/mars.png'), + alt: 'Portfolio', + title: 'Mars', + slug: 'Mars', + info: 'Designation', + Class: 'md:mt-24' + }, + { + image: getImgPath('/images/portfolio/humans.png'), + alt: 'Portfolio', + title: 'Everyday Humans', + slug: 'everyday-humans', + info: 'Designation', + Class: 'md:mt-0' + }, + { + image: getImgPath('/images/portfolio/roket-squred.png'), + alt: 'Portfolio', + title: 'Rocket Squared', + slug: 'rocket-squared', + info: 'Designation', + Class: 'md:mt-24' + }, + { + image: getImgPath('/images/portfolio/panda-logo.png'), + alt: 'Portfolio', + title: 'Panda Logo', + slug: 'panda-logo', + info: 'Designation', + Class: 'md:mt-0' + }, + { + image: getImgPath('/images/portfolio/humans.png'), + alt: 'Portfolio', + title: 'Fusion Dynamics', + slug: 'fusion-dynamics', + info: 'Designation', + Class: 'md:mt-0' + }, + { + image: getImgPath('/images/portfolio/cozycasa.png'), + alt: 'Portfolio', + title: 'InnovateX Ventures', + slug: 'innovate-x-ventures', + info: 'Designation', + Class: 'md:mt-24' + }, + { + image: getImgPath('/images/portfolio/mars.png'), + alt: 'Portfolio', + title: 'Nebula Holdings', + slug: 'nebula-holdings', + info: 'Designation', + Class: 'md:mt-0' + }, + { + image: getImgPath('/images/portfolio/panda-logo.png'), + alt: 'Portfolio', + title: 'Summit Partners', + slug: 'summit-partners', + info: 'Designation', + Class: 'md:mt-24' + }, + { + image: getImgPath('/images/portfolio/roket-squred.png'), + alt: 'Portfolio', + title: 'Apex Strategies', + slug: 'apex-strategies', + info: 'Designation', + Class: 'md:mt-0' + }, + +] \ No newline at end of file diff --git a/src/app/context/AuthDialogContext.tsx b/src/app/context/AuthDialogContext.tsx new file mode 100644 index 0000000..2aced2b --- /dev/null +++ b/src/app/context/AuthDialogContext.tsx @@ -0,0 +1,36 @@ +"use client" + +import React, { createContext, useState, ReactNode, Dispatch, SetStateAction } from "react"; + +// Define types for the context +interface AuthDialogContextType { + isSuccessDialogOpen: boolean; + isFailedDialogOpen: boolean; + isUserRegistered: boolean; + setIsSuccessDialogOpen: Dispatch>; + setIsFailedDialogOpen: Dispatch>; + setIsUserRegistered: Dispatch>; +} + +// Create context with type or null +export const AuthDialogContext = createContext(null); + +// Define the provider props type +interface AuthDialogProviderProps { + children: ReactNode; +} + +// Create a provider component +export const AuthDialogProvider: React.FC = ({ children }) => { + const [isSuccessDialogOpen , setIsSuccessDialogOpen] = useState(false); + const [isFailedDialogOpen , setIsFailedDialogOpen] = useState(false); + const [isUserRegistered , setIsUserRegistered] = useState(false); + + return ( + + {children} + + ); +}; + +export default AuthDialogContext; diff --git a/src/app/favicon.ico b/src/app/favicon.ico new file mode 100644 index 0000000..af164a7 Binary files /dev/null and b/src/app/favicon.ico differ diff --git a/src/app/globals.css b/src/app/globals.css new file mode 100644 index 0000000..036cca6 --- /dev/null +++ b/src/app/globals.css @@ -0,0 +1,141 @@ +@import 'tailwindcss'; + +@custom-variant dark (&:is(.dark *)); + +@theme { + --spacing-6xl: 75rem; + --container-screen-2xl: 83.75rem; + + --shadow-service: 0px 3px 20px 0px #8e9ca90d; + --shadow-deatail_shadow: 0px 20px 80px 0px #68758d26; + --shadow-dark-md: rgba(145, 158, 171, 0.2) 0px 0px 2px 0px, + rgba(145, 158, 171, 0.12) 0px 12px 24px -4px; + + --transition-duration-150: 150ms; + + --spacing-25: 25rem; + --spacing-29: 28rem; + --spacing-45: 45rem; + --spacing-50: 50rem; + --spacing-94: 22.5rem; + --spacing-120: 120rem; + --spacing-6_25: 6.25rem; + --spacing-70\%: 70%; + --spacing-40\%: 40%; + --spacing-30\%: 30%; + --spacing-60\%: 60%; + --spacing-8_5: 8.5rem; + --spacing-3_75: 3.75rem; + + --height-150: 750px; + --height-6_25: 6.25rem; + + --leading-extra-loose: 2.5; + --leading-2_5: 2.5rem; + + --inset-5\%: 5%; + --inset-35\%: 35%; + + --z-index-1: 1; + --z-index-2: 2; + --z-index-999: 999; + + --color-primary: #2f73f2; + --color-secondary: #547593; + --color-midnight_text: #102d47; + --color-grey: #668199; + --color-border: #ccd7e1; + --color-success: #3cd278; + --color-section: #f8fafc; + --color-darkmode: #081738; + --color-darklight: #000f30; + --color-dark_border: #224767; + --color-Sky-blue-mist: #c0d5fb; + + --background-image-gradient-radial: radial-gradient(var(--tw-gradient-stops)); + --background-image-gradient-conic: conic-gradient( + from 180deg at 50% 50%, + var(--tw-gradient-stops) + ); +} + +/* + The default border color has changed to `currentColor` in Tailwind CSS v4, + so we've added these compatibility styles to make sure everything still + looks the same as it did with Tailwind CSS v3. + + If we ever want to remove these styles, we need to add an explicit border + color utility to any element that depends on these defaults. +*/ +@layer base { + *, + ::after, + ::before, + ::backdrop, + ::file-selector-button { + border-color: var(--color-gray-200, currentColor); + } +} + +html { + scroll-behavior: smooth; + overflow-x: hidden; +} + +body { + @apply overflow-x-hidden; +} + +@layer base { + section { + @apply py-16; + } +} + +.margin_top { + @apply md:mt-[6.25rem] mt-0; +} +/* Slick Slider */ +.slick-slide, +.portfolio_slide { + @apply focus-visible:outline-0!; +} +.slick-dots li.slick-active button:before { + @apply opacity-100! text-primary! w-4! h-4!; +} +.slick-dots li button:before { + @apply text-base! text-[#BBC8D5]! opacity-100!; +} + +.blog-details p, +.blog-details hr { + @apply mb-8; +} + +.blog-details hr { + @apply border-border dark:border-dark_border; +} + +.blog-details strong { + @apply font-bold dark:text-white; +} + +.blog-details ul { + @apply mb-8 list-inside list-disc space-y-3; +} + +.blog-details ol { + @apply mb-8 list-inside list-decimal space-y-3; +} + +.blog-details h1 { + @apply mb-8 text-3xl font-bold text-midnight_text dark:text-white sm:text-4xl md:text-[40px] md:leading-[1.28]; +} + +.blog-details h2 { + @apply mb-8 text-2xl font-bold text-midnight_text dark:text-white sm:text-3xl md:text-[35px] md:leading-[1.28]; +} + +.blog-details h3 { + @apply mb-6 text-2xl font-bold dark:text-white sm:text-[28px] sm:leading-[40px]; +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 0000000..a8d342b --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,44 @@ +import { Inter } from "next/font/google"; +import "./globals.css"; +import Header from "@/components/Layout/Header"; +import Footer from "@/components/Layout/Footer"; +import { ThemeProvider } from "next-themes"; +import ScrollToTop from '@/components/ScrollToTop'; +import Aoscompo from "@/utils/aos"; +import NextTopLoader from 'nextjs-toploader'; +import SessionProviderComp from "@/components/nextauth/SessionProvider"; +import { AuthDialogProvider } from "./context/AuthDialogContext"; +const inter = Inter({ subsets: ["latin"] }); + + +export default function RootLayout({ + children, + session, +}: Readonly<{ + children: React.ReactNode; + session:any +}>) { + return ( + + + + + + + +
+ {children} +