Quick Answer: HGhub is an open-source, Chinese-language HGhub Tauri client that runs on Windows and Android. It pairs a Rust backend (reqwest, rustls) with a React 19, TypeScript, and Vite 7 frontend, and it plays HLS streams through hls.js. You build it with pnpm app:build for an NSIS installer or with the Gradle-based Android pipeline. The project is for learning and technical study only.

If you've been looking at the HGhub repository on GitHub and wondering how a small team wires Rust, a WebView, and a video player into one codebase, this walkthrough covers the architecture, the toolchain, and the build problems you're likely to hit. Most write-ups stop at "install dependencies and run." The real friction shows up in the environment, not the code.

Why Tauri 2 instead of Electron

Tauri 2 uses the operating system's native WebView rather than bundling Chromium. On Windows that's WebView2, and on Android it's the system WebView. The practical result is that Tauri installers are far smaller than typical Electron builds, because you aren't shipping a full browser engine with every app.

The trade-off is that you inherit WebView differences. Video codecs, CORS behavior, and media-element quirks vary between WebView2 and Android's WebView. That's why this project routes media through its own Rust-side layer instead of letting the WebView fetch everything directly. Here's the rule of thumb: if your app streams video, plan for the WebView to be the least predictable part of your stack.

The layout: frontend thin, Rust does the heavy lifting

The repository splits cleanly into two halves. The src/ folder holds the React frontend, with api.ts for command wrappers, store.tsx for global state such as navigation stack, user, local favorites, and theme, and components/ for the player surface and controls. The src-tauri/src/ folder holds the Rust side: net.rs for the request layer with retries, api.rs for business commands, media.rs for image decryption, HLS proxying, and caching, and session.rs for token persistence.

This split matters for a specific reason. Anything that touches the network, credentials, or binary data stays in Rust, where you control headers, timeouts, and error types. The frontend only sees clean, typed results. If you're building your own Tauri app, copy that boundary: keep secrets and raw bytes out of JavaScript.

The README also describes a custom protocol scheme. On Windows it's http://hg.localhost/*, and on Android it's https://hg.localhost/*. The scheme is generated per platform in Rust because a hardcoded value can fail to resolve inside the WebView. Here's where most people get stuck: they copy a protocol string from a Windows example and find that Android silently refuses to load media.

Building for Windows: the easy path

The desktop path is short. Run pnpm install, then pnpm app:dev for hot reload, and pnpm app:build to produce an NSIS installer. You need Rust (the README mentions the 1.9x line) and Node with pnpm.

Most failures on this path trace back to the filesystem. If your project sits on an exFAT drive, which doesn't support symbolic links, pnpm install fails with an ERR_PNPM_EISDIR error about a symlink. The fix in the repo is to keep node-linker=hoisted in .npmrc. That tells pnpm to flatten node_modules instead of creating links.

The second gotcha is esbuild. Recent pnpm versions block dependency build scripts by default, so vite build can fail with a missing binary. The project lists esbuild under pnpm.onlyBuiltDependencies in package.json to allow it. If you see a missing-binary error, check that allowlist before you reinstall anything.

Building for Android: where most time goes

Android is the harder target. You need the Android SDK and NDK, plus JDK 17. The README expects ANDROID_HOME, NDK_HOME (which points to $ANDROID_HOME/ndk/<version>), and JAVA_HOME to be set. Missing any one produces a "cannot find SDK or NDK" error that doesn't always name the variable it wants.

The workflow runs in three stages: pnpm android:init generates the Gradle project once, pnpm android:dev deploys to a device or emulator, and pnpm android:build outputs an APK. The first stage is the one people skip past. It creates src-tauri/gen/android, and everything later depends on that folder existing.

Here's the counter-intuitive part. On an exFAT drive, tauri android build can fail with Failed to create a symbolic link ... jniLibs, even though your code is fine. The README's workaround is manual: compile the Rust library for aarch64-linux-android, copy libhuangguo_client_lib.so into src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a/, and run Gradle directly with ./gradlew assembleDebug. It works, but you now own a step the tooling normally handles. Move the project to an NTFS or ext4 drive if you can. That's the fix that removes the whole class of errors.

Video playback: why HLS needs a proxy layer

The player uses hls.js to handle HLS streams, including AES-128 encryption. Plain playback in a browser-like context is easy. Playback inside a Tauri WebView gets harder because the media requests have to pass CORS checks and whatever referrer rules the origin enforces.

The project's answer is a Rust proxy. The media.rs module forwards playlists and segments through the custom protocol and rewrites key and segment URLs so the WebView requests only the local scheme. The cost is that every segment passes through your process, so you pay in memory and CPU, and you need a cache policy. Treat the proxy as part of your streaming pipeline, not a trick you add once and forget.

Don't skip the caching decision. Without a bounded cache, long playback sessions grow memory steadily on mobile devices, where the OS will kill background apps aggressively.

Trade-offs and what to watch for

Before you adopt this architecture for your own project, weigh these honestly:

ConcernTauri 2 (this project)ElectronNative (Kotlin / C#)
Installer sizeSmall, uses system WebViewLarge, bundles ChromiumSmallest per platform
Desktop and Android from one codebaseYes, with separate build setupsDesktop only by defaultNo, separate codebases
Media behaviorVaries by WebView engineConsistent ChromiumFull control via native players
Build complexityHigh on Android (SDK, NDK, Gradle)ModerateHigh, but familiar per platform

The table shows why the stack is attractive for a two-platform client. It also shows the cost: you trade consistency for size and reach. If your app's core job is consistent, high-performance video, a native player may serve you better.

The project itself carries a clear legal framing. Its README says it doesn't store or distribute audio or video, that the source content comes from third-party sites, and that users are responsible for compliance where they live. Treat that as a reminder to evaluate any app's licensing and content rights before you build on or deploy it.

Frequently Asked Questions

What is HGhub Tauri client?

HGhub is an open-source, Chinese-language third-party client built with Tauri 2, Rust, and React 19. It targets Windows and Android, uses hls.js for HLS playback, and is published on GitHub under the MIT license. The project describes itself as intended for learning and technical exchange.

How to build the HGhub Tauri client on Windows?

Install Rust, Node, and pnpm, then run pnpm install followed by pnpm app:build to create an NSIS installer. If you're on an exFAT drive, keep node-linker=hoisted in .npmrc, because symbolic links aren't supported there. Use pnpm app:dev for hot reload during development.

Why does the Tauri Android build fail on exFAT?

exFAT doesn't support symbolic links, so Tauri's jniLibs step can fail with a symlink error even when your code compiles. Copy the Rust .so file into jniLibs/arm64-v8a/ manually and run ./gradlew assembleDebug. Moving the project to NTFS or ext4 removes the problem entirely.

Is Tauri 2 better than Electron for video apps?

It depends on what you prioritize. Tauri 2 produces much smaller installers and supports Android from the same codebase, but media behavior depends on each platform's WebView. Electron offers more consistent Chromium behavior at the cost of a larger bundle. Test playback on every target before you commit.

Start by cloning the repository and running pnpm app:dev on your own machine, then note which step fails first and why. Pass this to anyone wrestling with a Tauri Android build on exFAT, and they'll save an afternoon.