Doop
Doop is an open-source multiplayer design canvas and design MCP for Claude Code, Codex, and any AI agent. Design side by side with agents — free in beta.
Remove backgrounds, upscale photos with AI, extract English and Nepali text with OCR, and edit, sign, merge and convert PDFs. Free, private, no install.
DesignTypeScript · PythonGitHub @AashiQMahatoOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
All-in-one image, text and PDF tools in your browser: AI background removal, upscaling, OCR for English and Nepali, and PDF editing, signing and conversion. Free and private: no install, and files are deleted after processing.
Taken from the repository README
Loading the full README.
Read the full README ↗Free online image, PDF and text tools in one app: remove backgrounds, upscale with AI, make passport photos, read text from images (English and Nepali), and merge, split, edit, sign and convert PDFs. No sign-up, and uploaded files are deleted automatically.
Live site: https://imagetools-358n.onrender.com
| Document tools | Background remover |
|---|---|
| Merge PDF | Text editor |
Every feature runs in one of three places:
| Feature | Browser | Node backend | Python |
|---|---|---|---|
| Image tools | |||
| Photo Editor (light, colour, filters, resize) | Canvas | — | — |
| Crop (straighten, ratios, rotate/flip) | Canvas | — | — |
| Image Compressor | Upload, preview | sharp | — |
| Background Remover | Upload, preview | Queue | BiRefNet-Massive |
| AI Upscaler (2× / 4×) | Upload, preview | upscayl-bin (needs a GPU) | — |
| AI Retouch | Brush and mask | Built-in engine (sharp) | LaMa (optional, better results) |
| Watermark Remover | Brush, found areas | Removal via retouch | Detection (OpenCV) |
| Passport & MRP Photo | Presets, crop, sheet | Crop, resize, print sheet | Face detection, background, HEIC |
| OCR Editor | Editor | tesseract (fallback) | PaddleOCR |
| PDF tools | |||
| PDF Viewer | pdf.js | — | — |
| Merge / Split / Organize / Rotate PDF | pdf.js thumbnails | pdf-lib | — |
| Images to PDF | Layout options | pdf-lib + sharp | — |
| Add Watermark / Page Numbers | Live preview | pdf-lib | — |
| Edit PDF / Sign PDF | Drawing layer, signature pad | pdf-lib | — |
| PDF to Images | Page picker | Jobs, ZIP download | PDFium |
| Compress PDF | Presets | Jobs | qpdf (pikepdf) |
| Protect / Unlock PDF | Password field | Jobs | pikepdf |
| PDF to Text | Result, export | Jobs, text cleanup | PDF text + PaddleOCR |
| PDF to Word | Preview, .docx download (original layout, or as edited) | Jobs, layout | pdfplumber + python-docx, PaddleOCR / Tesseract for scans |
| Text tools | |||
| Text Editor, Text Cleaner, Case Converter, Word Counter | Tiptap | — | — |
| Whiteboard | |||
Whiteboard (/whiteboard) | Excalidraw editor, autosave in IndexedDB | — | — |
| Part | Language | Main tools |
|---|---|---|
| Frontend | TypeScript, CSS | React 19, Vite, Tailwind CSS 4, Untitled UI, React Router, Zustand, pdf.js, Tiptap |
| Backend | TypeScript | Node.js 20.6+, Express 5, sharp, pdf-lib, Multer, Helmet |
| AI services | Python 3.11–3.13 | FastAPI, PyTorch (BiRefNet-Massive), PaddleOCR, OpenCV, PDFium, pikepdf |
studio_tools/
├── frontend/ React app (Vite)
│ └── src/
│ ├── pages/ one folder per page (Home, Pdf, Text, Ocr, …)
│ ├── features/ tool logic (editor, documents, pdf-canvas, ocr, text, …)
│ ├── components/ ui/ (Untitled UI), layout/, common/, landing/
│ ├── lib/ api client, constants (routes), seo
│ └── routes/ React Router config
├── backend/ Express API
│ ├── src/
│ │ ├── routes/ all /api routes (routes/index.ts)
│ │ ├── controllers/ HTTP layer only
│ │ ├── services/ pdf/, compression/, retouch/, ocr/, photo-generator/, …
│ │ └── config/env.ts every setting and its default
│ ├── python/image_service/ image + PDF service (BiRefNet-Massive, OpenCV, PDFium, pikepdf)
│ ├── python/ocr_service/ OCR service (PaddleOCR)
│ └── vendor/upscayl/ upscaler binary + models (installed by setup, git-ignored)
├── scripts/ setup-ml.sh, check-processing.sh
└── docs/screenshots/ images used in this README
The browser only talks to our backend (frontend → /api/* → backend → engine). It never sees API keys or calls outside services.
Requires Node.js 20.6+. The AI tools also need Python 3.11–3.13. The upscaler needs a Vulkan-capable GPU; Apple Silicon works.
npm install # root: installs concurrently
npm run install:all # frontend + backend packages
cp backend/.env.example backend/.env
scripts/setup-ml.sh # optional: Python services, models, upscaler (asks before downloading)
scripts/check-processing.sh # optional: checks which engines are ready
npm run dev # backend on :5000, frontend on http://localhost:5173
In development, Vite forwards /api to the backend, so no CORS setup is needed.
macOS: AirPlay Receiver uses port 5000. Turn it off (System Settings → General → AirDrop & Handoff), or set
PORT=5050inbackend/.envandAPI_PROXY_TARGET=http://localhost:5050infrontend/.env.
| Where | Command | What it does |
|---|---|---|
| root | npm run dev | Runs backend and frontend together |
| root | npm run build | Builds both apps |
frontend | npm run build | Type-checks, builds to dist/, writes SEO pages |
frontend | npm run lint | Lints with oxlint |
backend | npm run dev | API with hot reload (tsx) |
backend | npm run build / npm start | Compiles to dist/ / runs it |
backend | npm run typecheck | Type-checks without building |
The live site runs as two Render services:
| Render service | Type | URL | Must set |
|---|---|---|---|
| StudioTools_Frontend | Static site | https://imagetools-358n.onrender.com | VITE_API_BASE_URL=https://studiotools.onrender.com |
| StudioTools_Backend | Node web service | https://studiotools.onrender.com | FRONTEND_URL=https://imagetools-358n.onrender.com |
VITE_API_BASE_URL is built into the frontend's JavaScript. After changing it, use Manual Deploy → Clear build cache & deploy.
FRONTEND_URL is the browser origin the backend allows (CORS). It must match exactly, with no trailing /. You can list several, separated by commas.
Don't set PORT on Render. Render sets it.
The backend is on Render's free plan, so it sleeps when idle. The first request after a while can take up to a minute.
Python on the free plan: the "lite" Docker image. Render's Node runtime has no Python, so the backend runs from deploy/render/Dockerfile (a Docker web service, build context = repository root). It fits in 512 MB by leaving the heavy AI out:
REMBG_MODEL=none; the model alone needs ~400 MB).Everything runs at full quality on a machine with ~4 GB of memory using scripts/setup-ml.sh.
Check what the live backend can run: https://studiotools.onrender.com/api/health/processors
backend/.env: every setting, with notes, is in backend/.env.example. The main ones:
| Variable | Default | What it does |
|---|---|---|
PORT | 5000 | API port (local only) |
FRONTEND_URL | http://localhost:5173 | Allowed browser origin(s), comma-separated |
MAX_IMAGE_SIZE_MB | 10 | Image upload limit |
DOCUMENTS_MAX_PDF_MB | 100 | PDF upload limit |
BACKGROUND_REMOVAL | on | off skips the background-removal model (small servers) |
UPSCAYL_MODEL | upscayl-standard-4x | Upscaling model |
RETOUCH_PROVIDER | auto | auto, local, lama or iopaint |
OCR_PROVIDER | auto | auto, paddle or tesseract |
frontend/.env (optional)
| Variable | What it does |
|---|---|
VITE_API_BASE_URL | Backend URL for production builds. Leave empty in development. Never put secrets in a VITE_* variable. |
VITE_SITE_URL | The site's own address, for SEO links. Defaults to the one in the SEO config. |
API_PROXY_TARGET | Where the dev server forwards /api. Defaults to http://localhost:5000. |
.env files are git-ignored; only the .env.example files are committed.
All routes are under /api (see backend/src/routes/index.ts).
| Area | Routes |
|---|---|
| Health | GET /health, GET /health/processors |
| Images | POST /remove-background, /upscale, /retouch, /compress, /convert |
| Watermark | POST /watermark/detect, /watermark/remove |
| Photo generator | GET /photo-generator/presets, POST /photo-generator/process, /adjust, /sheet |
| OCR | POST /ocr |
| PDF (jobs) | POST /pdf/merge, /split, /organize, /to-images, /from-images, /compress, /watermark, /page-numbers, /to-text, /to-word, /protect, /unlock, /annotate |
| Jobs | GET /jobs/:id, GET /jobs/:id/files/:fileId, GET /jobs/:id/archive, DELETE /jobs/:id |
PDF tools start a job (202) that the browser follows at /jobs/:id. Results are deleted after 30 minutes. Errors look like { "success": false, "message", "code" }. More detail and curl examples: backend/README.md.
Licences of the processing engines and models: THIRD_PARTY_NOTICES.md.
| Tool | Route | Runs where | Needs |
|---|---|---|---|
| Object Remover | /object-remover | AI server (POST /api/remove-object) | LaMa ONNX (scripts/setup-ml.sh) or an IOPaint server (RETOUCH_SERVICE_URL). No classical fallback: without AI it says so (OBJECT_REMOVAL_UNAVAILABLE). |
| Photo Restoration | /photo-restoration | AI server (GET /api/restore/capabilities, POST /api/restore) | Denoise and fade: OpenCV (always). Scratches: LaMa or OpenCV Telea. Colorize: ECCV16 ONNX. Faces: GFPGAN 1.4 ONNX + YuNet. Enlarge: Upscayl. Each step is reported as available or not, independently. |
| Social Media Resizer | /social-media-resizer | Browser only | Nothing. Presets live in frontend/src/features/social-resizer/presets.ts (sources and verification date at the top). |
| Document Scanner | /document-scanner | Browser only | Nothing. Edge detection, perspective correction, clean-up and PDF export run on the device. The camera needs HTTPS. |
Models and licences: LaMa (Apache-2.0); GFPGAN v1.4 (Apache-2.0, ONNX conversion from huggingface.co/Neus/GFPGANv1.4); ECCV16 Colorful Image Colorization (BSD-2-Clause), exported to ONNX from the official weights by backend/python/scripts/export_colorization_onnx.py (needs PyTorch); Real-ESRGAN via Upscayl (see THIRD_PARTY_NOTICES.md). Weights are downloaded by scripts/setup-ml.sh into backend/python/.models/ (git-ignored, checksums verified).
PDF to Word: the Word file is built in the image service (backend/python/image_service/pdf_docx.py) from the PDF itself, page by page. Each page becomes a Word section of the same size. On a digital page, the text keeps its fonts, sizes, colours and exact positions. Exact line pitch and space before are used, never empty lines. Rows of pieces use tab stops, and side-by-side pieces and column regions use borderless tables. Ruled grids and boxes become Word tables with their borders and shading. Dividers become paragraph borders, including dashed ones. Embedded images and vector drawings (logos, charts, rotated text) become pictures in place. Lines are condensed slightly where the substitute font would otherwise wrap them. A scanned page is straightened, its text comes from the OCR lines, and logos, photos, signatures, stamps and rules are cropped from the scan, so OCR "text" read inside a stamp or a signature isn't kept. A broken Nepali text layer is repaired line by line from OCR. A page Word can't hold as a flow, such as a form or a layout where content would overlap or overflow, is laid out exactly instead. Its drawings become one picture, rendered from the PDF with the text taken out, and every line is an editable frame on top. The result screen offers this file ("Word — original layout") and also the edited text as Word.
QA: backend/python/scripts/docx_visual_qa.py converts the test PDFs (backend/python/tests/docx_fixtures), turns the Word files back into PDFs with LibreOffice, and compares renders, text, overlaps and clipping. scripts/docx_api_qa.py does the same through the API, so scans go through OCR. Known limits: fonts missing on the reader's computer are substituted, which can shift lines slightly. Vertical rules outside tables can't be drawn in a Word flow, so such pages fall back to exact layout. Equations are kept as text or as pictures, not as Word equations. Repeated headers and footers stay on each page rather than moving into Word's header and footer.
High quality inpainting (optional): Object Remover and AI Retouch (Remove, Repair) can use PowerPaint v2-1 (SD 1.5 + BrushNet; Apache-2.0 weights, MIT code, based on Realistic Vision 6.0 under CreativeML OpenRAIL-M) instead of LaMa. A Quality setting appears on those pages only when the server can run it. It runs in its own process (backend/python/inpaint_service, its own .venv-inpaint because it needs diffusers 0.27), starts on first use, and unloads after 90 s idle. If it can't run or fails, LaMa does the job and the page says so (X-Inpaint-Fallback); a result is never labelled PowerPaint unless it was. Install with PREMIUM_INPAINT=on scripts/setup-ml.sh. Benchmark: backend/python/benchmarks/inpaint_bench.py (see its header). Smooth, Enhance and Relight remain classical.
Deployment: the free Render service (deploy/render/Dockerfile, 512 MB, no GPU) doesn't ship these models. With VITE_AI_API_BASE_URL pointing at the AI server (npm run ai-server), Object Remover and Photo Restoration run there. Without it, Object Remover reports that AI inpainting isn't available, and Photo Restoration offers only its OpenCV steps. The resizer and the scanner need no server.
/whiteboard (navbar: Whiteboard) runs the Excalidraw drawing engine, @excalidraw/excalidraw 0.18.1 (MIT), inside a Studio Tools workspace. The site's navbar and footer step aside. Everything runs in the browser.
src/features/whiteboard/): a header (WhiteboardTopBar) with the way back, the board's editable title, undo/redo, zoom (−, a zoom menu with 100% / fit / selection, +), the local save status, Library, an Export menu and a More menu (open, new board, find, command palette, shortcuts, dark mode, grid, snapping, canvas colour, editor language). The drawing tools sit in a docked strip (WhiteboardToolbar): a vertical rail from 800 px wide, a scrollable row above the canvas below that, with frame, web embed, laser pointer and Mermaid under More tools, and the tool lock. Menus, tooltips and dialogs use React Aria; the look uses the site's tokens and font (whiteboard.css maps them onto the editor's own CSS variables).setActiveTool, updateScene, scrollToContent, toggleSidebar, the export utilities); undo/redo press the editor's own buttons, kept in the page out of sight, because the package has no public undo call. On phones the editor's bottom bar (edit style, duplicate, delete, undo, redo) stays. Its AI features (text to diagram, wireframe to code) are off (aiEnabled={false}); there is no live collaboration or share link..excalidraw file named after the board; More export options… opens the editor's own dialog (scale, background, selection only, embedded scene). Open file… reads .excalidraw files (and PNG/SVG with an embedded scene, and .excalidrawlib libraries) after a confirmation; New board clears the board after a confirmation and can be undone. The editor's own shortcuts (Ctrl+O, Ctrl+Shift+E) still open its file picker and export dialog.src/features/whiteboard/): each change is saved to IndexedDB (studio-tools-whiteboard) in the native format via serializeAsJSON, 400 ms after editing pauses (at most every 3 s while drawing), and when the tab is hidden or closed. Images are kept with the drawing; scroll and zoom are kept too. On load the save is restored through loadFromBlob, which validates and migrates it; a save that can't be read is kept aside under scene-unreadable and the editor opens blank. The shape library is saved in the same database (), and adds libraries from libraries.excalidraw.com.useHandleLibraryvite.config.ts copies them from the installed package to dist/excalidraw/<version>/fonts/ and src/features/whiteboard/assetPath.ts sets window.EXCALIDRAW_ASSET_PATH to match. CJK text loads only the Xiaolai pieces it needs.