curl -fsSL -o docker-compose.yml https://raw.githubusercontent.com/clip-fish/web/master/docker-compose.yml
curl -fsSL -o config.json https://raw.githubusercontent.com/clip-fish/web/master/public/config.template.json
docker compose up -d- What Is Clip Fish?
- Features
- FAQ
- Self-Hosting
- Using Firestore
- Local Development
- Runtime Configuration
- Scripts
- License
Clip Fish is a web‑based app for quickly sharing links, text snippets, and files. Open the site on one device, scan the QR code with another, and you instantly get a private, end‑to‑end‑encrypted WebRTC tunnel with no installs, no sign‑ups, and no middleman servers ferrying your data.
Try it out at https://clip.fish.
- Fast & Secure Transfers: Direct peer‑to‑peer via WebRTC.
- End‑to‑End Encryption: Messages encrypted on your device.
- No Installs or Signups: Just open the page and scan.
- User‑Controlled Sessions: Sessions stay active until you clear them.
- Pluggable Back‑ends: Defaults to Express+WebSocket; also supports Firestore.
- MIT‑licensed: Free to fork, remix, and use commercially.
Q. Is Clip Fish free to use?
A. Yes. Use it for free at https://clip.fish and the code is MIT‑licensed.
Q. Where is my data stored?
A. Message content stays in your browser’s storage (IndexedDB); only minimal session metadata is sent to the server.
Q. What if a device loses connection?
A. Re‑open the same session URL or rescan the QR code to reconnect instantly.
Q. How long does a session stay active?
A. Indefinitely, until you click Clear Session or open a new session URL.
You can run the full Clip Fish stack (front‑end, signaling, API, and MongoDB) with a single docker compose up.
All you need are two files.
# Grab the top‑level Docker Compose file
curl -fsSL \
-o docker-compose.yml \
https://raw.githubusercontent.com/clip-fish/web/master/docker-compose.yml
# Grab the runtime config template
curl -fsSL \
-o config.json \
https://raw.githubusercontent.com/clip-fish/web/master/public/config.template.jsonOpen config.json and edit the values as desired. See Runtime Configuration for details.
The docker-compose.yml assumes you are using the WebSocket signaling server and the Express + MongoDB server. If you prefer a serverless setup, you can configure the front-end to use Firebase Firestore instead. For more details on this, see Using Firestore.
docker compose up -dYou’ll now have four services:
- web – front‑end served by Nginx on port 80
- ws – WebSocket signaling on port 3000
- api – Express + MongoDB session store on port 2000
- mongo – MongoDB data store on port 27017
To shut down & remove containers, run:
docker compose downInstead of running multiple servers for signaling & session storage, you can choose to use Cloud Firestore. Firebase Hosting is also a convenient option for hosting the front-end.
- A Firebase project
- Firebase CLI installed
- Your
config.jsonready withsignaling: "Firestore"andsessionStore: "Firestore"
git clone https://github.com/clip-fish/web.git
cd web
npm installDownload your Firebase SDK snippet, then in config.json set:
{
"signaling": "Firestore",
"sessionStore": "Firestore",
"firebase": { /* your project keys */ }
}See Initialize a Firebase project for more details about initializing a project.
firebase login
firebase init hosting firestore
# When prompted:
# • Pick your Firebase project
# • Set public directory to "dist"
# • Configure as a single‑page app? Yes
npm run build
firebase deploy --only hosting,firestore:rulesYour site is now live on Firebase, using Firestore.
You’ll need three repos (only web if using Firestore):
git clone https://github.com/clip-fish/web.git
git clone https://github.com/clip-fish/ws-server.git
git clone https://github.com/clip-fish/session-api.gitThen in three terminals:
-
Web UI
cd web npm install npm run dev # serves on http://localhost:5173
-
WebSocket server
cd ws-server npm install npm run dev # listens on ws://localhost:3000
-
Session API
cd session-api npm install npm run dev # listens on http://localhost:2000
Now open your browser to http://localhost:5173 and start sharing.
These are all the configuration values you can set in config.json.
| Setting | Type | Description | Default |
|---|---|---|---|
signaling |
"WebSocket" | "Firestore" |
Which transport to use for WebRTC signaling | "WebSocket" |
sessionStore |
"Express" | "Firestore" |
Where to store session metadata (devices & messages) | "Express" |
peerImpl |
"SimplePeer" | "Raw" |
Which WebRTC implementation to use for data‑channels | "SimplePeer" |
wsUrl |
string |
URL of the WebSocket signaling server (when signaling = "WebSocket") |
ws://localhost:3000 |
apiUrl |
string |
Base HTTP URL for the session API (when sessionStore = "Express") |
http://localhost:2000 |
firebase.* |
string |
Firebase configurations | "" |
storeTextMessageContent |
boolean |
Whether to persist text messages in storage | false |
defaultMaxTransferSize |
number |
Max bytes per WebRTC message | 262144 (256 KB) |
maxMessageChunkSize |
number |
Max bytes per chunk when splitting large payloads | 2097152 (2 MB) |
messageLoadTimeout |
number |
Timeout (ms) for loading messages from peers | 10000 |
enableAnalytics |
boolean |
Whether to initialize Google Analytics | false |
| Command | Description |
|---|---|
npm run dev |
Vite dev server + local WS & API |
npm run build |
Type‑check & production build |
npm run preview |
Preview the production build (dist) |
npm run lint |
Run ESLint on src/ |
This project is licensed under the MIT License. See the LICENSE file for details.