Skip to content

feat: add peer-drop — browser-based P2P file and text sharing#33

Merged
nirokato merged 3 commits into
mainfrom
feat/peer-drop
Apr 1, 2026
Merged

feat: add peer-drop — browser-based P2P file and text sharing#33
nirokato merged 3 commits into
mainfrom
feat/peer-drop

Conversation

@nirokato
Copy link
Copy Markdown
Owner

@nirokato nirokato commented Apr 1, 2026

Summary

  • New project: peer-drop — AirDrop-style file and text sharing between two devices, entirely peer-to-peer via WebRTC (PeerJS). Single index.html, no build step, no server-side data handling.
  • Room code in URL hash (#FOXR) + QR code for easy phone-to-laptop pairing
  • Bidirectional file transfer with 64KB chunking, progress bars, speed estimates, and accept/decline prompts
  • Text/clipboard sharing with URL detection and copy buttons
  • Full infrastructure wiring: tofu registration, homepage link, CLAUDE.md update

What's included

File Change
projects/peer-drop/index.html Full MVP app (~965 lines)
projects/peer-drop/docs/PRD.md Product requirements document
tofu/variables.tf Added peer-drop to projects set
projects/homepage/index.html Added project link
CLAUDE.md Added to projects table

Security review completed

  • XSS mitigated: text messages use DOM API (createElement/textContent), not innerHTML
  • All peer-supplied IDs sanitized via allowlist regex
  • 500MB file size cap prevents memory exhaustion attacks
  • Chunk indices bounds-checked
  • Clipboard API fallback for non-secure contexts

Test plan

  • Open page — verify room code + QR code display
  • Open room URL on second device/tab — verify WebRTC connection
  • Send file from device A to B — verify accept prompt, progress bar, auto-download
  • Send file from B to A — verify bidirectional works
  • Send text message — verify display and copy button
  • Send URL — verify it renders as clickable link
  • Disconnect one peer — verify host shows room code again, joiner reconnects
  • Drop multiple files — verify sequential queue processing
  • Test on mobile (iOS Safari, Android Chrome) — verify file picker and layout

https://claude.ai/code/session_01VKqBtXoos5n1xj1VDL7Cb7

claude added 3 commits April 1, 2026 20:58
Single-file static app using PeerJS for WebRTC data channels.
Room code in URL hash for easy pairing, QR code for mobile,
bidirectional file transfer with chunked progress, and text sharing.

Includes infrastructure registration (tofu), homepage link, and
CLAUDE.md projects table update.

https://claude.ai/code/session_01VKqBtXoos5n1xj1VDL7Cb7
Security:
- Fix XSS in text messages by using DOM API instead of innerHTML
- Sanitize all peer-supplied transfer IDs with allowlist regex
- Add 500MB file size cap to prevent memory bomb via malicious offers
- Validate chunk indices to prevent out-of-bounds writes
- Add clipboard API fallback for non-secure contexts

UX:
- Fix vertical overflow when activity feed grows (flex-start + padding)
- Host recovers after disconnect (shows room code again)
- Hide send section on disconnect for both peers
- Filter out 0-byte files from send queue

QA:
- Add try/catch in processQueue so failed transfers don't freeze queue
- Fix backpressure check to drain buffer before resuming
- Add clipboard error handling with textarea fallback

https://claude.ai/code/session_01VKqBtXoos5n1xj1VDL7Cb7
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 1, 2026

OpenTofu Plan

Plan output
cloudflare_pages_project.project["clock"]: Refreshing state... [id=andy-apps-clock]
cloudflare_pages_project.project["homepage"]: Refreshing state... [id=andy-apps-homepage]
cloudflare_pages_project.project["weft"]: Refreshing state... [id=andy-apps-weft]
data.cloudflare_zone.zone: Reading...
cloudflare_pages_project.preview: Refreshing state... [id=andy-apps-preview]
data.cloudflare_zone.zone: Read complete after 1s [id=a7f7a62f2c2b914baa9b82b9e41a29c5]
cloudflare_pages_domain.domain["weft"]: Refreshing state... [id=df0069d6-a9c4-411d-b52b-88227318b108]
cloudflare_pages_domain.domain["clock"]: Refreshing state... [id=74b72e0f-818d-420e-859a-f0437bd35828]
cloudflare_pages_domain.domain["homepage"]: Refreshing state... [id=2c55d7af-683f-4463-aa98-5bc7b1e707cd]
cloudflare_record.cname["homepage"]: Refreshing state... [id=c2155ce7863f7e7689dc3f05367746e2]
cloudflare_record.cname["clock"]: Refreshing state... [id=d0e16b835decb7bb06f5feb0736801e3]
cloudflare_record.cname["weft"]: Refreshing state... [id=e2411dbb4de2318f0f00d1d47b584e4d]

OpenTofu used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

OpenTofu will perform the following actions:

  # cloudflare_pages_domain.domain["peer-drop"] will be created
  + resource "cloudflare_pages_domain" "domain" {
      + account_id   = "6050946b66172190524579962c958e5a"
      + domain       = "peer-drop.apps.andymolenda.com"
      + id           = (known after apply)
      + project_name = "andy-apps-peer-drop"
      + status       = (known after apply)
    }

  # cloudflare_pages_project.project["peer-drop"] will be created
  + resource "cloudflare_pages_project" "project" {
      + account_id        = "6050946b66172190524579962c958e5a"
      + created_on        = (known after apply)
      + domains           = (known after apply)
      + id                = (known after apply)
      + name              = "andy-apps-peer-drop"
      + production_branch = "main"
      + subdomain         = (known after apply)
    }

  # cloudflare_record.cname["peer-drop"] will be created
  + resource "cloudflare_record" "cname" {
      + allow_overwrite = true
      + content         = (known after apply)
      + created_on      = (known after apply)
      + hostname        = (known after apply)
      + id              = (known after apply)
      + metadata        = (known after apply)
      + modified_on     = (known after apply)
      + name            = "peer-drop.apps"
      + proxiable       = (known after apply)
      + proxied         = true
      + ttl             = (known after apply)
      + type            = "CNAME"
      + value           = (known after apply)
      + zone_id         = "a7f7a62f2c2b914baa9b82b9e41a29c5"
    }

Plan: 3 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  ~ project_urls = {
      + peer-drop = "https://peer-drop.apps.andymolenda.com"
        # (3 unchanged attributes hidden)
    }

─────────────────────────────────────────────────────────────────────────────

Saved the plan to: tfplan

To perform exactly these actions, run the following command to apply:
    tofu apply "tfplan"

@nirokato nirokato merged commit 3bcc9b8 into main Apr 1, 2026
3 checks passed
@nirokato nirokato deleted the feat/peer-drop branch April 6, 2026 23:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants