Skip to content

feat: full SEO optimization - all 14 languages#99

Open
yysam123456-source wants to merge 71 commits into
PDFCraftTool:mainfrom
yysam123456-source:seo-optimization
Open

feat: full SEO optimization - all 14 languages#99
yysam123456-source wants to merge 71 commits into
PDFCraftTool:mainfrom
yysam123456-source:seo-optimization

Conversation

@yysam123456-source

Copy link
Copy Markdown

本次更新

✅ 已完成

  1. 12 种非英语语言工具内容翻译(72 工具 × 4 字段)
  2. 13 种语言 metaDescription 翻译 + en.ts 优化到 150-160 字符
  3. OG 图片更新(1200×630px,蓝紫渐变)
  4. 构建验证(1700+ 静态页面,无错误)
  5. 页面功能验证(14 语言首页 + 24 个工具页全部 HTTP 200)

📊 构建状态

  • ✅ Next.js 静态导出成功
  • ✅ 所有语言 meta 标签正确渲染
  • ✅ 阿拉伯语 RTL 配置正确

🔜 待优化(后续 PR)

  • OG 图片动态生成(当前使用静态 og-image.png)
  • 内部链接策略优化

yysam123456 added 30 commits May 29, 2026 21:26
- wrangler.toml for Cloudflare Pages deployment
- pnpm-lock.yaml for reproducible builds
- pnpm-workspace.yaml for build allow list
- scripts/cloudflare-cleanup.mjs: remove libreoffice-wasm from out/ when CF_PAGES=1
- decompress-wasm.mjs: skip decompression on CF_PAGES builds
- package.json: add cloudflare-cleanup to postbuild pipeline
- libreoffice-wasm files (47MB+27MB) exceed Cloudflare Pages 25MB limit
- pymupdf-wasm files kept (all under 25MB)
- src/middleware.ts: redirect / to /en (308 permanent), all routes
- src/config/site.ts: update domain to pdf.craftisle.com (fixes sitemap/canonical)
- src/app/layout.tsx: add AdSense script via NEXT_PUBLIC_ADSENSE_CLIENT env
- src/components/ads/AdSlot.tsx: unified ad component (dev placeholder / prod AdSense)
- src/components/tools/ToolPage.tsx: inject 2 ad slots (below-interface + below-faq)
- src/lib/libreoffice/converter.ts: NEXT_PUBLIC_WASM_CDN_URL env var for R2 base path
- scripts/upload-wasm-to-r2.sh: wrangler script to upload libreoffice-wasm to R2
- package.json: add r2:upload script

LibreOffice WASM files (47MB+27MB) exceed CF Pages 25MB limit.
Now served from R2 via NEXT_PUBLIC_WASM_CDN_URL env var.
Post-build cleanup still removes them from CF Pages output.
- public/_redirects: SPA fallback rule (/* /index.html 200)
- Ensures /en/merge-pdf etc. return 200 instead of 404
- File is copied to out/ by Next.js static export
- cloudflare-cleanup.mjs: only remove files >25MB (keep JS workers), not entire dir
- converter.ts: JS files load locally from app server, WASM/Data from CDN
  - LOCAL_JS_PATH for soffice.js/workers (<500KB, deployed by CF Pages)
  - WASM_DATA_CDN_PATH for soffice.wasm/soffice.data from GitHub Release
- asset-loader.ts: auto-discover chunked files (part_0..N) when manifest missing
  - Falls back to chunk discovery on 404 without needing .manifest.json

The GitHub Release v1.0.0-wasm has chunked assets ready.
JS files stay small and get deployed with CF Pages normally.
- converter.ts: point all WASM/data URLs to raw.githubusercontent.com/yysam123456-source/pdfcraft/wasm-assets
- converter.ts: DecompressionStream for .gz files in browser
- asset-loader.ts: remove dead chunk reassembly code
- Cloudflare Pages 25MB limit bypassed via external CDN
- wasm-assets branch hosts soffice.wasm.gz (47MB) + soffice.data.gz (27MB)
LibreOffice expects fonts at /inst/share/fonts/truetype/ but
injectFonts() writes to /instdir/share/fonts/truetype/.
Added FS.symlink('/instdir', '/inst') in injectFonts()
so both paths resolve to the same location.

Fixes: 'still waiting on run dependencies: dependency: cp /inst/share/fonts/truetype/NotoSansSC-Regular.ttf'
…ncies hang)

Root cause: createPreloadedFile() uses async fetch, but preRun does not
wait for it, so LibreOffice starts before fonts are written, causing
'still waiting on run dependencies: dependency: cp /inst/share/fonts/truetype/NotoSansSC-Regular.ttf'

Fix:
1. loadModule(): store options.fonts on Module object (a.fonts = this.options.fonts || [])
2. preRun callback: replace createPreloadedFile with synchronous FS.writeFile,
   writing font ArrayBuffers from self.Module.fonts to BOTH /instdir/ and /inst/ paths

Fixes: #issue
Generate metaDescription: 150-160 chars, include primary keyword + 'free' + 'online' + CTA
Expand keywords: 8-12 long-tail phrases per tool
Use Node.js line-by-line state machine v11 (correctly handles description template literal)
- Create .env.example with NEXT_PUBLIC_ADSENSE_CLIENT documentation
- Update wrangler.toml with AdSense setup instructions
- Single NEXT_PUBLIC_ADSENSE_CLIENT switch controls all pdfcraft.com ads
- Cloudflare Pages: set var in Dashboard Settings → Variables and Secrets
- Updated site name, creator, SEO metadata to Craftisle PDF
- Changed layout.tsx title and description
- Updated site.ts config (name, creator, keywords)
- Added logo.svg asset
- Updated globals.css with Craftisle brand colors
…[category])

- Add /workflow to STATIC_PAGES (was missing despite route existing)
- Create /terms route (page.tsx + TermsPageClient.tsx) referenced by navConfig.footerNav but missing on disk
- Add /tools/category/[category] dynamic pages (all 6 TOOL_CATEGORIES) to sitemap
- Fix getSitemapUrlCount() to include categoryPagesCount
- Fix sitemap.ts import: TOOL_CATEGORIES from @/types/tool (not @/config/tools)
yysam123456 added 30 commits June 5, 2026 12:14
- Add metadata.terms.title and metadata.terms.description
- Fixes MISSING_MESSAGE errors in Cloudflare Pages build
- 13 locales updated: en, ar, de, es, fr, id, it, ja, ko, pt, ro, vi, zh, zh-TW
- This should fix og:image localhost:3000 issue (metadata generation failure)
- tools/[tool]/page.tsx: add metadataBase to both early-return branches
  (tool not found / content not found) to eliminate build warnings
- public/_redirects: remove invalid comment lines (Cloudflare does not support /* comments)
- Fixes 'metadataBase property in metadata export is not set' warning
- tools/category/[category]/page.tsx: add metadataBase to generateMetadata return
- metadata.ts: add generateTermsMetadata function
- terms/page.tsx: use generateTermsMetadata instead of generateAboutMetadata
- index.ts: add generateTermsMetadata to the metadata re-export list
- Fixes 'Attempted import error: generateTermsMetadata is not exported from @/lib/seo'
- Add LanguageSelector import
- Replace empty placeholder div with actual LanguageSelector component
- Fix missing ')' in tTools() calls in WatermarkTool.tsx
- Fix tTools scope issue in RemoveBlankPagesTool.tsx (moved useTranslations inside PageCard)
- Fix preRun type error in libreoffice/converter.ts (commented out preRun, added 'as any' cast)
- Remove double toolname prefix in tTools() calls:
  - EditPdfTool.tsx: editPdf.xxx -> xxx
  - WatermarkTool.tsx: watermark.xxx -> xxx
  - StampsTool.tsx: stamps.xxx -> xxx
  - TableOfContentsTool.tsx: tableOfContents.xxx -> xxx
  - RemoveBlankPagesTool.tsx: removeBlankPages.xxx -> xxx
- Build now passes (1701 pages generated successfully)
…in worker

- Add console.log before and after attachFileFromMemory calls
- Use startGetAttachments/numberGetAttachments to verify attachments were added
- Help diagnose why output PDF does not contain uploaded attachments
- fr/de/ja/ko/pt/it/id/vi/ro/zh-TW: translated (concurrent)
- ar: needs verification (RTL language)
- es: translated (serial, first completion)
- Fix vi.ts export name in index.ts (toolContentVi)
- Remove .bak backup files
…escription

- Translate tool content (description/howToUse/useCases/faq) for 12 non-English languages
- Optimize en.ts metaDescription length (150-160 chars) for better CTR
- Update .gitignore to exclude *.bak and *.sh files
- All 14 languages now have localized tool content (en already optimized)
- Build verified: 1700+ pages generated successfully
- All 72 tools now have localized metaDescription per language
- Build verified: 1700+ pages generated, all meta tags rendered correctly
- Verified JA/ES/AR pages: meta description present in generated HTML
- rtl config already correct in config.ts (ar direction: rtl)
- Regenerate og-image.png using sharp (gradient background, branded design)
- Previous og-image.png was returning 403 (Cloudflare blocking)
- New image: 1200x630px, blue-purple gradient, PDFCraft branding
- Verified: image loads correctly via local server (HTTP 200)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant