jhodgkin 4ac34ca943
Deploy to Dev / Deploy & Smoke Test (push) Successful in 23s
Add admin config screen (issue #14)
Lets the photographer edit config/site.json from /dashboard instead
of SSHing in and hand-editing the file. Two tiers:
- Quick-edit form for the fields actually touched day to day (site
  title/tagline/hero, photographer bio, contact/social, Venmo
  username, session pricing, theme colors)
- Raw JSON textarea for everything else (portfolio categories,
  locations, session types, Immich settings) - the form's fields are
  a subset of this, not a separate source of truth

Backend: GET/PUT /api/admin/config, gated by the existing requireAdmin
middleware (OIDC admin session or legacy ADMIN_SECRET). PUT validates
the body is an object with the required top-level sections, writes
atomically (temp file + rename), and keeps one prior version as
site.json.bak before overwriting.

Required a docker-compose.yml change: the api service had no volume
mount for config/ at all before this (only portfolio/nginx did, and
read-only) - added a read-write mount so the API can actually write
the file the live site reads.
2026-07-20 06:37:20 +00:00
2026-07-20 06:37:20 +00:00
2026-07-20 06:37:20 +00:00
2026-07-20 06:37:20 +00:00

LisiLou Photography Portfolio

A lightweight, configurable photography portfolio website designed to integrate with Immich for image hosting and client gallery access.

Features

  • 🎨 Elegant, modern design - Clean photography-focused aesthetic
  • ⚙️ Easy configuration - Update content via JSON files, no code changes needed
  • 📱 Fully responsive - Looks great on all devices
  • 🖼️ Immich integration - Direct links to shared albums for portfolio and client galleries
  • 👥 Multi-photographer support - Configure multiple profiles for different photographers
  • 🐳 Docker ready - Easy deployment with Docker and Docker Compose
  • 🔄 CI/CD ready - Gitea Actions workflow included

Quick Start

Local Development

  1. Clone this repository
  2. Customize config/site.json with your information
  3. Add your images to public/images/
  4. Run with Docker:
docker compose up -d
  1. Visit http://localhost:8080

Configuration

All site content is configured through config/site.json. Here's what you can customize:

Site Settings

{
  "site": {
    "title": "Your Photography Name",
    "tagline": "Your tagline here",
    "description": "SEO description"
  }
}

Social Media

{
  "social": {
    "instagram": "your.handle",
    "facebook": "yourpage",
    "pinterest": "yourprofile",
    "tiktok": "yourhandle"
  }
}

Immich Integration

{
  "immich": {
    "baseUrl": "https://photos.yourdomain.com",
    "publicAlbumPrefix": "/share/"
  }
}

Portfolio Categories

{
  "portfolio": {
    "categories": [
      {
        "id": "seniors",
        "name": "Senior Portraits",
        "description": "Celebrate your milestone",
        "coverImage": "/images/portfolio/seniors-cover.jpg",
        "immichAlbumId": "your-immich-album-share-id"
      }
    ]
  }
}

Theme Customization

{
  "theme": {
    "primaryColor": "#8B7355",
    "accentColor": "#D4C5B5",
    "textColor": "#2C2C2C",
    "backgroundColor": "#FDFBF9"
  }
}

Adding Portfolio Images

  1. Create cover images for each portfolio category
  2. Place them in public/images/portfolio/
  3. Update the coverImage paths in config/site.json
  4. Get the share IDs from your Immich albums and add them to immichAlbumId

Clients can enter their gallery code (Immich share ID) on the website. They'll be redirected to their Immich shared album.

Workflow:

  1. Create a shared album in Immich for your client
  2. Give them the share ID as their "gallery code"
  3. They enter it on your website and are taken directly to their photos

Deployment

With Docker Compose

  1. Copy files to your server:
scp -r . user@server:/opt/lisilou-portfolio/
  1. Create the external network:
docker network create web
  1. Start the container:
cd /opt/lisilou-portfolio
docker compose up -d

With Reverse Proxy (Traefik/Nginx)

If using Traefik, add labels to docker-compose.yml:

services:
  portfolio:
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.portfolio.rule=Host(`lisilou.com`)"
      - "traefik.http.routers.portfolio.tls=true"
      - "traefik.http.routers.portfolio.tls.certresolver=letsencrypt"

Gitea Actions CI/CD

  1. Set up Gitea Actions on your Gitea instance

  2. Add these secrets to your repository:

    • REGISTRY_USERNAME - Container registry username
    • REGISTRY_PASSWORD - Container registry password
    • DEPLOY_HOST - Your server hostname
    • DEPLOY_USER - SSH username
    • DEPLOY_KEY - SSH private key
  3. Update .gitea/workflows/deploy.yml with your registry URL

  4. Push to main branch to trigger automatic deployment

Multi-Photographer Support

To support multiple photographers:

  1. Create additional config files (e.g., config/photographer2.json)
  2. Update config/profiles.json:
{
  "profiles": {
    "lisilou": {
      "enabled": true,
      "domain": "lisilou.com",
      "configFile": "site.json"
    },
    "photographer2": {
      "enabled": true,
      "domain": "photographer2.com",
      "configFile": "photographer2.json"
    }
  },
  "defaultProfile": "lisilou",
  "multiTenant": true
}
  1. Add multi-tenant routing to nginx.conf (or use separate containers)

File Structure

lisilou-portfolio/
├── config/
│   ├── site.json          # Main configuration
│   └── profiles.json      # Multi-profile config
├── public/
│   └── images/
│       ├── portfolio/     # Portfolio cover images
│       ├── logo.png       # Site logo
│       └── favicon.ico    # Favicon
├── src/
│   └── index.html         # Main HTML file
├── .gitea/
│   └── workflows/
│       └── deploy.yml     # CI/CD workflow
├── docker-compose.yml
├── Dockerfile
├── nginx.conf
└── README.md

Updating Content

To update text/settings:

  1. Edit config/site.json
  2. The changes are applied immediately (no rebuild needed)

To update images:

  1. Add new images to public/images/
  2. Update paths in config/site.json
  3. Changes are applied immediately

To update code:

  1. Edit src/index.html
  2. Rebuild the Docker image:
docker compose build
docker compose up -d

Or push to Git and let CI/CD handle it.

License

MIT License - Feel free to use and modify for your photography business!

S
Description
LisiLou Photography Portfolio — lightweight Immich-integrated portfolio site
Readme 532 KiB
Languages
HTML 63.8%
JavaScript 27.7%
Shell 8%
Dockerfile 0.5%