Initial commit
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
# 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 |
|
||||
Reference in New Issue
Block a user