Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive

- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,9 @@ dist-ssr

/target
/.direnv

# Generated relay keys/tokens
*.jwk
*.jwt
.terraform
.wrangler
4 changes: 0 additions & 4 deletions .gitmodules

This file was deleted.

26 changes: 8 additions & 18 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@ Hang is a real-time communication platform that combines **closed-source applica

### Open Source vs Closed Source

This repository contains:
- **Closed Source**: The `hang` application (opinionated conferencing UI and business logic)
- **Open Source**: The `moq/` submodule (generic media streaming libraries)

The `moq` submodule contains generic, reusable libraries for media streaming that should remain framework-agnostic and broadly applicable.
- **Open Source**: [moq](https://github.com/moq-dev/moq) (generic media streaming libraries, consumed as npm packages)

## Essential Commands

Expand All @@ -36,12 +33,10 @@ just fix

## Architecture

### MOQ Submodule (`/moq/`) - **Open Source**
Generic media streaming libraries linked as a git submodule:
- **Location**: Git submodule from https://github.com/kixelated/moq (moq-preview branch)
- **Purpose**: Generic, framework-agnostic media streaming over WebTransport/QUIC
- **Languages**: TypeScript and Rust implementations
- **Packages**: `@kixelated/moq`, `@kixelated/hang`, `@kixelated/signals`, `@kixelated/moq-token`
### MOQ Libraries — **Open Source**
Published npm packages from [moq](https://github.com/moq-dev/moq):
- **Packages**: `@moq/lite`, `@moq/hang`, `@moq/signals`, `@moq/publish`, `@moq/watch`, `@moq/token`
- **Relay**: `moq-relay` binary provided via nix flake for local development (`dev/relay/`)

### Frontend (`/app`) - **Closed Source**
Hang-specific conferencing UI and application logic:
Expand All @@ -68,7 +63,7 @@ Hang-specific server and business logic:
2. **WebTransport Rooms**: Real-time media streaming via MOQ protocol
3. **OAuth Flow**: Authentication with Google/Discord through popup windows
4. **Edge-first**: All backend services run on Cloudflare's edge network
5. **Submodule Linking**: MOQ libraries linked via git submodule and bun workspaces
5. **MOQ Libraries**: Published npm packages from the open-source moq project

## Development Tips

Expand All @@ -77,15 +72,10 @@ Hang-specific server and business logic:
- `just check` runs linting, TypeScript, and Rust checks
- `just fix` fixes formatting and linting issues across all languages

### Working with the MOQ Submodule
- **Location**: `./moq/` (git submodule)
- **Branch**: `moq-preview`
- **Dependencies**: Automatically linked via bun workspace configuration
- **Updates**: Use `git submodule update --remote` to sync with upstream

### Working with Media over QUIC
- Generic MOQ implementation in the `moq/` submodule
- MOQ libraries are installed from npm (`@moq/*` packages)
- Hang-specific integration in `app/room/` folder
- Local relay server config in `dev/relay/` (uses `moq-relay` from nix flake)
- Uses WebTransport and QUIC under the hood

## Code Style
Expand Down
16 changes: 7 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,33 @@ Hang combines a closed-source application layer with an [open-source media strea
- **app** — Web frontend built with SolidJS, Vite, and Tailwind CSS v4
- **api** — Backend running on Cloudflare Workers with Hono and Drizzle ORM
- **native** — Desktop/mobile app using Tauri v2
- **moq** — Open-source media streaming library using WebTransport and QUIC (git submodule)

The frontend and backend share types via Hono RPC. Real-time media is streamed over WebTransport using the MOQ protocol, handled by the `moq/` submodule.
The frontend and backend share types via Hono RPC. Real-time media is streamed over WebTransport using the [MOQ protocol](https://github.com/moq-dev/moq), consumed as published npm packages (`@moq/*`).

## Project Structure

```
app/ Web frontend (SolidJS + Vite)
api/ Backend API (Cloudflare Workers + Hono)
native/ Desktop/mobile app (Tauri v2)
moq/ Media over QUIC libraries (git submodule → github.com/kixelated/moq)
dev/relay/ Local relay server config
```
Comment on lines 18 to 23
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a language identifier to the fenced project-structure block.

This currently trips markdownlint MD040.

💡 Suggested fix
-```
+```text
 app/        Web frontend (SolidJS + Vite)
 api/        Backend API (Cloudflare Workers + Hono)
 native/     Desktop/mobile app (Tauri v2)
 dev/relay/  Local relay server config
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.22.0)</summary>

[warning] 18-18: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @README.md around lines 18 - 23, The fenced code block that lists the project
structure (the block containing the lines starting with "app/ Web
frontend (SolidJS + Vite)", "api/ Backend API (Cloudflare Workers +
Hono)", "native/ Desktop/mobile app (Tauri v2)", and "dev/relay/ Local
relay server config") needs a language identifier to satisfy markdownlint MD040;
update the opening fence from totext so the block becomes a labeled
plaintext code block.


</details>

<!-- fingerprinting:phantom:poseidon:hawk:5ca8007f-9d0b-410f-888f-fecd37b49e9a -->

<!-- This is an auto-generated comment by CodeRabbit -->


## Prerequisites

**Required:**
- [bun](https://bun.sh) — package manager and runtime
- [just](https://github.com/casey/just) — command runner
- [Rust](https://rustup.rs) — for the native app and MOQ relay
- [Rust](https://rustup.rs) — for the native app

**Recommended:**
- [Nix](https://nixos.org) + [direnv](https://direnv.net) — handles all dependencies automatically via `flake.nix`

## Getting Started

Clone the repo with submodules:
Clone the repo:

```sh
git clone --recurse-submodules https://github.com/moq-dev/hang.live.git
git clone https://github.com/moq-dev/hang.live.git
cd hang.live
```

Expand All @@ -61,7 +59,7 @@ just dev

- **api** — Cloudflare Workers dev server (via wrangler)
- **app** — Vite dev server on port 1420
- **moq** — MOQ relay server
- **relay** — MOQ relay server

## Commands

Expand All @@ -76,7 +74,7 @@ just dev

## MOQ (Media over QUIC)

The `moq/` directory is a git submodule containing [moq](https://github.com/kixelated/moq) — an open-source library for real-time media streaming over WebTransport and QUIC. It provides the protocol implementation and relay server that Hang uses for low-latency audio/video delivery. See the [moq README](moq/README.md) and [moq.dev](https://moq.dev) for full documentation.
Hang uses [moq](https://github.com/moq-dev/moq) — an open-source library for real-time media streaming over WebTransport and QUIC. The `@moq/*` npm packages provide the protocol implementation, and the `moq-relay` binary (via nix flake) runs the local relay server. See [moq.dev](https://moq.dev) for full documentation.

## License

Expand Down
3 changes: 2 additions & 1 deletion api/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ default:
just --list

dev:
just ../dev/relay/auth-key
bun wrangler d1 migrations apply DB --local
bun wrangler dev --var "RELAY_SECRET:$(cat ../moq/dev/root.jwk)" --var "RELAY_URL:http://${TAURI_DEV_HOST:-localhost}:4443"
bun wrangler dev --var "RELAY_SECRET:$(cat ../dev/relay/root.jwk)" --var "RELAY_URL:http://${TAURI_DEV_HOST:-localhost}:4443"
Comment on lines 9 to +12
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add an explicit preflight check for root.jwk.

Running cd api && just dev fails with a low-context cat error if the key hasn’t been generated yet. A guard here makes local setup failures much clearer.

💡 Suggested patch
 dev:
 	bun wrangler d1 migrations apply DB --local
-	bun wrangler dev --var "RELAY_SECRET:$(cat ../dev/relay/root.jwk)" --var "RELAY_URL:http://${TAURI_DEV_HOST:-localhost}:4443"
+	test -f ../dev/relay/root.jwk || (echo "Missing ../dev/relay/root.jwk. Run: cd dev/relay && just auth-token" >&2; exit 1)
+	bun wrangler dev --var "RELAY_SECRET:$(cat ../dev/relay/root.jwk)" --var "RELAY_URL:http://${TAURI_DEV_HOST:-localhost}:4443"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
dev:
bun wrangler d1 migrations apply DB --local
bun wrangler dev --var "RELAY_SECRET:$(cat ../moq/dev/root.jwk)" --var "RELAY_URL:http://${TAURI_DEV_HOST:-localhost}:4443"
bun wrangler dev --var "RELAY_SECRET:$(cat ../dev/relay/root.jwk)" --var "RELAY_URL:http://${TAURI_DEV_HOST:-localhost}:4443"
dev:
bun wrangler d1 migrations apply DB --local
test -f ../dev/relay/root.jwk || (echo "Missing ../dev/relay/root.jwk. Run: cd dev/relay && just auth-token" >&2; exit 1)
bun wrangler dev --var "RELAY_SECRET:$(cat ../dev/relay/root.jwk)" --var "RELAY_URL:http://${TAURI_DEV_HOST:-localhost}:4443"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/justfile` around lines 9 - 11, The dev justfile target should guard the
cat ../dev/relay/root.jwk call with an explicit preflight check: before invoking
bun wrangler dev, test that ../dev/relay/root.jwk exists (e.g., using [ -f ] or
test -f) and if it’s missing emit a clear error message and exit non-zero; then
read the key into a variable and pass it via --var "RELAY_SECRET:$(cat ...)" and
keep the existing RELAY_URL line unchanged. Locate the dev target in the
justfile and add the existence check and early exit immediately before the bun
wrangler dev invocation so the failure is descriptive rather than a bare cat
error.


build:
bun run build
Expand Down
2 changes: 1 addition & 1 deletion api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
},
"dependencies": {
"@hono/zod-validator": "^0.7.2",
"@moq/token": "workspace:*",
"@moq/token": "^0.1.2",
"drizzle-orm": "^0.44.5",
"hono": "^4.9.4",
"jose": "^6.0.13",
Expand Down
13 changes: 6 additions & 7 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
"scripts": {
"dev": "bunx --bun vite --open",
"build": "bunx --bun vite build",
"check": "tsc --noEmit && biome check && bun run check:shaders",
"check:shaders": "glslangValidator src/room/gl/shaders/*.vert src/room/gl/shaders/*.frag",
"check": "tsc --noEmit && biome check",
"fix": "biome check --fix",
"tauri": "tauri"
},
Expand All @@ -18,11 +17,11 @@
"@fontsource-variable/montserrat": "^5.2.6",
"@hang/api": "workspace:*",
"@huggingface/transformers": "^4.0.0",
"@moq/hang": "workspace:*",
"@moq/lite": "workspace:*",
"@moq/publish": "workspace:*",
"@moq/signals": "workspace:*",
"@moq/watch": "workspace:*",
"@moq/hang": "^0.2.1",
"@moq/lite": "^0.1.7",
"@moq/publish": "^0.2.3",
"@moq/signals": "^0.1.4",
"@moq/watch": "^0.2.3",
"@solidjs/router": "^0.15.3",
"@tailwindcss/vite": "^4.1.12",
"@tauri-apps/api": "^2.8.0",
Expand Down
4 changes: 4 additions & 0 deletions app/src/worklet.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare module "*?worklet" {
const url: string;
export default url;
}
Loading
Loading