No description
  • JavaScript 85.8%
  • Python 7.5%
  • CSS 4.5%
  • Nix 1.7%
  • HTML 0.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Nimmo 53f0099c8f
All checks were successful
Build and Push Attic Cache / build (push) Successful in 25s
Handle gallery deletion request failures
2026-09-18 22:01:06 +01:00
.forgejo Build Redview packages in Attic CI 2026-08-12 18:30:44 +01:00
.github Build Redview packages in Attic CI 2026-08-12 18:30:44 +01:00
bdfr-patches Resume jobs and order BDFR downloads 2026-06-06 11:19:31 +01:00
downloaders feat(nix): tunnel rip traffic through userspace proxy 2026-08-12 11:04:52 +01:00
lib remove count from autocomplete: lightweight query + no count in UI 2026-09-18 10:14:12 +01:00
nix Refresh npm dependencies 2026-09-18 21:43:39 +01:00
public Handle gallery deletion request failures 2026-09-18 22:01:06 +01:00
routes remove count from autocomplete: lightweight query + no count in UI 2026-09-18 10:14:12 +01:00
scripts offload sqlite reads to worker threads and add tag indexing script 2026-09-17 22:01:31 +01:00
tests offload sqlite reads to worker threads and add tag indexing script 2026-09-17 22:01:31 +01:00
.dockerignore Improve Docker build caching 2026-05-30 13:57:02 +01:00
.gitignore feat: tag videos via evenly-spaced ffmpeg frame sampling 2026-09-14 09:02:20 +01:00
AGENTS.md chore: convert CLAUDE.md to AGENTS.md, drop outdated manual openapi step 2026-07-06 23:29:21 +01:00
db.js feat: add subreddit themes gallery 2026-07-26 00:02:59 +01:00
docker-compose.amd.yml Build Redview packages in Attic CI 2026-08-12 18:30:44 +01:00
docker-compose.local.yml Build Redview packages in Attic CI 2026-08-12 18:30:44 +01:00
docker-compose.nvidia.yml Build Redview packages in Attic CI 2026-08-12 18:30:44 +01:00
docker-compose.override.yml Split heavy Python deps into cached layers; fix merge duplicate confirm 2026-06-01 17:40:16 +01:00
Dockerfile.amd feat: tag videos via evenly-spaced ffmpeg frame sampling 2026-09-14 09:02:20 +01:00
Dockerfile.cpu feat: tag videos via evenly-spaced ffmpeg frame sampling 2026-09-14 09:02:20 +01:00
Dockerfile.nvidia feat: tag videos via evenly-spaced ffmpeg frame sampling 2026-09-14 09:02:20 +01:00
flake.lock feat: add Nix flake deployment packaging 2026-07-26 12:02:20 +01:00
flake.nix Build Redview packages in Attic CI 2026-08-12 18:30:44 +01:00
LICENSE chore: adopt EUPL-1.2 licence 2026-09-06 16:32:10 +01:00
openapi.base.json feat(review): rework review later from per-image to per-poster 2026-07-06 23:03:51 +01:00
package-lock.json Refresh npm dependencies 2026-09-18 21:43:39 +01:00
package.json Refresh npm dependencies 2026-09-18 21:43:39 +01:00
paseo.json Add Paseo PR workflow instructions 2026-07-26 22:09:54 +01:00
pyrightconfig.json Group media by post when sorting 2026-05-16 19:56:49 +01:00
README.md offload sqlite reads to worker threads and add tag indexing script 2026-09-17 22:01:31 +01:00
report.md Build Redview packages in Attic CI 2026-08-12 18:30:44 +01:00
requirements-amd-torch.txt Split heavy Python deps into cached layers; fix merge duplicate confirm 2026-06-01 17:40:16 +01:00
requirements-amd.txt Split heavy Python deps into cached layers; fix merge duplicate confirm 2026-06-01 17:40:16 +01:00
requirements-cpu.txt Split heavy Python deps into cached layers; fix merge duplicate confirm 2026-06-01 17:40:16 +01:00
requirements.txt Split heavy Python deps into cached layers; fix merge duplicate confirm 2026-06-01 17:40:16 +01:00
scanner.js Restructure media database entities 2026-06-07 08:12:59 +01:00
server.js Add direct URLs for primary views 2026-09-18 21:26:29 +01:00
tagger-amd.py fix: weight tag batches by frame count to avoid CUDA OOM on videos 2026-09-14 09:13:08 +01:00
tagger.py fix: weight tag batches by frame count to avoid CUDA OOM on videos 2026-09-14 09:13:08 +01:00
THIRD-PARTY-NOTICES chore: adopt EUPL-1.2 licence 2026-09-06 16:32:10 +01:00

redview

An offline Reddit media viewer. Browse, slideshow, and tag images and videos downloaded via BDFR or similar tools.

Features

  • Gallery — infinite-scroll grid with search, sorting (newest/oldest/A–Z/random), and active tag filters
  • Slideshow — auto-advances through images (configurable duration) and plays videos to completion
  • Browse by subreddit / poster — sortable by image count or alphabetically; cross-reference modals show which subreddits a user posts in (or which users post in a subreddit), with inline favourite toggles
  • Tag browser — autocomplete search, multi-select tag filters, top-tags grid sortable by count or A–Z
  • Favourites — mark images, users, and subreddits as favourites; bulk-import favourite subreddits or users from a .txt file
  • Block — hide all content from a poster or subreddit; block/unblock from the list view or slideshow; purge blocked content from disk
  • Delete — remove an image from disk directly from the slideshow
  • GPU tagging — WD-ViT Tagger v3 (Danbooru-trained) via ONNX Runtime; tags untagged images or reprocesses everything; videos are tagged via 5 evenly-spaced frames (extracted with ffmpeg) with the tag list merged and deduplicated; batch size auto-detected from available VRAM
  • BDFR Rip — trigger BDFR downloads from within the app; automatically rips all favourited subreddits and users, respecting block lists
  • Auto-scan — configurable folder watch interval

Requirements

  • NixOS with the native flake module (recommended), or Docker + Docker Compose
  • For native NVIDIA deployments, a NixOS NVIDIA driver configuration
  • AMD GPU with ROCm support (/dev/kfd, /dev/dri) for the legacy AMD Compose configuration (see Setup)

Setup

The native NixOS deployment is the supported production path. Docker Compose files remain available for local or legacy deployments; build their images locally because this project no longer publishes Docker images. For NixOS, see Native NixOS deployment.

1. Clone the repo

git clone <repo-url>
cd redview

2. Configure environment

Create a .env file:

NAS_IP=192.168.1.100
NAS_MEDIA_PATH=/volume1/your/share
HF_TOKEN=          # optional — only needed for gated HuggingFace models

The compose file mounts an NFS share using NAS_IP and NAS_MEDIA_PATH. To use a local path instead, remove the NFS volume block and bind-mount directly:

volumes:
  - /path/to/your/media:/media

3. Start

Use the compose file matching your GPU:

# AMD
docker compose -f docker-compose.amd.yml up -d

# NVIDIA
docker compose -f docker-compose.nvidia.yml up -d

The app is available at http://localhost:3210.

Native NixOS deployment

The flake exports a native NixOS module. It runs Node.js and the Python workers directly under systemd; no container runtime is involved. Add the repository as a flake input and enable the service in a host configuration:

{
  inputs.redview.url = "git+ssh://git@git.nimmog.uk/nimmo/redview";

  # In nixosConfigurations.<host>.modules:
  ({ pkgs, ... }: let
    redviewNvidia =
      inputs.redview.packages.${pkgs.stdenv.hostPlatform.system}.redview-nvidia;
  in {
    imports = [ inputs.redview.nixosModules.default ];
    services.redview = {
      enable = true;
      accelerator = "nvidia";
      mediaDir = "/mnt/media";
      package = redviewNvidia;
      pythonEnvironment = redviewNvidia.passthru.pythonEnvironment;
    };
  })
}

The module creates a dedicated service account and persistent directories for the database, model cache, media, and BDFR configuration. cpu uses the default nixpkgs ONNX Runtime environment. For amd, provide a Python environment containing the native AMD TheRock torch/torchvision wheels plus onnx, onnx2torch, Pillow, NumPy, and Hugging Face Hub. For nvidia, provide an environment containing onnxruntime-gpu and its CUDA runtime. environmentFiles or environment.HF_TOKEN can provide optional Hugging Face authentication.

The native package is built on commits to main and pushed to the shared nixos Attic cache. The default redview package is the CPU application; redview-nvidia is the CUDA runtime bundle for an RTX 4070 (SM 8.9), including the Python tagging and BDFR environment used by Lyra. Consumers need the cache configured, for example:

{
  nix.settings = {
    substituters = [ "https://attic.nimmog.uk/nixos" ];
    trusted-public-keys = [ "nixos:tNn8ouVBQkqLS2qTq86V50TCL1AGn2NgwEhpxReo6jU=" ];
  };
}

Docker (legacy): the supplied Compose files build their local image. Start them with docker compose -f docker-compose.nvidia.yml up --build -d (or substitute docker-compose.amd.yml).

First run

  1. Go to Settings → add /media (or a subfolder) as a gallery folder
  2. Click Scan All Folders Now — indexes all media into the database
  3. Optionally go to Settings → Image Tagging → click Tag Untagged Images to run the GPU tagger

The tagger downloads the WD-ViT Tagger v3 model (~350 MB) on first use and caches it in the redview-data directory.

File naming convention

Filenames are expected to follow the BDFR format:

REDDITOR__post-title__postID.ext

The poster name is parsed from everything before the first __ (double underscore). Subreddits are inferred from the subfolder name within the library root.

Environment variables

Variable Default Description
PORT 3000 Internal server port
DATA_DIR /data Database and model cache location
TAG_THRESHOLD 0.35 Minimum confidence for a tag to be kept (0–1)
TAG_BATCH_SIZE auto Override auto-detected GPU batch size
TAG_VIDEO_FRAMES 5 Frames extracted per video (evenly spaced) for tagging
HF_TOKEN — HuggingFace token for gated model access
REDDIT_ACCESS_TOKEN — Optional Reddit OAuth bearer-token override for fetching subreddit descriptions. By default Redview reuses BDFR's authenticated OAuth configuration from ~/.config/bdfr.
BDFR_CONFIG_PATH BDFR's config.cfg or default_config.cfg Optional path to BDFR's OAuth configuration file when it is not in the standard location

Large library tag index

For a large, existing database, build the covering tag filter index once during a maintenance window. Stop Redview's writers first and allow room for SQLite to build the index. Supply the actual database path explicitly:

npm run db:index-tags -- --db /var/lib/redview/redview.db

The command verifies the index and is safe to run again. SQLite stores it in redview.db, so it survives service restarts and does not rebuild at startup. Normal startup does not create this optional index on an existing library.

API

All endpoints are available at http://localhost:3210. Useful for external tools (e.g. BDFR post-processing scripts).

Authentication

All API and media endpoints require an X-Api-Key header (or ?api_key= query parameter). The key is generated on first start and shown in the server logs. It can also be found in Settings → API Key.

curl -s http://localhost:3210/api/favourites \
  -H 'X-Api-Key: your-key-here'

Favourites

Method Endpoint Body / Query Description
GET /api/favourites ?type=subreddit|poster List all favourites (optionally filtered by type)
POST /api/favourites { type, value } Add a single favourite
DELETE /api/favourites { type, value } Remove a single favourite
POST /api/favourites/bulk { type, values: [] } Add multiple favourites (duplicates ignored)

Blocked

Method Endpoint Body / Query Description
GET /api/blocked — List all blocked entries
POST /api/blocked { type, value } Block a single user or subreddit
DELETE /api/blocked { type, value } Unblock by type and value
DELETE /api/blocked/:id — Unblock by entry ID
POST /api/blocked/bulk { type, values: [] } Block multiple entries (duplicates ignored)
GET /api/blocked/purge — Preview purge: returns counts of files that would be deleted
POST /api/blocked/purge — Delete all files belonging to blocked users/subreddits from disk and database

type is "subreddit" or "poster" in all cases.

Cross-reference

Method Endpoint Description
GET /api/posters/:poster/subreddits Subreddits a user has media in, with counts and favourite status
GET /api/subreddits/:subreddit/posters Users who have media in a subreddit, with counts and favourite status

Examples

Mark a list of subreddits as favourites:

curl -s -X POST http://localhost:3210/api/favourites/bulk \
  -H 'X-Api-Key: your-key-here' \
  -H 'Content-Type: application/json' \
  -d '{"type":"subreddit","values":["pics","videos","aww"]}'

List all favourite subreddits:

curl -s http://localhost:3210/api/favourites?type=subreddit \
  -H 'X-Api-Key: your-key-here'

Stack

  • Backend — Node.js, Express, better-sqlite3 (SQLite WAL mode); routes split across routes/ by domain
  • Frontend — Vanilla JS SPA, no build step
  • Tagger (NVIDIA) — Python, native ONNX Runtime CUDA bundle, built for SM 8.9
  • Tagger (AMD) — Python, PyTorch ROCm via TheRock, ONNX Runtime, Pillow, HuggingFace Hub; base image ubuntu:24.04

Licence

Copyright (c) 2026 Redview contributors. Licensed under the EUPL-1.2.

Redview's original code is licensed under the European Union Public Licence 1.2 (EUPL-1.2).

This repository also contains or builds with third-party software that remains under its own licence. See THIRD-PARTY-NOTICES for the important exceptions, including the GPLv3 BDFR integration and the Apache-2.0 WD-ViT model downloaded at runtime.