{"id":51018774,"url":"https://github.com/stellarlinkco/p2pfile","last_synced_at":"2026-06-21T14:30:21.302Z","repository":{"id":363835805,"uuid":"1264914700","full_name":"stellarlinkco/p2pfile","owner":"stellarlinkco","description":"Browser-first P2P file transfer with Share Links, Access Codes, QR entry, WebRTC DataChannel, relay fallback, and short-lived sessions.","archived":false,"fork":false,"pushed_at":"2026-06-10T14:11:39.000Z","size":463,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-10T16:09:47.836Z","etag":null,"topics":["bun","file-transfer","hono","p2p","react","typescript","vite","webrtc"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stellarlinkco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-10T09:41:21.000Z","updated_at":"2026-06-10T14:15:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/stellarlinkco/p2pfile","commit_stats":null,"previous_names":["stellarlinkco/p2pfile"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/stellarlinkco/p2pfile","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stellarlinkco%2Fp2pfile","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stellarlinkco%2Fp2pfile/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stellarlinkco%2Fp2pfile/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stellarlinkco%2Fp2pfile/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stellarlinkco","download_url":"https://codeload.github.com/stellarlinkco/p2pfile/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stellarlinkco%2Fp2pfile/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34612946,"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-06-21T02:00:05.568Z","response_time":54,"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":["bun","file-transfer","hono","p2p","react","typescript","vite","webrtc"],"created_at":"2026-06-21T14:30:19.994Z","updated_at":"2026-06-21T14:30:21.296Z","avatar_url":"https://github.com/stellarlinkco.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# P2P File\n\nBrowser-first file transfer for sending files directly between two browsers. P2P File creates a short-lived session with a Share Link, Access Code, and QR Code that all point to the same transfer window. File contents stay on the peer path by default and only use relay transport when connectivity requires it.\n\n## Screenshots\n\n### Sender console\n\n![Sender console screenshot](docs/screenshots/sender-console.png)\n\n### Receiver preview\n\n![Receiver preview screenshot](docs/screenshots/receiver-preview.png)\n\n## What it does\n\n- Sender selects one or more files and creates a Temporary Session Window.\n- Receiver opens the Share Link, Access Code, or QR Code and sees a metadata-only Frozen Manifest before claiming.\n- One receiver can claim a session at a time; later visitors see an occupied or completed notice.\n- Transfers prefer Direct Transfer over WebRTC DataChannel and disclose Relayed Transfer when fallback is used.\n- Multi-file transfers are serial. Completed files can be retained on receiver retry; unfinished files restart at file boundaries.\n- Completed sessions enter a short-lived read-only Completed Session View for the sender and original receiver.\n\n## Scope boundaries\n\nThis v1 intentionally does not provide folder transfer, partial receive, sender reattach after refresh, PWA/desktop/CLI surfaces, durable transfer history, upload-to-cloud fallback, or an extra application-layer passphrase.\n\n## Repository layout\n\n```text\napps/web        React 19 + Vite sender/receiver app built into Cloudflare Static Assets\napps/edge       Cloudflare Worker API, WebSocket relay, Durable Objects, and SPA fallback\napps/signal     legacy Bun signaling service kept for non-Worker experiments\npackages/shared Zod schemas, protocol types, shared constants\ntests/e2e       Playwright browser E2E coverage\nscripts         repo guard scripts for naming, size, dependency boundaries, and cutover checks\n```\n\n## Stack\n\n- Runtime/package manager/test runner: Bun 1.x\n- Frontend: React 19, TypeScript, Vite, React Router v7, Tailwind CSS 4\n- Runtime: Cloudflare Workers with Static Assets and Durable Objects\n- Local tooling: Bun 1.x, Wrangler, Playwright, Biome\n- Transfer: WebRTC DataChannel with STUN/TURN configuration and WebSocket relay fallback\n- Validation: Zod, Bun test, Playwright, Biome\n\n## Getting started\n\n```bash\njust setup\njust dev\n```\n\nLocal Cloudflare parity service:\n\n- Worker app, API, WebSocket signaling, and SPA fallback: `http://127.0.0.1:8788`\n- Status endpoint: `http://127.0.0.1:8788/api/status`\nIf `just` is not installed, use the equivalent Bun scripts from `package.json`.\n\n## Configuration\n\nBuild-time variables:\n\n```bash\nVITE_TURN_URL=turn:turn.example.com:3478\nVITE_TURN_USERNAME=example-user\nVITE_TURN_CREDENTIAL=example-password\n```\n\nThe browser client uses same-origin `/api/*` and `/ws/*` by default, so the Cloudflare route does not need a separate signal origin.\nWrangler reads the Worker entrypoint, Static Assets binding, Durable Object bindings, and Durable Object migrations from `wrangler.toml`.\n\n## Cloudflare deployment\n\n`wrangler.toml` is the approved deployment contract:\n\n- Worker entrypoint: `apps/edge/src/index.ts`\n- Static Assets: `./apps/web/dist` bound as `ASSETS`\n- SPA fallback: `not_found_handling = \"single-page-application\"` for `/`, `/receive`, and `/f/:sessionId`\n- Worker API routes: `/api/*`\n- Worker WebSocket routes: `/ws/*`\n- Durable Objects: `SESSION_OBJECT` (`SessionDurableObject`) and `SESSION_DIRECTORY` (`SessionDirectory`) with SQLite migrations\n\nUse the Cloudflare command surface:\n\n```bash\nbun run dev:cloudflare     # builds apps/web/dist, then starts wrangler dev\nbun run deploy:cloudflare  # builds apps/web/dist, then runs wrangler deploy\n```\n\nThe Cloudflare route is a single Worker deployment. It does not need the legacy signal service, a reverse proxy, or an external live-session store for the approved path.\nTURN credentials are still optional for restrictive NAT/firewall environments; transfer contents remain browser-to-browser or in-flight relay frames only.\n\n\n## Cost and plan\n\n- The current Cloudflare deployment uses SQLite-backed Durable Objects, so it can run on the Workers Free plan.\n- Free-plan limits are enforced as hard caps. If you exceed them, the affected operation fails instead of silently billing overage.\n- Workers Paid starts at $5/month. Cloudflare budget alerts notify on spend thresholds but do not stop usage.\n- If you want a hard stop at your own quota, add an application-level gate before creating new sessions or accepting new sockets.\n\n## Validation commands\n\nUse the root `justfile` as the canonical command surface:\n\n```bash\njust dev-cloudflare     # builds apps/web/dist, then starts wrangler dev on the Worker path\njust deploy-cloudflare  # builds apps/web/dist, then runs wrangler deploy\njust lint               # naming, file length, dependency boundaries, Biome\njust typecheck          # shared, signal, web, and edge TypeScript validation\njust test-unit          # Bun unit/integration tests, including Cloudflare cutover validation\njust test-e2e           # Playwright browser E2E tests\njust build              # workspace builds\njust check              # lint + typecheck + tests + build\n```\n\nCurrent E2E coverage includes Share Link entry, Access Code entry, QR Code entry, direct transfer, relay fallback disclosure, retry-budget exhaustion, interrupted receiver resume, occupied sessions, sender-ended sessions, storage failure handling, and mobile no-horizontal-overflow checks.\n\n## Security and privacy notes\n\n- Share Links are bearer credentials.\n- Share surfaces are marked non-indexable and previews stay generic.\n- Frozen Manifest exposes metadata only before claim; no file thumbnails or content preview are shown.\n- The Worker coordinates sessions and signals; file contents are not uploaded to application storage.\n\n## Documentation\n\n- Domain language and invariants: [`CONTEXT.md`](CONTEXT.md)\n- Runtime/product rules: [`docs/mvp-product-rules.md`](docs/mvp-product-rules.md)\n- Feature scope and acceptance criteria: [`docs/feature-spec/p2p-file-first-version-feature-spec.md`](docs/feature-spec/p2p-file-first-version-feature-spec.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstellarlinkco%2Fp2pfile","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstellarlinkco%2Fp2pfile","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstellarlinkco%2Fp2pfile/lists"}