f58f5534c67c8e357692904ef824abb4c303cc9e
Deploy to Dev / Deploy & Smoke Test (push) Successful in 27s
Step reorder (still 7 steps): Info (5) → Contract (6) → Payment (7) - Client info moved to step 5 so it's available for the contract signature name and the personalised Venmo note before the payment step - Contract is now step 6 (initContractStep triggered on step 6 entry) - Step 7 is the full payment step — no separate confirm step needed Payment step (step 7): - Compact summary table: date, session type, length, location - Large price display from siteConfig.booking.pricing - "Pay on Venmo" button linking to: https://venmo.com/<username>?txn=pay&amount=<price>¬e=<encoded-note> Note format: "LisiLou Booking - [SessionType] on [Date]" - QR code rendered from GET /api/venmo-qr?url=<encoded> (server-side SVG via qrcode package, site colours applied) - "I've sent payment" checkbox gates the Submit button - Clicking Submit creates booking with payment_status='pending_confirmation', then signs the contract — success screen shown immediately Configuration: venmoUsername lives in config/site.json under booking.venmoUsername — change it there to point at any Venmo account with no code change and no rebuild. API additions: - GET /api/venmo-qr?url= — validates url starts with venmo.com, returns SVG - POST /api/bookings now accepts payment_status field Closes #7 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
- Clone this repository
- Customize
config/site.jsonwith your information - Add your images to
public/images/ - Run with Docker:
docker compose up -d
- 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
- Create cover images for each portfolio category
- Place them in
public/images/portfolio/ - Update the
coverImagepaths inconfig/site.json - Get the share IDs from your Immich albums and add them to
immichAlbumId
Client Gallery Access
Clients can enter their gallery code (Immich share ID) on the website. They'll be redirected to their Immich shared album.
Workflow:
- Create a shared album in Immich for your client
- Give them the share ID as their "gallery code"
- They enter it on your website and are taken directly to their photos
Deployment
With Docker Compose
- Copy files to your server:
scp -r . user@server:/opt/lisilou-portfolio/
- Create the external network:
docker network create web
- 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
-
Set up Gitea Actions on your Gitea instance
-
Add these secrets to your repository:
REGISTRY_USERNAME- Container registry usernameREGISTRY_PASSWORD- Container registry passwordDEPLOY_HOST- Your server hostnameDEPLOY_USER- SSH usernameDEPLOY_KEY- SSH private key
-
Update
.gitea/workflows/deploy.ymlwith your registry URL -
Push to main branch to trigger automatic deployment
Multi-Photographer Support
To support multiple photographers:
- Create additional config files (e.g.,
config/photographer2.json) - 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
}
- 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:
- Edit
config/site.json - The changes are applied immediately (no rebuild needed)
To update images:
- Add new images to
public/images/ - Update paths in
config/site.json - Changes are applied immediately
To update code:
- Edit
src/index.html - 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!
Description
Languages
HTML
63.8%
JavaScript
27.7%
Shell
8%
Dockerfile
0.5%