A Progressive Web App (PWA) for stamping documents offline. Drag, resize, rotate, and position stamps on documents with precision. Perfect for batch processing documents that need signatures and stamps.
- Drag & Drop Positioning: Click and drag stamps anywhere on the document
- Rotation Control: Rotate stamps to any angle (-180° to 180°)
- Opacity Adjustment: Preview stamp placement with transparency
- Resize Support: Scale stamps up or down with mouse or keyboard
- Keyboard Shortcuts: Arrow keys for precise positioning
- Position Persistence: Stamp position/settings saved between sessions
- Batch Processing: Replace document while keeping stamp position
- Offline Support: Works completely offline after first load
- PWA Installable: Install as a standalone app on desktop/mobile
cd offline-stamper
npm installnpm run devOpen your browser to http://localhost:5173
npm run build
npm run preview- Upload Document: Click "Document Image" and select your document
- Upload Stamp: Click "Stamp PNG" and select your stamp (transparent PNG recommended)
- Position Stamp:
- Drag the stamp to position it
- Use corner handle to resize
- Use sliders for opacity and rotation
- Download: Click "💾 Download" to save the stamped document
- Batch Process: Click "🔄 Replace Doc" to stamp another document (stamp stays in place)
| Keys | Action |
|---|---|
←↑→↓ |
Move stamp by 1px |
Shift + Arrow |
Move stamp by 10px |
+ or = |
Scale stamp up |
- or _ |
Scale stamp down |
R |
Reset stamp position |
D |
Download stamped document |
The app saves your stamp position, size, rotation, and opacity in browser localStorage. This means:
- Reloading the page keeps your settings
- Perfect for batch processing multiple documents
- Settings persist until you click "Reset Position"
After the first visit:
- All app files are cached
- Works without internet
- Can be installed as a standalone app
- No data is sent to any server
- Downloads preserve original document resolution
- Stamps rendered with smooth anti-aliasing
- PNG format maintains transparency
- Timestamped filenames prevent overwriting
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Opera 76+
All modern browsers with Canvas API and service worker support.
This project includes automatic GitHub Pages deployment.
- Push your code to GitHub
- Enable GitHub Pages in Settings → Pages → Source: GitHub Actions
- Your site will automatically deploy on every push
Deploy to any static hosting:
npm run build
# Upload the dist/ folder to your hosting provider- 100% Local Processing: All operations happen in your browser
- No Server Uploads: Documents and stamps never leave your device
- No Analytics: Zero tracking or data collection
- No External Dependencies: After first load, works completely offline
- Vanilla JavaScript (ES modules)
- HTML5 Canvas API
- Vite build tool
- Vite PWA plugin with Workbox
- localStorage for state persistence
offline-stamper/
├── index.html # Main HTML with UI
├── app.js # Core stamping logic
├── vite.config.js # Vite + PWA configuration
├── package.json # Dependencies
├── public/ # Static assets
│ ├── icon.png
│ ├── icon-192.png
│ └── icon-512.png
└── dist/ # Production build
The app is structured as a single-page application:
- index.html: UI layout and styles
- app.js: Canvas rendering, event handling, state management
The app uses HTML5 Canvas with transformation matrices for:
- Rotation around stamp center point
- Hit detection with inverse transforms
- High-quality image smoothing
State is managed in a simple object with localStorage sync:
{
x: number, // X position
y: number, // Y position
scale: number, // Scale factor
rotation: number, // Rotation in degrees
opacity: number // Opacity 0-1
}Stamp not appearing:
- Ensure you uploaded both document and stamp
- Check stamp file is a valid image (PNG recommended)
Can't resize stamp:
- Drag the small square handle in the bottom-right corner
- Use
+and-keys for keyboard resizing
Position not saving:
- Check browser localStorage is enabled
- Some browsers in private mode don't persist localStorage
MIT License - Feel free to use for any purpose
- PWA Plugin: vite-plugin-pwa
- Build Tool: Vite