Snapit is a cross-platform clipboard sync system that keeps your clipboard in sync across your Mac, Android phone, and browser in real time. Beyond plain text, it handles rich snippets, team-shared libraries, and direct file transfers between any two of your devices — all end-to-end through a relay server you can self-host.
| Copy anywhere, paste everywhere | Clipboard syncs the moment you copy — no button to press |
| File transfer | Send a file from Android to Mac (or vice versa) over a secure WebSocket relay |
| Team libraries | Share snippet collections across a team with role-based access |
| Works offline | Local SQLite cache on every client; syncs deltas when reconnected |
| Self-hostable | The entire backend is open source and ships as a single Docker Compose stack |
┌──────────────────────────────────────────────────────────────────────┐
│ Clients │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ Web App │ │ Desktop │ │ Mobile │ │
│ │ Next.js 14 │ │ Flutter │ │ Flutter + Android │ │
│ │ (Vercel) │ │ macOS/Win │ │ Background sync via │ │
│ └──────┬───────┘ └──────┬───────┘ │ WorkManager + FCM │ │
│ │ │ └───────────┬──────────────┘ │
└──────────┼─────────────────┼────────────────────┼─────────────────┘
│ │ │
└────────────────┬┘ │
│ HTTPS / WSS / SSE │
│ │
┌─────────────▼─────────────────────▼──┐
│ nginx + Cloudflare │
│ TLS termination · Real-IP headers │
└─────────────────┬──────────────────────┘
│
┌─────────────────▼──────────────────────┐
│ Flask API (Gunicorn) │
│ │
│ REST endpoints /snap/* │
│ SSE stream /events │
│ WebSocket relay /snap/transfer/* │
└────────┬──────────────────┬─────────────┘
│ │
┌──────────▼──┐ ┌─────────▼──────────┐
│ MySQL │ │ Redis │
│ (primary │ │ SSE pub/sub · │
│ store) │ │ rate-limit · │
└─────────────┘ │ Celery broker │
└─────────┬──────────┘
│
┌───────────▼──────────┐
│ Celery Workers │
│ email dispatch · │
│ subscription jobs │
└─────────┬─────────────┘
│
┌──────────────▼──────────────┐
│ Firebase FCM · Resend │
│ push notifications · email │
└─────────────────────────────┘
- Client copies text → POST
/snap/sync/pushwith the new item - Server stores it, then publishes a
syncevent on Redis - SSE connections on all other devices receive the event instantly
- Receiving client pulls the delta → item appears in clipboard history
- Mobile clients that are backgrounded wake up via FCM push then pull on open
- Sender POSTs
/snap/transfer/start→ server creates a session and broadcaststransfer_incomingvia SSE to the target device - Target opens a WebSocket to
/snap/transfer/<id>/recv - Sender opens a WebSocket to
/snap/transfer/<id>/sendand streams binary chunks - Server relays chunks in real time; never writes to disk
- On completion, server signals EOF sentinel; receiver closes and saves the file
| Repo | Role | Language / Framework |
|---|---|---|
| snap_BE | REST API, SSE event stream, WebSocket file-transfer relay, Celery workers | Python · Flask |
| snap_FE | Web dashboard, marketing site, billing portal | JavaScript · Next.js 14 |
| snap_PC | Desktop app — macOS (Homebrew) and Windows | Dart · Flutter |
| snap_mobile | Android app with background sync and share-sheet integration | Dart · Flutter |
| homebrew-tap | Homebrew Cask for brew install --cask snapit |
Ruby · Homebrew |
| Layer | Technology |
|---|---|
| Framework | Flask 3 · Gunicorn |
| Database | MySQL · SQLAlchemy 2 · Alembic (migrations) |
| Real-time | Server-Sent Events (SSE) · Redis pub/sub |
| File transfer | WebSocket relay via flask-sock |
| Background jobs | Celery + Redis broker |
| Auth | JWT (PyJWT) · refresh-token rotation |
| Billing | Paystack (subscriptions + webhooks) |
| Push notifications | Firebase Admin SDK (FCM) |
| Resend API · SMTP fallback | |
| Rate limiting | Flask-Limiter + Redis |
| Observability | Sentry · structlog |
| Containerisation | Docker · Docker Compose · GHCR |
| Reverse proxy | nginx · Cloudflare |
| CI/CD | GitHub Actions — build → push to GHCR → SSH deploy → migration → health check |
| Layer | Technology |
|---|---|
| Framework | Next.js 14 (App Router) · React 18 |
| Language | JavaScript |
| Styling | Tailwind CSS v4 · shadcn/ui · Base UI |
| Auth | iron-session (server-side sessions) |
| HTTP | Axios |
| Real-time | SSE (EventSource) · WebSocket (file transfer) |
| Billing UI | Paystack inline checkout |
| Deployment | Vercel |
| Layer | Technology |
|---|---|
| Framework | Flutter (macOS · Windows) |
| Language | Dart |
| State | Riverpod 2 |
| Navigation | GoRouter |
| HTTP / SSE | Dio |
| Storage | flutter_secure_storage · SharedPreferences |
| Encryption | pointycastle (AES-256-GCM + PBKDF2) |
| Distribution | DMG (macOS, ad-hoc signed) · Homebrew tap · GitHub Releases |
| CI/CD | GitHub Actions — tag push → build DMG → GitHub Release → tap formula auto-update |
| Layer | Technology |
|---|---|
| Framework | Flutter (Android) |
| Language | Dart |
| State | Riverpod 2 |
| Navigation | GoRouter |
| HTTP / SSE | Dio |
| Local DB | SQLite via sqflite |
| Encryption | pointycastle (AES-256-GCM + PBKDF2) |
| Background sync | WorkManager |
| Push notifications | Firebase Cloud Messaging (FCM) |
| Share sheet | receive_sharing_intent |
| File picking | file_picker |
| Storage | flutter_secure_storage |
- Real-time clipboard sync across all signed-in devices over SSE
- Clipboard history with full-text search, local SQLite cache
- Soft-delete with delta-pull — bandwidth-efficient, conflict-free
- Device management — name, track, and revoke individual devices
- Peer-to-peer relay over server WebSocket — no file stored server-side
- Progress indicator and timeout handling on both sender and receiver
- Automatic SSE notification to the target device
- Works across all platform combinations (Android ↔ Mac, Mac ↔ Web, etc.)
- Create a team and invite members
- Shared snippet libraries with role-based access
- Real-time push to all team members on update
| Plan | Sync | History | Transfer | Teams |
|---|---|---|---|---|
| Free | ✓ | 100 items | ✗ | ✗ |
| Pro | ✓ | Unlimited | ✓ | ✗ |
| Pro AI | ✓ | Unlimited | ✓ | ✗ |
| Team | ✓ | Unlimited | ✓ | ✓ |
- User management, plan overrides, broadcast messaging
- Coupon system with percentage and flat discounts
- System health dashboard
The full REST API is documented in openapi.yaml and available as a ready-to-import Postman collection in this repo.
Import into Postman:
- Open Postman → Import → select
Snapit.postman_collection.json - Set the
baseUrlcollection variable (https://api.snapit.ink/snapfor production,http://localhost:5559/snapfor local) - Run Auth → Login — access and refresh tokens are captured automatically into collection variables
- All other requests are ready to use
The collection covers all endpoints across Auth, Devices, Sync, File Transfer, Events (SSE), Billing, Teams, and Admin — including pre-request scripts that auto-save tokens and IDs.
Visit snapit.ink, create an account, then install the client for your platform:
# macOS
brew tap coderbenny/tap
brew install --cask snapit
brew trust --cask coderbenny/tap/snapitAndroid: download the APK from the latest release
The backend runs as a single Docker Compose stack. You need:
- A server with Docker and Docker Compose installed
- MySQL and Redis running on the host
- A domain with an SSL certificate (Certbot recommended)
git clone https://github.com/coderbenny/snap_BE.git
cd snap_BE
cp .env.example .env # fill in your values
docker compose up -dSee the snap_BE README for the full environment variable reference, nginx config, and migration guide.
Contributions are welcome across all parts of the system. Here's how to get oriented:
snap_BE → Python/Flask — start with app/routes/ and app/services/
snap_FE → Next.js — start with the app/ directory
snap_PC → Flutter desktop — start with lib/features/
snap_mobile → Flutter Android — start with lib/features/
Before you open a PR:
- Check the open issues in the relevant repo — your bug/feature may already be tracked
- For significant changes, open an issue first to discuss the approach
- Follow the existing code style — each repo has its own linting config
- Write or update tests where applicable
Good first issues are labelled across repos. If you're new to the codebase, the backend is the best place to start — the API is fully documented in openapi.yaml.
MIT — see LICENSE. Each component repository carries the same license.
