Files
NibasaViewer/CLAUDE.md
Miguel Astor 078eb25b66 Updated CLAUDE.md to reflect performance optimizations.
Updated documentation to reflect recent changes:
- Changed image detection from MIME-type to extension-based
- Added Performance Optimizations section explaining the change
- Updated Code Patterns to use is_image_file() instead of filetype
- Marked filetype as legacy dependency (no longer actively used)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-27 01:48:13 -04:00

5.2 KiB
Raw Permalink Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Nibasa Viewer is a lightweight, pure HTML+CSS gallery viewer designed for compatibility with older browsers. It uses Django as a backend framework but serves images directly from the filesystem rather than using database models.

Key Design Principles:

  • Filesystem-first architecture (no image/folder models in database)
  • No JavaScript or modern frontend frameworks
  • Broad browser compatibility (uses HTML tables, not flexbox/grid)
  • Dark theme optimized for image viewing
  • Lazy thumbnail generation with on-disk caching

Development Commands

# Install dependencies
pip install -r requirements.txt

# Run development server
python manage.py runserver

# Create user for gallery access (required)
python manage.py shell
>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user('<USERNAME>', '<EMAIL>', '<PASSWORD>')
>>> user.save()
>>> exit()

# Pre-generate all thumbnails (optional, done on-demand otherwise)
python manage.py makethumbnails

# Django admin commands
python manage.py migrate
python manage.py createsuperuser
python manage.py collectstatic

Architecture

Single App Structure

The project has one Django app: viewer. All gallery functionality is consolidated here:

  • views.py - Gallery directory browsing and image viewing (viewer/views.py:65-189)
  • utils.py - Thumbnail generation helpers
  • templates/ - Pure HTML templates (no JavaScript)
  • static/ - CSS styling and navigation icons

Filesystem as Data Source:

  • Images served from GALLERY_ROOT path (configured in local_settings.py)
  • Thumbnails cached in THUMBNAILS_ROOT path
  • No database models for images or directories
  • Directory structure navigated using Python's pathlib

Static File Routing:

  • /imgs/ → Original images from GALLERY_ROOT
  • /thumbs/ → Cached thumbnails from THUMBNAILS_ROOT
  • /static/ → CSS and navigation icons

Authentication

Uses Django's built-in django.contrib.auth system:

  • All gallery views protected with @login_required decorator
  • Users manually created via Django shell (no signup form)
  • Database only stores user accounts (SQLite)
  • Login/logout redirects configured in NibasaViewer/settings.py:108-110

View Logic

gallery_view() function (viewer/views.py:65-189) handles both:

  1. Directory browsing when path points to folder:

    • Lists subdirectories and images
    • Supports search with recursive directory scanning (viewer/views.py:32-52)
    • Paginates images at 28 per page (7 columns × 4 rows)
    • Converts flat image lists to table rows for HTML rendering
  2. Image viewing when path points to file:

    • Displays single image with prev/next navigation
    • Finds sibling images in same directory
    • Links to full-resolution image

Thumbnail Generation

Lazy generation approach (viewer/utils.py):

  • Thumbnails created on-demand when viewing gallery
  • 128×128 pixel size (hardcoded)
  • Uses Pillow for image processing
  • Fast extension-based image detection (no MIME-type I/O)

Batch pre-generation:

  • python manage.py makethumbnails command available
  • Useful for initial setup or after adding many images

Performance Optimizations

Extension-based image filtering (viewer/utils.py:17-27):

  • Uses is_image_file() helper that checks file extensions instead of reading file contents
  • Supported extensions defined in IMAGE_EXTENSIONS constant
  • Eliminates ~99% of I/O operations when listing directories
  • Significantly faster than MIME-type detection for large directories

Configuration

Required Local Settings

Create NibasaViewer/local_settings.py (not in git):

from pathlib import Path

GALLERY_ROOT = Path('/path/to/your/images')
THUMBNAILS_ROOT = Path('/path/to/thumbnail/cache')

# Production settings
DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com']
SECRET_KEY = 'your-secret-key'

Pagination Constants

Defined in viewer/views.py:23-25:

  • CELLS_PER_ROW = 7 - Image grid columns
  • ROWS_PER_PAGE = 4 - Image grid rows
  • IMAGES_PER_PAGE = 28 - Total images per page

Production Deployment

Systemd service files included for Gunicorn deployment:

  • nibasaviewer.service - Service configuration
  • nibasaviewer.socket - Socket activation

Default production location: /var/lib/NibasaViewer

Dependencies

  • Django 4.2.3 - Web framework
  • Pillow 10.0.0 - Image processing (thumbnails)
  • filetype 1.2.0 - Legacy dependency (no longer actively used)
  • gunicorn 21.2.0 - WSGI server (production)

Code Patterns

Template rendering:

  • All views use render(request, template, context)
  • Context includes pagination data, image paths, and navigation state

Path handling:

  • Use pathlib.Path for all filesystem operations
  • Convert to relative paths for URLs: image.relative_to(settings.GALLERY_ROOT)
  • Gallery URLs follow pattern: /gallery/{relative_path}

Image filtering:

  • Use is_image_file(path) from viewer.utils to validate image files
  • Fast extension-based detection (checks IMAGE_EXTENSIONS set)
  • Supports common formats: JPEG, PNG, GIF, WebP, BMP, TIFF, SVG
  • Accepts both pathlib.Path and string paths