diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..1faf13d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,152 @@ +# 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.)