{"id":50320335,"url":"https://github.com/deadinternetfox/frogtalk","last_synced_at":"2026-05-29T03:04:26.522Z","repository":{"id":352386941,"uuid":"1214946975","full_name":"deadinternetfox/frogtalk","owner":"deadinternetfox","description":"FrogTalk - End-to-end encrypted chat with voice \u0026 video calls","archived":false,"fork":false,"pushed_at":"2026-05-26T16:12:54.000Z","size":104374,"stargazers_count":11,"open_issues_count":0,"forks_count":5,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-26T16:16:42.481Z","etag":null,"topics":["android","chat","docker","electron","fastapi","federation","ios","messaging","python","self-hosted","social-network","video-chat","voice-chat","webrtc","websockets"],"latest_commit_sha":null,"homepage":"https://frogtalk.xyz","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/deadinternetfox.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-19T09:12:15.000Z","updated_at":"2026-05-26T16:12:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/deadinternetfox/frogtalk","commit_stats":null,"previous_names":["deadinternetfox/frogtalk"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/deadinternetfox/frogtalk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deadinternetfox%2Ffrogtalk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deadinternetfox%2Ffrogtalk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deadinternetfox%2Ffrogtalk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deadinternetfox%2Ffrogtalk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deadinternetfox","download_url":"https://codeload.github.com/deadinternetfox/frogtalk/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deadinternetfox%2Ffrogtalk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33634615,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","chat","docker","electron","fastapi","federation","ios","messaging","python","self-hosted","social-network","video-chat","voice-chat","webrtc","websockets"],"created_at":"2026-05-29T03:04:24.802Z","updated_at":"2026-05-29T03:04:26.506Z","avatar_url":"https://github.com/deadinternetfox.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!--\n       _____             _____     _ _\n      |  ___| __ ___    |_   _|_ _| | | __\n      | |_ | '__/ _ \\  _  | |/ _` | | |/ /\n      |  _|| | | (_) || |_| | (_| | |   \u003c\n      |_|  |_|  \\___/  \\___/ \\__,_|_|_|\\_\\\n\n      A federated, end-to-end encrypted chat platform\n--\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n# 🐸 FrogTalk\n\n\u003cp\u003e\nA censorship-free, federated, end-to-end encrypted chat platform.\u003cbr\u003e\n\u003cstrong\u003eThis checkout is the active \u003ccode\u003edev\u003c/code\u003e branch\u003c/strong\u003e — try the live stack at\n\u003ca href=\"https://frogtalk.xyz\"\u003efrogtalk.xyz\u003c/a\u003e before changes reach \u003ca href=\"https://frogtalk.app\"\u003efrogtalk.app\u003c/a\u003e.\u003cbr\u003e\n\u003cstrong\u003ePre-alpha:\u003c/strong\u003e expect bugs, breaking changes, and incomplete hardening. Not production-ready.\n\u003c/p\u003e\n\n[![Branch](https://img.shields.io/badge/branch-dev-2563eb)](https://github.com/deadinternetfox/frogtalk/tree/dev)\n[![Pre-alpha](https://img.shields.io/badge/status-pre--alpha-orange)](https://frogtalk.app/security)\n[![Release](https://img.shields.io/github/v/release/deadinternetfox/frogtalk?display_name=release\u0026sort=semver\u0026color=4caf50)](https://github.com/deadinternetfox/frogtalk/releases)\n[![License](https://img.shields.io/github/license/deadinternetfox/frogtalk?color=4caf50)](LICENSE)\n[![Docker](https://img.shields.io/badge/ghcr.io-frogtalk-4caf50?logo=docker\u0026logoColor=white)](https://github.com/deadinternetfox/frogtalk/pkgs/container/frogtalk)\n[![Stars](https://img.shields.io/github/stars/deadinternetfox/frogtalk?label=stars\u0026style=flat\u0026color=4caf50)](https://github.com/deadinternetfox/frogtalk/stargazers)\n\n[🧪 frogtalk.xyz — live dev node](https://frogtalk.xyz) ·\n[🌐 frogtalk.app — production hub](https://frogtalk.app) ·\n[📥 Downloads](https://frogtalk.xyz/#downloads) ·\n[📚 Node guide](https://frogtalk.xyz/docs/node) ·\n[🔌 API reference](https://frogtalk.xyz/docs/api) ·\n[🛡️ Security](https://frogtalk.xyz/security)\n\n\u003c/div\u003e\n\n---\n\n## 🔧 Active development branch (`dev`)\n\nYou are reading the **contributor default** in git. This branch tracks day-to-day work and deploys to the **development node** at [frogtalk.xyz](https://frogtalk.xyz).\n\n| | **Development (`dev`)** | **Production (`master`)** |\n|---|-------------------------|---------------------------|\n| **Git branch** | `dev` (this tree) | `master` |\n| **Public URL** | [frogtalk.xyz](https://frogtalk.xyz) | [frogtalk.app](https://frogtalk.app) |\n| **Client default** | `client/official-node.json` → `https://frogtalk.xyz` | → `https://frogtalk.app` |\n| **Board identity** | 🔧 Development \u0026 support · `@frogtalk-support` | Frog General · `@frog-general` |\n| **Federation directory** | Still published from **frogtalk.app** | Hub (`FROGTALK_FEDERATION_DIRECTORY_HUB=1` on Main) |\n| **Stability** | May break without notice | Slightly more stable; still pre-alpha |\n\n**Clone this branch:**\n\n```bash\ngit clone -b dev https://github.com/deadinternetfox/frogtalk.git\ncd frogtalk\n```\n\n**Contributing:** open PRs into `dev`. After review and testing on `.xyz`, maintainers promote to `master` for `.app` deploys. See [CONTRIBUTING.md](CONTRIBUTING.md).\n\n**Intentional diff vs `master`:** almost all files match; the usual exception is `client/official-node.json` (home node URL). This README is **dev-only** (not present on `master`).\n\n---\n\n## What is FrogTalk?\n\nFrogTalk is a **self-hostable, federated chat and social node**: FastAPI + SQLite on the server,\nvanilla JS in the browser, optional Frog Channel imageboard, Discord/Telegram bridges, WebRTC calls,\nand **Ed25519-signed federation** between independent operators. Clients encrypt DMs (Signal Protocol)\nand private channels (AES-GCM) before data reaches your disk.\n\n- **Try the dev instance (this branch):** [frogtalk.xyz/app](https://frogtalk.xyz/app) — bleeding edge, may reset or break\n- **Use the production hub:** [frogtalk.app/app](https://frogtalk.app/app) — **pre-alpha**, no uptime or data guarantees\n- **Run your own:** install under `/opt/frogtalk`, complete the **CLI setup wizard**, join the mesh — **[full VPS guide](docs/NODE_INSTALL.md)** · **[web guide](https://frogtalk.app/docs/node)**\n\n### Branches \u0026 public hosts\n\n| Branch | Default client node | Live host | Role |\n|--------|---------------------|-----------|------|\n| **`master`** | `frogtalk.app` | [frogtalk.app](https://frogtalk.app) | Pre-alpha **production hub** — official directory, stable line for operators |\n| **`dev`** | `dev branch` | `dev` branch docs | **Active development** — features land here first; may break without notice |\n| **Tor** (any branch) | varies | `.onion` | Hidden service; `FROGTALK_HOME_PAGE=tor` — vanity search via `node/scripts/tor_vanity_onion.sh` |\n\n**Workflow:** fork and PR into **`dev`**. After testing, maintainers merge **`dev` → `master`** for production deploys. The only intentional code diff between branches in git is usually `client/official-node.json` (see [client/README.md](client/README.md)); **`dev`** also carries a contributor-focused root README.\n\n**Official directory:** `https://frogtalk.app/api/network/servers` (hub is always **frogtalk.app**, not `.xyz`).\n\n---\n\n## ✨ Why run your own node?\n\n\u003e **Your chat, your server, your keys.** No company in the middle, no plaintext on disk, no telemetry tax.\n\n- **Censorship resistance** — more independent nodes means no single kill switch\n- **Policy control** — moderation, federation peers, and bridges on your terms\n- **Privacy** — you operate the infrastructure users connect to (still E2E for DMs/private rooms)\n- **Federation** — your users can talk to people on other nodes in the same mesh\n\n- 🔐 **Real E2E** — Signal Protocol (X3DH + Double Ratchet) for DMs, per-room AES-256-GCM (AAD-bound, with key rotation on ban/kick) for private channels. The server stores ciphertext and nothing else.\n- 🌐 **Federated** — your node talks to other nodes; users, profiles, posts, rooms and DMs replicate across the swamp.\n- 🧅 **Tor-native** — flip a flag and your node lives behind a `.onion`; clearnet IP never leaks.\n- 📱 **Everywhere** — Web, Android (APK), iOS (TestFlight), Windows portable, Linux AppImage / `.deb`, and Electron desktop.\n- 🎵 **More than chat** — DMs, group calls (WebRTC), reels, friend wall, music rooms (YT/Spotify/SoundCloud), Frog Channel imageboard, GIF picker, custom emojis.\n- ⚒️ **Full API** — REST + WebSocket for bots, bridges and custom clients. Discord and Telegram bridges ship in-tree.\n\n---\n\n## Features\n\n| | |\n|---|---|\n| 🔐 **E2E Encryption** | Signal Protocol for DMs (X3DH + Double Ratchet) and per-room AES-256-GCM (AAD-bound v2 wire format, automatic key rotation on ban/kick) for private channels, client-side only — the server never sees plaintext |\n| 🌐 **Federated** | Your node joins the global FrogTalk directory and talks to other nodes |\n| 🔁 **Cross-node Sync** | Home-signed account import when traveling: profile, themes, client prefs, joined channel settings (slowmode, forwarding lock, themes), DM thread prefs, friends/following, FrogSocial posts — see [SECURITY_MODEL.md](docs/SECURITY_MODEL.md) |\n| ⚡ **Real-time** | WebSocket messaging with auto-reconnect, typing indicators, reactions |\n| 🔒 **Private Rooms** | Passphrase-protected rooms — only members with the passphrase can decrypt |\n| 💬 **Direct Messages** | Fully encrypted DMs between any two users |\n| 🖼️ **Frog Channel Imageboard** | Anonymous 4chan-style thread board with replies, likes, image/video/audio posts, greentext, live board chat, and moderator approval tools |\n| 🎞️ **Reels** | Vertical short-video feed with hot/new/top sorting, reactions, reposts, and comments |\n| 📎 **File Sharing** | Images, video, and file attachments up to 8 MB |\n| 🤖 **Discord \u0026 Telegram Bridges** | Mirror rooms to/from Discord channels or Telegram chats |\n| 🔔 **Push Notifications** | Web push for mobile and desktop |\n| 🛡️ **Admin Dashboard** | Moderation tools, live server stats, user management |\n| 🔞 **18+ Content Warnings** | Optional moderator labels on public channels; session age gate before history (not message scanning) |\n| 🧩 **Bot API** | Full REST + WebSocket API for building bots and integrations |\n| 🧅 **Tor / Onion Routing** | Nodes can advertise a `.onion` address; federation traffic and client connections route through Tor when onion mode is enabled. Onion handoff links target `/app`, and clearnet address is never leaked for onion-only nodes |\n\n---\n\n## Download\n\n\u003e **Pre-alpha builds** — for testing only. Expect crashes, breaking API changes, and incomplete security review. Do not rely on these for sensitive communications until we leave pre-alpha.\n\n| Platform | Latest | Notes |\n|----------|--------|-------|\n| 🌐 **Web** | [Open in browser](https://frogtalk.app) | No install needed |\n| 🤖 **Android** | [Latest APK](https://frogtalk.app/download/android) | v1.6.27 (232) — sideload; FCM incoming calls |\n| 📦 **Android (Play)** | [AAB in build mirror](github-build-mirror/frogtalk-v232.aab) | Google Play upload bundle |\n| 🐧 **Linux AppImage** | [Latest AppImage](https://frogtalk.app/download/linux) | `chmod +x` then run |\n| 📦 **Linux .deb** | [Latest .deb](https://frogtalk.app/download/deb) | `sudo dpkg -i \u003cdownloaded_file\u003e.deb` |\n| 🪟 **Windows (Portable .exe)** | [Latest portable .exe](https://frogtalk.app/download/windows) | Portable single-file — just run |\n| 🪟 **Windows (.zip)** | [Latest .zip](https://frogtalk.app/download/windows-zip) | Unzip, then run `FrogTalk.exe` |\n| 🍎 **macOS** | [Open in browser](https://frogtalk.app) | Native macOS build not published yet |\n\n---\n\n## Linux quick start (chat client)\n\nPick one way to run FrogTalk on Linux — all clients talk to a node (default\n[`frogtalk.app`](https://frogtalk.app); change server in **Settings → Network**).\n\n### Download (fastest)\n\n```bash\n# AppImage — no install, any distro\ncurl -fsSL -o FrogTalk.AppImage \"$(curl -fsSL https://api.github.com/repos/deadinternetfox/frogtalk/releases/latest \\\n  | grep -o 'https://[^\"]*AppImage' | head -1)\"\nchmod +x FrogTalk.AppImage\n./FrogTalk.AppImage\n\n# .deb — Debian / Ubuntu / Mint\ncurl -fsSL -o frogtalk.deb \"$(curl -fsSL https://api.github.com/repos/deadinternetfox/frogtalk/releases/latest \\\n  | grep -o 'https://[^\"]*_amd64.deb' | head -1)\"\nsudo dpkg -i frogtalk.deb\nfrogtalk\n```\n\nOr use the buttons on **[GitHub Releases](https://github.com/deadinternetfox/frogtalk/releases/latest)** or [frogtalk.app/download](https://frogtalk.app).\n\n### Build from source (desktop)\n\n```bash\ngit clone https://github.com/deadinternetfox/frogtalk.git\ncd frogtalk\nbash client/desktop/scripts/build-linux-release.sh\n# Artifacts: client/desktop/builds/*.AppImage and *.deb\n```\n\nDetails: [`client/README.md`](client/README.md).\n\n### Browser only\n\nOpen **[frogtalk.app/app](https://frogtalk.app/app)** — no install; works on Linux mobile and desktop browsers.\n\n---\n\n## Self-Host (run your own node)\n\n**Docs:** [docs/NODE_INSTALL.md](docs/NODE_INSTALL.md) (VPS, DNS, firewall, nginx, HTTPS, backups) ·\n[https://frogtalk.app/docs/node](https://frogtalk.app/docs/node) (same flow on the live site)\n\n### Quick start (fresh Linux VPS)\n\n```bash\ncd /opt\ngit clone https://github.com/deadinternetfox/frogtalk.git\ncd frogtalk\n\n# CLI install wizard (venv, .env, symlinks) — not a browser UI\nexport PUBLIC_URL=\"https://chat.yourdomain.com\"\nbash node/scripts/install.sh setup -y --public-url \"$PUBLIC_URL\"\nbash node/scripts/install.sh federation -y --public-url \"$PUBLIC_URL\"\nsudo bash node/scripts/install.sh systemd -y\n```\n\nOr use the **interactive menu:** `bash node/scripts/install.sh` → setup · federation · systemd · status. See [docs/NODE_INSTALL.md](docs/NODE_INSTALL.md) for a full copy-paste VPS guide.\n\nPut **nginx + certbot** in front (ports 80/443), keep uvicorn on `127.0.0.1:8080`, set\n`PUBLIC_URL=https://chat.yourdomain.com` and matching `ALLOWED_ORIGINS`. See the VPS guide for UFW,\nSSH keys, and troubleshooting.\n\n**Admin account:** user `admin` on first boot — password from `ADMIN_PASSWORD` in `.env`, or a\none-time generated value in `journalctl` if left empty (rotate after login).\n\n\u003e Runtime state lives at `/opt/frogtalk/` (`.env`, `data/`, `secrets/`, `venv/`). Code is\n\u003e `/opt/frogtalk/node/`. `node/data` and `node/.env` must be **symlinks**, not real folders.\n\n### Install wizard (CLI)\n\n| Entry | What it does |\n|-------|----------------|\n| `bash node/scripts/install.sh` | Interactive menu |\n| `bash node/scripts/install.sh setup` | `node_setup_wizard.sh` — venv, `.env`, symlinks |\n| `bash node/scripts/install.sh federation` | Directory sync, hub announce, pubkey pin, board peer pills |\n| `bash node/scripts/install.sh systemd` | Install `frogtalk.service` |\n| `bash node/scripts/install.sh status` | `/api/ping` + federation peer list |\n\nWizard source: `node/scripts/node_setup_wizard.sh`. Users register at **`/app`** after the node is up.\n\n### Federation setup\n\n```bash\nbash node/scripts/node_federation_join.sh --install-dir /opt/frogtalk -y \\\n  --public-url https://chat.yourdomain.com\n```\n\n- Directory feed (default): `https://frogtalk.app/api/network/servers`\n- **Hub announce:** with the same `FROGTALK_FEDERATION_TOKEN` on Main and your node, federation join POSTs to `…/servers/register` so you appear on [frogtalk.app](https://frogtalk.app/api/network/servers) (verify with curl to Main, not only your local `/api/network/servers`)\n- Peer **Ed25519 keys** are pinned from each peer’s `/api/network/status`\n- Re-run after changing `PUBLIC_URL`, onion URL, or major upgrades\n\n**Official mesh nodes** (directory + optional `fallback_peers` in your mesh JSON when the directory HTTP fetch fails):\n\n| Node | Clearnet | Notes |\n|------|----------|--------|\n| FrogTalk Main | `https://frogtalk.app` | Production hub · board `@frog-general` |\n| FrogTalk Dev | `dev branch` | Development instance · board `@frogtalk-support` |\n| FrogTalk Tor Mirror | `.onion` only | Listed in **Settings → Network** when configured |\n\nFederation is **not hardcoded** in application source. Hub operators copy\n[`node/deploy/federation-mesh.example.json`](node/deploy/federation-mesh.example.json) →\n`federation-mesh.local.json` and set `FROGTALK_FEDERATION_MESH_FILE`. The public FrogTalk fleet\nlayout is documented as an example only:\n[`federation-mesh.frogtalk.example.json`](node/deploy/federation-mesh.frogtalk.example.json).\nSee [node/deploy/README.md](node/deploy/README.md#federation-mesh-config-open-source).\n\n### Manual install (no wizard)\n\n```bash\ngit clone https://github.com/deadinternetfox/frogtalk.git /opt/frogtalk\ncd /opt/frogtalk\npython3 -m venv venv \u0026\u0026 source venv/bin/activate\npip install -r node/requirements.txt\ncp node/deploy/env.example .env\nmkdir -p data secrets\nln -sfn /opt/frogtalk/data node/data \u0026\u0026 ln -sfn /opt/frogtalk/.env node/.env\ncd node \u0026\u0026 python main.py\n```\n\n### Updates\n\n```bash\nbash node/scripts/install.sh update\nbash node/scripts/install.sh update-apply -y\nbash node/scripts/install.sh federation -y   # refresh peers after releases\n```\n\n### Security notes (operators)\n\n- Use **SSH keys**; do not commit `.env`, tokens, or passwords to git\n- `FROGTALK_FEDERATION_REQUIRE_SIGS=1` (default in wizard) — reject unsigned federation events\n- `FROGTALK_AUTO_UPDATE_ENABLED=0` until `FROGTALK_RELEASE_SIGNERS` is set\n- Expose **nginx** on 443, not raw uvicorn on the public internet\n- Report issues: [frogtalk.app/security](https://frogtalk.app/security)\n\n### Troubleshooting\n\n| Problem | Fix |\n|---------|-----|\n| Empty DB / missing tables | `node/data` must symlink to `/opt/frogtalk/data` — run setup or federation join |\n| Domain 502, local `:8080` OK | Match `PORT` in `.env` with nginx `proxy_pass`; behind Cloudflare tunnel use `PORT=8000` + `FROGTALK_NGINX_TUNNEL_LISTEN=1` (see deploy README) |\n| `/board/` 404 on clearnet | Route tunnel through **nginx on 8080**, not uvicorn directly — `install.sh board-nginx` |\n| Wrong board pill URLs | Optional `FROGTALK_BOARD_PEER_CANONICAL_FILE` — see `board-peer-canonical.example.json` |\n| Federation peers, no delivery | Re-run `federation -y`; check pinned pubkey in DB (`install.sh status`) |\n| CORS in browser | Add your HTTPS origin to `ALLOWED_ORIGINS` |\n\nMore: [docs/NODE_INSTALL.md](docs/NODE_INSTALL.md#troubleshooting)\n\n### Server Web Admin (node management)\n\nEnable the secure node management dashboard:\n\n```bash\nexport FROGTALK_SERVER_WEBUI_ENABLED=1\nexport FROGTALK_SERVER_WEBUI_USER=serveradmin\nexport FROGTALK_SERVER_WEBUI_PASSWORD='set-a-strong-password'\n```\n\nThen open:\n\n- URL: `https://your-host/server`\n- Login: `FROGTALK_SERVER_WEBUI_USER` / `FROGTALK_SERVER_WEBUI_PASSWORD`\n\nCapabilities include live hardware telemetry (CPU/memory/disk/uptime), federation node inventory, node probe, and block/unblock controls.\n\nThe panel now includes a novice-friendly onboarding checklist with explicit warnings for missing HTTPS, public-IP exposure, and recommended federation safety toggles (Tor auto-block and non-SSL peer auto-block).\n\nNode Control also includes a per-node easter-egg editor: upload images/audio/video, format rich text, and set the hidden popup that appears after seven taps on the frog trigger for that node.\n\n### Tor / Onion Hidden Service\n\nTo run your node as a Tor hidden service (`.onion` only, no clearnet exposure):\n\n```bash\nexport FROGTALK_TOR_ENABLED=1\nexport FROGTALK_ONION_URL=http://youronionaddress.onion\n# Leave FROGTALK_BASE_URL unset or empty to be onion-only\n```\n\nUse the onion app surface for user links and server switching:\n\n```text\nhttp://youronionaddress.onion/app\n```\n\nClients using *Prefer onion endpoints* in Network Settings will automatically route all federation traffic through Tor. The clearnet IP is never shared with the directory or other nodes when `FROGTALK_TOR_ENABLED=1` and no `FROGTALK_BASE_URL` is set.\n\nOnion-capable nodes display a `🧅 ONION` badge in the server list, and the node card shows the `.onion` address with a one-click copy button instead of a clearnet URL.\n\n### Production (systemd)\n\n```bash\nsudo cp node/deploy/frogtalk.service /etc/systemd/system/frogtalk.service\n# Defaults: WorkingDirectory=/opt/frogtalk/node, EnvironmentFile=/opt/frogtalk/.env\n# edit User if you're not deploying as `deploy`\nsudo systemctl daemon-reload\nsudo systemctl enable --now frogtalk\nsudo systemctl status frogtalk\n```\n\nLogs: `journalctl -u frogtalk -f`\n\n### Docker\n\n```bash\n# Build from the repo root, pointed at node/Dockerfile.\ndocker build -f node/Dockerfile -t frogtalk .\ndocker run -d -p 8080:8080 \\\n  -e ADMIN_PASSWORD=your_password \\\n  -v $(pwd)/data:/app/data \\\n  --name frogtalk frogtalk\n```\n\n### Nginx + HTTPS\n\n```nginx\nserver {\n    listen 443 ssl;\n    server_name chat.yourdomain.com;\n\n    location / {\n        proxy_pass http://127.0.0.1:8080;\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection \"upgrade\";\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n    }\n}\n```\n\nFull node setup: **[docs/NODE_INSTALL.md](docs/NODE_INSTALL.md)** · **[frogtalk.app/docs/node](https://frogtalk.app/docs/node)**\n\n---\n\n## API \u0026 Bots\n\nFrogTalk has a full REST + WebSocket API. Build bots, integrations, and custom clients.\n\n```\nGET  /api/rooms          # list public rooms\nPOST /api/messages       # send a message (with bridge_token)\nWS   /ws/{room}          # real-time message stream\n```\n\nFull reference: **[frogtalk.app/docs/api](https://frogtalk.app/docs/api)** — includes\n`PATCH /api/auth/client-prefs` (`preferred_node_url`, `prefer_onion`, notification sounds)\nfor Settings → Network and federation account sync.\n\n---\n\n## Encryption Model\n\nFrogTalk's crypto is layered by context so each surface gets the strongest\npractical guarantee:\n\n- **Direct messages — Signal Protocol.** X3DH key agreement against the\n  recipient's published prekey bundle establishes a Double Ratchet session.\n  Every DM advances the ratchet, so forward secrecy is per-message and a\n  device compromise tomorrow can't decrypt today's traffic.\n- **Room messages — per-channel AES-256-GCM with AAD binding + key rotation.**\n  Private channels are sealed with a 256-bit AES-GCM key derived (HKDF-SHA-256)\n  from a shared channel secret distributed to new members through their\n  already-established Signal DM session. Ciphertext is bound to a specific\n  room id and key version via AES-GCM Additional Authenticated Data\n  (`room:\u003cid\u003e:v\u003cN\u003e`, v2 wire format `[0x02][iv:12][ct+tag]`), so a captured\n  ciphertext cannot be replayed against another room or an older key. When a\n  member is banned or kicked, or a moderator presses **Rotate room key now**,\n  a fresh key is generated client-side and fanned out to every remaining\n  member via their Signal DM session; the rotation is announced in-channel\n  as a system message. Public channels intentionally have no key — they are\n  designed to be world-readable and are stored encrypted-at-rest only.\n- **Voice/video calls — DTLS fingerprint signing.** SDP offers and answers\n  carry an XEdDSA signature over the call's DTLS fingerprint so a hostile\n  signalling server can't silently MITM the media path. A Safety-Numbers\n  panel surfaces the verified peer identity.\n- **Wall posts — per-post AEAD wrapped to followers.** Each post is sealed\n  with a fresh AES-256-GCM key; that key is then wrapped to each follower\n  via their Signal DM session, so only the intended audience can read it.\n- **Bridged channels.** Channels with an outbound Discord/Telegram bridge\n  intentionally fall back to plaintext so the bridge can forward the\n  message text to the third-party platform; this is clearly indicated in\n  the channel header. **Bridges are not available for private (E2EE) rooms**\n  — forwarding to Discord/Telegram would leak plaintext to a third-party\n  service and defeat end-to-end encryption, so all four bridge-create\n  endpoints reject private rooms with HTTP 403. DMs are never bridged.\n- **Private keys** are generated client-side and never leave the device.\n  They live in IndexedDB (web/desktop) or the OS keystore (Android/iOS).\n\nIn-app the **🔒 Encryption info** modal exposes the current safety number\nfor a DM, or the channel's encryption mode for a room.\n\n---\n\n## Repository Structure\n\n```\nfrogtalk/\n├── client/                       # everything end-users install\n│   ├── desktop/                  # Electron source + builds\n│   │   ├── app/                  # Electron source (main.js / preload.js / renderer)\n│   │   └── builds/               # Electron output artifacts (gitignored)\n│   └── mobile/\n│       ├── android/              # Android Studio project (Capacitor + native shell)\n│       └── ios/                  # iOS Xcode project\n├── node/                         # the federated server (everything ops cares about)\n│   ├── main.py                   # FastAPI app entrypoint\n│   ├── database.py               # SQLite schema + migrations\n│   ├── routers/                  # FastAPI route modules\n│   ├── static/                   # web client + marketing pages served by the node\n│   ├── board/                    # Frog Channel PHP imageboard → public /board/\n│   ├── deploy/                   # systemd / nginx / env.example\n│   ├── scripts/\n│   │   ├── install.sh            # unified installer menu (recommended)\n│   │   ├── node_setup_wizard.sh  # guided self-host setup\n│   │   ├── node_update_check.sh  # safe update check / apply\n│   │   ├── deploy.sh             # rsync node/ to one host\n│   │   ├── build_server_release.sh\n│   │   └── migrations/           # one-shot historical migrations\n│   ├── tests/                    # pytest suite (sanitizers, proxy, security)\n│   ├── requirements.txt\n│   ├── Dockerfile                # docker build -f node/Dockerfile -t frogtalk .\n│   └── builds/                   # release tarballs (gitignored)\n├── bot-examples/                 # standalone reference bots\n├── github-build-mirror/          # release binaries published to GitHub\n├── docs/\n│   ├── README.md                 # index of public operator docs\n│   ├── NODE_INSTALL.md           # VPS install + federation (start here for ops)\n│   └── SECURITY_MODEL.md         # encryption + threat model\n├── README.md / SECURITY.md / CONTRIBUTING.md / CONTRIBUTORS.md / LICENSE\n└── .gitignore / .dockerignore / .fallowrc.json\n```\n\nOn a running node, operator state (`.env`, `data/`, `secrets/`, `venv/`) lives at\n`/opt/frogtalk/` and the runtime source at `/opt/frogtalk/node/`. The setup wizard\nwires symlinks (`node/data`, `node/.env`, `node/secrets`) so the FastAPI process\ncan stay with cwd=`node/` without copying operator secrets into the source tree.\n\nDetailed structure + migration rules: [`node/README.md`](node/README.md) · security model: [`docs/SECURITY_MODEL.md`](docs/SECURITY_MODEL.md)\n\n---\n\n## Open source \u0026 contributing\n\nFrogTalk is **MIT-licensed** and developed in the open. The encryption primitives are well-studied (X3DH + Double Ratchet for DMs, per-room AES-256-GCM for private channels, DTLS-fingerprint signing for calls). We publish the [security model](docs/SECURITY_MODEL.md) and welcome audits.\n\n### Get involved\n\n- 🐛 **Bug or security issue?** Report at **\u003chttps://frogtalk.app/security\u003e** — anonymous submissions accepted. For sensitive disclosures: `security@frogtalk.app`.\n- 🛠️ **Code contribution?** See **[CONTRIBUTING.md](CONTRIBUTING.md)** for branch workflow and review expectations.\n- 🛠️ **Feature idea?** File a [feature request](https://github.com/deadinternetfox/frogtalk/issues/new?template=feature_idea.md).\n- 📣 **Run a node.** More nodes = more censorship-resistance. Self-host guide above.\n- 💬 **Spread the word.** Community projects need a community.\n\nResearchers who responsibly disclose are credited in the security advisory and on the [Hall of Fame](https://frogtalk.app/security#hall-of-fame).\n\n### Contributing (quick start)\n\n1. Fork the repo and branch from **`dev`** (or `master` if `dev` is not available yet).\n2. Run `node --check node/static/js/\u003cfile\u003e.js` for any JS you touched.\n3. Run `python3 -m py_compile node/\u003cfile\u003e.py` for any Python you touched.\n4. Open a PR with the template filled in. For security fixes, include a PoC.\n5. Add yourself to `CONTRIBUTORS.md` in the same PR if you want repo credit.\n\nSee [`/security`](https://frogtalk.app/security) for scope, threat model, and what counts as a vulnerability.\n\n---\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeadinternetfox%2Ffrogtalk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeadinternetfox%2Ffrogtalk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeadinternetfox%2Ffrogtalk/lists"}