EasyDrawer is a self-hosted, filesystem-based PDF management app designed for users who want a clean, private, and efficient way to organize large PDF libraries. It acts as a lightweight interface to your existing folders, giving you the ability to browse, tag, edit, and manage documents without locking them into a proprietary structure.
The project has been used privately for months but is not yet production-ready. It is intended for users with basic development knowledge who can troubleshoot, adapt setups, and understand the filesystem implications.
-
Filesystem-like Import & Organization Import and reorganize PDFs in a folder structure that directly mirrors your host filesystem. All changes (moving, deleting) happen on your real files.
-
Folder & File Management Create folders, delete items, or assign tags — all from the web interface.
-
Tag-Based Organization Classify PDFs using tags, with search and filtering capabilities.
-
Bulk Editing Apply tags or modifications to multiple items at once.
-
Full-Text Search (via MeiliSearch) Enables fast, indexed text search inside PDFs.
-
Paginated Browsing Smooth navigation through large libraries.
-
Fast Thumbnail Generation Thumbnails are cached on disk for faster repeated access.
-
Built-In PDF Reader Ships with a custom PDF viewer built using EmbedPDF.
Supported features:
- Standard in-viewer text search
- Zooming, scrolling, and area zoom
- Zone capture and PDF export
- Annotations and nested bookmarks (stored in the database)
- Reading progress persistence
- Optional local PDF saving to reduce loading times and save bandwidth
-
OPDS v1 Catalog Support EasyDrawer exposes an OPDS v1 endpoint so compatible e-readers can browse and download PDFs. See OPDS section below for details.
-
Docker-Ready Deployment Comes with a sample
docker-compose.ymlfor easy setup.
EasyDrawer performs real operations on your filesystem. Actions like moving, or deleting PDFs affect the actual files.
Before connecting your real collection, please:
Get comfortable with how import, moving, and deletion behave.
- Multi-selection works using Ctrl + Left Click only.
- Moving folders flattens subfolders. When you move a folder, the nested structure is not preserved yet — this will change once hierarchical operations are implemented.
- Frontend: React, Chakra UI, React-icons, Vite
- Backend: Node.js, Express, Prisma ORM, PostgreSQL
- Deployment: Docker & Docker Compose
- Additional system dependencies:
webp,poppler-utils, - Pip requirements:
pymupdfThe stack may evolve as the project grows.
EasyDrawer provides a simple OPDS v1 catalog endpoint, allowing compatible e-readers and apps to browse and download your PDFs.
http://<backend-address>:<port>/catalog/
Once connected to the catalog, you can browse your library in two ways:
Navigate PDFs using the same folder structure as your host filesystem.
Browse PDFs by tags:
- The catalog first presents a list of available tags
- Selecting a tag filters the catalog
- Selecting additional tags expands the filter using logical OR
Sample docker-compose.yml for backend, frontend, database, and migrations:
services:
back-end:
container_name: pdfmanbackend
image: pdfmanapp/pdfmanbackend:latest
environment:
DATABASE_URL: postgresql://myuser:mypassword@db:5432/PDFMAN
FOLDER_PATH: /pdfs/
THUMBNAIL_FOLDER: /thumbnails/
PORT: 3001
MEILISEARCH_API: http://localhost:7700
ports:
- "3001:3001"
depends_on:
- db
volumes:
- /path/to/pdfs/folder:/pdfs:rw
- thumbnails:/thumbnails:rw
restart: always
front-end:
container_name: pdfmanfrontend
image: pdfmanapp/pdfmanfrontend:latest
ports:
- "5173:80"
environment:
- API=http://localhost:3001/
- MEILISEARCH_URL=http://localhost:7700
depends_on:
- back-end
db:
image: postgres:17
container_name: postgresdb
restart: always
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
POSTGRES_DB: PDFMAN
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
thumbnails:EasyDrawer uses MeiliSearch for full-text PDF indexing. Installation instructions: 👉 https://www.meilisearch.com/docs
-
Clone the repository
git clone https://github.com/mustnotcan/pdfman-backend.git cd pdfman-backend -
Install dependencies
npm install
-
Configure environment variables Create
.env:DATABASE_URL=postgresql://myuser:mypassword@localhost:5432/PDFMAN FOLDER_PATH=/absolute/path/to/pdfs THUMBNAIL_FOLDER=/absolute/path/to/thumbnails PORT=3001 MEILISEARCH_API=http://localhost:7700
-
Run database migrations
npx prisma migrate dev
-
Start the development server
npm run dev
or:
npm start
Not yet. Can be added to library, but the thumbnail won't be generated and won't open in the reader.
No. Metadata (author, title, keywords, creation date) is ignored. Organization is purely based on filenames, folder structure, and user-defined tags.
No. EasyDrawer is explicitly designed as an interface to your filesystem, not a background synchronizer or indexer. Changes made outside the app need to be manually refreshed or re-scanned.
Not yet. Moving a folder currently flattens all the contents. This will change when hierarchical operations are implemented.
Not recommended yet. It is stable for personal use but still under active development.
EasyDrawer is released under the MIT License, except where otherwise noted.
Important: This project depends on PyMuPDF, licensed under AGPLv3. Deployments that include PyMuPDF must comply with the AGPLv3, which requires providing source code for any network-accessible service using it.
More details:
- PyMuPDF License: https://pymupdf.readthedocs.io/en/latest/about.html#license-and-copyright
- AGPLv3 License: https://www.gnu.org/licenses/agpl-3.0.en.html
⚠️ Provided as-is under active development. No guarantee of stability or bug-free operation.

