Pdf3md
A modern, user-friendly web application that converts PDF documents to clean, formatted Markdown text.
Install / Use
/learn @murtaza-nasir/Pdf3mdREADME
PDF to Markdown and Word Converter
This project is dual-licensed. Please see the License section for comprehensive details.
PDF3MD is a web application designed for efficient conversion of PDF documents into well-structured Markdown and Microsoft Word (DOCX) formats. It features a React-based frontend and a Python Flask backend, providing a seamless user experience with real-time progress updates.
Screenshots

Core Features
- PDF to Markdown Conversion: Transforms PDF documents into clean, readable Markdown, preserving structural elements.
- Markdown to Word (DOCX) Conversion: Converts user-provided Markdown text to DOCX format using Pandoc for high-fidelity output.
- Multi-File Upload: Supports uploading and processing multiple PDF files simultaneously for PDF to Markdown conversion.
- Drag & Drop Interface: User-friendly file uploads via drag and drop or traditional file selection.
- Real-time Progress Tracking: Detailed status updates during the conversion process for each file.
- File Information Display: Shows original filename, file size, page count, and conversion timestamp.
- Modern and Responsive UI: Intuitive interface designed for ease of use across various devices.
Technology Stack
- Frontend: React, Vite
- Backend: Python, Flask
- PDF Processing: PyMuPDF4LLM
- Markdown to DOCX Conversion: Pandoc
Getting Started
The easiest and recommended way to run PDF3MD is using the provided Docker quick start script.
Prerequisites
- Docker Engine
- Docker Compose (typically included with Docker Desktop)
Using Pre-built Docker Images (Recommended)
This method uses pre-built Docker images from Docker Hub for quick setup. You'll need the docker-compose.yml and docker-start.sh script from the repository.
-
Prepare Required Files:
- Create a directory for your application (e.g.,
mkdir pdf3md-app && cd pdf3md-app). docker-compose.yml: Create a file nameddocker-compose.ymlin this directory and paste the following content into it:services: backend: image: docker.io/learnedmachine/pdf3md-backend:latest container_name: pdf3md-backend ports: - "6201:6201" environment: - PYTHONUNBUFFERED=1 - FLASK_ENV=production - TZ=America/Chicago volumes: - ./pdf3md/temp:/app/temp # Creates a local temp folder for backend processing if needed restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:6201/"] interval: 30s timeout: 10s retries: 3 start_period: 40s frontend: image: docker.io/learnedmachine/pdf3md-frontend:latest container_name: pdf3md-frontend ports: - "3000:3000" depends_on: - backend restart: unless-stopped healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/"] interval: 30s timeout: 10s retries: 3 start_period: 40s networks: default: name: pdf3md-networkdocker-start.sh: Download thedocker-start.shscript from the pdf3md GitHub repository's main branch and place it in the same directory.- Make the script executable:
chmod +x ./docker-start.sh - (Optional) For development mode using local source code (which requires cloning the full repository), you would also need
docker-compose.dev.ymlfrom the repository.
- Create a directory for your application (e.g.,
-
Start in Production Mode: In the directory where you placed
docker-compose.ymlanddocker-start.sh, run:./docker-start.sh startThis will pull the latest images from Docker Hub and start the application.
- Access Frontend:
http://localhost:3000 - Access Backend API:
http://localhost:6201
- Access Frontend:
-
Start in Development Mode (with hot-reloading):
./docker-start.sh devThis uses local source code for development if
docker-compose.dev.ymlis present and configured for local mounts. Otherwise, it may behave like production mode depending on the script's logic.- Access Frontend (Vite Dev Server, if using local source):
http://localhost:5173 - Access Backend API:
http://localhost:6201
- Access Frontend (Vite Dev Server, if using local source):
-
Other Useful Script Commands:
./docker-start.sh stop # Stop all services ./docker-start.sh status # Check running services ./docker-start.sh logs # View logs from services ./docker-start.sh rebuild dev example.com # Rebuild development with custom domain ./docker-start.sh help # Display all available script commands
Direct Docker Compose Usage (Alternative with Pre-built Images)
If you prefer to use Docker Compose commands directly with the pre-built images without the docker-start.sh script:
Direct Deployment
-
Create
docker-compose.yml:- Create a directory for your application (e.g.,
mkdir pdf3md && cd pdf3md). - Create a file named
docker-compose.ymlin this directory and paste the content provided in the section above (under "Using Pre-built Docker Images (Recommended)").
- Create a directory for your application (e.g.,
-
Pull and Start Services: In the directory where you created
docker-compose.yml, run:docker compose pull # Pulls the latest images specified in docker-compose.yml docker compose up -d -
Access Application:
- With default settings: Frontend at
http://localhost:3000, Backend API athttp://localhost:6201 - With custom domain: Frontend at
http://example.com:3000, Backend API athttp://example.com:6201
- With default settings: Frontend at
-
Stop Services:
docker compose down
Development Environment (Using Local Source Code)
This setup is for developing the application locally, not using pre-built images for development.
- Clone the Repository:
git clone https://github.com/murtaza-nasir/pdf3md.git cd pdf3md - Start Services:
Use the
docker-compose.dev.ymlfile, which is typically configured to build images locally and mount source code.docker compose -f docker-compose.dev.yml up --build - Access Application:
- With default settings: Frontend (Vite) at
http://localhost:5173, Backend API athttp://localhost:6201 - With custom domain/IP: Frontend at
http://192.168.1.100:5173, Backend API athttp://192.168.1.100:6201
- With default settings: Frontend (Vite) at
- Stop Services:
docker compose -f docker-compose.dev.yml down
Manual Setup (Running without Docker)
This method involves running the frontend and backend services directly on your machine without Docker, typically for development or if you prefer not to use Docker.
- Clone the Repository:
If you haven't already, clone the repository to get the source code:
git clone https://github.com/murtaza-nasir/pdf3md.git cd pdf3md
Backend (Flask)
- Navigate to the
pdf3mdsub-directory (if you are in the root of the cloned repo):cd pdf3md - Install Python dependencies:
pip install -r requirements.txt - Start the backend server:
python app.py(The backend will be available athttp://localhost:6201)
Frontend (React)
- In a new terminal, navigate to the
pdf3mdsub-directory (if you are in the root of the cloned repo):cd pdf3md - Install Node.js dependencies:
npm install - Start the frontend development server:
npm run dev(The frontend will be available athttp://localhost:5173)
Convenience Scripts
The pdf3md sub-directory contains scripts for managing both services:
./start_server.sh: Starts both frontend and backend../stop_server.sh: Stops both services. (Ensure these scripts are executable:chmod +x ./start_server.sh ./stop_server.sh)
Usage Instructions
- Open the PDF3MD application in your web browser.
- Upload one or more PDF files using the drag-and-drop area or by clicking to select files.
- Monitor the real-time progress as each PDF is converted.
- Once a file is processed, the resulting Markdown will be displayed.
- You can then:
- Copy the Markdown text (from PDF to MD conversion).
- In "MD → Word" mode, input Markdown and download the content as a DOCX file (powered by Pandoc).
Configuration Notes
- Backend Port: The Flask server runs on port
6201by default, configurable inpdf3md/app.py. - Frontend API Proxy: The Vite development server proxies API requests. If the backend port changes, update
pdf3md/vite.config.js. - Environment Variables (Docker):
FLASK_ENV:developmentorproduction.FLASK_DEBUG:1for debug mode.TZ: Timezone configuration for the backend container. You can modify this in the Docker Compose files to match your local timezone (e.g.,America/New_York).
Network Configuration and Access
The application is designed wi
