Skip to content

Commit f21f855

Browse files
committed
CastDrop: React + Cloudflare Worker + R2 video casting
- Drag/drop video upload to Cloudflare R2 - Chromecast support via Cast SDK + native streaming URL - Range request support for seeking - Auto-cleanup on page close + 1hr expiry - GitHub Actions deploy pipeline
0 parents  commit f21f855

33 files changed

Lines changed: 4319 additions & 0 deletions

.github/workflows/deploy.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Deploy to Cloudflare R2
2+
3+
on:
4+
push:
5+
branches: [main]
6+
workflow_dispatch:
7+
8+
concurrency:
9+
group: "deploy"
10+
cancel-in-progress: false
11+
12+
jobs:
13+
build-and-deploy:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
19+
- name: Setup Node.js
20+
uses: actions/setup-node@v4
21+
with:
22+
node-version: '20'
23+
cache: 'npm'
24+
25+
- name: Install dependencies
26+
run: npm install
27+
28+
- name: Build Site
29+
run: npm run build
30+
31+
- name: Install Worker Dependencies
32+
run: |
33+
cd worker
34+
npm install
35+
36+
- name: Deploy Site and Worker
37+
env:
38+
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
39+
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_KEY }}
40+
run: |
41+
cd worker
42+
npm run deploy:site

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules
2+
dist
3+
*.local
4+
.wrangler

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# 📺 CastDrop
2+
3+
Drop a video. Cast it to your TV.
4+
5+
Upload a local video file, get a temporary streaming URL, and cast it to your Chromecast in native quality. Videos are automatically deleted after 1 hour or when you close the page.
6+
7+
## How it works
8+
9+
1. Drag & drop (or select) a video file
10+
2. File uploads to Cloudflare R2 (temporary storage)
11+
3. Cast the video to your Chromecast using Chrome's built-in Cast or the Cast button
12+
4. Video is deleted when you leave the page (or after 1 hour max)
13+
14+
## Tech Stack
15+
16+
- **Frontend:** React + TypeScript + Vite
17+
- **Backend:** Cloudflare Worker + R2
18+
- **Casting:** Google Cast SDK (default media receiver)
19+
20+
## Development
21+
22+
```bash
23+
npm install
24+
npm run dev
25+
```
26+
27+
## Deployment
28+
29+
Set these GitHub repository secrets:
30+
- `CLOUDFLARE_ACCOUNT_ID`
31+
- `CLOUDFLARE_API_KEY`
32+
33+
Push to `main` to trigger automatic deployment.
34+
35+
## License
36+
37+
MIT

eslint.config.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import js from '@eslint/js'
2+
import globals from 'globals'
3+
import reactHooks from 'eslint-plugin-react-hooks'
4+
import reactRefresh from 'eslint-plugin-react-refresh'
5+
import tseslint from 'typescript-eslint'
6+
7+
export default tseslint.config(
8+
{ ignores: ['dist'] },
9+
{
10+
extends: [js.configs.recommended, ...tseslint.configs.recommended],
11+
files: ['**/*.{ts,tsx}'],
12+
languageOptions: {
13+
ecmaVersion: 2020,
14+
globals: globals.browser,
15+
},
16+
plugins: {
17+
'react-hooks': reactHooks,
18+
'react-refresh': reactRefresh,
19+
},
20+
rules: {
21+
...reactHooks.configs.recommended.rules,
22+
'react-refresh/only-export-components': [
23+
'warn',
24+
{ allowConstantExport: true },
25+
],
26+
},
27+
},
28+
)

index.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8"/>
5+
<link rel="icon" type="image/svg+xml" href="/favicon.svg"/>
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
7+
<title>CastDrop</title>
8+
<meta name="description" content="Drop a video. Cast it to your TV.">
9+
</head>
10+
<body>
11+
<div id="root"></div>
12+
<script type="module" src="/src/main.tsx"></script>
13+
</body>
14+
</html>

0 commit comments

Comments
 (0)