diff --git a/docs/project_status_report_2026-03-10.md b/docs/project_status_report_2026-03-10.md index b5a62b9..610316e 100644 --- a/docs/project_status_report_2026-03-10.md +++ b/docs/project_status_report_2026-03-10.md @@ -1,6 +1,7 @@ # SaaS-PDF Project Status Report Generated on: 2026-03-10 +Updated on: 2026-03-25 Branch reviewed: feature/seo-content ## Executive Summary @@ -27,7 +28,7 @@ The main remaining gaps are consistency and production hardening: ### Backend -- Flask application factory with 24 registered blueprints +- Flask application factory with 33 registered blueprints - Celery async task processing - Redis-backed task flow - Service-oriented architecture under backend/app/services @@ -133,7 +134,7 @@ Implemented pages: Notes: -- Contact currently uses a mailto flow rather than a backend contact form endpoint. +- Contact now uses a backend submission endpoint plus direct email fallback. - About, Privacy, and Terms are SEO-enabled pages with structured metadata. ## Phase 6 — Technical SEO Optimization @@ -215,11 +216,11 @@ The following improvements were started as part of this implementation step: 1. Refresh docs/tool_inventory.md so it becomes the current source of truth again. 2. Remove duplicate Helmet metadata from tool components that are already wrapped by ToolLandingPage. 3. Replace placeholder domain values in public SEO files with the production domain. -4. Decide whether contact should remain mailto-based or move to a backend endpoint. +4. Surface or intentionally defer the tools that exist in routes but are not shown on the homepage. 5. Run full backend and frontend test/build validation in the target environment. ## Final Assessment SaaS-PDF is no longer just a basic MVP. It is already a broad multi-tool document-processing platform with strong progress across product scope, frontend SEO architecture, and backend task-based processing. -The current priority is not missing core features. The current priority is tightening consistency, production configuration, and documentation so the implemented work is easier to maintain and safer to ship. \ No newline at end of file +The current priority is not missing core features. The current priority is tightening consistency, production configuration, homepage/catalog alignment, and documentation so the implemented work is easier to maintain and safer to ship. diff --git a/docs/seo_strategy.md b/docs/seo_strategy.md index 7d5a9e3..aef5b2f 100644 --- a/docs/seo_strategy.md +++ b/docs/seo_strategy.md @@ -12,7 +12,7 @@ | **OpenGraph tags** | `og:title`, `og:description`, `og:url`, `og:type`, `og:site_name`, `og:locale` on all pages | | **Twitter cards** | `twitter:card`, `twitter:title`, `twitter:description` on all pages | | **Structured data** | `WebSite`, `Organization`, `WebPage`, `WebApplication`, `BreadcrumbList`, `FAQPage` JSON-LD | -| **Sitemap** | Auto-generated via `scripts/generate_sitemap.py` — 37 URLs (5 pages + 32 tools) | +| **Sitemap** | Auto-generated via frontend SEO scripts — current committed snapshot contains 245 URLs across static pages, blog posts, tool routes, and programmatic SEO pages | | **robots.txt** | Allows all crawlers; blocks `/api/`, `/account`, auth pages | | **Internationalization** | Full i18n in EN, AR, FR — all tool pages, SEO content, and static pages | | **Font loading** | `dns-prefetch` + `preconnect` + `display=swap` for Google Fonts | @@ -58,7 +58,7 @@ VITE_GOOGLE_SITE_VERIFICATION=your-verification-code ## 3. SEO Content Architecture -### 3.1 Tool Landing Pages (32 pages) +### 3.1 Tool Landing Pages (44 direct tool routes + programmatic SEO pages) Each tool page (`/tools/{slug}`) renders via `ToolLandingPage` wrapper: @@ -79,7 +79,7 @@ All text is i18n-driven from `seo.{toolKey}.*` keys in EN/AR/FR. |------|--------|---------| | `/` | `WebSite` + `Organization` | Homepage with hero + tool grid | | `/about` | `WebPage` | Mission, technology, security | -| `/contact` | `WebPage` | Contact form (mailto-based) | +| `/contact` | `WebPage` | Contact form backed by `/api/contact/submit` plus email fallback | | `/privacy` | `WebPage` | Privacy policy | | `/terms` | `WebPage` | Terms of service | @@ -87,7 +87,7 @@ All text is i18n-driven from `seo.{toolKey}.*` keys in EN/AR/FR. | File | Purpose | |------|---------| -| `sitemap.xml` | All 37 indexable URLs with priority and changefreq | +| `sitemap.xml` | Current public snapshot includes 245 indexable URLs with priority and changefreq values | | `robots.txt` | Crawler directives + sitemap pointer | | `llms.txt` | AI/LLM discoverability file | | `humans.txt` | Team credits | @@ -106,7 +106,7 @@ All text is i18n-driven from `seo.{toolKey}.*` keys in EN/AR/FR. - [ ] Verify Core Web Vitals pass (LCP < 2.5s, FID < 100ms, CLS < 0.1) **Content:** -- [ ] Publish all 32 tool pages with full SEO content +- [ ] Publish and maintain the 44 direct tool pages with full SEO content - [ ] Ensure hreflang tags work across EN/AR/FR (add `hreflang` links if using subdomains or subdirectories) - [ ] Add FAQ schema to all tool pages (already done) @@ -209,7 +209,7 @@ All text is i18n-driven from `seo.{toolKey}.*` keys in EN/AR/FR. **Key differentiators for Dociva:** 1. **Trilingual** — EN/AR/FR from day one (Arabic market is largely unserved) 2. **No signup** — zero friction, instant file processing -3. **32 tools** — broader coverage than most competitors +3. **44 direct tool routes** — broad product coverage with room to surface more of the catalog on the homepage 4. **AI-powered tools** — OCR, Chat PDF, Summarize, Translate (unique value) 5. **Privacy-first** — files auto-deleted within 30 minutes @@ -219,7 +219,7 @@ All text is i18n-driven from `seo.{toolKey}.*` keys in EN/AR/FR. ``` □ Review Search Console for crawl errors and fix immediately -□ Check index coverage — ensure all 37+ pages are indexed +□ Check index coverage — ensure the current sitemap inventory is being indexed as expected □ Review top queries — identify rising keywords to create content for □ Publish 8–16 blog posts (2–4/week × 3 languages) □ Build 5–10 backlinks through outreach diff --git a/docs/tool_inventory.md b/docs/tool_inventory.md index f3a14ac..62d723e 100644 --- a/docs/tool_inventory.md +++ b/docs/tool_inventory.md @@ -1,274 +1,328 @@ -# Dociva — Tool Inventory & Competitive Gap Analysis +# Dociva — Current Tool Inventory & Competitive Gap Analysis -> Generated: March 7, 2026 -> Branch: `feature/critical-maintenance-and-editor` +> Updated: March 25, 2026 +> Source of truth: current code in `frontend/src/App.tsx`, `frontend/src/pages/HomePage.tsx`, `backend/app/routes`, and `backend/app/routes/v1/tools.py` --- -## 1. Platform Infrastructure +## 1. Current Platform Snapshot -| Component | Technology | Status | -|---|---|---| -| Backend | Flask + Gunicorn | ✅ Production-ready | -| Frontend | React + Vite + TypeScript + Tailwind | ✅ Production-ready | -| Task Queue | Celery + Redis | ✅ 3 queues (default, image, pdf_tools) | -| Scheduler | Celery Beat | ✅ Expired-file cleanup every 30 min | -| Database | SQLite | ✅ Users, API keys, history, usage events | -| Storage | Local + S3 (optional) | ✅ Presigned URLs | -| Auth | Session-based + API Key (B2B) | ✅ Free & Pro plans | -| Security | Talisman CSP, rate limiting, CORS, input sanitization | ✅ | -| i18n | react-i18next (en, ar, fr) | ✅ All tools translated | -| Monetization | Google AdSense slots | ✅ Integrated | -| Email | SMTP (password reset) | ✅ | -| Docker | docker-compose (dev + prod) | ✅ | -| Nginx | Reverse proxy + SSL | ✅ | +| Area | Current state | +|---|---| +| Backend | Flask + Gunicorn + Celery + Redis | +| Frontend | React + Vite + TypeScript + Tailwind | +| Storage | Local filesystem + optional S3 | +| Accounts | Session auth + usage history + API keys | +| Monetization | Ad slots + pricing page + Stripe subscription plumbing | +| API | `/api/v1/*` B2B surface for a significant subset of tools | +| i18n | English, Arabic, French | +| SEO | Tool landing pages + structured data + generated public SEO files | -### Plans & Quotas - -| | Free | Pro | -|---|---|---| -| Web requests/month | 50 | 500 | -| API requests/month | — | 1,000 | -| Max file size | 50 MB | 100 MB | -| History retention | 25 | 250 | -| API key access | ❌ | ✅ | - -### Registered Blueprints: 18 - -| Blueprint | Prefix | Purpose | -|---|---|---| -| `health_bp` | `/api` | Health check | -| `auth_bp` | `/api/auth` | Login, register, forgot/reset password | -| `account_bp` | `/api/account` | Profile, API keys, usage | -| `admin_bp` | `/api/internal/admin` | Plan management | -| `convert_bp` | `/api/convert` | PDF ↔ Word | -| `compress_bp` | `/api/compress` | PDF compression | -| `image_bp` | `/api/image` | Image convert & resize | -| `video_bp` | `/api/video` | Video to GIF | -| `history_bp` | `/api` | User history | -| `pdf_tools_bp` | `/api/pdf-tools` | Merge, split, rotate, watermark, etc. | -| `flowchart_bp` | `/api/flowchart` | AI flowchart extraction | -| `tasks_bp` | `/api/tasks` | Task status polling | -| `download_bp` | `/api/download` | Secure file download | -| `v1_bp` | `/api/v1` | B2B API (all tools) | -| `config_bp` | `/api/config` | Dynamic limits | -| `ocr_bp` | `/api/ocr` | OCR text extraction | -| `removebg_bp` | `/api/remove-bg` | Background removal | -| `pdf_editor_bp` | `/api/pdf-editor` | PDF text annotations | - ---- - -## 2. Existing Tools — Complete Inventory (21 tools) - -### 2.1 PDF Tools (14) - -| # | Tool | Endpoint | Service | Task | Component | Route | i18n | B2B API | -|---|---|---|---|---|---|---|---|---| -| 1 | **Compress PDF** | `POST /api/compress/pdf` | `compress_service` | `compress_pdf_task` | `PdfCompressor.tsx` | `/tools/compress-pdf` | ✅ | ✅ | -| 2 | **PDF to Word** | `POST /api/convert/pdf-to-word` | `pdf_service` | `convert_pdf_to_word` | `PdfToWord.tsx` | `/tools/pdf-to-word` | ✅ | ✅ | -| 3 | **Word to PDF** | `POST /api/convert/word-to-pdf` | `pdf_service` | `convert_word_to_pdf` | `WordToPdf.tsx` | `/tools/word-to-pdf` | ✅ | ✅ | -| 4 | **Merge PDF** | `POST /api/pdf-tools/merge` | `pdf_tools_service` | `merge_pdfs_task` | `MergePdf.tsx` | `/tools/merge-pdf` | ✅ | ✅ | -| 5 | **Split PDF** | `POST /api/pdf-tools/split` | `pdf_tools_service` | `split_pdf_task` | `SplitPdf.tsx` | `/tools/split-pdf` | ✅ | ✅ | -| 6 | **Rotate PDF** | `POST /api/pdf-tools/rotate` | `pdf_tools_service` | `rotate_pdf_task` | `RotatePdf.tsx` | `/tools/rotate-pdf` | ✅ | ✅ | -| 7 | **PDF to Images** | `POST /api/pdf-tools/pdf-to-images` | `pdf_tools_service` | `pdf_to_images_task` | `PdfToImages.tsx` | `/tools/pdf-to-images` | ✅ | ✅ | -| 8 | **Images to PDF** | `POST /api/pdf-tools/images-to-pdf` | `pdf_tools_service` | `images_to_pdf_task` | `ImagesToPdf.tsx` | `/tools/images-to-pdf` | ✅ | ✅ | -| 9 | **Watermark PDF** | `POST /api/pdf-tools/watermark` | `pdf_tools_service` | `watermark_pdf_task` | `WatermarkPdf.tsx` | `/tools/watermark-pdf` | ✅ | ✅ | -| 10 | **Protect PDF** | `POST /api/pdf-tools/protect` | `pdf_tools_service` | `protect_pdf_task` | `ProtectPdf.tsx` | `/tools/protect-pdf` | ✅ | ✅ | -| 11 | **Unlock PDF** | `POST /api/pdf-tools/unlock` | `pdf_tools_service` | `unlock_pdf_task` | `UnlockPdf.tsx` | `/tools/unlock-pdf` | ✅ | ✅ | -| 12 | **Add Page Numbers** | `POST /api/pdf-tools/page-numbers` | `pdf_tools_service` | `add_page_numbers_task` | `AddPageNumbers.tsx` | `/tools/page-numbers` | ✅ | ✅ | -| 13 | **PDF Editor** | `POST /api/pdf-editor/edit` | `pdf_editor_service` | `edit_pdf_task` | `PdfEditor.tsx` | `/tools/pdf-editor` | ✅ | ❌ | -| 14 | **PDF Flowchart** | `POST /api/flowchart/extract` + 3 | `flowchart_service` | `extract_flowchart_task` | `PdfFlowchart.tsx` | `/tools/pdf-flowchart` | ✅ | ✅ | - -### 2.2 Image Tools (4) - -| # | Tool | Endpoint | Service | Task | Component | Route | i18n | B2B API | -|---|---|---|---|---|---|---|---|---| -| 15 | **Image Converter** | `POST /api/image/convert` | `image_service` | `convert_image_task` | `ImageConverter.tsx` | `/tools/image-converter` | ✅ | ✅ | -| 16 | **Image Resize** | `POST /api/image/resize` | `image_service` | `resize_image_task` | `ImageResize.tsx` | `/tools/image-resize` | ✅ | ✅ | -| 17 | **OCR** | `POST /api/ocr/image` + `/pdf` | `ocr_service` | `ocr_image_task` / `ocr_pdf_task` | `OcrTool.tsx` | `/tools/ocr` | ✅ | ❌ | -| 18 | **Remove Background** | `POST /api/remove-bg` | `removebg_service` | `remove_bg_task` | `RemoveBackground.tsx` | `/tools/remove-background` | ✅ | ❌ | - -### 2.3 Video Tools (1) - -| # | Tool | Endpoint | Service | Task | Component | Route | i18n | B2B API | -|---|---|---|---|---|---|---|---|---| -| 19 | **Video to GIF** | `POST /api/video/to-gif` | `video_service` | `create_gif_task` | `VideoToGif.tsx` | `/tools/video-to-gif` | ✅ | ✅ | - -### 2.4 Text Tools — Client-Side Only (2) - -| # | Tool | Backend | Component | Route | i18n | -|---|---|---|---|---|---| -| 20 | **Word Counter** | None (JS) | `WordCounter.tsx` | `/tools/word-counter` | ✅ | -| 21 | **Text Cleaner** | None (JS) | `TextCleaner.tsx` | `/tools/text-cleaner` | ✅ | - -### Feature Flags - -| Flag | Default | Controls | -|---|---|---| -| `FEATURE_EDITOR` | `false` | OCR, Remove Background, PDF Editor routes (403 when off) | - ---- - -## 3. Test Coverage - -| Category | Test Files | Tests | -|---|---|---| -| Auth | `test_auth.py` | 5 | -| Config | `test_config.py` | 3 | -| Password reset | `test_password_reset.py` | 8 | -| Maintenance | `test_maintenance_tasks.py` | 8 | -| Compress | `test_compress.py`, `test_compress_service.py`, `test_compress_tasks.py` | 6 | -| Convert | `test_convert.py`, `test_convert_tasks.py` | 6 | -| Image | `test_image.py`, `test_image_service.py`, `test_image_tasks.py` | ~18 | -| Video | `test_video.py`, `test_video_service.py`, `test_video_tasks.py` | ~12 | -| PDF tools | `test_pdf_tools.py`, `test_pdf_tools_service.py`, `test_pdf_tools_tasks.py` | ~50 | -| Flowchart | `test_flowchart_tasks.py` | ~6 | -| OCR | `test_ocr.py`, `test_ocr_service.py` | 12 | -| Remove BG | `test_removebg.py` | 3 | -| PDF Editor | `test_pdf_editor.py` | 7 | -| Infra | `test_download.py`, `test_health.py`, `test_history.py`, `test_rate_limiter.py`, `test_sanitizer.py`, `test_storage_service.py`, `test_file_validator.py`, `test_utils.py`, `test_tasks_route.py` | ~36 | -| **TOTAL** | **30 files** | **180 ✅** | - ---- - -## 4. Missing Tools — Competitive Gap Analysis - -Comparison against: iLovePDF, SmallPDF, TinyWow, PDF24, Adobe Acrobat Online. - -### 4.1 HIGH PRIORITY — Core tools competitors all have - -| # | Tool | Category | Complexity | Dependencies | Notes | -|---|---|---|---|---|---| -| 1 | **Compress Image** | Image | Low | Pillow (exists) | JPEG/PNG/WebP quality reduction + resize. Pillow already installed. | -| 2 | **PDF to Excel** | PDF → Office | Medium | `camelot-py` or `tabula-py` | Table extraction from PDFs — high user demand. | -| 3 | **PDF to PowerPoint** | PDF → Office | Medium | `python-pptx` | Convert PDF pages to PPTX slides (images per slide or OCR). | -| 4 | **Excel to PDF** | Office → PDF | Medium | LibreOffice CLI | Same pattern as Word to PDF. | -| 5 | **PowerPoint to PDF** | Office → PDF | Medium | LibreOffice CLI | Same pattern as Word to PDF. | -| 6 | **HTML to PDF** | Web → PDF | Low | `weasyprint` or `playwright` | Input URL or HTML snippet → PDF. | -| 7 | **Reorder / Rearrange Pages** | PDF | Low | PyPDF2 (exists) | Drag-and-drop page reorder UI → backend rebuilds PDF. | -| 8 | **Extract Pages** | PDF | Low | PyPDF2 (exists) | Similar to Split but with visual page picker. Already partially covered by Split tool. | -| 9 | **Sign PDF** | PDF | Medium | ReportLab + canvas | Draw/upload signature → overlay onto PDF page. | -| 10 | **PDF Repair** | PDF | Low | PyPDF2 (exists) | Read → rewrite to fix broken xref tables. | - -### 4.2 MEDIUM PRIORITY — Differentiators present on 2–3 competitors - -| # | Tool | Category | Complexity | Dependencies | Notes | -|---|---|---|---|---|---| -| 11 | **PDF to PDF/A** | PDF | Medium | Ghostscript (exists) | Archival format conversion. | -| 12 | **Flatten PDF** | PDF | Low | PyPDF2 (exists) | Remove form fields / annotations → flat page. | -| 13 | **Crop PDF** | PDF | Medium | PyPDF2 (exists) | Crop margins / adjust page boundaries. | -| 14 | **Compare PDFs** | PDF | High | `diff-match-patch` + PyPDF2 | Side-by-side visual diff of two documents. | -| 15 | **QR Code Generator** | Utility | Low | `qrcode` + Pillow | Text/URL → QR image. Client-side possible but backend for API. | -| 16 | **Barcode Generator** | Utility | Low | `python-barcode` | Generate Code128, EAN, UPC barcodes. | -| 17 | **Image Crop** | Image | Low | Pillow (exists) | Visual cropping UI → backend Pillow crop. | -| 18 | **Image Rotate / Flip** | Image | Low | Pillow (exists) | 90°/180°/270° + horizontal/vertical flip. | -| 19 | **Image Filters** | Image | Low | Pillow (exists) | Grayscale, sepia, blur, sharpen, brightness, contrast. | - -### 4.3 LOW PRIORITY — Advanced / niche (1–2 competitors, premium features) - -| # | Tool | Category | Complexity | Dependencies | Notes | -|---|---|---|---|---|---| -| 20 | **AI Chat with PDF** | AI | High | OpenRouter (exists) | Upload PDF → ask questions. Flowchart service has partial foundation. | -| 21 | **AI PDF Summarizer** | AI | Medium | OpenRouter (exists) | Extract text → prompt LLM for summary. | -| 22 | **AI PDF Translator** | AI | Medium | OpenRouter (exists) | Extract text → translate via LLM → overlay or return translated doc. | -| 23 | **PDF Form Filler** | PDF | High | ReportLab + PyPDF2 | Detect form fields → UI to fill → save. | -| 24 | **Redact PDF** | PDF | Medium | ReportLab + PyPDF2 | Blackout sensitive text regions. | -| 25 | **PDF Metadata Editor** | PDF | Low | PyPDF2 (exists) | Edit title, author, subject, keywords. | -| 26 | **eSign / Digital Signature** | PDF | High | `cryptography` + PKCS#7 | Cryptographic digital signatures (different from visual sign). | -| 27 | **Batch Processing** | All | Medium | Existing tasks | Upload multiple files → apply same operation to all. | -| 28 | **GIF to Video** | Video | Medium | ffmpeg (exists) | Reverse of Video to GIF. | -| 29 | **Video Compress** | Video | Medium | ffmpeg (exists) | Reduce video file size. | -| 30 | **Audio Extract** | Video | Low | ffmpeg (exists) | Extract audio track from video → MP3/WAV. | -| 31 | **Screenshot to PDF** | Utility | Low | Pillow (exists) | Paste screenshot → generate PDF (similar to Images to PDF). | -| 32 | **Markdown to PDF** | Utility | Low | `markdown` + WeasyPrint | Render Markdown → PDF. | -| 33 | **JSON / CSV Viewer** | Utility | Low | Client-side | Pretty-print structured data. | - ---- - -## 5. Implementation Readiness Matrix - -Tools grouped by effort required (backend dependencies already present in the project): - -### Ready to build (dependencies exist: PyPDF2, Pillow, Ghostscript, ffmpeg) - -| Tool | Effort | Reuses | -|---|---|---| -| Compress Image | ~2h | `image_service.py` + Pillow | -| Reorder Pages | ~3h | `pdf_tools_service.py` + PyPDF2 | -| Extract Pages | ~2h | Split tool pattern | -| PDF Repair | ~2h | PyPDF2 read/write | -| Flatten PDF | ~2h | PyPDF2 | -| Crop PDF | ~3h | PyPDF2 MediaBox | -| Image Crop | ~2h | Pillow | -| Image Rotate/Flip | ~2h | Pillow | -| Image Filters | ~3h | Pillow ImageFilter | -| PDF Metadata Editor | ~2h | PyPDF2 | -| PDF to PDF/A | ~2h | Ghostscript (exists in Dockerfile) | -| QR Code Generator | ~2h | `qrcode` pip package | -| AI PDF Summarizer | ~3h | `ai_chat_service.py` + OpenRouter | -| GIF to Video | ~2h | ffmpeg | -| Audio Extract | ~2h | ffmpeg | - -### Need new dependencies (1 pip package) - -| Tool | New Dependency | Effort | -|---|---|---| -| PDF to Excel | `camelot-py[cv]` or `tabula-py` | ~4h | -| PDF to PowerPoint | `python-pptx` | ~4h | -| Excel to PDF | LibreOffice CLI (exists) | ~3h | -| PowerPoint to PDF | LibreOffice CLI (exists) | ~3h | -| HTML to PDF | `weasyprint` or `playwright` | ~4h | -| Sign PDF | ReportLab (exists) + canvas overlay | ~6h | -| Barcode Generator | `python-barcode` | ~2h | -| Markdown to PDF | `markdown` + `weasyprint` | ~3h | - -### Requires significant new architecture - -| Tool | Complexity | Effort | -|---|---|---| -| AI Chat with PDF | RAG pipeline or full-doc prompt | ~8h | -| AI PDF Translator | OCR + LLM + overlay | ~8h | -| PDF Form Filler | Field detection + fill engine | ~10h | -| Redact PDF | Region detection + blackout overlay | ~6h | -| Compare PDFs | Diff algorithm + visual rendering | ~10h | -| eSign / Digital Signature | PKCS#7 cryptographic signing | ~10h | -| Batch Processing | Queue orchestration for multi-file | ~6h | -| Video Compress | ffmpeg transcoding | ~4h | - ---- - -## 6. Summary +### Operational counts | Metric | Count | |---|---| -| **Existing tools** | 21 | -| **Missing HIGH priority** | 10 | -| **Missing MEDIUM priority** | 9 | -| **Missing LOW priority** | 14 | -| **Total gap** | 33 | -| **Backend tests** | 180 ✅ | -| **Frontend build** | ✅ Clean | -| **Blueprints** | 18 | -| **Celery task modules** | 10 | -| **Service files** | 15 | -| **i18n languages** | 3 (en, ar, fr) | +| Registered blueprints | 33 | +| Backend route modules | 33 | +| Backend service modules | 32 | +| Backend task modules | 20 | +| Frontend tool components | 44 | +| Direct frontend tool routes | 44 | +| Homepage tool cards surfaced | 33 | +| Backend test files | 38 | +| Frontend test files | 6 | -### Competitor Parity Score +### Plans & quotas -| Competitor | Their tools | We match | Coverage | -|---|---|---|---| -| iLovePDF | ~25 core | ~16 | 64% | -| SmallPDF | ~21 core | ~15 | 71% | -| TinyWow | ~50+ (many AI) | ~14 | 28% | -| PDF24 | ~30 core | ~17 | 57% | +From `backend/app/services/policy_service.py`: -### Recommended Next Sprint +| Plan | Web requests/month | API requests/month | History retention | Effective upload limits | +|---|---:|---:|---:|---| +| Free | 50 | — | 25 | Base file-size limits from backend config | +| Pro | 500 | 1,000 | 250 | 2x backend file-size limits | -**Highest ROI — 6 tools to reach 80%+ parity with SmallPDF/iLovePDF:** +--- -1. Compress Image (Pillow — already installed) -2. PDF to Excel (`camelot-py`) -3. HTML to PDF (`weasyprint`) -4. Sign PDF (ReportLab overlay) -5. Reorder Pages (PyPDF2 — already installed) -6. PDF to PowerPoint (`python-pptx`) +## 2. Current Tool Inventory — 44 Direct Tool Routes + +These are the currently wired tool routes in `frontend/src/App.tsx`. + +### 2.1 Core PDF Tools (14) + +1. Compress PDF +2. PDF to Word +3. Word to PDF +4. Merge PDF +5. Split PDF +6. Rotate PDF +7. PDF to Images +8. Images to PDF +9. Watermark PDF +10. Protect PDF +11. Unlock PDF +12. Add Page Numbers +13. PDF Editor +14. PDF Flowchart + +### 2.2 Image Tools (6) + +15. Image Converter +16. Image Resize +17. Compress Image +18. OCR +19. Remove Background +20. Image to SVG + +### 2.3 Conversion Tools (2) + +21. PDF to Excel +22. HTML to PDF + +### 2.4 PDF Extra Tools (3) + +23. Remove Watermark +24. Reorder PDF +25. Extract Pages + +### 2.5 AI Tools (4) + +26. Chat with PDF +27. Summarize PDF +28. Translate PDF +29. Extract Tables + +### 2.6 Utility / Other Tools (1) + +30. QR Code Generator + +### 2.7 Video Tools (1) + +31. Video to GIF + +### 2.8 Text Tools (2) + +32. Word Counter +33. Text Cleaner + +### 2.9 Phase 2 — PDF Conversion (4) + +34. PDF to PowerPoint +35. Excel to PDF +36. PowerPoint to PDF +37. Sign PDF + +### 2.10 Phase 2 — PDF Extra (4) + +38. Crop PDF +39. Flatten PDF +40. Repair PDF +41. PDF Metadata Editor + +### 2.11 Phase 2 — Image & Utility (3) + +42. Image Crop +43. Image Rotate / Flip +44. Barcode Generator + +--- + +## 3. Homepage Coverage vs Full Catalog + +The codebase exposes **44** tool routes, but the homepage currently surfaces **33** tools. + +### Surfaced on homepage + +The homepage includes the core catalog and several growth-focused tools, including: + +- Core PDF tools +- Core image tools +- OCR / remove background +- PDF to Excel +- HTML to PDF +- Chat / summarize / translate / table extraction +- QR code +- Video to GIF +- Word counter / text cleaner + +### Implemented but not surfaced on homepage + +The following routes exist but are not currently represented on the homepage tool grid: + +- PDF to PowerPoint +- Excel to PDF +- PowerPoint to PDF +- Sign PDF +- Crop PDF +- Flatten PDF +- Repair PDF +- PDF Metadata Editor +- Image Crop +- Image Rotate / Flip +- Barcode Generator + +This is an important product and growth gap: implementation breadth is currently ahead of homepage discovery. + +--- + +## 4. Backend / API Coverage + +### Web app coverage + +The web app has direct frontend routes for all 44 tools listed above. + +### B2B API coverage + +`backend/app/routes/v1/tools.py` exposes a substantial subset of the platform through `/api/v1/*`, including: + +- PDF conversion and compression +- Major PDF tools +- Image conversion and resize +- Video to GIF +- OCR +- Remove background +- AI PDF workflows +- PDF to Excel +- HTML to PDF +- QR and barcode generation +- PDF to PowerPoint / Excel to PDF / PowerPoint to PDF +- Sign PDF +- Crop / flatten / repair / metadata +- Image crop / image rotate-flip + +This means the platform is no longer only a consumer-facing tools site; it already has real API-product potential. + +--- + +## 5. Test & Quality Snapshot + +### Backend + +- `38` backend test files currently exist under `backend/tests` +- Sample backend verification run on March 25, 2026: + - `backend/tests/test_file_validator.py` + - `backend/tests/test_html_to_pdf.py` + - `backend/tests/test_auth.py` + - `backend/tests/test_history.py` + - Result: `24/24` tests passed + +### Frontend + +- `6` frontend test files currently exist under `frontend/src` +- Verified on March 25, 2026: + - Result: `64/64` tests passed + +### Build + +- Frontend production build passes successfully + +--- + +## 6. What Is No Longer Missing + +The earlier inventory marked many of the following as gaps. They are now implemented in the current codebase: + +- Compress Image +- PDF to Excel +- PDF to PowerPoint +- Excel to PDF +- PowerPoint to PDF +- HTML to PDF +- Reorder PDF Pages +- Extract Pages +- Sign PDF +- PDF Repair +- Flatten PDF +- Crop PDF +- QR Code Generator +- Barcode Generator +- Image Crop +- Image Rotate / Flip +- AI Chat with PDF +- PDF Summarizer +- PDF Translator +- Table Extractor +- PDF Metadata Editor + +--- + +## 7. Remaining Competitive Gaps + +Compared against iLovePDF, Smallpdf, PDF24, TinyWow, and Adobe Acrobat online flows, the main remaining gaps are now more focused. + +### High-value remaining gaps + +1. PDF comparison / diff +2. PDF to PDF/A +3. Batch processing workflows +4. True cryptographic digital signature / eSign +5. PDF form filler +6. PDF redaction +7. Video compression +8. Audio extraction from video +9. GIF to video +10. Image filters / adjustments + +### Strategic gaps, not just feature gaps + +1. Homepage/catalog mismatch +2. Documentation drift +3. Full production validation for monetization and analytics +4. Sharper positioning for the strongest tool clusters + +--- + +## 8. Competitive Position Today + +### Where Dociva is strong + +- Unusually broad tool coverage for an early-stage codebase +- Trilingual product surface from the start +- Real SaaS primitives already in place: plans, quotas, billing, API keys +- Async processing architecture suitable for file workflows +- Stronger-than-average SEO foundation for this stage + +### Where Dociva is still weaker than category leaders + +- Brand trust and distribution +- Workflow polish on every tool +- Product discovery consistency +- Team/business collaboration features +- Proof of production traction + +--- + +## 9. Recommended Next Sprint + +### Product quality + +1. Keep frontend tests green as part of CI +2. Run a broader backend validation pass +3. Audit hidden tools and decide whether to surface or intentionally defer them + +### Documentation + +1. Keep this file as the current source of truth for tool counts +2. Update project status and SEO docs whenever route counts or sitemap scale change + +### Growth + +1. Focus on 8 high-intent landing pages first: + - Compress PDF + - PDF to Word + - Word to PDF + - Merge PDF + - PDF to Excel + - OCR + - Remove Background + - HTML to PDF +2. Improve conversion from free use to account creation to Pro/API + +--- + +## 10. Bottom Line + +The project is no longer a 21-tool MVP. It is currently a **44-route document-processing platform** with a real SaaS foundation and a growing competitive surface. + +The core challenge has shifted: + +> The next bottleneck is no longer raw feature count. It is consistency, positioning, discovery, and turning breadth into measurable growth. diff --git a/frontend/src/hooks/useTaskPolling.test.ts b/frontend/src/hooks/useTaskPolling.test.ts index 614c7ab..d12df62 100644 --- a/frontend/src/hooks/useTaskPolling.test.ts +++ b/frontend/src/hooks/useTaskPolling.test.ts @@ -225,6 +225,6 @@ describe('useTaskPolling', () => { await vi.runAllTimersAsync(); }); - expect(result.current.error).toBe('Task failed.'); + expect(result.current.error).toBe('Processing failed. Please try again.'); }); }); diff --git a/frontend/src/pages/InternalAdminPage.test.tsx b/frontend/src/pages/InternalAdminPage.test.tsx index f549fc9..076f2e3 100644 --- a/frontend/src/pages/InternalAdminPage.test.tsx +++ b/frontend/src/pages/InternalAdminPage.test.tsx @@ -5,6 +5,9 @@ import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest'; import InternalAdminPage from './InternalAdminPage'; import { useAuthStore } from '@/stores/authStore'; import { + getAdminPlanInterest, + getAdminSystemHealth, + getAdminUserStats, getInternalAdminContacts, getInternalAdminOverview, listInternalAdminUsers, @@ -18,6 +21,9 @@ vi.mock('@/stores/authStore', () => ({ })); vi.mock('@/services/api', () => ({ + getAdminPlanInterest: vi.fn(), + getAdminSystemHealth: vi.fn(), + getAdminUserStats: vi.fn(), getInternalAdminContacts: vi.fn(), getInternalAdminOverview: vi.fn(), listInternalAdminUsers: vi.fn(), @@ -37,7 +43,7 @@ const authState = { function renderPage() { return render( - + @@ -56,11 +62,49 @@ describe('InternalAdminPage', () => { (selector: (state: typeof authState) => unknown) => selector(authState) ); (getInternalAdminOverview as Mock).mockReset(); + (getAdminSystemHealth as Mock).mockReset(); + (getAdminPlanInterest as Mock).mockReset(); + (getAdminUserStats as Mock).mockReset(); (listInternalAdminUsers as Mock).mockReset(); (getInternalAdminContacts as Mock).mockReset(); (markInternalAdminContactRead as Mock).mockReset(); (updateInternalAdminUserPlan as Mock).mockReset(); (updateInternalAdminUserRole as Mock).mockReset(); + + (getAdminSystemHealth as Mock).mockResolvedValue({ + ai_configured: true, + ai_model: 'nvidia/nemotron-3-super-120b-a12b:free', + ai_budget_used_percent: 25, + error_rate_1h: 0, + tasks_last_1h: 0, + failures_last_1h: 0, + database_size_mb: 1.5, + }); + (getAdminPlanInterest as Mock).mockResolvedValue({ + total_clicks: 0, + unique_users: 0, + clicks_last_7d: 0, + clicks_last_30d: 0, + by_plan: [], + recent: [], + }); + (getAdminUserStats as Mock).mockResolvedValue({ + total_users: 2, + new_last_7d: 1, + new_last_30d: 2, + pro_users: 1, + free_users: 1, + daily_registrations: [{ day: '2026-03-16', count: 1 }], + most_active_users: [ + { + id: 2, + email: 'operator@example.com', + plan: 'free', + created_at: '2026-03-16T10:00:00Z', + total_tasks: 3, + }, + ], + }); }); it('shows the admin sign-in form for anonymous users', () => { @@ -129,13 +173,19 @@ describe('InternalAdminPage', () => { renderPage(); await waitFor(() => { - expect(screen.getByText('Users and monetization')).toBeTruthy(); + expect(screen.getByText('Top tools')).toBeTruthy(); }); - fireEvent.click(screen.getByRole('button', { name: 'Set admin' })); + fireEvent.click(screen.getByRole('button', { name: 'Users' })); + + await waitFor(() => { + expect(screen.getByText('User management')).toBeTruthy(); + }); + + fireEvent.click(screen.getByRole('button', { name: 'Admin' })); await waitFor(() => { expect(updateInternalAdminUserRole).toHaveBeenCalledWith(2, 'admin'); }); }); -}); \ No newline at end of file +}); diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index 5786046..79c4cb3 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -29,22 +29,6 @@ text-rendering: optimizeLegibility; } - /* تحسين تحميل الخطوط لتقليل CLS */ - @font-face { - font-family: 'Inter'; - font-style: normal; - font-weight: 400; - src: local('Inter'), url('/fonts/Inter.woff2') format('woff2'); - font-display: swap; - } - @font-face { - font-family: 'Tajawal'; - font-style: normal; - font-weight: 400; - src: local('Tajawal'), url('/fonts/Tajawal.woff2') format('woff2'); - font-display: swap; - } - /* RTL Support */ [dir="rtl"] body { font-family: 'Tajawal', 'Inter', system-ui, sans-serif; diff --git a/frontend/src/test/setup.ts b/frontend/src/test/setup.ts new file mode 100644 index 0000000..033ff29 --- /dev/null +++ b/frontend/src/test/setup.ts @@ -0,0 +1,6 @@ +import '@testing-library/jest-dom/vitest'; +import '@/i18n'; + +if (typeof window !== 'undefined') { + window.localStorage.setItem('i18nextLng', 'en'); +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index c0d3b88..dd282bd 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -24,6 +24,7 @@ export default defineConfig({ test: { globals: true, environment: 'jsdom', + setupFiles: ['./src/test/setup.ts'], }, resolve: { alias: {