A privacy-first, in-browser document signer. Upload a document, add your signature, download the signed PDF — your file never leaves your browser.
- Upload anything — PDF, Word, Excel, PowerPoint, images, or text files. Non-PDF office files are converted to PDF by a small, optional, self-hosted LibreOffice service.
- Add a signature — either:
- Upload an image of your signature — a smart, luminance-based background remover strips the paper background, with a live-preview threshold slider, or
- Draw it directly on a signature pad.
- Place it — drag, resize, and position the signature anywhere on any page.
- Download — get the signed PDF instantly.
The UI is bilingual-friendly (Arabic RTL first) and uses icons rather than emojis.
All signing happens inside your browser. Rendering (pdf.js), signature stamping, and saving (pdf-lib) are done entirely client-side — the document is never uploaded to any server.
The only optional server component is the Office→PDF conversion step (convert.py), needed only for Word/Excel/PowerPoint/text inputs — and you host that yourself. PDFs and images never touch it. The converter keeps nothing: each request runs in a private temp directory that is deleted immediately after conversion.
| Piece | Role |
|---|---|
index.html |
The whole app — UI, pdf.js rendering, signature tools, pdf-lib stamping/saving. Pure static file. |
vendor/ |
Offline-vendored libraries (pdf.js, pdf-lib) — works with no internet access. |
convert.py |
Optional Flask microservice (127.0.0.1:8000): converts office/text files to PDF via LibreOffice headless. Hardened: size limits, extension allowlist, isolated per-job profiles, hard timeouts with process-group kill, concurrency cap, and no shell. |
Just signing PDFs and images? No server needed at all:
# open index.html directly, or serve the folder statically:
python3 -m http.server 8080
# -> http://localhost:8080Want Word/Excel/PowerPoint support too? Run the converter beside it:
sudo apt install libreoffice python3-flask fonts-noto # or your distro's equivalents
python3 convert.py # listens on 127.0.0.1:8000Then have your web server proxy /convert to 127.0.0.1:8000 (nginx example):
location /convert {
proxy_pass http://127.0.0.1:8000/convert;
client_max_body_size 64m;
}That's it — static files + one optional endpoint.
PRs are welcome! Keep the core principle intact: no document data may leave the browser (the converter is the single, explicit exception, and it must remain stateless).
MIT © 2026 Ahmed. Bundled third-party libraries are listed in THIRD-PARTY.md.
أداة توقيع مستندات تحترم خصوصيتك — كل شيء يجري داخل متصفّحك.
- ارفع أي ملف — PDF أو Word أو Excel أو PowerPoint أو صورة أو ملف نصي. الملفات المكتبية غير الـPDF تُحوَّل إلى PDF عبر خدمة LibreOffice صغيرة اختيارية تستضيفها بنفسك.
- أضف توقيعك — إمّا:
- رفع صورة لتوقيعك، مع إزالة خلفية ذكية (تعتمد على الإضاءة/اللمعان) وشريط ضبط بمعاينة حيّة، أو
- رسمه مباشرة بلوحة رسم.
- ضعه على الورقة — اسحبه وكبّره وحرّكه على أي صفحة.
- نزّل — احصل على الـPDF الموقّع فوراً.
الواجهة عربية RTL أولاً، وتستخدم أيقونات بدل الإيموجي.
كل عملية التوقيع تتم داخل المتصفّح. العرض (pdf.js) وختم التوقيع والحفظ (pdf-lib) كلها على جهازك — المستند لا يُرفع إلى أي سيرفر.
الاستثناء الوحيد الاختياري هو خطوة تحويل ملفات أوفيس إلى PDF (convert.py)، وتلزم فقط لملفات Word/Excel/PowerPoint/النصوص — وأنت من يستضيفها. ملفات PDF والصور لا تمرّ بها إطلاقاً. والمحوّل لا يحتفظ بشيء: كل طلب يعمل في مجلد مؤقت خاص يُحذف فور انتهاء التحويل.
| الجزء | الدور |
|---|---|
index.html |
التطبيق كاملاً — الواجهة، عرض pdf.js، أدوات التوقيع، الختم والحفظ بـpdf-lib. ملف ثابت بحت. |
vendor/ |
المكتبات مضمّنة محلياً (pdf.js وpdf-lib) — يعمل بلا إنترنت. |
convert.py |
خدمة Flask اختيارية (127.0.0.1:8000): تحويل الملفات المكتبية/النصية إلى PDF عبر LibreOffice headless. محصّنة: حد حجم، قائمة امتدادات مسموحة، ملف تعريف معزول لكل مهمة، مهلة صارمة تقتل مجموعة العملية بالكامل، حدّ للتزامن، وبلا shell. |
توقيع PDF وصور فقط؟ لا تحتاج أي سيرفر:
# افتح index.html مباشرة، أو قدّم المجلد كملفات ثابتة:
python3 -m http.server 8080
# -> http://localhost:8080تبي دعم Word/Excel/PowerPoint؟ شغّل المحوّل بجانبها:
sudo apt install libreoffice python3-flask fonts-noto
python3 convert.py # يستمع على 127.0.0.1:8000ثم وجّه مسار /convert من خادم الويب إلى 127.0.0.1:8000 (مثال nginx موجود في القسم الإنجليزي أعلاه).
المساهمات مرحّب بها! حافظ على المبدأ الأساسي: لا تخرج بيانات المستند من المتصفّح (المحوّل هو الاستثناء الوحيد الصريح، ويجب أن يبقى بلا حالة/تخزين).
MIT © 2026 Ahmed. المكتبات المضمّنة موثّقة في THIRD-PARTY.md.