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

163 lines
5.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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('<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
### 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
- 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):
```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** - 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