All projects
SampleSample · unsupportedUnsupported · no SLA

Immich B2 Backend

Self-hosted, Immich-style photo-library backend that stores originals, thumbnails, CLIP embeddings, smart tags, and EXIF sidecars on Backblaze B2 via the S3-compatible API. CLIP semantic search and smart tags are powered by real OpenCLIP (ViT-B-32/openai). FastAPI + Next.js sample.

Built for: Privacy-conscious self-hosters who want full ownership plus unlimited archival capacity on B2, and AI engineers who want a reference for a media pipeline whose storage layer is Backblaze B2.

MIT licensed · Updated Aug 18, 2026

Dashboard with photo count, write-amplification ratio, storage-by-prefix breakdown and ML status
The dashboard shows the photo count, total bytes on B2, the write-amplification ratio, a storage-by-prefix breakdown, and CLIP ML status.

What it's built with

Each piece of the stack, and the job it does in this project.

Next.js 16 + React 19
Web frontend for the library, search, upload, and dashboard screens
Tailwind CSS v4 + shadcn/ui
Design tokens and reusable interface primitives
TanStack Query
Client-side data fetching, caching, dedup, and retry
FastAPI + Pydantic v2
Typed Python API with a layered architecture and validated boundaries
boto3 + Backblaze B2
S3-compatible object storage access, isolated in the repo layer
Pillow
EXIF/metadata extraction and thumbnail generation
OpenCLIP (open-clip-torch, ViT-B-32/openai) + torch
Optional on-device engine for CLIP embeddings, smart tags, and semantic search
pnpm workspaces
TypeScript and Python monorepo workflow

Core capabilities

What the project does out of the box, before you write any code of your own.

  • Photo ingest with a real B2 fan-out

    Each uploaded original goes straight to B2, then fans out into thumbnails and an EXIF sidecar (always), plus a CLIP embedding and smart tags when the optional ML layer is installed — every derivative landing under Immich-style structured prefixes.

  • CLIP semantic search and smart tags

    Natural-language search and zero-shot smart tags run on real OpenCLIP (open-clip-torch, model ViT-B-32/openai) — Immich's own default model — cosine-ranked against embeddings stored in B2.

  • Library gallery with full asset detail

    A library/-scoped gallery opens each photo to its original, thumbnails, tags, EXIF, and embedding status, with edit, re-run ML, and delete actions.

  • B2 as the single source of truth

    Originals, ML artifacts, previews, and metadata all persist to B2 over the S3-compatible API, with no separate database — the library is reconstructed by listing the sidecar/ prefix.

  • Write-amplification dashboard and file explorer

    The dashboard surfaces the exact write-amplification ratio and storage-by-prefix breakdown, and a reusable full-bucket file explorer browses every prefix.

  • Layered, agent-ready reference

    A strictly layered FastAPI backend with structural tests, a checked OpenAPI contract, and agent-optimized docs so an AI coding agent can read the repo and start contributing immediately.

A closer look

More screens from the running project.

Library gallery of photos scoped to the library/ prefix
The Library gallery is scoped to the library/ prefix, with every card marked "AI tagged" and favorites flagged.
Asset detail dialog with original, smart tags, EXIF, description and embedding
Asset detail shows the original, CLIP smart tags with scores, EXIF, an editable description and tags, and the ViT-B-32/openai embedding, all living on B2.
Semantic search results ranked by CLIP similarity score
Semantic search embeds a natural-language query with the same on-device CLIP model and cosine-ranks it against the embeddings stored in B2, with a score on each result.
Upload page with a drag-and-drop dropzone for photos
Upload is drag-and-drop ingest that sends each original straight to B2, then fans it out into thumbnails, an EXIF sidecar, a CLIP embedding, and smart tags.

Choose it for the right job

Immich B2 Backend is a head start for a specific shape of project, not a supported, general-purpose product.

Use it when

  • You want a working reference for a media pipeline whose storage layer is B2: ingest, derivative fan-out, on-device ML, and semantic search, all persisting over the S3-compatible API.
  • You want to store a whole photo library — originals plus thumbnails, ML artifacts, and metadata sidecars — on B2 rather than in a database or on local disk.
  • You want semantic search and smart tags on your library from a real OpenCLIP engine you run yourself, on CPU by default with GPU/MPS auto-detected.
  • You want a faithful, minimal model of how Immich uses external object storage, with production-minded controls (strict architecture, contract checks, tests) to build on.

Choose another path when

  • You need a complete, hosted photo service: this provides no managed hosting, user accounts, or authentication, and is single-tenant (user_id="demo").
  • You need face recognition, video transcoding, or multi-tenant isolation out of the box — these are documented extension points, deliberately scoped out.
  • You expect production security, operations, capacity, and compliance decisions to be made for you rather than owned before you adapt it.
  • You only need generic file uploads and object storage without the ML pipeline — the Vibe Coding Starter Kit is a lighter starting point.
Sample · unsupported

Project status and support

Report issues through GitHub Issues on the repository; this sample is provided as-is with no service-level agreement.