An entry for the streamplace vod showcase
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs

+449 -3
+5 -3
.gitignore
··· 22 22 /build 23 23 dist 24 24 25 - # compiled binaries 26 - at-run 27 - at-run-runner 25 + # compiled binaries (bun build --compile output) 26 + /at-run 27 + /at-run-runner 28 + packages/at-run/cli/at-run 29 + packages/at-run/runner/at-run-runner 28 30 29 31 # misc 30 32 .DS_Store
+81
README.md
··· 1 + # streamhut 2 + 3 + AtmosphereConf 2026 Code Jam entry - serverless execution on AT Protocol. 4 + 5 + ## What is this? 6 + 7 + A proof-of-concept system for running JavaScript bundles stored on your AT Protocol PDS. Your code is your data. 8 + 9 + - **at-run**: Deploy and execute JS bundles from any PDS 10 + - **VOD app**: AtmosphereConf video streaming backend built on at-run 11 + 12 + ## Project Structure 13 + 14 + ``` 15 + ├── packages/at-run/ 16 + │ ├── runtime/ # Core types for bundle authors 17 + │ ├── cli/ # Deploy bundles to PDS 18 + │ ├── runner/ # HTTP server for execution 19 + │ └── lexicons/ # AT Protocol schemas 20 + 21 + ├── apps/ 22 + │ ├── vod/ # AtmosphereConf VOD bundle 23 + │ └── web/ # Video player frontend 24 + ``` 25 + 26 + ## Quick Start 27 + 28 + ```bash 29 + # Install dependencies 30 + bun install 31 + 32 + # Login to your PDS 33 + bun packages/at-run/cli/src/index.ts login 34 + 35 + # Build and deploy the VOD bundle 36 + bun build apps/vod/src/index.ts --outfile=apps/vod/dist/bundle.js --target=browser 37 + bun packages/at-run/cli/src/index.ts deploy apps/vod/dist/bundle.js 38 + 39 + # Start the runner 40 + bun packages/at-run/runner/src/index.ts 41 + 42 + # Test it 43 + curl http://localhost:3000/bundle/YOUR_DID/atmosphereconf-vod/latest/listVideos 44 + ``` 45 + 46 + ## How It Works 47 + 48 + 1. **Write** a bundle with declared permissions using `@at-run/runtime` 49 + 2. **Build** with Bun targeting browser (for Deno compatibility) 50 + 3. **Deploy** to your PDS as a blob with metadata record 51 + 4. **Execute** via any runner - fetches bundle, sandboxes with Deno, returns result 52 + 53 + ```typescript 54 + import { manifest, endpoint } from "@at-run/runtime" 55 + 56 + export const bundle = manifest({ 57 + name: "my-api", 58 + permissions: { net: ["api.example.com"] }, 59 + }) 60 + 61 + export const getData = endpoint({ 62 + handler: async () => { 63 + const res = await fetch("https://api.example.com/data") 64 + return res.json() 65 + }, 66 + }) 67 + ``` 68 + 69 + ## Documentation 70 + 71 + - [at-run README](./packages/at-run/README.md) - Full documentation 72 + - [VOD Bundle](./apps/vod/README.md) - Example bundle 73 + 74 + ## Requirements 75 + 76 + - [Bun](https://bun.sh) - Runtime and bundler 77 + - [Deno](https://deno.land) - Sandbox execution 78 + 79 + ## License 80 + 81 + MIT
+122
apps/vod/README.md
··· 1 + # AtmosphereConf VOD Bundle 2 + 3 + An at-run bundle providing video listing, metadata, and muxed HLS playlist generation for AtmosphereConf 2026 recordings. 4 + 5 + ## Endpoints 6 + 7 + ### `listVideos` 8 + 9 + List all available VOD recordings. 10 + 11 + ```bash 12 + curl http://localhost:3000/bundle/did:plc:xxx/atmosphereconf-vod/latest/listVideos 13 + ``` 14 + 15 + Response: 16 + ```json 17 + { 18 + "videos": [ 19 + { 20 + "uri": "at://did:plc:xxx/place.stream.video/abc123", 21 + "title": "Opening Keynote", 22 + "creator": "did:plc:yyy", 23 + "duration": 3600000000000, 24 + "createdAt": "2026-03-30T09:00:00Z" 25 + } 26 + ] 27 + } 28 + ``` 29 + 30 + ### `getVideo` 31 + 32 + Get metadata for a specific video. 33 + 34 + ```bash 35 + curl -X POST http://localhost:3000/bundle/did:plc:xxx/atmosphereconf-vod/latest/getVideo \ 36 + -H "Content-Type: application/json" \ 37 + -d '{"uri": "at://did:plc:xxx/place.stream.video/abc123"}' 38 + ``` 39 + 40 + ### `getVideoStreams` 41 + 42 + Get available quality levels and audio tracks. 43 + 44 + ```bash 45 + curl -X POST http://localhost:3000/bundle/did:plc:xxx/atmosphereconf-vod/latest/getVideoStreams \ 46 + -H "Content-Type: application/json" \ 47 + -d '{"uri": "at://did:plc:xxx/place.stream.video/abc123"}' 48 + ``` 49 + 50 + Response: 51 + ```json 52 + { 53 + "uri": "at://...", 54 + "streams": [ 55 + { 56 + "quality": "1080p", 57 + "width": 1920, 58 + "height": 1080, 59 + "bandwidth": 2996327, 60 + "codecs": "avc1.42c01f,mp4a.40.2", 61 + "frameRate": 59.498 62 + } 63 + ], 64 + "audioTracks": [ 65 + { "name": "opus", "default": false }, 66 + { "name": "mp4a.40.2", "default": true } 67 + ] 68 + } 69 + ``` 70 + 71 + ### `getPlaylist` 72 + 73 + Generate a muxed HLS master playlist combining video and audio tracks. 74 + 75 + ```bash 76 + curl -X POST http://localhost:3000/bundle/did:plc:xxx/atmosphereconf-vod/latest/getPlaylist \ 77 + -H "Content-Type: application/json" \ 78 + -d '{"uri": "at://did:plc:xxx/place.stream.video/abc123", "quality": "1080p"}' 79 + ``` 80 + 81 + Response (HLS m3u8): 82 + ``` 83 + #EXTM3U 84 + #EXT-X-VERSION:6 85 + #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="opus",DEFAULT=NO,... 86 + #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="mp4a.40.2",DEFAULT=YES,... 87 + #EXT-X-STREAM-INF:BANDWIDTH=2996327,CODECS="avc1.42c01f,mp4a.40.2",... 88 + https://vod-beta.stream.place/... 89 + ``` 90 + 91 + ## Permissions 92 + 93 + ```json 94 + { 95 + "net": [ 96 + "vod-beta.stream.place", 97 + "iameli.com", 98 + "plc.directory" 99 + ] 100 + } 101 + ``` 102 + 103 + ## Build & Deploy 104 + 105 + ```bash 106 + # Build 107 + bun build apps/vod/src/index.ts --outfile=apps/vod/dist/bundle.js --target=browser 108 + 109 + # Deploy 110 + bun packages/at-run/cli/src/index.ts deploy apps/vod/dist/bundle.js 111 + ``` 112 + 113 + ## Usage with Frontend 114 + 115 + Point your hls.js player at the `getPlaylist` endpoint: 116 + 117 + ```javascript 118 + const hls = new Hls() 119 + const playlistUrl = `${RUNNER_URL}/bundle/${DID}/atmosphereconf-vod/latest/getPlaylist?uri=${encodeURIComponent(videoUri)}&quality=1080p` 120 + hls.loadSource(playlistUrl) 121 + hls.attachMedia(videoElement) 122 + ```
+241
packages/at-run/README.md
··· 1 + # at-run 2 + 3 + Serverless JavaScript execution on AT Protocol. Deploy bundles to your PDS, execute them anywhere. 4 + 5 + ``` 6 + ┌─────────────┐ deploy ┌─────────────┐ 7 + │ CLI │ ───────────► │ PDS │ 8 + │ at-run │ │ (your data) │ 9 + └─────────────┘ └──────┬──────┘ 10 + │ fetch 11 + 12 + ┌─────────────┐ request ┌─────────────┐ sandbox ┌─────────────┐ 13 + │ Client │ ───────────► │ Runner │ ───────────► │ Deno │ 14 + └─────────────┘ │ (Bun HTTP) │ │ (sandboxed) │ 15 + └─────────────┘ └─────────────┘ 16 + ``` 17 + 18 + ## Packages 19 + 20 + - **@at-run/runtime** - Core types and helpers for bundle authors 21 + - **@at-run/cli** - Deploy bundles to your PDS 22 + - **@at-run/runner** - HTTP server that fetches and executes bundles 23 + 24 + ## Quick Start 25 + 26 + ### 1. Create a Bundle 27 + 28 + ```typescript 29 + // my-api/index.ts 30 + import { manifest, endpoint } from "@at-run/runtime" 31 + 32 + // Declare bundle metadata and permissions 33 + export const bundle = manifest({ 34 + name: "my-api", 35 + description: "My serverless API", 36 + permissions: { 37 + net: ["api.example.com"], // allowed network hosts 38 + }, 39 + }) 40 + 41 + // Define endpoints 42 + export const hello = endpoint({ 43 + handler: async (args: { name?: string }) => { 44 + return { message: `Hello, ${args.name || "world"}!` } 45 + }, 46 + }) 47 + 48 + export const fetchData = endpoint({ 49 + handler: async () => { 50 + const res = await fetch("https://api.example.com/data") 51 + return res.json() 52 + }, 53 + }) 54 + ``` 55 + 56 + ### 2. Build the Bundle 57 + 58 + ```bash 59 + bun build my-api/index.ts --outfile=dist/bundle.js --target=browser 60 + ``` 61 + 62 + > **Important:** Use `--target=browser` for Deno compatibility. 63 + 64 + ### 3. Deploy to Your PDS 65 + 66 + ```bash 67 + # Login (one-time) 68 + at-run login 69 + 70 + # Deploy 71 + at-run deploy dist/bundle.js 72 + ``` 73 + 74 + Output: 75 + ``` 76 + Bundle: dist/bundle.js (12.3 KB) 77 + Name: my-api 78 + Version: 0.1.0 79 + 80 + ✓ Deployed! 81 + AT URI: at://did:plc:xxx/dev.mainasara.at-run.beta.bundle/my-api-0-1-0 82 + ``` 83 + 84 + ### 4. Execute via Runner 85 + 86 + ```bash 87 + # Start the runner 88 + at-run-runner 89 + 90 + # Call your endpoint 91 + curl -X POST http://localhost:3000/bundle/did:plc:xxx/my-api/latest/hello \ 92 + -H "Content-Type: application/json" \ 93 + -d '{"name": "Alice"}' 94 + 95 + # Response: {"message": "Hello, Alice!"} 96 + ``` 97 + 98 + ## CLI Reference 99 + 100 + ### Commands 101 + 102 + | Command | Description | 103 + |---------|-------------| 104 + | `at-run login` | Authenticate with your PDS | 105 + | `at-run logout` | Clear saved session | 106 + | `at-run whoami` | Show current user | 107 + | `at-run deploy <bundle.js>` | Deploy a bundle | 108 + | `at-run list` | List deployed bundles | 109 + | `at-run delete <name\|rkey>` | Delete bundle(s) | 110 + 111 + ### Version Flags 112 + 113 + ```bash 114 + at-run deploy bundle.js # Bumps patch: 0.1.0 -> 0.1.1 115 + at-run deploy bundle.js --minor # Bumps minor: 0.1.1 -> 0.2.0 116 + at-run deploy bundle.js --major # Bumps major: 0.2.0 -> 1.0.0 117 + at-run deploy bundle.js --version=2.0.0 # Explicit version 118 + ``` 119 + 120 + ## Runner Reference 121 + 122 + ### URL Formats 123 + 124 + | Format | Example | 125 + |--------|---------| 126 + | Raw AT URI | `/at://did:plc:xxx/dev.mainasara.at-run.beta.bundle/my-api-0-1-0/hello` | 127 + | Named + version | `/bundle/did:plc:xxx/my-api/0.1.0/hello` | 128 + | Named + latest | `/bundle/did:plc:xxx/my-api/latest/hello` | 129 + | Local (dev only) | `/local/path/to/bundle.js/hello` | 130 + 131 + ### Environment Variables 132 + 133 + | Variable | Description | 134 + |----------|-------------| 135 + | `PORT` | Server port (default: 3000) | 136 + | `DEV` | Enable local bundle execution | 137 + | `SANDBOX_LOCAL` | Sandbox local bundles too | 138 + 139 + ### Request Format 140 + 141 + **GET** with query params: 142 + ``` 143 + GET /bundle/did/name/latest/endpoint?arg1=value1&arg2=value2 144 + ``` 145 + 146 + **GET** with JSON args: 147 + ``` 148 + GET /bundle/did/name/latest/endpoint?args={"arg1":"value1"} 149 + ``` 150 + 151 + **POST** with JSON body: 152 + ``` 153 + POST /bundle/did/name/latest/endpoint 154 + Content-Type: application/json 155 + 156 + {"arg1": "value1"} 157 + ``` 158 + 159 + ## Permissions 160 + 161 + Bundles declare required permissions in their manifest. The runner enforces these via Deno's permission system. 162 + 163 + ```typescript 164 + export const bundle = manifest({ 165 + name: "my-api", 166 + permissions: { 167 + net: ["api.example.com", "cdn.example.com"], // Network access 168 + read: ["/data"], // Filesystem read 169 + write: ["/tmp"], // Filesystem write 170 + env: ["API_KEY"], // Environment variables 171 + run: ["ffmpeg"], // Subprocess execution 172 + }, 173 + }) 174 + ``` 175 + 176 + ### Per-Endpoint Permissions 177 + 178 + Endpoints can declare additional restrictions: 179 + 180 + ```typescript 181 + export const restrictedEndpoint = endpoint({ 182 + permissions: { 183 + net: ["internal.example.com"], // Only this host, even if manifest allows more 184 + }, 185 + handler: async () => { 186 + // ... 187 + }, 188 + }) 189 + ``` 190 + 191 + The effective permissions are the **intersection** of manifest and endpoint permissions. 192 + 193 + ## Lexicon 194 + 195 + Records are stored in `dev.mainasara.at-run.beta.bundle`: 196 + 197 + ```json 198 + { 199 + "$type": "dev.mainasara.at-run.beta.bundle", 200 + "name": "my-api", 201 + "description": "My serverless API", 202 + "version": "0.1.0", 203 + "blob": { "$type": "blob", "ref": { "$link": "bafkrei..." }, ... }, 204 + "permissions": { "net": ["api.example.com"] }, 205 + "createdAt": "2026-04-01T00:00:00.000Z" 206 + } 207 + ``` 208 + 209 + ## Development 210 + 211 + ### Local Testing 212 + 213 + ```bash 214 + # Build your bundle 215 + bun build src/index.ts --outfile=dist/bundle.js --target=browser 216 + 217 + # Start runner in dev mode 218 + DEV=true bun packages/at-run/runner/src/index.ts 219 + 220 + # Test locally (unsandboxed) 221 + curl http://localhost:3000/local/$(pwd)/dist/bundle.js/hello 222 + 223 + # Test locally with sandbox 224 + SANDBOX_LOCAL=true DEV=true bun packages/at-run/runner/src/index.ts 225 + ``` 226 + 227 + ### Requirements 228 + 229 + - **Bun** - Runtime and bundler 230 + - **Deno** - Sandbox execution (must be in PATH) 231 + 232 + ## Why at-run? 233 + 234 + - **Portable**: Your code lives on your PDS, not a vendor's servers 235 + - **Sandboxed**: Deno enforces declared permissions at runtime 236 + - **Versioned**: Semantic versioning with automatic bumping 237 + - **Decentralized**: Anyone can run a runner, bundles are fetched from any PDS 238 + 239 + ## License 240 + 241 + MIT