VZZK
downloads 56,000+ · broadcasts served 55,600+ (as of 2026-08)
- What
- A desktop bot app for streamers on Chzzk, Naver's live-streaming platform.
- Why
- Reading chat, answering donations and running screen effects while broadcasting is more than one person can hold at once.
- How
- It takes chat and donation events over a socket, runs eleven kinds of bot, and draws the results as a live overlay on the OBS scene — a Tauri v2, Angular and Rust (actix-web) desktop app with a NestJS cloud API.
- New
- Three operating-system builds are published through GitHub Actions, run single-handed without a commercial release service.


- Repositories:
vzzk(desktop app),vzzk-api(cloud API) - Period: first commit 2024-05-22 through today, 2026-08-06
- Two reference dates: numbers from GA4/BigQuery come from the dashboard snapshot of 2026-08-06; numbers from the repos (commits, tags, tests) come from the
vzzk/vzzk-apiworking trees on that same date - USD figures are approximations at an assumed ₩1,400/USD
1. Key numbers
| Metric | Value | Definition / observation window |
|---|---|---|
| Cumulative sessions | 55,193 | Sum of session_start sessions, 2024-07-07 – 2026-08-05, 759 days. Sits on the same per-dimension row structure as DAU, so it isn't fully free of double-counting |
| Avg. DAU, last 30 days | 90.6 | +19.8% against 75.6 a year earlier, +0.6% against 90.1 in the prior 30 days. Sums per-dimension rows, so it's an upper bound, useful for trend comparison |
| 4-week / 8-week retention | 36.7% / 32.3% | Share of a cohort active at least once in that week. The denominator is only the cohort actually observed that long. Week 14 is the furthest observable |
| Errors per session, last 30 days | 0.16% (5 of 3,128 sessions) | Counts only explicitly logged %Fail events — there is no unhandled-exception or crash telemetry. All 5 were chzzk_loginFail; 26 of 30 days had zero errors |
| Donations observed on streams while vzzk was running | ₩30,027,318 (~US$21,400) / 44 streamers | Sum of price on donation events, 2026-05-01 – 2026-08-06, 98 days. This is not vzzk's revenue, and this data can't settle whether vzzk caused these donations |
| Estimated cumulative donations | median ₩254M (~US$181,000), interval ₩116M – ₩401M | Monte Carlo, 10,000 runs. 22 of the 26 months (2024-07 – 2026-04) are backcast from the 98-day observation. This is a sampling-uncertainty interval and excludes error from the backcast assumptions |
| vzzk's own monthly revenue | ₩89,341 (~US$64) | Chzzk channel subscription payout. Identical in 2026-06 and 2026-07 (= zero net subscriber growth). Infrastructure cost about ₩7,000 (server, $5/month). Subscriber data sits outside the analytics pipeline — I can't see churn or renewals |
Other numbers: 82 release tags over 749 days (median 2 days between tags, 72 of them with a published GitHub Release), 1,196 commits, 176 Rust tests and 944 web test cases (coverage was not measured), $0/month for analytics infrastructure (within the BigQuery and GA4 Export free tiers — I didn't instrument usage, and API server and storage costs are not in this figure).
2. What the product can do today
① Every event is handled on the streaming PC — direct integration with third-party desktop apps
Chzzk chat and donation events are received and processed on the streamer's own machine, so vzzk can talk directly to the other broadcast tools running there. It connects to TITS (avatar object-throwing) over a local WebSocket at ws://localhost:42069; TTS is played straight to the OS audio device through Rust rodio, which puts it outside browser autoplay policy and tab focus and lets it route into OBS through a virtual audio cable; song requests spawn yt-dlp as a child process and stream through a local HTTP Range proxy. A hosted web service cannot structurally cross that boundary. The cost is that local access control had to be built by hand (src-tauri/src/local_guard.rs).
② The server holds no streamer identity data — the blast radius of a breach is structurally small
In 2026-07, Chzzk published a streamer advisory about a personal-data breach at an external integrated platform (emails, nicknames, internal user IDs; for some users, legal names, dates of birth, phone numbers, carriers). vzzk-api collects none of those fields. There is no ORM, no migration, and no user table anywhere in the codebase; a viewer session carries only channelId, channelName, and expiresAt, and never a Chzzk access token. Streamer tokens live in the OS credential store on the user's PC, not on the server, and login uses a PKCE exchange code that never puts a token in the deep link. There is no personal-data database to breach in the first place. (Caveat: the remote overlay state read path is still unauthenticated — §8.1.)
③ Tauri distribution and auto-update, self-operated without a commercial service
The part usually solved by a subscription service such as CrabNebula Cloud is built here out of GitHub Actions and object storage alone: a four-platform matrix build (Windows MSI / macOS arm64 and x64 / Linux AppImage), a minisign signature per artifact, a deployment that uploads only the updater manifest with no-cache, automated code-signing certificate renewal with CI secret propagation, and a workflow that verifies release credentials before the release runs. Signed distribution and auto-update run with no subscription fee.
④ A standing environment for making product decisions from data
GA4 events are designed as a three-tier taxonomy — activation, core action, error — exported to BigQuery as a continuous 759-day time series, and baked by 26 queries into a single serverless HTML dashboard. Which bots actually get used, and where users drop off, are answerable as individual questions. That environment is what made a judgment like "on-demand bot conversion of 1.8–7.9%" possible, and it is where the 4 aggregation defects were found.
Proven along the way: a security audit removed 4 symmetric secrets from the shipped binary (HMAC → Ed25519 public-key verification); backward-compatibility paths are retired on observation — 14 consecutive days of zero calls — rather than instinct; and 4 dashboard aggregation defects were found and fixed (including right-censoring in retention, W14 8.2% → 38.4%).
3. My role — solo development and operations
With no reviewer available, holding this scale meant spending time moving judgment out of human memory and into automated gates and conventions committed to the repo.
| Area | What I own |
|---|---|
| Product | Scope for all 11 bots, overlay protocol design, PRO gating policy |
| Client | Angular 17 (Signal state + RxJS events, shared bot base class), Rust (actix-web SSE server, OAuth/PKCE, entitlement verification, keychain) |
| Server | NestJS vzzk-api — remote overlay sync, viewer session encryption, rate limiting, Firebase fallback |
| Release | GitHub Actions 4-platform matrix build, code signing, minisign-signed auto-update, workflow that pre-verifies release credentials |
| Quality | cargo test / Karma tests, purpose-built static lint for overlays, test gates on both PRs and releases |
| Data | GA4 event taxonomy design, BigQuery pipeline, dashboard generator, revenue estimation model |
| Operations | 82 releases, automated annual certificate renewal, infrastructure cost management |
What makes solo work possible: generic base classes and code generation that hold the cost of adding a bot constant (npm run gen:service), auto-generated Rust↔TypeScript type bindings (npm run gen:bindings, 28 commands + 20 types), a custom AST lint for overlay HTML that never passes through a bundler, and 39 rule, workflow, and skill definitions for AI agents — the loading and routing mechanism comes from the agent tooling, and what I wrote are the definition files layered on top.
What I'm leaving on the record: a single-instance architecture with no scaling path opened up, legacy compatibility paths L1–L5 still unremoved, an instrumentation gap in SR pricing (1 of 33,077 events), no observed macOS usage in the wild, a growth plateau running 13 consecutive complete months, and the gap between the scale the technical structure carries and revenue in the ₩80,000s per month. Details in §8 of the full portfolio.