Skip to content

Commit

Permalink
FilePizza v2 🍕 (#134)
Browse files Browse the repository at this point in the history
Ship it.
  • Loading branch information
kern authored Dec 29, 2024
1 parent e4fb343 commit e402c80
Show file tree
Hide file tree
Showing 127 changed files with 12,107 additions and 16,747 deletions.
6 changes: 6 additions & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- Use TypeScript.
- Use function syntax for defining React components. Define the prop types inline.
- If a value is exported, it should be exported on the same line as its definition.
- Always define the return type of a function or component.
- Use Tailwind CSS for styling.
- Don't use trailing semicolons.
4 changes: 2 additions & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.DS_Store
.next
node_modules
dist
resources
dist
20 changes: 0 additions & 20 deletions .github/main.workflow

This file was deleted.

9 changes: 6 additions & 3 deletions .github/workflows/push.yml → .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
on: push
name: Build on push
name: main
on:
push:
branches:
- main
jobs:
build:
name: Docker build, tag, and push
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: actions/checkout@v4
- name: Docker build, tag, and push
uses: pangzineng/Github-Action-One-Click-Docker@master
env:
Expand Down
19 changes: 19 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: tests
on: [push]
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- run: pnpm install
- run: pnpm lint:check
- run: pnpm format:check
- run: pnpm type:check
- run: pnpm build
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.DS_Store
.next
node_modules
dist
tsconfig.tsbuildinfo
13 changes: 0 additions & 13 deletions .npmignore

This file was deleted.

9 changes: 9 additions & 0 deletions .prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict';

module.exports = {
semi: false,
trailingComma: 'all',
singleQuote: true,
printWidth: 80,
tabWidth: 2,
};
14 changes: 9 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
FROM node:alpine
MAINTAINER Alexander Kern <[email protected]>
FROM node:lts-alpine

RUN apk add --no-cache pnpm

COPY package.json pnpm-lock.yaml ./
RUN pnpm install
COPY . ./
RUN npm install && npm run build
RUN pnpm build

ENV PORT 3000
ENV NODE_ENV production
EXPOSE 80
CMD node ./dist/index.js
EXPOSE 3000
CMD pnpm start
78 changes: 30 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,69 +1,51 @@
<a href="https://xkcd.com/949/"><img src="http://imgs.xkcd.com/comics/file_transfer.png" alt="XKCD 949" width="30%" align="right" /></a> <img src="src/static/images/wordmark.png" alt="FilePizza wordmark" width="50%" /> <h3>Peer-to-peer file transfers in your browser</h3>
<a href="https://xkcd.com/949/"><img src="http://imgs.xkcd.com/comics/file_transfer.png" alt="XKCD 949" width="30%" align="right" /></a> <img src="public/images/wordmark.png" alt="FilePizza wordmark" width="50%" /> <h3>Peer-to-peer file transfers in your browser</h3>

*Cooked up by [Alex Kern](https://kern.io) & [Neeraj Baid](http://neeraj.io) while eating Sliver @ UC Berkeley.*

Using [WebRTC](http://www.webrtc.org), FilePizza eliminates the initial upload step required by other web-based file sharing services. When senders initialize a transfer, they receive a "tempalink" they can distribute to recipients. Upon visiting this link, recipients' browsers connect directly to the sender’s browser and may begin downloading the selected file. Because data is never stored in an intermediary server, the transfer is fast, private, and secure.
Using [WebRTC](http://www.webrtc.org), FilePizza eliminates the initial upload step required by other web-based file sharing services. Because data is never stored in an intermediary server, the transfer is fast, private, and secure.

A hosted instance of FilePizza is available at [file.pizza](https://file.pizza).

## Requirements

* node `0.12.x`
* npm `2.x.x`

## Installation

The recommended way to deploy FilePizza is as a [Docker container](https://hub.docker.com/r/kern/filepizza). WebRTC only works over HTTPS, so you'll either have to get a signed HTTPS key/certificate from a CA such as [Let's Encrypt](https://letsencrypt.org/getting-started/) or generate your own [self-signed pair](https://devcenter.heroku.com/articles/ssl-certificate-self) and trust it. Then, to run FilePizza (with HTTPS termination):

$ docker run \
-p 8080:8080 -e PORT=8080 \
-e HTTPS_KEY=/config/server.key \
-e HTTPS_CERT=/config/server.crt \
-v mylocalpath:/config \
-it kern/filepizza:master

You can specify your own ICE STUN/TURN servers for better connectivity behind NATs by passing a JSON encoding of the array via env var `ICE_SERVERS`. Alternatively, if you'd like to use [Twilio's STUN/TURN service](https://www.twilio.com/stun-turn), you can specify your SID and token using the `TWILIO_SID` and `TWILIO_TOKEN` environment variables, respectively.

You can specify your own Webtorrent tracker(s) using the `WEBTORRENT_TRACKERS` environment variable, comma-delimited.

If you want to use [Google Analytics](https://marketingplatform.google.com/about/analytics/), you can specify your UA code using the `GA_ACCESS_TOKEN="UA-00000000-1"` environment variable.

## Development

$ git clone https://github.com/kern/filepizza.git
$ npm install
$ npm run-script build
$ npm start

FilePizza is an isomorphic React application which uses the Flux application architecture. ES6 features are used liberally and compiled using Babel. Views are rendered on the server, store data is serialized and sent to the client, which then picks up where the server left off.

Both client and server JavaScript files can be found in `lib/`. `lib/server.js` and `lib/client.js` are the server and client entrypoints, respectively. `lib/components/`, `lib/stores/`, and `lib/actions/` contain the corresponding Flux modules, implemented using [alt](https://github.com/goatslacker/alt). `lib/routes.js` serves as the isomorphic routes file using [react-router](https://github.com/rackt/react-router).
```
$ git clone https://github.com/kern/filepizza.git
$ pnpm install
$ pnpm dev
$ pnpm build
$ pnpm start
```

Client-side JavaScript and CSS are compiled using webpack and are available at `/app.js`.
## Running with Docker

## FAQ

**Where are my files sent?** Your files never touch our server. Instead, they are sent directly from the uploader's browser to the downloader's browser using WebTorrent and WebRTC. This requires that the uploader leave their browser window open until the transfer is complete.
```
$ pnpm docker:build
$ pnpm docker:up
$ pnpm docker:down
```

**Can multiple people download my file at once?** Yes! Just send them your tempalink.
## Stack

**How big can my files be?** Chrome has issues supporting files >500 MB. Firefox does not have any issues with large files, however.
* Next.js
* Tailwind
* TypeScript
* React
* PeerJS for WebRTC
* View Transitions
* Redis (optional)

**What happens when I close my browser?** The tempalink is invalidated. If a downloader has completed the transfer, that downloader will continue to seed to incomplete downloaders, but no new downloads may be initiated.
## FAQ

**Are my files encrypted?** Yes, all WebRTC communications are automatically encrypted using public-key cryptography.
**How are my files sent?** Your files are sent directly from your browser to the downloader's browser. They never pass through our servers. FilePizza uses WebRTC to send files. This requires that the uploader leave their browser window open until the transfer is complete.

**My files are sending slowly!** Transfer speed is dependent on your network connection.
**Can multiple people download my file at once?** Yes! Just send them your short or long URL.

## Troubleshooting
**How big can my files be?** As big as your browser can handle.

If you receive a `Error: EMFILE, too many open files` error when running `npm
start` on a Mac, this is a result of Browserify's compilation step opening up a
large number of npm modules all at once. You'll have to increase the maximum
number of open files allowed on your system:
**What happens when I close my browser?** The URLs for your files will no longer work. If a downloader has completed the transfer, that downloader will continue to seed to incomplete downloaders, but no new downloads may be initiated.

$ sysctl -w kern.maxfiles=20480
**Are my files encrypted?** Yes, all WebRTC communications are automatically encrypted using public-key cryptography because of DTLS. You can add an optional password to your upload for an extra layer of security.

## License & Acknowledgements

FilePizza is released under the [BSD 3-Clause license](https://github.com/kern/filepizza/blob/master/LICENSE). A huge thanks to [WebTorrent](https://github.com/feross/webtorrent) which we use for the file transfers under the hood, and to [iblowyourdesign](https://dribbble.com/iblowyourdesign) for the pizza illustration.
FilePizza is released under the [BSD 3-Clause license](https://github.com/kern/filepizza/blob/master/LICENSE). A huge thanks to [iblowyourdesign](https://dribbble.com/iblowyourdesign) for the pizza illustration.
11 changes: 11 additions & 0 deletions bin/peerjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env node
const express = require('express')
const { ExpressPeerServer } = require('peer')

const app = express();
const server = app.listen(9000);
const peerServer = ExpressPeerServer(server, {
path: '/filepizza'
})

app.use('/peerjs', peerServer)
23 changes: 0 additions & 23 deletions docker-compose.yaml

This file was deleted.

24 changes: 24 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: '3'
services:
redis:
image: redis:latest
ports:
- 6379:6379
networks:
- filepizza
filepizza:
build: .
image: kern/filepizza:master
ports:
- 8080:8080
environment:
- PORT=8080
- REDIS_URL=redis://redis:6379
networks:
- filepizza
depends_on:
- redis

networks:
filepizza:
driver: bridge
33 changes: 33 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// @ts-check

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config({
extends: [
eslint.configs.recommended,
tseslint.configs.recommended,
],
rules: {
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_' },
],
'@typescript-eslint/no-use-before-define': [
'error',
{ variables: false },
],
'@typescript-eslint/promise-function-async': 'off',
'@typescript-eslint/require-await': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
'import/no-unused-modules': 'off',
'import/group-exports': 'off',
'import/no-extraneous-dependencies': 'off',
'new-cap': 'off',
'no-inline-comments': 'off',
'no-shadow': 'warn',
'no-use-before-define': 'off',
},
files: ['src/**/*.ts[x]'],
ignores: ['legacy', 'node_modules', '.next'],
});
5 changes: 5 additions & 0 deletions next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
9 changes: 9 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
// Disable strict mode to avoid calling useEffect twice in development.
// The uploader and downloader are both using useEffect to listen for peerjs events
// which causes the connection to be created twice.
reactStrictMode: false,
}

module.exports = nextConfig
Loading

0 comments on commit e402c80

Please sign in to comment.