Skip to content

OxiCloud v0.8.0 — "Airframe"

Latest

Choose a tag to compare

@DioCrafts DioCrafts released this 21 Jun 10:31

🛩️ OxiCloud v0.8.0 — "Airframe"

0.7.0 "Slipstream" taught OxiCloud to move. 0.8.0 "Airframe" rebuilt the thing it moves in.

The entire frontend — every screen, every interaction — was torn out and rebuilt from scratch in SvelteKit. Photos learned where your pictures were taken and who's in them. A plugin runtime opened the door to extending OxiCloud safely. And the upload path was hardened, again and again, until it stopped flinching at anything you throw at it — even named pipes.

This is the airframe release. New skin, new bones, same engine — and a platform that's ready to grow.

Self-hosted. No vendor. No telemetry. Just your data, in a cockpit that was rebuilt around it.

✨ Headline features

🧩 A brand-new frontend — rewritten in SvelteKit (Svelte 5)

The vanilla-JS/CSS app that carried OxiCloud through six releases is gone. The whole UI is now a SvelteKit single-page app — Svelte 5 runes + TypeScript, Vite, adapter-static:

  • Type-safe end to end, code-split and lazy-loaded so the initial bundle is small.
  • An in-memory listing cache, virtualization, and badge batching so big folders paint instantly.
  • A unified API layer (lib/api/endpoints/*), reactive rune stores, and a bespoke i18n that reads the same locale files.
  • The legacy /static app and its tooling were removed entirely.

(#478, #486, #492, #506, #509)

📍 Photos: Places & People

Your library now knows geography and faces:

  • Places — a map view that plots photos by their real capture location, with EXIF GPS recovery via nom-exif when the primary parser rejects a file, and a lightweight world map fallback when no basemap is installed.
  • People — face grouping, paired with a gallery/lightbox polish pass.

(#485, #497, #499)

🧩 WASM plugin system (M0)

The first milestone of an extensibility story: sandboxed, observe-only plugins compiled to WebAssembly, with the CI plumbing (check/clippy/test) to keep them honest. Huge thanks to @BCNelson. (#475, #459)

🗂️ Drives

Groundwork for multiple drives: ReBAC moved into a role-centric model, drives surfaced in the sidebar, and the UI wired to the new shape. (#465, #479, #507)

⬆️ Uploads that don't flinch

The upload path was hardened relentlessly this cycle:

  • Batch dedup-check + instant by-hash uploads — content the server already has uploads with zero bytes on the wire; one request resolves a whole folder.
  • Idempotent re-upload + auto-retry — a partially-uploaded folder self-completes, and re-uploading byte-identical content is a clean no-op instead of a wall of "already exists" errors.
  • Self-aborting watchdog + bounded delta-worker connections — no more stalls or browser connection-pool exhaustion that froze big folder uploads at "93%".
  • Skips non-regular files (FIFOs / sockets / devices) up front — a copied service tree full of named pipes no longer hangs a lane; you get "N uploaded · M skipped (not regular files)".
  • Drag-out-to-OS download + folder drag-drop upload.
  • Version auto-reload — an open tab notices a fresh deploy (_app/version.json polling) and reloads itself, so it never runs stale code after a rebuild.

(#500, #502, #503, plus the upload-hardening sweep on main)

🏎️ Performance

  • Folder listing: in-memory cache + virtualization + badge batching so navigation is instant (#492).
  • Lazy-loaded heavy components shrink the initial bundle (#506).
  • Cache-stampede coalescing (single-flight) on content/transcode/search caches + DB pool safeguards (statement timeout + saturation monitor) (#508).
  • Six measured backend optimizations — downloads, CDC reads, content cache, write path (#462).
  • Batched resource resolution + live-role re-validation on every request (#484).

🔒 Reliability & security

  • CalDAV / CardDAV client connectivity repaired (#481).
  • Blob GC hardened and the content-index worker supervised so it restarts cleanly (#483).
  • The SPA and the Places map boot under a strict CSPscript-src 'self' + per-inline-script SHA-256 hashes + 'wasm-unsafe-eval' for the BLAKE3/FastCDC and map WASM (#495).
  • OIDC providers can be trusted via system certificates (#490, thanks @fkocik).
  • The container starts cleanly for non-root users (#474, thanks @Cilenco).
  • NextCloud login page migrated from build.rs to askama templates (#493).
  • 5 deprecated list endpoints removed, superseded by the cursor-paginated /resources feed (#501).
  • /by-hash works even when the source blob is trashed (#472); i18n locale dir honours OXICLOUD_STATIC_PATH (#468); a sweep of NextCloud/WebDAV bugs found by end-to-end tests (#473).

✅ Tests & CI

End-to-end WebDAV + NextCloud coverage (#450), expanded API tests (#452), a load & benchmark harness (#451), WASM check/clippy/test in CI (#459), front-end test cleanup (#460), and HTTP-log diagnostics targets (#449).

⚙️ Upgrade notes

  • Requires Rust 1.93+ (edition 2024) and PostgreSQL 13+ with pg_trgm and ltree. Migrations apply automatically on startup.
  • The frontend is now SvelteKit, built by Vite into static-dist/ and served by the Rust web layer (unmatched client routes fall back to the SPA shell). The legacy /static app is gone.
  • Strict CSP is on by default (script-src 'self' + per-script hashes + 'wasm-unsafe-eval'); any custom inline scripts you injected will be blocked — add a hash or move them to a file.
  • New surface: an observe-only WASM plugin runtime and multi-drive groundwork.

💛 Thank you — built by the community, again

Edouard Vanbelle (@EdouardVanbelle) — 56 commits this cycle. The Drives foundation and the ReBAC→role-centric move, the end-to-end WebDAV/NextCloud test suite that flushed out a pile of real bugs, the i18n and UI fixes, and relentless polish. Still, simply, a crack. 👑

Bradley Nelson (@BCNelson) — a spectacular first cycle: he kicked off the SvelteKit rewrite and built the sandboxed WASM plugin system (M0). Two of this release's pillars are his. Welcome, and thank you. 🙌

And huge thanks to:

New Contributors

To every self-hoster running OxiCloud on a box in a closet: this one was rebuilt around you. ❤️

Full Changelog: v0.7.0...v0.8.0

What's Changed

  • chore(logs): add specific target for HTTP logs to help diagnostics by @EdouardVanbelle in #449
  • fix(i18n): locale dir based on OXICLOUD_STATIC_PATH by @EdouardVanbelle in #468
  • refactor/ui: fix js types + correct owner display by @EdouardVanbelle in #471
  • feat(by-hash): allow /by-hash even if blob is trashed by @EdouardVanbelle in #472
  • fix(docker) Fix start up for non root users by @Cilenco in #474
  • Add M0 WASM plugin system (sandboxed, observe-only) by @BCNelson in #475
  • fix(nextcloud+webdav) fix bugs found via end to end tests by @EdouardVanbelle in #473
  • Fix broken CI by @EdouardVanbelle in #477
  • feat(drive): prepare drive implementation: move ReBAC into Role centric by @EdouardVanbelle in #465
  • test/prepare load and benchmark test by @EdouardVanbelle in #451
  • fix(dav): repair CalDAV/CardDAV client connectivity (#480) by @DioCrafts in #481
  • Harden blob GC and supervise the content-index worker by @DioCrafts in #483
  • Batch resource resolution and live-role re-validation on every request by @DioCrafts in #484
  • feat: Photos evolution — Places (map) & People (faces) + gallery polish by @DioCrafts in #485
  • Rewrite frontend in SvelteKit — updated to main, with Places/People/Photos ported by @DioCrafts in #486
  • Rewrite frontend in SvelteKit (Svelte 5) by @BCNelson in #478
  • docs(claude): describe the SvelteKit frontend in CLAUDE.md by @DioCrafts in #487
  • Optimize folder listing with caching, virtualization, and badge batching by @DioCrafts in #492
  • Allow the use of system certificates to trust OIDC provider by @fkocik in #490
  • feat/drive impl by @EdouardVanbelle in #479
  • Migrate Nextcloud login page from build.rs to askama templates by @DioCrafts in #493
  • fix: make the SPA boot and Places map work under strict CSP by @DioCrafts in #495
  • fix(ui): remove default link underline from sidebar nav items by @DioCrafts in #496
  • fix(photos): recover EXIF GPS via nom-exif when kamadak-exif rejects the file by @DioCrafts in #497
  • feat(photos): show a lightweight world map in Places when no basemap is installed by @DioCrafts in #499
  • feat(files): drag-out-to-OS download + folder drag-drop upload (#500) by @DioCrafts in #504
  • feat(shares): external-user vignette — avatar, email & internal/external badge (#500) by @DioCrafts in #503
  • feat(files): bookmarkable file-preview URL + multi-drag count ghost (#500) by @DioCrafts in #502
  • refactor(api): remove 5 deprecated list endpoints superseded by /resources by @DioCrafts in #501
  • fix(sidebar): key nav icon colours off data-section, not DOM order by @DioCrafts in #505
  • perf(frontend): lazy-load heavy components to shrink initial bundle by @DioCrafts in #506
  • feat(drive): add drive in side bar + correct some glitch with new UI: by @EdouardVanbelle in #507
  • perf: cache-stampede coalescing + DB safeguards; ui/i18n fixes by @DioCrafts in #508
  • chore(frontend): remove the legacy vanilla-JS frontend and its tooling by @DioCrafts in #509

New Contributors

Full Changelog: v0.7.0...v0.8.0