khalidadil
  • Joined on 2025-08-25

@khalidadil/filebot-react (0.2.0)

Published 2026-09-26 08:22:53 +00:00 by khalidadil

Installation

@khalidadil:registry=
npm install @khalidadil/filebot-react@0.2.0
"@khalidadil/filebot-react": "0.2.0"

About this package

@khalidadil/filebot-react

React bindings over @khalidadil/filebot-client: a provider that carries the host client and server-signed bucket bases, an <Image> that builds a signed srcset by string concatenation (SSR-safe), a useGallery hook, and useUploader + <Uploader> + <QrUpload> components. No CSS, no data-fetching dependency, no server secrets — the browser only ever sees host-minted grants and signed bases.

Publishes to the private Gitea registry https://git.kadil.dev/api/packages/khalidadil/npm/ (never GitHub), installable with no token.

pnpm add @khalidadil/filebot-react

Peers: react >=18, react-dom >=18. Runtime deps: @khalidadil/filebot-client, @khalidadil/filebot-signing.

Provider and bucket bases

<FilebotProvider> gives the tree a host client (talking to your app's file router) and a map of bucket bases — a bucket uuid → a server-signed base URL plus its ladder and presets, so <Image fileRef> builds a srcset locally with no per-image round trip.

import { FilebotProvider } from "@khalidadil/filebot-react";

<FilebotProvider
  mount="/api/filebot"
  bases={initialBases}                 // seeded from the server render (bucket uuid → BucketBase)
  refreshBases={async () => {
    const r = await fetch("/demo/bases", { method: "POST" }); // YOUR host route (see below)
    return r.json();                    // Record<bucketId, { base, exp, ladder, presets }>
  }}
>
  <App />
</FilebotProvider>

A BucketBase is { base, exp, ladder, presets } where exp is unix seconds (or null for a public bucket).

refreshBases is host-supplied (E-5 / OI-1)

v1 has no built-in host {mount}/bases route — a signed base is a capability, so minting one is your app's authorization decision. You supply refreshBases; the examples/host-app reference implements it as POST /demo/bases. The provider then:

  • schedules a refresh at min(exp) − 300 s;
  • coalesces <Image>-driven requestBaseRefresh() calls (missing/expiring base, or an image onError) over a 1 s window;
  • runs refreshes single-flight — a failure keeps the old bases and the next automatic attempt waits at least 30 s;
  • never lets an incoming base replace a fresher one (a later exp wins; a public exp: null always applies).

Without refreshBases, bases stay exactly as seeded.

<Image>

import { Image } from "@khalidadil/filebot-react";

<Image fileRef={photo.ref} preset="card" maxWidth={640} alt="" />   // srcset from the provider's base
<Image media={signedMedia} alt="" />                                 // a FileMedia the server already signed
<Image src={absoluteSignedUrl} alt="" />                             // an already-built URL

In fileRef mode the srcset is built over bases[bucketId]; when the bucket lacks the requested preset it falls back to a ladder width (w/<n>). On a missing/expiring base or a load error it asks the provider to refresh, once per base.

Hooks and components

const { items, isLoading, loadMore } = useGallery({ identifier: "album:42" });

const up = useUploader({ route: "avatars", maxFilesPerInit: 1 });
<Uploader route="avatars" onUploadAccepted={(e) => setAvatar(e.fileId)} />
<QrUpload route="avatars" />   // renders the QR, streams uploaded/ready counts

useUploader / <Uploader> wrap the client's createUploader; the callbacks (onUploadAccepted, onRejected, onRestored, onFileStatus) and Uppy's pause/resume/retry/remove are the same surface documented in @khalidadil/filebot-client.

SSR

Nothing touches window during render; timers only start in effects, so the provider and <Image> render identically on the server and hydrate cleanly.

Testing

pnpm --filter @khalidadil/filebot-react test runs the component suite under @happy-dom/global-registrator (no services). test/pack.test.ts asserts the published tarball ships dist/** + README.md + package.json only with the exact runtime deps. See Features/SDKs.md in the vault for the full picture.

Release

Part of the five-package lockstep set; packages/filebot-server/scripts/lockstep-check.ts prints (never runs) the gated publish. Publishing needs the lead's go and Khalid's approval.

Dependencies

Dependencies

ID Version
@khalidadil/filebot-client 0.2.0
@khalidadil/filebot-signing 0.2.0

Development Dependencies

ID Version
@happy-dom/global-registrator ^20.14.5
@types/node ^22.10.0
@types/react ^19
@types/react-dom ^19
react ^19.0.0
react-dom ^19.0.0
tsx ^4.19.2
typescript ^5.7.0

Peer Dependencies

ID Version
react >=18
react-dom >=18
Details
npm
2026-09-26 08:22:53 +00:00
0
latest
22 KiB
Assets (1)
Versions (2) View all
0.2.0 2026-09-26
0.1.0 2026-09-18