Production-focused, minimal Next.js + TypeScript resume editor that keeps all conversions server-side.
- Upload PDF resume from browser.
- Server converts PDF -> DOCX (LibreOffice headless), then DOCX -> HTML (
mammoth). - Edit HTML in a TipTap WYSIWYG editor.
- Download final PDF (preferred DOCX -> PDF via LibreOffice; fallback via Puppeteer HTML -> PDF).
- Download DOCX version.
- Optional OCR endpoint (
/api/ocr) usingtesseract.js. - Temp file cleanup, max upload size validation, mime validation, basic in-memory rate limiting.
- Next.js pages router + API routes
- TypeScript across frontend/backend
- TipTap editor
- Conversion libraries:
mammoth,html-docx-js, LibreOffice (soffice), Puppeteer fallback
pages/index.tsxUI for upload/edit/downloadcomponents/Editor.tsxTipTap editor wrapperpages/api/upload.tsPDF -> DOCX -> HTMLpages/api/save.tsedited HTML -> DOCX -> PDF/DOCXpages/api/download-docx.tsfetch stored DOCX by fileIdpages/api/ocr.tsOCR draft endpointlib/conversion and temp-file helperstests/Jest tests for conversion endpoint flowsscripts/smoke.tsfull conversion chain script
- Install dependencies:
npm install
- Install LibreOffice and Chromium dependencies:
- Ubuntu/Debian:
sudo apt-get update sudo apt-get install -y libreoffice fonts-dejavu-core
- Ubuntu/Debian:
- Optional env vars:
export TEMP_DIR=./tmp export MAX_UPLOAD_BYTES=10485760 export RATE_LIMIT_PER_MINUTE=30
- Start app:
npm run dev
- Open http://localhost:3000
docker compose up --buildUpload resume:
curl -X POST http://localhost:3000/api/upload \
-F "resume=@data/sample_resume.pdf"Save edited HTML as PDF:
curl -X POST http://localhost:3000/api/save \
-H "Content-Type: application/json" \
-d '{"html":"<h1>Experience</h1><p>Example</p>","format":"pdf"}' \
--output out/resume_final.pdfSave edited HTML as DOCX:
curl -X POST http://localhost:3000/api/save \
-H "Content-Type: application/json" \
-d '{"html":"<h1>Education</h1><p>University</p>","format":"docx"}' \
--output out/resume_final.docxOCR draft endpoint:
curl -X POST http://localhost:3000/api/ocr -F "file=@scan.png"npm testnpm run smokeProduces out/resume_final.pdf.
- Replace in-memory file map/rate-limiter with Redis for multi-instance deployments.
- Add queue worker (BullMQ) for heavy conversions.
- Add antivirus scanning for uploaded files.
- Improve OCR for PDF by rasterizing pages first, then running OCR per page.
- Add auth and object storage (S3/GCS) for persistent download links.