diff --git a/SEO-README.md b/SEO-README.md new file mode 100644 index 0000000..575d24c --- /dev/null +++ b/SEO-README.md @@ -0,0 +1,171 @@ +# SEO 优化说明 + +本项目已完成基础 SEO 优化,以下是已实施的改动。 + +## 已完成的优化项 + +### 1. HTML Meta 标签优化 ✅ + +在 `index.html` 中添加了完整的 SEO 元数据: + +- **基础 Meta 标签** + - title, description, keywords + - author, theme-color + - canonical URL + +- **Open Graph 标签**(社交媒体分享优化) + - og:type, og:url, og:title + - og:description, og:image, og:site_name + +- **Twitter Card 标签** + - twitter:card, twitter:title + - twitter:description, twitter:image + +- **结构化数据**(JSON-LD) + - Schema.org WebSite 类型标记 + - 提升搜索引擎理解能力 + +### 2. SEO 配置文件 ✅ + +- **`public/robots.txt`** - 搜索引擎爬虫规则 + - 允许所有爬虫访问 + - 指定 sitemap 位置 + +- **`public/sitemap.xml`** - 站点地图(自动生成) + - 包含所有工具页面 URL + - 设置更新频率和优先级 + - 通过 `scripts/generate-sitemap.ts` 自动生成 + +- **`public/manifest.json`** - PWA 配置 + - 支持渐进式 Web 应用 + - 改善移动端体验 + +### 3. 构建流程优化 ✅ + +- **`package.json`** + - 构建时自动生成 sitemap + - 添加 tsx 依赖用于运行生成脚本 + +## 文件清单 + +### 新增文件 +``` +public/ +├── robots.txt # 爬虫规则 +├── sitemap.xml # 站点地图(自动生成) +└── manifest.json # PWA 配置 + +scripts/ +└── generate-sitemap.ts # Sitemap 生成脚本 +``` + +### 修改文件 +``` +index.html # 添加 SEO meta 标签和结构化数据 +package.json # 添加 sitemap 生成命令 +``` + +## 使用说明 + +### 开发 +```bash +pnpm install # 安装依赖 +pnpm dev # 启动开发服务器 +``` + +### 构建 +```bash +pnpm run build # 构建项目(自动生成 sitemap) +pnpm run generate:sitemap # 单独生成 sitemap +``` + +### 部署前检查 + +⚠️ **重要:部署前必须更新配置文件中的域名!** + +需要将以下文件中的 `https://litek.typist.cc` 替换为你的实际域名: + +1. **`index.html`** + - canonical URL + - Open Graph URL 和 image + - Twitter Card image + - Structured Data URL + +2. **`public/robots.txt`** + - Sitemap URL + +3. **`scripts/generate-sitemap.ts`** + - BASE_URL 常量 + +更新后重新构建: +```bash +pnpm run build +``` + +## SEO 验证 + +### 部署后验证 + +1. **提交 sitemap 到 Google Search Console** + - 访问 https://search.google.com/search-console + - 添加网站资源 + - 提交 sitemap: `https://你的域名/sitemap.xml` + +2. **测试结构化数据** + - 访问 https://validator.schema.org/ + - 输入网站 URL + - 检查是否有错误 + +3. **测试 Open Graph 预览** + - Facebook: https://developers.facebook.com/tools/debug/ + - Twitter: https://cards-dev.twitter.com/validator + +4. **性能测试** + - Google PageSpeed Insights: https://pagespeed.web.dev/ + - 目标分数: SEO > 95 + +## 可访问的 URL + +部署后,以下 URL 应该可以正常访问: + +- `https://你的域名/` - 主页 +- `https://你的域名/robots.txt` - 爬虫规则 +- `https://你的域名/sitemap.xml` - 站点地图 +- `https://你的域名/manifest.json` - PWA 配置 +- `https://你的域名/tool/uuid` - UUID 工具 +- `https://你的域名/tool/json` - JSON 工具 +- `https://你的域名/tool/base64` - Base64 工具 +- `https://你的域名/tool/network/dns` - DNS 工具 +- ... 其他工具页面 + +## 添加新工具时更新 SEO + +当添加新工具时,需要更新 `scripts/generate-sitemap.ts`: + +```typescript +const tools = [ + // 现有工具... + { path: '/tool/你的新工具', priority: '0.9' }, +]; +``` + +然后重新构建项目。 + +## SEO 效果预期 + +- **1-2 周**:搜索引擎开始索引页面 +- **1-2 月**:主要关键词开始有排名 +- **3-6 月**:稳定的搜索排名和自然流量增长 + +## 技术栈 + +- React 19 + TypeScript +- Vite (Rolldown) +- React Router v7 +- Radix UI + Tailwind CSS 4 +- Nginx + +## 联系方式 + +需要更多工具或有建议?联系:litek@mail.typist.cc + diff --git a/index.html b/index.html index dfa2974..f558672 100644 --- a/index.html +++ b/index.html @@ -2,9 +2,56 @@ - - Lite Kit + + + Lite Kit - Lightweight Online Tools + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/package.json b/package.json index 2496b60..78ade65 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "type": "module", "scripts": { "dev": "vite", - "build": "tsc -b && vite build", + "build": "npm run generate:sitemap && tsc -b && vite build", + "generate:sitemap": "tsx scripts/generate-sitemap.ts", "lint": "eslint .", "preview": "vite preview", "release:patch": "npm version patch && git push --follow-tags", @@ -43,6 +44,7 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.22", "globals": "^16.4.0", + "tsx": "^4.19.2", "tw-animate-css": "^1.4.0", "typescript": "~5.9.3", "typescript-eslint": "^8.45.0", @@ -53,7 +55,8 @@ "vite": "npm:rolldown-vite@7.1.14" }, "onlyBuiltDependencies": [ - "@swc/core" + "@swc/core", + "esbuild" ] } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a67820a..2660f75 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,7 +31,7 @@ importers: version: 1.2.8(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@tailwindcss/vite': specifier: ^4.1.16 - version: 4.1.16(rolldown-vite@7.1.14(@types/node@24.9.1)(jiti@2.6.1)) + version: 4.1.16(rolldown-vite@7.1.14(@types/node@24.9.1)(esbuild@0.25.11)(jiti@2.6.1)(tsx@4.20.6)) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -83,7 +83,7 @@ importers: version: 19.2.2(@types/react@19.2.2) '@vitejs/plugin-react': specifier: ^5.1.0 - version: 5.1.0(rolldown-vite@7.1.14(@types/node@24.9.1)(jiti@2.6.1)) + version: 5.1.0(rolldown-vite@7.1.14(@types/node@24.9.1)(esbuild@0.25.11)(jiti@2.6.1)(tsx@4.20.6)) eslint: specifier: ^9.36.0 version: 9.38.0(jiti@2.6.1) @@ -96,6 +96,9 @@ importers: globals: specifier: ^16.4.0 version: 16.4.0 + tsx: + specifier: ^4.19.2 + version: 4.20.6 tw-animate-css: specifier: ^1.4.0 version: 1.4.0 @@ -107,7 +110,7 @@ importers: version: 8.46.2(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) vite: specifier: npm:rolldown-vite@7.1.14 - version: rolldown-vite@7.1.14(@types/node@24.9.1)(jiti@2.6.1) + version: rolldown-vite@7.1.14(@types/node@24.9.1)(esbuild@0.25.11)(jiti@2.6.1)(tsx@4.20.6) packages: @@ -203,6 +206,162 @@ packages: '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + '@esbuild/aix-ppc64@0.25.11': + resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.11': + resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.11': + resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.11': + resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.11': + resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.11': + resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.11': + resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.11': + resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.11': + resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.11': + resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.11': + resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.11': + resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.11': + resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.11': + resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.11': + resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.11': + resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.11': + resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.11': + resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.11': + resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.11': + resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.11': + resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.11': + resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.11': + resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.11': + resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.11': + resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.11': + resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.9.0': resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1035,6 +1194,11 @@ packages: resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} engines: {node: '>=10.13.0'} + esbuild@0.25.11: + resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -1153,6 +1317,9 @@ packages: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} engines: {node: '>=6'} + get-tsconfig@4.13.0: + resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1489,6 +1656,9 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -1609,6 +1779,11 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsx@4.20.6: + resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==} + engines: {node: '>=18.0.0'} + hasBin: true + tw-animate-css@1.4.0: resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} @@ -1810,6 +1985,84 @@ snapshots: tslib: 2.8.1 optional: true + '@esbuild/aix-ppc64@0.25.11': + optional: true + + '@esbuild/android-arm64@0.25.11': + optional: true + + '@esbuild/android-arm@0.25.11': + optional: true + + '@esbuild/android-x64@0.25.11': + optional: true + + '@esbuild/darwin-arm64@0.25.11': + optional: true + + '@esbuild/darwin-x64@0.25.11': + optional: true + + '@esbuild/freebsd-arm64@0.25.11': + optional: true + + '@esbuild/freebsd-x64@0.25.11': + optional: true + + '@esbuild/linux-arm64@0.25.11': + optional: true + + '@esbuild/linux-arm@0.25.11': + optional: true + + '@esbuild/linux-ia32@0.25.11': + optional: true + + '@esbuild/linux-loong64@0.25.11': + optional: true + + '@esbuild/linux-mips64el@0.25.11': + optional: true + + '@esbuild/linux-ppc64@0.25.11': + optional: true + + '@esbuild/linux-riscv64@0.25.11': + optional: true + + '@esbuild/linux-s390x@0.25.11': + optional: true + + '@esbuild/linux-x64@0.25.11': + optional: true + + '@esbuild/netbsd-arm64@0.25.11': + optional: true + + '@esbuild/netbsd-x64@0.25.11': + optional: true + + '@esbuild/openbsd-arm64@0.25.11': + optional: true + + '@esbuild/openbsd-x64@0.25.11': + optional: true + + '@esbuild/openharmony-arm64@0.25.11': + optional: true + + '@esbuild/sunos-x64@0.25.11': + optional: true + + '@esbuild/win32-arm64@0.25.11': + optional: true + + '@esbuild/win32-ia32@0.25.11': + optional: true + + '@esbuild/win32-x64@0.25.11': + optional: true + '@eslint-community/eslint-utils@4.9.0(eslint@9.38.0(jiti@2.6.1))': dependencies: eslint: 9.38.0(jiti@2.6.1) @@ -2351,12 +2604,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.16 '@tailwindcss/oxide-win32-x64-msvc': 4.1.16 - '@tailwindcss/vite@4.1.16(rolldown-vite@7.1.14(@types/node@24.9.1)(jiti@2.6.1))': + '@tailwindcss/vite@4.1.16(rolldown-vite@7.1.14(@types/node@24.9.1)(esbuild@0.25.11)(jiti@2.6.1)(tsx@4.20.6))': dependencies: '@tailwindcss/node': 4.1.16 '@tailwindcss/oxide': 4.1.16 tailwindcss: 4.1.16 - vite: rolldown-vite@7.1.14(@types/node@24.9.1)(jiti@2.6.1) + vite: rolldown-vite@7.1.14(@types/node@24.9.1)(esbuild@0.25.11)(jiti@2.6.1)(tsx@4.20.6) '@tybys/wasm-util@0.10.1': dependencies: @@ -2493,7 +2746,7 @@ snapshots: '@typescript-eslint/types': 8.46.2 eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react@5.1.0(rolldown-vite@7.1.14(@types/node@24.9.1)(jiti@2.6.1))': + '@vitejs/plugin-react@5.1.0(rolldown-vite@7.1.14(@types/node@24.9.1)(esbuild@0.25.11)(jiti@2.6.1)(tsx@4.20.6))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) @@ -2501,7 +2754,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.43 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: rolldown-vite@7.1.14(@types/node@24.9.1)(jiti@2.6.1) + vite: rolldown-vite@7.1.14(@types/node@24.9.1)(esbuild@0.25.11)(jiti@2.6.1)(tsx@4.20.6) transitivePeerDependencies: - supports-color @@ -2607,6 +2860,35 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.0 + esbuild@0.25.11: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.11 + '@esbuild/android-arm': 0.25.11 + '@esbuild/android-arm64': 0.25.11 + '@esbuild/android-x64': 0.25.11 + '@esbuild/darwin-arm64': 0.25.11 + '@esbuild/darwin-x64': 0.25.11 + '@esbuild/freebsd-arm64': 0.25.11 + '@esbuild/freebsd-x64': 0.25.11 + '@esbuild/linux-arm': 0.25.11 + '@esbuild/linux-arm64': 0.25.11 + '@esbuild/linux-ia32': 0.25.11 + '@esbuild/linux-loong64': 0.25.11 + '@esbuild/linux-mips64el': 0.25.11 + '@esbuild/linux-ppc64': 0.25.11 + '@esbuild/linux-riscv64': 0.25.11 + '@esbuild/linux-s390x': 0.25.11 + '@esbuild/linux-x64': 0.25.11 + '@esbuild/netbsd-arm64': 0.25.11 + '@esbuild/netbsd-x64': 0.25.11 + '@esbuild/openbsd-arm64': 0.25.11 + '@esbuild/openbsd-x64': 0.25.11 + '@esbuild/openharmony-arm64': 0.25.11 + '@esbuild/sunos-x64': 0.25.11 + '@esbuild/win32-arm64': 0.25.11 + '@esbuild/win32-ia32': 0.25.11 + '@esbuild/win32-x64': 0.25.11 + escalade@3.2.0: {} escape-string-regexp@4.0.0: {} @@ -2736,6 +3018,10 @@ snapshots: get-nonce@1.0.1: {} + get-tsconfig@4.13.0: + dependencies: + resolve-pkg-maps: 1.0.0 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -2994,9 +3280,11 @@ snapshots: resolve-from@4.0.0: {} + resolve-pkg-maps@1.0.0: {} + reusify@1.1.0: {} - rolldown-vite@7.1.14(@types/node@24.9.1)(jiti@2.6.1): + rolldown-vite@7.1.14(@types/node@24.9.1)(esbuild@0.25.11)(jiti@2.6.1)(tsx@4.20.6): dependencies: '@oxc-project/runtime': 0.92.0 fdir: 6.5.0(picomatch@4.0.3) @@ -3007,8 +3295,10 @@ snapshots: tinyglobby: 0.2.15 optionalDependencies: '@types/node': 24.9.1 + esbuild: 0.25.11 fsevents: 2.3.3 jiti: 2.6.1 + tsx: 4.20.6 rolldown@1.0.0-beta.41: dependencies: @@ -3083,6 +3373,13 @@ snapshots: tslib@2.8.1: {} + tsx@4.20.6: + dependencies: + esbuild: 0.25.11 + get-tsconfig: 4.13.0 + optionalDependencies: + fsevents: 2.3.3 + tw-animate-css@1.4.0: {} type-check@0.4.0: diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..82f49e1 --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,21 @@ +{ + "name": "Lite Kit - Lightweight Online Tools", + "short_name": "Lite Kit", + "description": "Free online tools including UUID generator, JSON formatter, Base64 encoder/decoder, network testing tools and more", + "start_url": "/", + "display": "standalone", + "background_color": "#000000", + "theme_color": "#000000", + "orientation": "portrait-primary", + "icons": [ + { + "src": "/lite.svg", + "type": "image/svg+xml", + "sizes": "any" + } + ], + "categories": ["utilities", "productivity"], + "lang": "en", + "dir": "ltr" +} + diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..421c28d --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,21 @@ +# Allow all crawlers +User-agent: * +Allow: / + +# Sitemaps +Sitemap: https://litek.typist.cc/sitemap.xml + +# Common bots +User-agent: Googlebot +Allow: / + +User-agent: Bingbot +Allow: / + +User-agent: Baiduspider +Allow: / + +# Crawl-delay for less aggressive bots +User-agent: * +Crawl-delay: 1 + diff --git a/public/sitemap.xml b/public/sitemap.xml new file mode 100644 index 0000000..70865f9 --- /dev/null +++ b/public/sitemap.xml @@ -0,0 +1,63 @@ + + + + https://litek.typist.cc + 2025-10-29 + weekly + 1.0 + + + https://litek.typist.cc/tool + 2025-10-29 + weekly + 0.9 + + + https://litek.typist.cc/tool/uuid + 2025-10-29 + monthly + 0.9 + + + https://litek.typist.cc/tool/json + 2025-10-29 + monthly + 0.9 + + + https://litek.typist.cc/tool/base64 + 2025-10-29 + monthly + 0.9 + + + https://litek.typist.cc/tool/network/dns + 2025-10-29 + monthly + 0.8 + + + https://litek.typist.cc/tool/network/ping + 2025-10-29 + monthly + 0.8 + + + https://litek.typist.cc/tool/network/tcping + 2025-10-29 + monthly + 0.8 + + + https://litek.typist.cc/tool/network/speedtest + 2025-10-29 + monthly + 0.8 + + + https://litek.typist.cc/tool/network/ipquery + 2025-10-29 + monthly + 0.8 + + diff --git a/scripts/generate-sitemap.ts b/scripts/generate-sitemap.ts new file mode 100644 index 0000000..e048771 --- /dev/null +++ b/scripts/generate-sitemap.ts @@ -0,0 +1,83 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +interface SitemapUrl { + loc: string; + lastmod: string; + changefreq: string; + priority: string; +} + +const BASE_URL = 'https://litek.typist.cc'; +const currentDate = new Date().toISOString().split('T')[0]; + +const tools = [ + { path: '/tool/uuid', priority: '0.9' }, + { path: '/tool/json', priority: '0.9' }, + { path: '/tool/base64', priority: '0.9' }, + { path: '/tool/network/dns', priority: '0.8' }, + { path: '/tool/network/ping', priority: '0.8' }, + { path: '/tool/network/tcping', priority: '0.8' }, + { path: '/tool/network/speedtest', priority: '0.8' }, + { path: '/tool/network/ipquery', priority: '0.8' }, +]; + +const urls: SitemapUrl[] = [ + { + loc: BASE_URL, + lastmod: currentDate, + changefreq: 'weekly', + priority: '1.0', + }, + { + loc: `${BASE_URL}/tool`, + lastmod: currentDate, + changefreq: 'weekly', + priority: '0.9', + }, +]; + +// Add all tool pages +tools.forEach((tool) => { + urls.push({ + loc: `${BASE_URL}${tool.path}`, + lastmod: currentDate, + changefreq: 'monthly', + priority: tool.priority, + }); +}); + +function generateSitemap(): string { + let xml = '\n'; + xml += '\n'; + + urls.forEach((url) => { + xml += ' \n'; + xml += ` ${url.loc}\n`; + xml += ` ${url.lastmod}\n`; + xml += ` ${url.changefreq}\n`; + xml += ` ${url.priority}\n`; + xml += ' \n'; + }); + + xml += '\n'; + return xml; +} + +// Generate and write sitemap +const sitemap = generateSitemap(); +const publicDir = path.resolve(__dirname, '../public'); +const sitemapPath = path.join(publicDir, 'sitemap.xml'); + +// Ensure public directory exists +if (!fs.existsSync(publicDir)) { + fs.mkdirSync(publicDir, { recursive: true }); +} + +fs.writeFileSync(sitemapPath, sitemap, 'utf-8'); +console.log(`✅ Sitemap generated successfully at ${sitemapPath}`); +