Skip to content
ZERONE
Nazad na Insights
Arhitektonski patterni2026-07-06 · 8 min čitanja

Anatomy of a Blender add-on that speaks OAuth and REST — without freezing the UI

Blender's bpy API runs on the main thread. A blocking HTTP call for a 500 MB .blend upload leaves Blender 'not responding' for 90 seconds — most users kill the process. Fix: background worker with a timer callback into the main thread, plus OAuth device flow (no browser callback needed).

Our zer0one-blender-addon (on GitHub) adds a `File → Send to ZER0ONE Lab` menu to Blender. Click and the current scene ships to the Cinema Render backend. First version took ~2 weeks — the first days every iteration came back with "Blender not responding". Three problems to solve, typical for any Blender add-on that talks to external APIs.

Problem 1: auth flow without a browser callback

Standard OAuth: user clicks login, browser opens, provider redirects back to `localhost:8080/callback`, app reads the code. Works for web apps. In Blender it doesn't — you can't reliably start an HTTP server in the Blender process (breaks on Windows firewalls, macOS sandbox, various Linux distros).

Clean solution: OAuth 2.0 Device Flow (RFC 8628). Add-on posts to `/oauth/device/code`, server returns `device_code` + `user_code` + `verification_uri`. Add-on shows the user: "open `https://zer0onelab.com/device\` and enter code `ABCD-1234`". User does it from any device — phone, another laptop. Add-on polls `/oauth/token` every 5 seconds until server returns the access token.

No browser callback, no HTTP server in Blender. Works on studio render machines that don't have a browser.

Implementation note: Blender's embedded Python doesn't ship `requests`, but `urllib.request` covers all OAuth calls. Saves a dependency-bundle question.

Problem 2: async without asyncio (bpy doesn't play nice with asyncio)

Blender runs Python in the main thread. `bpy.ops` and scene modifications must be on the main thread. Background-thread calls to bpy either crash or produce undefined behaviour.

A 500 MB upload at 100 Mbps takes ~45 seconds. On the main thread, Blender is hard-frozen. Users kill the process.

Pattern: an `UploadThread` in the background does the blocking upload with progress callback. Blender-side we register `bpy.app.timers.register(status_poll)` — Blender calls the callback in the main thread every 200 ms. Background thread does the work, timer syncs status back. No asyncio needed, no bpy race conditions.

Problem 3: chunked upload and retry

500 MB uploads over flaky WiFi drop after 3 minutes with connection reset. User has to restart. After the third time the add-on gets uninstalled.

Fix: chunked upload with resume token. 8 MB blocks per HTTP PUT. Server remembers the last successful block index. On reconnect the add-on asks for the last received block and continues from there. We implement it over Cloudflare R2's S3-compatible multipart upload — ~120 lines of client-side code, zero server-side special code.

What else we learned

  • Blender 4.2+ has a new extensions system. Old zip format still works, but new add-ons should ship the extensions manifest so Blender can distribute via the Extensions Marketplace. That's the SEO channel for Blender add-ons.
  • Version compatibility is a committee. A 4.2 add-on usually runs in 4.3, often not in 5.0. Our `bl_info` block lists exact supported versions.
  • Users love a changelog in the add-on itself. We show a short "what's new" popup on first launch after an update. Reduces support tickets noticeably.

Meta-lesson

A good Blender add-on differs from a bad one in three details: auth without a browser (device flow), uploads without freeze (background thread + timer callback), errors with recovery (chunked + resume). All three are standard distributed-systems patterns from web dev but rarely done cleanly in the Blender ecosystem. Do them properly and you stand out from 80 % of cloud integrations in the Blender world.

Full add-on is open source on GitHub, MIT-licensed. It's one of the client layers of ZER0ONE Lab Cinema Render.

Sličan požar?

Verovatno smo već videli nešto slično. Javite se.

Započni razgovor