# surf.nathan.rip Momentum Mod surf replay hosting - video + `.mtv` replay files with automatic map tier badges, stage splits, and PB history. ## Architecture | Layer | Stack | |-------|-------| | Frontend | React + Vite + Tailwind CSS v4 | | Backend | ElysiaJS (Bun) | | Storage | RustFS (S3-compatible) | | Database | SQLite | ## How it works 1. Upload a video + `.mtv` replay file via the auth-gated upload page 2. Backend parses the `.mtv` binary header for metadata (map, player, time, Steam ID, stage splits) 3. Map tier and thumbnail are fetched from the Momentum Mod API 4. Video uploads go directly to RustFS via presigned URLs (no size limit) 5. If a better time is uploaded for the same map+player, the PB is updated and the old run is archived as a previous PB ## Setup ```bash # Backend cd backend cp .env.example .env # edit with your credentials bun install bun run dev # Frontend cd frontend bun install bun run dev ``` The frontend dev server proxies `/api` to `localhost:3001`. ## Environment variables | Variable | Required | Description | |----------|----------|-------------| | `ADMIN_TOKEN` | Yes | Bearer token for upload/delete auth | | `RUSTFS_ENDPOINT` | No | S3 endpoint (default: `http://localhost:9000`) | | `RUSTFS_ACCESS_KEY` | No | S3 access key | | `RUSTFS_SECRET_KEY` | No | S3 secret key | | `RUSTFS_BUCKET` | No | S3 bucket name (default: `surf`) | | `RUSTFS_PUBLIC` | No | Public read access (default: `true`) | | `PORT` | No | Server port (default: `3001`) | | `DB_PATH` | No | SQLite path (default: `./data/surf.db`) | | `STATIC_DIR` | No | Frontend static files (default: `./public`) | ## RustFS setup 1. Create a bucket called `surf` in your RustFS instance 2. Set bucket to public read for direct video URLs 3. Configure CORS on the bucket to allow `PUT` from your frontend origin (required for presigned video uploads) 4. Create an IAM policy with `s3:ListBucket`, `s3:GetObject`, `s3:PutObject`, `s3:DeleteObject` on `surf/*` ## .mtv file format 195-byte binary header followed by JSON stats and LZMA-compressed replay data. | Offset | Size | Field | |--------|------|-------| | 0x00 | 4 | Magic (`MMTV` = 0x56544D4D) | | 0x04 | 4 | Version | | 0x10 | 64 | Map name (null-terminated) | | 0x50 | 41 | Map hash | | 0x7B | 4 | Tick interval (float) | | 0x7F | 8 | Steam ID (uint64) | | 0x87 | 32 | Player name (null-terminated) | | 0xA9 | 8 | Run time (double) | | 0xB1 | 4 | Total ticks |