# 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 ```bash # 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('', '', '') >>> 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 ### Gallery Data Flow **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 - MIME-type validation via `filetype` library **Batch pre-generation:** - `python manage.py makethumbnails` command available - Useful for initial setup or after adding many images ## Configuration ### Required Local Settings Create `NibasaViewer/local_settings.py` (not in git): ```python 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** - MIME-type detection - **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 `filetype.is_image(str(path))` to validate image files - Supports common formats (JPEG, PNG, GIF, WebP, etc.)