inter-project-deployment-updates

This commit is contained in:
Manish Tanwar 2026-02-27 20:33:26 +05:30
parent 988429a759
commit ac275a9259
20 changed files with 861 additions and 3176 deletions

View file

@ -28,7 +28,8 @@
"Bash(bash:*)",
"Bash(dos2unix:*)",
"WebSearch",
"WebFetch(domain:ai.google.dev)"
"WebFetch(domain:ai.google.dev)",
"Bash(cp:*)"
]
}
}

View file

@ -17,26 +17,25 @@ cinema-studio-pro/
│ │ ├── authConfig.js # MSAL authentication config
│ │ └── App.jsx # Root component
│ ├── .env # Frontend environment variables (gitignored)
│ ├── .env.example # Frontend env template
│ ├── .env.local # Local dev template
│ ├── .env.production # Production template
│ └── package.json
├── backend/ # PHP backend APIs
│ ├── api.php # Image generation API
│ ├── video_api.php # Video generation API
│ ├── stream_video.php # Video streaming
│ ├── api.php # Image generation API
│ ├── video_api.php # Video generation API
│ ├── stream_video.php # Video streaming
│ ├── enhance_prompt.php # Prompt optimization
│ ├── session_manager.php # Multi-user session management
│ ├── AuthMiddleware.php # SSO authentication
│ ├── uploads/ # Temporary file storage
│ ├── .env # Backend environment variables (gitignored)
│ ├── .env.example # Backend env template
│ └── composer.json # PHP dependencies
├── MDFiles/ # Documentation
│ ├── README.md
│ ├── INSTALL.md
│ ├── AI_IMPLEMENTATION_GUIDE.md
│ ├── QUICK_REFERENCE.md
│ └── AUTH_README.md
└── CLAUDE.md # This file
│ ├── AuthMiddleware.php # SSO authentication (required by api.php)
│ ├── JWTValidator.php # Azure AD token validation
│ ├── uploads/ # Temporary file storage
│ ├── .env # Backend environment variables (gitignored)
│ ├── .env.local # Local dev template
│ ├── .env.production # Production template
│ └── composer.json # PHP dependencies
├── README.md # User-facing project overview
├── NEW_DEPLOYMENT.md # Production deployment guide (FileZilla + SSH)
└── CLAUDE.md # This file
```
@ -137,7 +136,7 @@ The Imagen 3 API via Gemini has a VERY SPECIFIC request format that differs from
- MIME type must match (typically `image/jpeg`)
- Base64 must be clean (no whitespace, no data URI prefix)
See `MDFiles/AI_IMPLEMENTATION_GUIDE.md` for complete details on this critical pattern.
See the Critical Patterns section below for the full request format rules.
### Session Management (Multi-User)
@ -300,7 +299,7 @@ NODE_ENV=development
# NOTE: Port variables NOT used in production (only for local dev)
# Production uses Apache on port 443 to serve built static files
VITE_BASE_PATH=/lux-studio/
VITE_API_URL=https://ai-sandbox.oliver.solutions/lux-studio-back
VITE_API_URL=https://ai-sandbox.oliver.solutions/lux-studio/api
VITE_GEMINI_API_KEY=AIzaSyC...
VITE_SSO_ENABLED=true
VITE_SSO_TENANT_ID=e519c2e6-bc6d-4fdf-8d9c-923c2f002385
@ -348,7 +347,7 @@ Edit `VideoGenTab.jsx` - update `durationOptions` array, ensure constraints matc
1. **Check API URL configuration** - Verify `VITE_API_URL` in frontend/.env matches backend server
2. Check browser console for API errors (404/500 = wrong API URL)
3. Check PHP error_log in project root
4. Verify `AI_IMPLEMENTATION_GUIDE.md` request format rules
4. Verify image editing parts order: image data MUST precede text (see Critical Patterns section)
5. Check `finishReason` in API response (IMAGE_RECITATION = blocked)
6. Ensure prompts are creative/detailed (10+ words)
@ -482,12 +481,8 @@ The application uses MSAL (Microsoft Authentication Library) for Azure AD SSO:
## Documentation References
For detailed implementation guides, see:
- `MDFiles/AI_IMPLEMENTATION_GUIDE.md` - Critical Imagen 3 API patterns
- `MDFiles/QUICK_REFERENCE.md` - Common patterns and gotchas
- `MDFiles/AUTH_README.md` - Azure AD SSO setup guide
- `MDFiles/INSTALL.md` - Server deployment instructions
- `MDFiles/README.md` - User-facing feature documentation
- `README.md` - User-facing project overview, setup, and troubleshooting
- `NEW_DEPLOYMENT.md` - Production deployment guide (FileZilla + SSH)
## API Rate Limits
@ -510,38 +505,27 @@ For detailed implementation guides, see:
## Build and Deployment
**Automated Deployment (Recommended):**
```bash
sudo ./deploy.sh # Full production deployment script
# Uses .env.production files
# Deploys to /opt/lux-studio-back/ and /var/www/html/lux-studio/
```
**Manual Frontend Build:**
**Frontend build:**
```bash
cd frontend
cp .env.production .env
npm run build
# Outputs to frontend/dist/
# Verify: grep -o "lux-studio/api" frontend/dist/assets/*.js | head -3
```
**Backend deployment:**
- Copy all `backend/` files to server
- Run `composer install` in backend directory
- Create `backend/.env` from `backend/.env.example`
- Set up `backend/uploads/sessions/` directory with write permissions (755)
- Configure web server (Apache .htaccess included, Nginx config in MDFiles/INSTALL.md)
**Frontend deployment:**
- Build frontend with `npm run build`
- Deploy `frontend/dist/` to web server or CDN
- Update `VITE_API_URL` in frontend/.env for production backend URL
- Update `VITE_SSO_REDIRECT_URI` to production URL
**Deployment** (FileZilla + SSH — see `NEW_DEPLOYMENT.md` for the full guide):
- Server: `ai-sandbox.oliver.solutions`
- Frontend static files → `/var/www/html/lux-studio/`
- Backend PHP files → `/var/www/html/lux-studio/api/`
- Delete old `assets/` folder on server before uploading new one (hash-named files change each build)
- Never overwrite the server's `/api/.env` (contains production secrets)
- `AuthMiddleware.php` is REQUIRED in `/api/``api.php` will crash without it
**Production checklist:**
- PHP 7.4+ installed
- Composer dependencies installed in backend/
- `backend/.env` with valid GEMINI_API_KEY and production SSO credentials
- `backend/uploads/sessions/` writable by web server
- HTTPS enabled (required for SSO)
- Frontend built and deployed with production env vars
- CORS configured on backend for frontend domain
- PHP 7.4+ installed on server
- `backend/.env` on server with valid GEMINI_API_KEY and `SSO_ENABLED=false`
- `backend/uploads/sessions/` writable by web server (chmod 755)
- HTTPS enabled (required for SSO redirect URI)
- Frontend built with `VITE_API_URL=https://ai-sandbox.oliver.solutions/lux-studio/api`
- CORS configured on backend for frontend domain (`FRONTEND_URL` in server `.env`)

View file

@ -1,937 +0,0 @@
# Lux Studio - Deployment Guide
Complete guide for deploying Lux Studio to production servers.
---
## Table of Contents
1. [Architecture Overview](#architecture-overview)
2. [Prerequisites](#prerequisites)
3. [Development Setup](#development-setup)
4. [Production Deployment](#production-deployment)
5. [Troubleshooting](#troubleshooting)
6. [Maintenance](#maintenance)
---
## Architecture Overview
```
┌─────────────────────────────┐
│ Production Server │
│ (HTTPS) │
└──────────┬──────────────────┘
┌──────┴───────┐
│ │
┌───▼────┐ ┌────▼─────────┐
│Frontend│ │/lux-studio- │
│/lux- │ │back/ │
│studio/ │ │(Proxy) │
└───┬────┘ └────┬─────────┘
│ │
│ ┌────▼─────────┐
│ │localhost:5015│
│ │PHP Service │
└───────►└──────────────┘
```
**Key Components:**
- **Frontend**: React SPA served as static files
- **Backend**: PHP service running on port 5015
- **Proxy**: Apache routes `/lux-studio-back/*``localhost:5015`
- **Storage**: IndexedDB (frontend) + file-based sessions (backend)
---
## Prerequisites
### Local Machine:
- [ ] Node.js 18+ and npm
- [ ] FileZilla or SFTP client
- [ ] Project files downloaded
### Production Server:
- [ ] Ubuntu/Debian Linux
- [ ] Apache web server with mod_rewrite, mod_proxy, mod_headers
- [ ] PHP 7.4+ with extensions: curl, json, mbstring, session
- [ ] Composer (PHP dependency manager)
- [ ] SSH access with sudo privileges
- [ ] HTTPS/SSL configured
### API Keys:
- [ ] Google Gemini API key from [Google AI Studio](https://aistudio.google.com/app/apikey)
- [ ] Azure AD tenant and client ID (for SSO)
---
## Development Setup
### 1. Install Dependencies
**Backend:**
```bash
cd backend
composer install
```
**Frontend:**
```bash
cd frontend
npm install
```
### 2. Configure Environment Variables
**Backend** (`backend/.env`):
```env
GEMINI_API_KEY=your-api-key-here
SSO_ENABLED=false
SSO_TENANT_ID=e519c2e6-bc6d-4fdf-8d9c-923c2f002385
SSO_CLIENT_ID=9079054c-9620-4757-a256-23413042f1ef
FRONTEND_URL=http://localhost:3000
```
**Frontend** (`frontend/.env`):
```env
VITE_API_URL=http://localhost:8000
VITE_GEMINI_API_KEY=your-api-key-here
VITE_SSO_ENABLED=true
VITE_SSO_TENANT_ID=e519c2e6-bc6d-4fdf-8d9c-923c2f002385
VITE_SSO_CLIENT_ID=9079054c-9620-4757-a256-23413042f1ef
VITE_SSO_REDIRECT_URI=http://localhost:3000
```
### 3. Start Development Servers
**Terminal 1 - Backend:**
```bash
cd backend
php -S localhost:8000
```
**Terminal 2 - Frontend:**
```bash
cd frontend
npm run dev
```
**Access:** Open `http://localhost:3000` in your browser
### 4. Development Workflow
- **Frontend SSO**: ENABLED - Shows Microsoft login
- **Backend SSO**: DISABLED - No token validation needed
- **Hot Reload**: Vite provides instant updates
- **Browser DevTools**: F12 to view console/network
---
## Production Deployment
### PART 1: Build Frontend
#### 1.1 Configure Production Environment
Create `frontend/.env`:
```env
VITE_API_URL=https://ai-sandbox.oliver.solutions/lux-studio-back
BACKEND_PORT=5015
VITE_GEMINI_API_KEY=AIzaSyCMKLSJJYEx4c6-TtBACnjdULrLzsr_fts
VITE_SSO_ENABLED=true
VITE_SSO_TENANT_ID=e519c2e6-bc6d-4fdf-8d9c-923c2f002385
VITE_SSO_CLIENT_ID=9079054c-9620-4757-a256-23413042f1ef
VITE_SSO_REDIRECT_URI=https://ai-sandbox.oliver.solutions/lux-studio/
NODE_ENV=production
```
**IMPORTANT:** Note the URL paths:
- Frontend: `https://ai-sandbox.oliver.solutions/lux-studio/`
- Backend API: `https://ai-sandbox.oliver.solutions/lux-studio-back/`
#### 1.2 Build Frontend
```bash
cd frontend
npm install
npm run build
```
**Expected Output:**
```
✓ built in 25s
dist/index.html 0.56 kB
dist/assets/index-[hash].js 1.2 MB
```
#### 1.3 Verify Build
```bash
ls -la frontend/dist/
```
Should contain:
- `index.html`
- `assets/` folder
- `LOGO/` folder
- Logo files (`.svg`, `.png`)
**Verify API paths in build:**
```bash
grep -o "lux-studio-back" frontend/dist/assets/*.js | head -5
```
Should show references to `/lux-studio-back/` (not `/api/`)
---
### PART 2: Upload Files to Server
#### 2.1 Connect via FileZilla
1. Open FileZilla
2. **Host**: `ai-sandbox.oliver.solutions`
3. **Protocol**: SFTP
4. **Port**: 22
5. **Username**: your-ssh-username
6. **Password**: your-ssh-password
#### 2.2 Upload Backend Files
**Remote path**: `/opt/lux-studio-back/`
Upload these files from `backend/`:
```
✓ api.php
✓ video_api.php
✓ stream_video.php
✓ enhance_prompt.php
✓ session_manager.php
✓ AuthMiddleware.php
✓ JWTValidator.php
✓ env_loader.php
✓ get_config.php
✓ get_current_image.php
✓ cleanup.php
✓ server-check.php
✓ composer.json
✓ .env.example
```
**DO NOT upload:**
- `.env` (create on server)
- `vendor/` (install via composer)
- `uploads/` (auto-created)
- Test files (`test.php`, `debug*.php`)
#### 2.3 Upload Frontend Files
**Remote path**: `/var/www/html/lux-studio/`
Upload ALL files from `frontend/dist/`:
```
✓ index.html
✓ assets/ (entire folder)
✓ LOGO/ (entire folder)
✓ *.svg files
✓ favicon.png
```
**CRITICAL:** Ensure all logo files are uploaded:
- `/var/www/html/lux-studio/LUX_STUDIO_LOGO.svg`
- `/var/www/html/lux-studio/LOGO/LUX_STUDIO_LOGO.svg`
- `/var/www/html/lux-studio/LOGO/LUX_STUDIO_LOGO.png`
---
### PART 3: Server Configuration
#### 3.1 SSH into Server
```bash
ssh your-username@ai-sandbox.oliver.solutions
```
#### 3.2 Install Composer (if needed)
Check if installed:
```bash
composer --version
```
If not installed:
```bash
cd ~
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer
php -r "unlink('composer-setup.php');"
composer --version
```
#### 3.3 Install Backend Dependencies
```bash
cd /opt/lux-studio-back
sudo -u www-data composer install --no-dev --optimize-autoloader
```
Verify:
```bash
ls -la vendor/
```
Should show `firebase/` (PHP-JWT library)
#### 3.4 Create Backend .env File
```bash
sudo nano /opt/lux-studio-back/.env
```
Paste:
```env
# Google Gemini API Key
GEMINI_API_KEY=AIzaSyCMKLSJJYEx4c6-TtBACnjdULrLzsr_fts
# Frontend URL for CORS (no trailing slash)
FRONTEND_URL=https://ai-sandbox.oliver.solutions/lux-studio
# Azure AD SSO (backend disabled, frontend handles it)
SSO_ENABLED=false
SSO_TENANT_ID=e519c2e6-bc6d-4fdf-8d9c-923c2f002385
SSO_CLIENT_ID=9079054c-9620-4757-a256-23413042f1ef
```
Save: `Ctrl+X`, `Y`, `Enter`
#### 3.5 Set Permissions
```bash
# Backend
sudo chown -R www-data:www-data /opt/lux-studio-back
sudo chmod -R 755 /opt/lux-studio-back
# Create uploads directory
sudo mkdir -p /opt/lux-studio-back/uploads/sessions
sudo chmod -R 777 /opt/lux-studio-back/uploads
# Frontend
sudo chown -R www-data:www-data /var/www/html/lux-studio
sudo chmod -R 755 /var/www/html/lux-studio
```
---
### PART 4: Configure Apache
#### 4.1 Enable Required Modules
```bash
sudo a2enmod rewrite
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod headers
sudo a2enmod ssl
```
#### 4.2 Edit Apache Configuration
```bash
sudo nano /etc/apache2/apache2.conf
```
Add this configuration (around line 290, after existing services):
```apache
# ==============================================================================
# LUX STUDIO CONFIGURATION
# ==============================================================================
# Backend API Proxy - Routes /lux-studio-back/* to localhost:5015/*
ProxyPass /lux-studio-back/ http://localhost:5015/
ProxyPassReverse /lux-studio-back/ http://localhost:5015/
# Frontend Directory - React SPA with client-side routing
<Directory /var/www/html/lux-studio>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /lux-studio/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.html [L]
</IfModule>
</Directory>
# Security - Deny direct access to backend source directory
<Directory /opt/lux-studio-back>
Require all denied
</Directory>
# CORS Headers for Backend API
<Location /lux-studio-back>
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "https://ai-sandbox.oliver.solutions"
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With"
Header set Access-Control-Allow-Credentials "true"
</IfModule>
</Location>
# ==============================================================================
# END LUX STUDIO CONFIGURATION
# ==============================================================================
```
**CRITICAL:** Ensure trailing slashes on ProxyPass/ProxyPassReverse lines!
#### 4.3 Test and Reload Apache
```bash
# Test configuration
sudo apache2ctl configtest
```
Should output: `Syntax OK`
```bash
# Reload Apache
sudo systemctl reload apache2
# Check status
sudo systemctl status apache2
```
---
### PART 5: Deploy Backend Service
#### 5.1 Create Systemd Service File
```bash
sudo nano /etc/systemd/system/lux-studio-backend.service
```
Paste:
```ini
[Unit]
Description=Lux Studio Backend API Service
Documentation=https://github.com/your-repo/cinema-studio-pro
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/lux-studio-back
EnvironmentFile=/opt/lux-studio-back/.env
ExecStart=/usr/bin/php -S 0.0.0.0:5015 -t /opt/lux-studio-back
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
```
Save: `Ctrl+X`, `Y`, `Enter`
#### 5.2 Start Backend Service
```bash
# Reload systemd
sudo systemctl daemon-reload
# Enable service (auto-start on boot)
sudo systemctl enable lux-studio-backend
# Start service
sudo systemctl start lux-studio-backend
# Check status
sudo systemctl status lux-studio-backend
```
**Expected output:**
```
● lux-studio-backend.service - Lux Studio Backend API Service
Active: active (running) since ...
Main PID: 12345 (php)
```
#### 5.3 Verify Port Listening
```bash
sudo netstat -tlnp | grep 5015
```
**Expected:**
```
tcp 0 0 0.0.0.0:5015 0.0.0.0:* LISTEN 12345/php
```
---
### PART 6: Verification & Testing
#### 6.1 Test Backend Directly
```bash
# Test backend on localhost
curl http://localhost:5015/server-check.php
```
Should return HTML with server diagnostics.
#### 6.2 Test Backend via Proxy
```bash
# Test proxied backend
curl https://ai-sandbox.oliver.solutions/lux-studio-back/server-check.php
```
Should return same HTML response.
#### 6.3 Test Frontend
Open browser and navigate to:
```
https://ai-sandbox.oliver.solutions/lux-studio/
```
**Expected:**
- ✅ Page loads without errors
- ✅ Lux Studio logo displays
- ✅ "Sign in with Microsoft" button appears
- ✅ No 404 errors in Network tab (F12)
- ✅ No console errors
#### 6.4 Test Full Application Flow
1. **Login:**
- Click "Sign in with Microsoft"
- Authenticate with Azure AD
- Should redirect back to app
2. **After Login:**
- ✅ Logo in header
- ✅ User name displayed
- ✅ Three tabs: Projects, Image Gen, Video Gen
3. **Create Project:**
- Click "Create New Project"
- Enter name
- Project appears in list
4. **Generate Image:**
- Select project
- Go to Image Gen tab
- Enter creative prompt (10+ words)
- Click Generate
- Image appears and saves to project
5. **Generate Video:**
- Go to Video Gen tab
- Enter video prompt
- Select duration
- Click Generate
- Video processes and saves
#### 6.5 Check for Errors
Open Browser DevTools (F12):
- **Console tab**: Should be clean, no errors
- **Network tab**: All requests should be 200 OK
- **Check API calls**: Should go to `/lux-studio-back/api.php` (not `/api/api.php`)
---
## Troubleshooting
### Issue: Backend Service Won't Start
**Check logs:**
```bash
sudo journalctl -u lux-studio-backend -n 50 --no-pager
```
**Common causes:**
- Port 5015 already in use
- PHP path incorrect
- Permission denied
- Missing .env file
**Solution:**
```bash
# Kill process on port 5015
sudo kill -9 $(sudo lsof -t -i:5015)
# Restart service
sudo systemctl restart lux-studio-backend
```
---
### Issue: Frontend Shows 404 or Blank Page
**Check Apache:**
```bash
sudo systemctl status apache2
sudo tail -50 /var/log/apache2/error.log
```
**Verify files exist:**
```bash
ls -la /var/www/html/lux-studio/index.html
ls -la /var/www/html/lux-studio/.htaccess
```
**Enable mod_rewrite:**
```bash
sudo a2enmod rewrite
sudo systemctl restart apache2
```
---
### Issue: API Requests Return 404
**Symptoms:**
- Browser console shows: `404 on /lux-studio-back/api.php`
**Check Apache proxy configuration:**
```bash
sudo grep -n "lux-studio-back" /etc/apache2/apache2.conf
```
Should show ProxyPass lines.
**Verify trailing slashes:**
```apache
# CORRECT:
ProxyPass /lux-studio-back/ http://localhost:5015/
ProxyPassReverse /lux-studio-back/ http://localhost:5015/
# WRONG (missing trailing slash):
ProxyPass /lux-studio-back/ http://localhost:5015
```
**Fix and reload:**
```bash
sudo nano /etc/apache2/apache2.conf
# Add trailing slashes
sudo apache2ctl configtest
sudo systemctl reload apache2
```
---
### Issue: API Requests Return 502 Bad Gateway
**Symptoms:**
- `502 Bad Gateway` on `/lux-studio-back/api.php`
**Cause:** Backend service is not running.
**Solution:**
```bash
# Check service status
sudo systemctl status lux-studio-backend
# If not running, start it
sudo systemctl start lux-studio-backend
# Check port
sudo netstat -tlnp | grep 5015
```
---
### Issue: API Requests Return 500 Internal Server Error
**Symptoms:**
- `500 Internal Server Error` on API calls
**Check backend logs:**
```bash
sudo journalctl -u lux-studio-backend -n 30 --no-pager
```
**Common causes:**
- Missing GEMINI_API_KEY in `.env`
- Missing composer dependencies
- PHP syntax error
- File permission issues
**Solutions:**
```bash
# Verify .env exists
cat /opt/lux-studio-back/.env | grep GEMINI_API_KEY
# Reinstall dependencies
cd /opt/lux-studio-back
sudo -u www-data composer install
# Check permissions
sudo chown -R www-data:www-data /opt/lux-studio-back
sudo chmod -R 755 /opt/lux-studio-back
# Restart service
sudo systemctl restart lux-studio-backend
```
---
### Issue: Logo Not Appearing
**Verify logo files:**
```bash
ls -la /var/www/html/lux-studio/*.svg
ls -la /var/www/html/lux-studio/LOGO/*.svg
```
**Check permissions:**
```bash
sudo chmod 644 /var/www/html/lux-studio/*.svg
sudo chmod 644 /var/www/html/lux-studio/LOGO/*
```
**Clear browser cache:**
- Press `Ctrl+Shift+R` (hard refresh)
- Or clear cache in DevTools
---
### Issue: CORS Errors
**Symptoms:**
- Browser console shows CORS policy errors
**Check backend .env:**
```bash
cat /opt/lux-studio-back/.env | grep FRONTEND_URL
```
Should be: `FRONTEND_URL=https://ai-sandbox.oliver.solutions/lux-studio`
**Restart services:**
```bash
sudo systemctl restart lux-studio-backend
sudo systemctl reload apache2
```
---
### Issue: Old Code Still Loading (Still seeing /api/ requests)
**Symptoms:**
- Browser Network tab shows requests to `/api/api.php` instead of `/lux-studio-back/api.php`
**Cause:** Browser is caching old JavaScript files.
**Solution:**
```bash
# 1. Verify new build was uploaded
ssh user@server
ls -lt /var/www/html/lux-studio/assets/ | head -5
# Check timestamps - should be recent
# 2. Verify new build contains correct paths
grep -o "lux-studio-back" /var/www/html/lux-studio/assets/*.js | head -5
# Should show multiple matches
# 3. Clear browser cache
# In browser: Ctrl+Shift+Delete → Clear cached files
# Hard refresh: Ctrl+F5 or Ctrl+Shift+R
```
---
## Maintenance
### View Backend Logs
```bash
# Recent logs
sudo journalctl -u lux-studio-backend -n 100 --no-pager
# Follow logs in real-time
sudo journalctl -u lux-studio-backend -f
# Logs since specific time
sudo journalctl -u lux-studio-backend --since "1 hour ago"
```
### View Apache Logs
```bash
# Error log
sudo tail -f /var/log/apache2/error.log
# Access log
sudo tail -f /var/log/apache2/access.log
```
### Service Management
```bash
# Start service
sudo systemctl start lux-studio-backend
# Stop service
sudo systemctl stop lux-studio-backend
# Restart service
sudo systemctl restart lux-studio-backend
# Check status
sudo systemctl status lux-studio-backend
# Enable auto-start on boot
sudo systemctl enable lux-studio-backend
```
### Cleanup Old Files
```bash
# Run cleanup script (removes files older than 24 hours)
cd /opt/lux-studio-back
sudo -u www-data php cleanup.php
# Set up automatic cleanup (cron job)
sudo crontab -e
```
Add this line to run cleanup daily at 3 AM:
```cron
0 3 * * * cd /opt/lux-studio-back && php cleanup.php >> /var/log/lux-studio-cleanup.log 2>&1
```
### Update Application
When deploying a new version:
```bash
# 1. Stop backend service
sudo systemctl stop lux-studio-backend
# 2. Upload new files via FileZilla (overwrite existing)
# 3. Update dependencies
cd /opt/lux-studio-back
sudo -u www-data composer install --no-dev --optimize-autoloader
# 4. Restart service
sudo systemctl start lux-studio-backend
# 5. Verify
sudo systemctl status lux-studio-backend
curl http://localhost:5015/server-check.php
```
### Backup Application
```bash
# Backup backend code
sudo tar -czf lux-studio-back-$(date +%Y%m%d).tar.gz /opt/lux-studio-back
# Backup frontend code
sudo tar -czf lux-studio-front-$(date +%Y%m%d).tar.gz /var/www/html/lux-studio
# Backup user uploads
sudo tar -czf lux-studio-uploads-$(date +%Y%m%d).tar.gz /opt/lux-studio-back/uploads/sessions/
# Move to backup location
sudo mv lux-studio-*.tar.gz ~/backups/
```
---
## Quick Reference
### Check Everything is Working
```bash
# Service status
sudo systemctl status lux-studio-backend
# Port listening
sudo netstat -tlnp | grep 5015
# Backend direct test
curl http://localhost:5015/server-check.php
# Backend via proxy
curl https://ai-sandbox.oliver.solutions/lux-studio-back/server-check.php
# Frontend files
ls -la /var/www/html/lux-studio/
# Logo files
ls -la /var/www/html/lux-studio/*.svg /var/www/html/lux-studio/LOGO/*
```
### Common Commands
```bash
# Restart everything
sudo systemctl restart lux-studio-backend
sudo systemctl reload apache2
# View all logs
sudo journalctl -u lux-studio-backend -f &
sudo tail -f /var/log/apache2/error.log
# Fix permissions
sudo chown -R www-data:www-data /opt/lux-studio-back
sudo chmod -R 755 /opt/lux-studio-back
sudo chmod -R 777 /opt/lux-studio-back/uploads
```
---
## Deployment Checklist
Before going live:
- [ ] Backend files uploaded to `/opt/lux-studio-back/`
- [ ] Frontend files uploaded to `/var/www/html/lux-studio/`
- [ ] Backend `.env` file created with API key
- [ ] Composer dependencies installed
- [ ] Apache proxy configured with trailing slashes
- [ ] Apache modules enabled (rewrite, proxy, headers)
- [ ] Systemd service created and enabled
- [ ] Backend service running on port 5015
- [ ] Logo files present and accessible
- [ ] HTTPS working (existing SSL certificates)
- [ ] Frontend loads without 404 errors
- [ ] API calls go to `/lux-studio-back/` (not `/api/`)
- [ ] Can login with Microsoft SSO
- [ ] Can create projects
- [ ] Can generate images
- [ ] Can generate videos
- [ ] No console errors in browser
- [ ] Backup created
---
## Support
For issues not covered in this guide:
- **Backend Logs:** `sudo journalctl -u lux-studio-backend -f`
- **Apache Logs:** `sudo tail -f /var/log/apache2/error.log`
- **Browser Console:** F12 → Console tab
- **Network Requests:** F12 → Network tab
---
**Deployment Date:** _______________
**Deployed By:** _______________
**Server:** ai-sandbox.oliver.solutions
**Version:** 1.0.0

File diff suppressed because it is too large Load diff

255
NEW_DEPLOYMENT.md Normal file
View file

@ -0,0 +1,255 @@
# Lux Studio — Deployment Guide
**Server:** ai-sandbox.oliver.solutions
**Frontend URL:** `https://ai-sandbox.oliver.solutions/lux-studio/`
**Backend URL:** `https://ai-sandbox.oliver.solutions/lux-studio/api/`
---
## Deployment Method
### Option A — Automated (if project is cloned on server)
If you have cloned `cinema-studio-pro` to `/opt/cinema-studio-pro/` on the server:
```bash
cd /opt/cinema-studio-pro
git pull # get latest changes
sudo ./deploy.sh # build + deploy everything automatically
```
The script handles the full build, file copy, Apache config, permissions, and verification.
---
### Option B — Manual (FileZilla from your local machine)
Follow Steps 16 below.
---
## Server Architecture
```
/var/www/html/lux-studio/
├── index.html ← React app entry point
├── assets/ ← Built JS/CSS bundles (hash-named)
├── LOGO/ ← Logo assets
├── LUX_STUDIO_LOGO.svg
├── favicon.png
├── logo.svg
├── .htaccess ← React router + security rules
├── generated_images/ ← (auto-created, do not touch)
├── generated_videos/ ← (auto-created, do not touch)
├── uploads/sessions/ ← (auto-created, do not touch)
└── api/ ← PHP backend (Apache serves directly)
├── .env ← Production secrets (never overwrite)
├── api.php
├── video_api.php
├── enhance_prompt.php
├── session_manager.php
├── stream_video.php
├── AuthMiddleware.php
├── JWTValidator.php
├── ... (all other .php files)
└── generated_videos/ ← Videos saved by PHP
```
Apache serves PHP files directly — no separate PHP service or proxy needed.
---
## Prerequisites (Local Machine)
- Node.js 18+ and npm
- FileZilla (SFTP)
- SSH client (optional, for verification)
---
## Every Time You Deploy
### Step 1 — Check `frontend/.env.production`
Open `frontend/.env.production` and confirm these values are set:
```env
VITE_BASE_PATH=/lux-studio/
VITE_API_URL=https://ai-sandbox.oliver.solutions/lux-studio/api
VITE_SSO_ENABLED=true
VITE_SSO_TENANT_ID=e519c2e6-bc6d-4fdf-8d9c-923c2f002385
VITE_SSO_CLIENT_ID=9079054c-9620-4757-a256-23413042f1ef
VITE_SSO_REDIRECT_URI=https://ai-sandbox.oliver.solutions/lux-studio/
```
> `VITE_API_URL` must point to `/lux-studio/api` — NOT `/lux-studio-back`.
> If it says `/lux-studio-back`, change it before building.
---
### Step 2 — Build the frontend
```bash
cd frontend
cp .env.production .env
npm run build
```
Output lands in `frontend/dist/`. Verify the correct API URL is baked in:
```bash
grep -o "lux-studio/api" frontend/dist/assets/*.js | head -3
# Should print: lux-studio/api
```
---
### Step 3 — FileZilla: Upload frontend
Connect via SFTP: host `ai-sandbox.oliver.solutions`, port `22`.
**Remote path:** `/var/www/html/lux-studio/`
| What | Local source | Server destination | Notes |
|------|--------------|--------------------|-------|
| App entry | `frontend/dist/index.html` | `index.html` | Overwrite |
| JS/CSS bundles | `frontend/dist/assets/` | `assets/` | **Delete old folder first**, then upload new |
| Logos | `frontend/dist/LOGO/` | `LOGO/` | Overwrite folder |
| SVG logo | `frontend/dist/LUX_STUDIO_LOGO.svg` | `LUX_STUDIO_LOGO.svg` | Overwrite |
| Favicon | `frontend/dist/favicon.png` | `favicon.png` | Overwrite |
| Logo | `frontend/dist/logo.svg` | `logo.svg` | Overwrite |
| Apache rules | `frontend/.htaccess` | `.htaccess` | Upload from root (not from dist/) |
> **Why delete `assets/` first:** Each build produces differently hash-named files
> (e.g. `index-DbAHmoFD.js`). Without deleting, old stale files accumulate.
---
### Step 4 — FileZilla: Upload backend
**Remote path:** `/var/www/html/lux-studio/api/`
Upload all files from `backend/` **except** those in the skip list below.
#### Files to upload (overwrite existing):
| File | Purpose |
|------|---------|
| `api.php` | Image generation API |
| `video_api.php` | Video generation API |
| `enhance_prompt.php` | Prompt optimization |
| `session_manager.php` | Multi-user session isolation |
| `stream_video.php` | Video streaming with range support |
| `get_current_image.php` | Session image retrieval |
| `get_config.php` | Config endpoint |
| `env_loader.php` | .env file parser |
| `webhook_logger.php` | API request logging |
| `config.php` | PHP configuration loader |
| `AuthMiddleware.php` | Auth orchestration (required by api.php) |
| `JWTValidator.php` | JWT token validation (required by AuthMiddleware) |
| `auth.php` | Auth endpoint |
| `cleanup.php` | Session file cleanup |
| `clear_session.php` | Clear session endpoint |
| `get_logs.php` | Log viewer endpoint |
| `get_session_file.php` | Session file endpoint |
| `index.php` | Backend index |
| `list_session_files.php` | Session file listing |
| `server-check.php` | Health check endpoint |
#### DO NOT upload:
| File | Reason |
|------|--------|
| `backend/.env` | Contains production secrets — **never overwrite** |
| `backend/test.php` | Debug tool, not for production |
| `backend/config.example.php` | Template only |
| `backend/.env.local` / `.env.production` / `.env.example` | Local/template files |
| `backend/vendor/` | Not required (SSO is disabled — JWT lib not loaded) |
| `backend/composer.json` | Only needed if running composer on server |
---
### Step 5 — Verify `.env` on server (SSH)
```bash
ssh your-username@ai-sandbox.oliver.solutions
cat /var/www/html/lux-studio/api/.env
```
Expected content:
```env
GEMINI_API_KEY=AIzaSyDs7EKdC9NLM5UqWlGUqeQO96TmSA-kos8
FRONTEND_URL=https://ai-sandbox.oliver.solutions/lux-studio
SSO_ENABLED=false
SSO_TENANT_ID=e519c2e6-bc6d-4fdf-8d9c-923c2f002385
SSO_CLIENT_ID=9079054c-9620-4757-a256-23413042f1ef
```
If the file is missing or needs updating:
```bash
sudo nano /var/www/html/lux-studio/api/.env
```
---
### Step 6 — Test in browser
1. Open `https://ai-sandbox.oliver.solutions/lux-studio/`
2. Hard refresh: `Ctrl + Shift + R`
3. Open F12 → Network tab
4. Check that:
- Login page loads with the Lux Studio logo
- After login, the Projects/Image Gen/Video Gen tabs are visible
- API calls go to `/lux-studio/api/api.php` (not `/lux-studio-back/`)
- No 404 errors in the Network tab
5. Create a project, generate an image with a 10+ word prompt, confirm it saves
---
## Troubleshooting
### API calls returning 404
Check the built JS has the correct URL:
```bash
grep -o "lux-studio/api" /var/www/html/lux-studio/assets/*.js | head -3
```
If empty or showing `/lux-studio-back`, rebuild with the correct `VITE_API_URL`.
### Old code still loading after upload
Browser cache. Force a hard refresh: `Ctrl + Shift + R`
Or: DevTools → Network → check "Disable cache" → refresh.
### Image generation crashing (500 error)
`AuthMiddleware.php` must be present in `/api/`. If it was just added, confirm it uploaded.
### `.env` missing on server
Create it manually via SSH (see Step 5 above). Without it, `GEMINI_API_KEY` is undefined and all API calls will fail.
### Permissions error on uploads
```bash
sudo chown -R www-data:www-data /var/www/html/lux-studio/api/uploads
sudo chmod -R 777 /var/www/html/lux-studio/api/uploads
```
---
## Quick Reference
| What changed | Action needed |
|-------------|---------------|
| Frontend only (JS/CSS/components) | Steps 2, 3 |
| Backend only (PHP files) | Step 4 |
| Both frontend and backend | Steps 2, 3, 4 |
| New `.env` values needed | Step 5 (SSH) |
---
**Last deployed:** 2026-02-27
**Server:** ai-sandbox.oliver.solutions

347
README.md
View file

@ -1,203 +1,192 @@
# Lux Studio - Cinema Studio Pro
# Lux Studio
AI-powered cinematography suite for professional image and video generation. Combines physics-based prompt engineering with Google's Imagen 3 and Veo 3.1 APIs.
AI-powered cinematography suite for professional image and video generation.
## Quick Start
**Live:** https://ai-sandbox.oliver.solutions/lux-studio/
### Prerequisites
- Node.js 18+ and npm
- PHP 7.4+
- Composer
- Google Gemini API Key ([Get one here](https://aistudio.google.com/app/apikey))
- Azure AD tenant (for SSO authentication - optional, can be disabled)
---
### Automated Setup (Recommended)
## What It Does
```bash
# Clone the repository
git clone <repository-url>
cd cinema-studio-pro
Lux Studio combines physics-based prompt engineering with Google's Imagen 3 and Veo 3.1 APIs in a project-first workflow. Create projects, generate cinematic images with professional camera and lens profiles, produce AI videos, annotate storyboards — all stored locally in your browser.
# Run the setup script
./setup.sh
```
The setup script will:
- Check prerequisites
- Install all dependencies
- Create `.env` files from examples
- Display port configuration and next steps
### Manual Installation (Alternative)
1. **Setup Backend**
```bash
cd backend
composer install
cp .env.example .env
# Edit .env and add your GEMINI_API_KEY
```
2. **Setup Frontend**
```bash
cd frontend
npm install
cp .env.example .env
# .env is already configured for local development
```
### Running the Application
**Terminal 1 - Backend:**
```bash
cd backend
php -S localhost:5015
```
**Terminal 2 - Frontend:**
```bash
cd frontend
npm run dev
```
**Access the application:**
Open your browser and navigate to: `http://localhost:3000`
### Configuration
Ports and URLs are controlled by `.env` files:
- **Backend Port**: Edit `BACKEND_PORT` in `backend/.env` (default: 5015)
- **Frontend Port**: Edit `FRONTEND_PORT` in `frontend/.env` (default: 3000)
- **Disable SSO**: Set `VITE_SSO_ENABLED=false` in `frontend/.env`
- **Switch to Production**: Comment/uncomment production URLs in `.env` files
For production deployment, see `.env.production` files and `DEPLOYMENT.md`.
---
## Features
### Image Generation (Imagen 3)
- **Cinematographer's Toolkit**: 40+ lighting presets, 8 camera bodies, 10 lens profiles
- **Physics-Based Prompts**: AI enhances prompts with real camera/lens characteristics
- **Reference Images**: Style transfer with up to 14 reference images
- **Iterative Editing**: Refine images with natural language
- 40+ cinematic lighting presets
- 8 cinema camera body profiles (sensor behaviour, dynamic range, grain)
- 10 lens profiles (bokeh, flares, chromatic aberration)
- Up to 14 reference images for style transfer
- Edit mode — refine a generated image with follow-up prompts
- Image upload for style transfer or editing
### Video Generation (Veo 3.1)
- **Text-to-Video & Image-to-Video**: Generate from prompts or reference frames
- **AI Prompt Optimizer**: Intelligent inference of camera movement and subject action
- **Native Audio**: Veo 3's built-in audio generation with dialogue support
- **Frame Extraction**: Pull stills from generated videos
- Text-to-video and image-to-video modes
- First-frame and last-frame interpolation (I2V)
- Standard and Fast model selection
- Duration options: 4s, 6s, 8s
- Frame extraction from generated videos
### Project Management
- **Project-First Workflow**: Organize generations into projects
- **Local Storage**: IndexedDB-based, no server required
- **Storyboard Editor**: Annotate and organize scenes with drag-to-reorder
- **Cross-Tab Usage**: Use generated images as video reference frames
### Project Workspace
- Project-first workflow — every image and video is tied to a project
- Persistent local storage via IndexedDB (no server account needed)
- Storyboard editor with drag-to-reorder panels and PDF export
### Authentication
- **MSAL SSO**: Microsoft Azure AD authentication
- **Toggleable**: Can be disabled for development
- **Development Credentials**: Pre-configured for quick start
- **Logout**: Easy logout from the application header
- Microsoft Azure AD SSO via MSAL (toggleable per environment)
---
## Tech Stack
| Layer | Technology |
|-------|-----------|
| Frontend | React 19, Vite, Tailwind CSS |
| Auth | @azure/msal-browser + @azure/msal-react |
| Backend | PHP 7.4+ (Apache, no separate service needed) |
| AI — Images | Google Imagen 3 via Gemini API |
| AI — Video | Google Veo 3.1 via Gemini API |
| Storage | IndexedDB (frontend) + session files (backend, auto-cleaned 24 h) |
---
## Prerequisites
- Node.js 18+
- PHP 7.4+
- Composer
- A Google Gemini API key — https://aistudio.google.com/app/apikey
- (Optional) Azure AD app registration for SSO
---
## Local Development
### 1. Configure environment files
```bash
cp backend/.env.local backend/.env
cp frontend/.env.local frontend/.env
```
Edit `backend/.env` and set your `GEMINI_API_KEY`.
### 2. Start both servers
**Recommended — automated:**
```bash
./setup.sh # Detects port conflicts, starts both servers, generates stop.sh
./stop.sh # Stop all servers
./status.sh # Check running status
```
**Manual:**
```bash
# Terminal 1 — Backend
cd backend
composer install
php -S localhost:5015
# Terminal 2 — Frontend
cd frontend
npm install
npm run dev
```
### 3. Open the app
http://localhost:3000
> SSO is enabled by default. To skip Azure AD login during development, set `VITE_SSO_ENABLED=false` in `frontend/.env` and restart.
---
## Environment Variables
### Backend (`backend/.env`)
| Variable | Description |
|----------|-------------|
| `GEMINI_API_KEY` | Google Gemini API key (required) |
| `FRONTEND_URL` | CORS allowed origin — no trailing slash |
| `SSO_ENABLED` | `true` / `false` — enable Azure AD auth |
| `BACKEND_PORT` | PHP dev server port (default: `5015`) |
| `SSO_TENANT_ID` | Azure AD tenant ID |
| `SSO_CLIENT_ID` | Azure AD client ID |
### Frontend (`frontend/.env`)
| Variable | Description |
|----------|-------------|
| `VITE_API_URL` | Backend base URL (e.g. `http://localhost:5015` for local) |
| `VITE_BASE_PATH` | App base path (`/` local, `/lux-studio/` production) |
| `VITE_GEMINI_API_KEY` | Gemini key for client-side prompt enhancement |
| `VITE_SSO_ENABLED` | `true` / `false` — show SSO login UI |
| `VITE_SSO_TENANT_ID` | Azure AD tenant ID |
| `VITE_SSO_CLIENT_ID` | Azure AD client ID |
| `VITE_SSO_REDIRECT_URI` | OAuth redirect URI (must match Azure AD portal exactly) |
---
## Production Deployment
See [NEW_DEPLOYMENT.md](NEW_DEPLOYMENT.md) for the full step-by-step guide (FileZilla + SSH).
**Server:** `ai-sandbox.oliver.solutions`
**Frontend path:** `/var/www/html/lux-studio/`
**Backend path:** `/var/www/html/lux-studio/api/`
Quick build summary:
```bash
cd frontend
cp .env.production .env
npm run build
# Upload frontend/dist/* per NEW_DEPLOYMENT.md Step 3
# Upload backend/*.php per NEW_DEPLOYMENT.md Step 4
```
---
## Troubleshooting
| Symptom | Fix |
|---------|-----|
| 404 on all API calls | Check `VITE_API_URL` is correct and the build was made after the change |
| Image generation 500 error | `AuthMiddleware.php` missing from `/api/` — upload it |
| `IMAGE_RECITATION` error | Prompt too generic — use 10+ descriptive words |
| Login redirect loop | `VITE_SSO_REDIRECT_URI` must match Azure AD portal exactly (include trailing slash) |
| Video stuck in PENDING | Check `video_operations.json` on the server; retry generation |
| Old code after deploy | Hard refresh: `Ctrl + Shift + R`, or delete `assets/` folder on server before re-uploading |
---
## Project Structure
```
cinema-studio-pro/
├── frontend/ # React frontend (port 3000)
├── frontend/ # React + Vite app
│ ├── src/
│ │ ├── components/ # React components
│ │ ├── hooks/ # Custom hooks
│ │ ├── authConfig.js # MSAL configuration
│ │ ├── components/ # UI components
│ │ ├── hooks/ # useProjects, useIndexedDB
│ │ ├── authConfig.js # MSAL config
│ │ └── App.jsx
│ ├── .env # Frontend environment variables
│ ├── .env.local # Local dev template
│ ├── .env.production # Production template
│ └── package.json
├── backend/ # PHP backend (port 8000)
│ ├── api.php # Image generation API
│ ├── video_api.php # Video generation API
│ ├── .env # Backend environment variables
│ └── composer.json
├── MDFiles/ # Documentation
└── CLAUDE.md # Development guide for AI assistants
├── backend/ # PHP APIs
│ ├── api.php # Image generation (Imagen 3)
│ ├── video_api.php # Video generation (Veo 3.1)
│ ├── enhance_prompt.php # AI prompt optimisation
│ ├── stream_video.php # Video streaming with Range support
│ ├── session_manager.php # Multi-user session isolation
│ ├── AuthMiddleware.php # SSO middleware (required by api.php)
│ ├── JWTValidator.php # Azure AD token validation
│ ├── uploads/ # Temp file storage (auto-cleaned)
│ ├── .env.local # Local dev template
│ └── .env.production # Production template
├── setup.sh # Start local dev servers
├── NEW_DEPLOYMENT.md # Production deployment guide
└── CLAUDE.md # AI assistant instructions
```
## Configuration Files
The application uses `.env` files for all configuration. Both local and production settings are managed through these files.
### Backend (.env) - Local Development
```env
BACKEND_PORT=5015
GEMINI_API_KEY=your-api-key-here
FRONTEND_URL=http://localhost:3000
SSO_ENABLED=false
SSO_TENANT_ID=e519c2e6-bc6d-4fdf-8d9c-923c2f002385
SSO_CLIENT_ID=15c0c4e2-bac0-4564-a3a6-c2717f00a6d9
```
### Frontend (.env) - Local Development
```env
FRONTEND_PORT=3000
BACKEND_PORT=5015
VITE_API_URL=http://localhost:5015
VITE_GEMINI_API_KEY=your-api-key-here
VITE_SSO_ENABLED=true
VITE_SSO_TENANT_ID=e519c2e6-bc6d-4fdf-8d9c-923c2f002385
VITE_SSO_CLIENT_ID=15c0c4e2-bac0-4564-a3a6-c2717f00a6d9
VITE_SSO_REDIRECT_URI=http://localhost:3000
NODE_ENV=development
```
**For Production:** See `.env.production` files in both `backend/` and `frontend/` directories.
## Development
### Quick Start Script
```bash
./setup.sh # Automated local setup
```
### Frontend Commands
```bash
cd frontend
npm run dev # Start development server (port from .env)
npm run build # Build for production
npm run lint # Run linter
npm run preview # Preview production build
```
### Backend Commands
```bash
cd backend
composer install # Install dependencies
php -S localhost:5015 # Start development server (use your BACKEND_PORT)
```
## Tech Stack
- **Frontend**: React 19, Vite, Tailwind CSS, MSAL, IndexedDB
- **Backend**: PHP 7.4+, Composer
- **AI Models**: Google Imagen 3, Veo 3.1, Gemini Pro
- **Authentication**: Microsoft Azure AD (MSAL)
## Documentation
Detailed documentation is available in the `MDFiles/` directory:
- `README.md` - Original user guide
- `INSTALL.md` - Deployment instructions
- `AI_IMPLEMENTATION_GUIDE.md` - Imagen 3 API patterns
- `AUTH_README.md` - Azure AD setup guide
- `QUICK_REFERENCE.md` - Common patterns
For development guidance, see `CLAUDE.md` in the root directory.
## License
MIT
## Security Notes
- Never commit `.env` files (already in .gitignore)
- API keys are sensitive - keep them secure
- HTTPS is required for production SSO
- Images auto-delete after 24 hours on the backend

View file

@ -8,17 +8,11 @@
# ----------------------------------------------------------------------------
# Backend Port Configuration
# ----------------------------------------------------------------------------
# Port on which the PHP backend server runs
# Port on which the PHP dev server runs locally
# Start backend with: php -S localhost:${BACKEND_PORT}
# NOTE: Not used in production — Apache serves PHP directly via mod_php
BACKEND_PORT=5015
# ----------------------------------------------------------------------------
# API Base Path (for video/file streaming URLs)
# ----------------------------------------------------------------------------
# For LOCAL development: Use /lux-studio-back (matches Vite proxy)
# For PRODUCTION: Set to your Apache proxy path (e.g., /lux-studio-back)
API_BASE_PATH=/lux-studio-back
# ----------------------------------------------------------------------------
# Google Gemini API Key (REQUIRED)
# ----------------------------------------------------------------------------

View file

@ -7,17 +7,10 @@
# ----------------------------------------------------------------------------
# Backend Port Configuration
# ----------------------------------------------------------------------------
# Port on which the PHP backend server runs locally
# Port on which the PHP dev server runs locally
# Start backend with: php -S localhost:5015
BACKEND_PORT=5015
# ----------------------------------------------------------------------------
# API Base Path (for video/file streaming URLs)
# ----------------------------------------------------------------------------
# For LOCAL development: Use /lux-studio-back (matches Vite proxy)
# For PRODUCTION: Set to your Apache proxy path (e.g., /lux-studio-back)
API_BASE_PATH=/lux-studio-back
# ----------------------------------------------------------------------------
# Google Gemini API Key (REQUIRED)
# ----------------------------------------------------------------------------

View file

@ -2,25 +2,10 @@
# Lux Studio Backend - PRODUCTION Environment Configuration
# ============================================================================
# This file contains production-ready settings
# Copy relevant values to .env when deploying to production server
# Server location: /opt/lux-studio-back/.env
# Deployed to: /var/www/html/lux-studio/api/.env (never overwritten by deploy.sh)
# Apache serves PHP directly via mod_php — no standalone server or proxy needed
# ============================================================================
# ----------------------------------------------------------------------------
# Backend Port Configuration
# ----------------------------------------------------------------------------
# NOTE: Backend runs on localhost:5015 (configured in systemd service)
# This port is NOT exposed to internet - only accessible via Apache proxy
# Port is hardcoded in lux-studio-backend.service, this is for reference only
BACKEND_PORT=5015
# ----------------------------------------------------------------------------
# API Base Path (for video/file streaming URLs)
# ----------------------------------------------------------------------------
# Apache proxy path - MUST match ProxyPass configuration in apache2.conf
# Used by video_api.php to generate correct video streaming URLs
API_BASE_PATH=/lux-studio-back
# ----------------------------------------------------------------------------
# Google Gemini API Key (REQUIRED)
# ----------------------------------------------------------------------------

View file

@ -1,7 +1,7 @@
# ==============================================================================
# LUX STUDIO BACKEND - SECURITY CONFIGURATION
# ==============================================================================
# Location: /opt/lux-studio-back/.htaccess
# Location: /var/www/html/lux-studio/api/.htaccess
# Purpose: Prevent direct browser access, allow only API endpoints
# ==============================================================================

757
deploy.sh
View file

@ -1,512 +1,281 @@
#!/bin/bash
################################################################################
# Lux Studio Full Deployment Script
# Purpose: Automated deployment of Lux Studio (backend + frontend)
# Usage: Place entire project in /opt/lux-studio-back/ and run: sudo ./deploy.sh
# Lux Studio — Production Deployment Script
#
# Usage:
# cd /opt/cinema-studio-pro
# sudo ./deploy.sh
#
# What it does:
# 1. Builds the React frontend using frontend/.env.production
# 2. Deploys built files → /var/www/html/lux-studio/
# 3. Deploys backend PHP → /var/www/html/lux-studio/api/
# 4. Verifies the deployment
#
# Apache serves PHP directly — no systemd service or proxy needed.
# Apache configuration (AllowOverride, modules) is managed separately by the operator.
# The backend .env on the server is never overwritten (preserves API keys).
################################################################################
set -e # Exit on any error
set -e
# Colors for output
# ─── Colors ───────────────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
NC='\033[0m'
# Configuration
PROJECT_DIR="/opt/lux-studio-back"
FRONTEND_DIR="/var/www/html/lux-studio"
SERVICE_NAME="lux-studio-backend"
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
APACHE_CONF="/etc/apache2/apache2.conf"
BACKEND_PORT=5015
# ─── Configuration ─────────────────────────────────────────────────────────────
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FRONTEND_SRC="$SCRIPT_DIR/frontend"
BACKEND_SRC="$SCRIPT_DIR/backend"
WEB_ROOT="/var/www/html/lux-studio"
API_ROOT="$WEB_ROOT/api"
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE} Lux Studio Full Deployment Script${NC}"
echo -e "${BLUE}========================================${NC}"
# PHP files that must never be deployed to the server
SKIP_PHP=("test.php" "config.example.php")
# ─── Helper functions ─────────────────────────────────────────────────────────
step() { echo ""; echo -e "${YELLOW}[$1] $2...${NC}"; }
ok() { echo -e "${GREEN}$1${NC}"; }
warn() { echo -e "${YELLOW}$1${NC}"; }
fail() { echo -e "${RED} Error: $1${NC}"; exit 1; }
# ─── Header ───────────────────────────────────────────────────────────────────
echo ""
echo -e "${BLUE}========================================"
echo -e " Lux Studio — Production Deployment"
echo -e "========================================${NC}"
echo ""
echo " Source: $SCRIPT_DIR"
echo " Frontend: $WEB_ROOT"
echo " Backend: $API_ROOT"
echo ""
# Check if running as root
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}Error: This script must be run as root${NC}"
echo "Please run: sudo $0"
exit 1
# ─── Root check ───────────────────────────────────────────────────────────────
[[ $EUID -ne 0 ]] && fail "This script must be run as root. Use: sudo ./deploy.sh"
# ─────────────────────────────────────────────────────────────────────────────
step "1/6" "Preflight checks"
# ─────────────────────────────────────────────────────────────────────────────
[ -d "$FRONTEND_SRC" ] || fail "frontend/ directory not found in $SCRIPT_DIR"
[ -d "$BACKEND_SRC" ] || fail "backend/ directory not found in $SCRIPT_DIR"
[ -f "$FRONTEND_SRC/.env.production" ] \
|| fail "frontend/.env.production not found — cannot build for production"
[ -f "$BACKEND_SRC/.env.production" ] \
|| warn "backend/.env.production not found — /api/.env will not be created automatically"
# Check required system commands
for cmd in php node npm; do
command -v "$cmd" &>/dev/null \
&& ok "$cmd: $(command -v $cmd)" \
|| fail "$cmd is not installed"
done
ok "Preflight passed"
# ─────────────────────────────────────────────────────────────────────────────
step "2/6" "Building frontend"
# ─────────────────────────────────────────────────────────────────────────────
cd "$FRONTEND_SRC"
# Always use .env.production for production builds — never use a cached .env
cp .env.production .env
ok "frontend/.env overwritten from .env.production"
# Install npm dependencies if node_modules is absent or package.json changed
echo " Checking npm dependencies..."
npm install --silent
ok "npm dependencies ready"
echo " Building (this may take 3060 seconds)..."
npm run build
ok "Build complete → frontend/dist/"
# Confirm the correct API path was baked into the bundle
if grep -qo "lux-studio/api" dist/assets/*.js 2>/dev/null; then
ok "API URL verified in bundle: lux-studio/api"
else
fail "Bundle does not contain 'lux-studio/api'. Check VITE_API_URL in frontend/.env.production"
fi
# Check if running from correct directory
CURRENT_DIR=$(pwd)
if [ "$CURRENT_DIR" != "$PROJECT_DIR" ]; then
echo -e "${YELLOW}⚠ Warning: Not running from $PROJECT_DIR${NC}"
echo "Current directory: $CURRENT_DIR"
cd "$SCRIPT_DIR"
# ─────────────────────────────────────────────────────────────────────────────
step "3/6" "Deploying frontend to $WEB_ROOT"
# ─────────────────────────────────────────────────────────────────────────────
mkdir -p "$WEB_ROOT"
# Delete old assets/ first — Vite produces differently hash-named files each
# build. Leaving old files causes stale JS to be served.
if [ -d "$WEB_ROOT/assets" ]; then
rm -rf "$WEB_ROOT/assets"
ok "Old assets/ removed (hash names change each build)"
fi
# Copy built output
cp "$FRONTEND_SRC/dist/index.html" "$WEB_ROOT/index.html"
cp -r "$FRONTEND_SRC/dist/assets" "$WEB_ROOT/assets"
ok "index.html and assets/ deployed"
# Copy static public assets (logos, favicon — not always present in all builds)
for item in LUX_STUDIO_LOGO.svg LUX_STUDIO_LOGO.png; do
src="$FRONTEND_SRC/dist/$item"
[ -e "$src" ] && cp "$src" "$WEB_ROOT/$item"
done
ok "Static assets deployed (LUX_STUDIO_LOGO.svg, LUX_STUDIO_LOGO.png)"
# .htaccess is NOT copied into dist/ by Vite — must be taken from source
if [ -f "$FRONTEND_SRC/.htaccess" ]; then
cp "$FRONTEND_SRC/.htaccess" "$WEB_ROOT/.htaccess"
ok ".htaccess deployed from frontend/.htaccess (not from dist/)"
else
warn "frontend/.htaccess not found — React Router deep links will break"
fi
chown -R www-data:www-data "$WEB_ROOT"
chmod -R 755 "$WEB_ROOT"
ok "Permissions set (www-data:www-data, 755)"
# ─────────────────────────────────────────────────────────────────────────────
step "4/6" "Deploying backend PHP to $API_ROOT"
# ─────────────────────────────────────────────────────────────────────────────
mkdir -p "$API_ROOT"
# Copy all .php files from backend/ except those in SKIP_PHP
PHP_COUNT=0
for php_file in "$BACKEND_SRC"/*.php; do
filename=$(basename "$php_file")
skip=false
for skip_name in "${SKIP_PHP[@]}"; do
[ "$filename" = "$skip_name" ] && skip=true && break
done
if [ "$skip" = false ]; then
cp "$php_file" "$API_ROOT/$filename"
PHP_COUNT=$((PHP_COUNT + 1))
fi
done
ok "$PHP_COUNT PHP files deployed (skipped: ${SKIP_PHP[*]})"
# Copy backend .htaccess (security rules, blocks .env/vendor/direct class access)
if [ -f "$BACKEND_SRC/.htaccess" ]; then
cp "$BACKEND_SRC/.htaccess" "$API_ROOT/.htaccess"
ok "Backend .htaccess deployed"
fi
# ── .env handling ──────────────────────────────────────────────────────────────
# The production .env contains the real GEMINI_API_KEY.
# NEVER overwrite it — only create it if it does not exist yet.
if [ -f "$API_ROOT/.env" ]; then
ok "/api/.env already exists — not overwritten (production secrets preserved)"
else
if [ -f "$BACKEND_SRC/.env.production" ]; then
cp "$BACKEND_SRC/.env.production" "$API_ROOT/.env"
ok "Created /api/.env from backend/.env.production"
echo ""
warn "ACTION REQUIRED: Verify GEMINI_API_KEY and FRONTEND_URL in /api/.env:"
warn " sudo nano $API_ROOT/.env"
echo ""
else
warn "backend/.env.production not found — /api/.env was NOT created"
warn "Create it manually: sudo nano $API_ROOT/.env"
warn "Required keys: GEMINI_API_KEY, FRONTEND_URL, SSO_ENABLED"
fi
fi
# Create uploads directory (PHP writes generated images/videos here)
mkdir -p "$API_ROOT/uploads/sessions"
# Set ownership before chmod so chmod applies correctly
chown -R www-data:www-data "$API_ROOT"
chmod -R 755 "$API_ROOT"
# www-data must be able to write generated files
chmod -R 777 "$API_ROOT/uploads"
ok "Permissions set (uploads/: 777 for www-data writes)"
# ─────────────────────────────────────────────────────────────────────────────
step "5/6" "Verifying deployment"
# ─────────────────────────────────────────────────────────────────────────────
ERRORS=0
check() {
# $1 = path to check, $2 = label, $3 = "warn" (non-fatal) or empty (fatal)
if [ -e "$1" ]; then
ok "$2"
elif [ "$3" = "warn" ]; then
warn "$2 not found"
else
echo -e "${RED}$2 — MISSING${NC}"
ERRORS=$((ERRORS+1))
fi
}
# Frontend
check "$WEB_ROOT/index.html" "index.html"
check "$WEB_ROOT/assets" "assets/ directory"
check "$WEB_ROOT/.htaccess" ".htaccess (frontend)" warn
# Backend
check "$API_ROOT/api.php" "api.php"
check "$API_ROOT/AuthMiddleware.php" "AuthMiddleware.php ← api.php requires this"
check "$API_ROOT/video_api.php" "video_api.php"
check "$API_ROOT/enhance_prompt.php" "enhance_prompt.php"
check "$API_ROOT/.htaccess" ".htaccess (backend)"
check "$API_ROOT/uploads/sessions" "uploads/sessions/"
if [ -f "$API_ROOT/.env" ]; then
ok "/api/.env present"
else
echo -e "${RED} ✗ /api/.env MISSING — all API calls will fail without it${NC}"
ERRORS=$((ERRORS+1))
fi
# Confirm bundle has the right API URL
if grep -qo "lux-studio/api" "$WEB_ROOT"/assets/*.js 2>/dev/null; then
ok "Bundle contains correct API path (lux-studio/api)"
else
warn "Could not verify API path in deployed bundle"
fi
# ─────────────────────────────────────────────────────────────────────────────
step "6/6" "Summary"
# ─────────────────────────────────────────────────────────────────────────────
echo ""
echo -e "${BLUE} Deployed:${NC}"
echo " Frontend → $WEB_ROOT"
echo " Backend → $API_ROOT"
echo ""
echo -e "${BLUE} Live URL:${NC}"
echo " https://ai-sandbox.oliver.solutions/lux-studio/"
echo ""
echo -e "${BLUE} Useful commands:${NC}"
echo " Check .env: sudo cat $API_ROOT/.env"
echo " Apache errors: sudo tail -f /var/log/apache2/error.log"
echo " Reload Apache: sudo systemctl reload apache2"
echo " Re-deploy: cd $SCRIPT_DIR && sudo ./deploy.sh"
echo ""
echo -e "${BLUE} Test checklist:${NC}"
echo " 1. Hard refresh in browser: Ctrl + Shift + R"
echo " 2. F12 → Network: API calls go to /lux-studio/api/ (not /lux-studio-back/)"
echo " 3. No 404 errors in the Network tab"
echo " 4. Create a project and generate an image with a 10+ word prompt"
echo ""
if [ $ERRORS -gt 0 ]; then
echo -e "${YELLOW}$ERRORS check(s) failed — review the output above before testing${NC}"
echo ""
exit 1
else
echo -e "${GREEN} ✓ All checks passed — deployment successful!${NC}"
echo ""
fi
echo -e "${YELLOW}[1/15] Checking project structure...${NC}"
# Check if backend directory exists
if [ ! -d "$PROJECT_DIR" ]; then
echo -e "${RED}Error: Project directory $PROJECT_DIR does not exist${NC}"
echo "Please upload the entire project to $PROJECT_DIR first"
exit 1
fi
echo -e "${GREEN} ✓ Project directory exists${NC}"
# Check if backend files exist
if [ ! -f "$PROJECT_DIR/api.php" ]; then
echo -e "${RED}Error: Backend files not found in $PROJECT_DIR${NC}"
echo "Please ensure backend PHP files are in $PROJECT_DIR"
exit 1
fi
echo -e "${GREEN} ✓ Backend files found${NC}"
# Check if frontend directory exists in project
FRONTEND_SOURCE="$PROJECT_DIR/frontend"
HAS_FRONTEND=false
if [ -d "$FRONTEND_SOURCE" ]; then
echo -e "${GREEN} ✓ Frontend directory found (will build and deploy)${NC}"
HAS_FRONTEND=true
else
echo -e "${YELLOW} ⚠ Frontend directory not found (backend-only deployment)${NC}"
fi
echo ""
echo -e "${YELLOW}[2/15] Checking system requirements...${NC}"
# Check PHP
if ! command -v php &> /dev/null; then
echo -e "${RED}Error: PHP is not installed${NC}"
exit 1
fi
PHP_VERSION=$(php -v | head -n 1 | cut -d " " -f 2 | cut -d "." -f 1-2)
echo -e "${GREEN} ✓ PHP $PHP_VERSION installed${NC}"
# Check Composer
if ! command -v composer &> /dev/null; then
echo -e "${YELLOW} ⚠ Composer not found, installing...${NC}"
cd ~
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php --quiet --install-dir=/usr/local/bin --filename=composer
php -r "unlink('composer-setup.php');"
echo -e "${GREEN} ✓ Composer installed${NC}"
else
COMPOSER_VERSION=$(composer --version | head -n 1 | cut -d " " -f 3)
echo -e "${GREEN} ✓ Composer $COMPOSER_VERSION installed${NC}"
fi
# Check Apache
if ! command -v apache2 &> /dev/null; then
echo -e "${RED}Error: Apache is not installed${NC}"
exit 1
fi
echo -e "${GREEN} ✓ Apache installed${NC}"
# Check Node.js if frontend exists
if [ "$HAS_FRONTEND" = true ]; then
if ! command -v node &> /dev/null; then
echo -e "${YELLOW} ⚠ Node.js not found, installing...${NC}"
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs
echo -e "${GREEN} ✓ Node.js installed${NC}"
else
NODE_VERSION=$(node -v)
echo -e "${GREEN} ✓ Node.js $NODE_VERSION installed${NC}"
fi
if ! command -v npm &> /dev/null; then
echo -e "${RED}Error: npm is not installed${NC}"
exit 1
fi
NPM_VERSION=$(npm -v)
echo -e "${GREEN} ✓ npm $NPM_VERSION installed${NC}"
fi
echo ""
echo -e "${YELLOW}[3/15] Installing backend dependencies...${NC}"
cd "$PROJECT_DIR"
# Install Composer dependencies
if [ ! -d "vendor" ]; then
echo " Installing PHP dependencies..."
sudo -u www-data composer install --no-dev --optimize-autoloader
echo -e "${GREEN} ✓ PHP dependencies installed${NC}"
else
echo -e "${GREEN} ✓ PHP dependencies already installed${NC}"
fi
echo ""
echo -e "${YELLOW}[4/15] Configuring backend environment...${NC}"
# Create .env if not exists
if [ ! -f "$PROJECT_DIR/.env" ]; then
if [ -f "$PROJECT_DIR/.env.production" ]; then
cp "$PROJECT_DIR/.env.production" "$PROJECT_DIR/.env"
echo -e "${GREEN} ✓ Created .env from .env.production${NC}"
echo -e "${GREEN} ✓ Production settings applied${NC}"
else
echo -e "${RED} Error: .env.production not found${NC}"
echo -e "${YELLOW} Please ensure backend/.env.production exists${NC}"
exit 1
fi
else
echo -e "${GREEN} ✓ .env file exists${NC}"
echo -e "${YELLOW} ⚠ Using existing .env (not overwriting)${NC}"
fi
# Create uploads directory
mkdir -p "$PROJECT_DIR/uploads/sessions"
echo -e "${GREEN} ✓ Uploads directory created${NC}"
# Set backend permissions
chown -R www-data:www-data "$PROJECT_DIR"
chmod -R 755 "$PROJECT_DIR"
chmod -R 777 "$PROJECT_DIR/uploads"
echo -e "${GREEN} ✓ Backend permissions set${NC}"
echo ""
echo -e "${YELLOW}[5/15] Building and deploying frontend...${NC}"
if [ "$HAS_FRONTEND" = true ]; then
cd "$FRONTEND_SOURCE"
# Check for production .env
if [ ! -f ".env" ]; then
if [ -f ".env.production" ]; then
echo " Creating frontend .env from .env.production..."
cp ".env.production" ".env"
echo -e "${GREEN} ✓ Created frontend .env with production settings${NC}"
else
echo -e "${RED} Error: .env.production not found${NC}"
echo -e "${YELLOW} Please ensure frontend/.env.production exists${NC}"
exit 1
fi
else
echo -e "${GREEN} ✓ Frontend .env exists${NC}"
echo -e "${YELLOW} ⚠ Using existing .env (not overwriting)${NC}"
fi
# Install npm dependencies
echo " Installing npm dependencies..."
npm install --silent
echo -e "${GREEN} ✓ npm dependencies installed${NC}"
# Build frontend
echo " Building frontend (this may take 30-60 seconds)..."
npm run build
echo -e "${GREEN} ✓ Frontend built successfully${NC}"
# Deploy frontend
echo " Deploying frontend to $FRONTEND_DIR..."
mkdir -p "$FRONTEND_DIR"
rm -rf "$FRONTEND_DIR"/*
cp -r dist/* "$FRONTEND_DIR/"
# Copy .htaccess if exists
if [ -f ".htaccess" ]; then
cp ".htaccess" "$FRONTEND_DIR/"
echo -e "${GREEN} ✓ .htaccess copied${NC}"
fi
# Set frontend permissions
chown -R www-data:www-data "$FRONTEND_DIR"
chmod -R 755 "$FRONTEND_DIR"
echo -e "${GREEN} ✓ Frontend deployed to $FRONTEND_DIR${NC}"
# Verify deployment
if [ -f "$FRONTEND_DIR/index.html" ]; then
echo -e "${GREEN} ✓ Frontend deployment verified${NC}"
else
echo -e "${RED} Error: Frontend deployment failed${NC}"
exit 1
fi
else
echo -e "${YELLOW} ⚠ Skipping frontend build (no frontend directory)${NC}"
fi
echo ""
echo -e "${YELLOW}[6/15] Setting up systemd service...${NC}"
# Check if service file exists in project
if [ -f "$PROJECT_DIR/lux-studio-backend.service" ]; then
if [ ! -f "$SERVICE_FILE" ] || [ "$PROJECT_DIR/lux-studio-backend.service" -nt "$SERVICE_FILE" ]; then
echo " Copying service file to systemd..."
cp "$PROJECT_DIR/lux-studio-backend.service" "$SERVICE_FILE"
chmod 644 "$SERVICE_FILE"
echo -e "${GREEN} ✓ Service file installed${NC}"
else
echo -e "${GREEN} ✓ Service file already up to date${NC}"
fi
else
if [ ! -f "$SERVICE_FILE" ]; then
echo -e "${RED} Error: Service file not found${NC}"
echo " Please ensure lux-studio-backend.service exists in project root"
exit 1
fi
echo -e "${GREEN} ✓ Service file exists${NC}"
fi
echo ""
echo -e "${YELLOW}[7/15] Configuring Apache...${NC}"
# Enable required modules
echo " Enabling Apache modules..."
a2enmod rewrite proxy proxy_http headers ssl 2>/dev/null || true
echo -e "${GREEN} ✓ Apache modules enabled${NC}"
# Check if Apache config already has Lux Studio configuration
if grep -q "lux-studio-back" "$APACHE_CONF"; then
echo -e "${GREEN} ✓ Apache configuration already present${NC}"
else
echo " Adding Lux Studio configuration to Apache..."
# Create backup
cp "$APACHE_CONF" "${APACHE_CONF}.backup-$(date +%Y%m%d-%H%M%S)"
echo -e "${GREEN} ✓ Apache config backed up${NC}"
# Check if apache config file exists in project
if [ -f "$PROJECT_DIR/lux-studio-apache.conf" ]; then
# Add configuration
cat >> "$APACHE_CONF" << 'EOF'
# ==============================================================================
# LUX STUDIO CONFIGURATION
# ==============================================================================
# Backend API Proxy
ProxyPass /lux-studio-back/ http://localhost:5015/
ProxyPassReverse /lux-studio-back/ http://localhost:5015/
# Frontend Directory
<Directory /var/www/html/lux-studio>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# Security - Block backend source access
<Directory /opt/lux-studio-back>
Require all denied
</Directory>
# CORS Headers
<Location /lux-studio-back>
Header set Access-Control-Allow-Origin "https://ai-sandbox.oliver.solutions"
Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With"
Header set Access-Control-Allow-Credentials "true"
</Location>
# ==============================================================================
# END LUX STUDIO CONFIGURATION
# ==============================================================================
EOF
echo -e "${GREEN} ✓ Apache configuration added${NC}"
else
echo -e "${YELLOW} ⚠ Apache config file not found, please add manually${NC}"
echo " Add the contents of lux-studio-apache.conf to $APACHE_CONF"
fi
fi
# Test Apache configuration
echo " Testing Apache configuration..."
if apache2ctl configtest 2>&1 | grep -q "Syntax OK"; then
echo -e "${GREEN} ✓ Apache configuration valid${NC}"
else
echo -e "${RED} Error: Apache configuration invalid${NC}"
apache2ctl configtest
exit 1
fi
# Reload Apache
echo " Reloading Apache..."
systemctl reload apache2
echo -e "${GREEN} ✓ Apache reloaded${NC}"
echo ""
echo -e "${YELLOW}[8/15] Checking for port conflicts...${NC}"
if lsof -Pi :$BACKEND_PORT -sTCP:LISTEN -t >/dev/null 2>&1 ; then
echo -e "${YELLOW} ⚠ Port $BACKEND_PORT is already in use${NC}"
PID=$(lsof -Pi :$BACKEND_PORT -sTCP:LISTEN -t)
PROCESS=$(ps -p $PID -o comm=)
echo " Process: $PROCESS (PID: $PID)"
if [[ $PROCESS == *"php"* ]]; then
echo " Stopping existing PHP service..."
systemctl stop $SERVICE_NAME 2>/dev/null || true
sleep 2
# Force kill if still running
if lsof -Pi :$BACKEND_PORT -sTCP:LISTEN -t >/dev/null 2>&1 ; then
echo " Force killing process on port $BACKEND_PORT..."
kill -9 $PID 2>/dev/null || true
sleep 1
fi
echo -e "${GREEN} ✓ Port cleared${NC}"
else
echo -e "${RED} Error: Port $BACKEND_PORT is used by another service${NC}"
exit 1
fi
else
echo -e "${GREEN} ✓ Port $BACKEND_PORT is available${NC}"
fi
echo ""
echo -e "${YELLOW}[9/15] Starting backend service...${NC}"
systemctl daemon-reload
echo -e "${GREEN} ✓ Systemd daemon reloaded${NC}"
systemctl enable $SERVICE_NAME
echo -e "${GREEN} ✓ Service enabled (auto-start on boot)${NC}"
systemctl start $SERVICE_NAME
echo " Waiting for service to initialize..."
sleep 3
# Check if service started
if systemctl is-active --quiet $SERVICE_NAME; then
echo -e "${GREEN} ✓ Backend service started${NC}"
else
echo -e "${RED} Error: Service failed to start${NC}"
echo " Checking logs:"
journalctl -u $SERVICE_NAME -n 20 --no-pager
exit 1
fi
echo ""
echo -e "${YELLOW}[10/15] Verifying backend service...${NC}"
# Check port is listening
if lsof -Pi :$BACKEND_PORT -sTCP:LISTEN -t >/dev/null 2>&1 ; then
echo -e "${GREEN} ✓ Backend listening on port $BACKEND_PORT${NC}"
else
echo -e "${RED} Error: Backend not listening on port $BACKEND_PORT${NC}"
exit 1
fi
# Test backend directly
echo " Testing backend API..."
if curl -f -s http://localhost:$BACKEND_PORT/server-check.php > /dev/null 2>&1; then
echo -e "${GREEN} ✓ Backend API responding${NC}"
else
echo -e "${YELLOW} ⚠ Backend API test failed (might be normal)${NC}"
fi
echo ""
echo -e "${YELLOW}[11/15] Testing Apache proxy...${NC}"
# Get server domain from Apache config or use localhost
DOMAIN=$(grep -m 1 "ServerName" "$APACHE_CONF" | awk '{print $2}')
if [ -z "$DOMAIN" ]; then
DOMAIN="localhost"
fi
echo " Testing proxy to backend..."
if curl -f -s -k "https://$DOMAIN/lux-studio-back/server-check.php" > /dev/null 2>&1; then
echo -e "${GREEN} ✓ Apache proxy working${NC}"
else
echo -e "${YELLOW} ⚠ Proxy test failed (might need manual verification)${NC}"
fi
echo ""
echo -e "${YELLOW}[12/15] Verifying frontend deployment...${NC}"
if [ -f "$FRONTEND_DIR/index.html" ]; then
echo -e "${GREEN} ✓ Frontend index.html exists${NC}"
else
echo -e "${YELLOW} ⚠ Frontend index.html not found${NC}"
fi
if [ -d "$FRONTEND_DIR/assets" ]; then
ASSET_COUNT=$(ls -1 "$FRONTEND_DIR/assets" 2>/dev/null | wc -l)
echo -e "${GREEN} ✓ Frontend assets directory exists ($ASSET_COUNT files)${NC}"
else
echo -e "${YELLOW} ⚠ Frontend assets directory not found${NC}"
fi
if [ -f "$FRONTEND_DIR/LUX_STUDIO_LOGO.svg" ]; then
echo -e "${GREEN} ✓ Logo file exists${NC}"
else
echo -e "${YELLOW} ⚠ Logo file not found${NC}"
fi
echo ""
echo -e "${YELLOW}[13/15] Checking API paths in build...${NC}"
if [ -d "$FRONTEND_DIR/assets" ]; then
# Check if built files use correct API path
if grep -r "lux-studio-back" "$FRONTEND_DIR/assets"/*.js >/dev/null 2>&1; then
echo -e "${GREEN} ✓ Frontend uses correct API path (/lux-studio-back/)${NC}"
else
echo -e "${YELLOW} ⚠ Could not verify API path in frontend build${NC}"
fi
# Check for old API path
if grep -r '"/api/api.php"' "$FRONTEND_DIR/assets"/*.js >/dev/null 2>&1; then
echo -e "${RED} ✗ Frontend still uses old API path (/api/)${NC}"
echo " This will cause 404 errors. Rebuild frontend with correct configuration."
fi
fi
echo ""
echo -e "${YELLOW}[14/15] Service status...${NC}"
systemctl status $SERVICE_NAME --no-pager | head -10
echo ""
echo -e "${YELLOW}[15/15] Final health checks...${NC}"
# Summary
BACKEND_OK="✓"
FRONTEND_OK="✓"
PROXY_OK="✓"
if ! systemctl is-active --quiet $SERVICE_NAME; then
BACKEND_OK="✗"
fi
if [ ! -f "$FRONTEND_DIR/index.html" ]; then
FRONTEND_OK="✗"
fi
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Deployment Complete!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo -e "${BLUE}Status Summary:${NC}"
echo -e " Backend Service: ${BACKEND_OK}"
echo -e " Frontend Files: ${FRONTEND_OK}"
echo -e " Apache Proxy: ${PROXY_OK}"
echo ""
echo -e "${BLUE}Deployment Information:${NC}"
echo " Backend Port: $BACKEND_PORT"
echo " Backend Dir: $PROJECT_DIR"
echo " Frontend Dir: $FRONTEND_DIR"
echo " Service Name: $SERVICE_NAME"
echo ""
echo -e "${BLUE}Access URLs:${NC}"
echo " Frontend: https://ai-sandbox.oliver.solutions/lux-studio/"
echo " Backend: https://ai-sandbox.oliver.solutions/lux-studio-back/"
echo ""
echo -e "${BLUE}Service Commands:${NC}"
echo " Status: sudo systemctl status $SERVICE_NAME"
echo " Logs: sudo journalctl -u $SERVICE_NAME -f"
echo " Restart: sudo systemctl restart $SERVICE_NAME"
echo ""
echo -e "${BLUE}Testing:${NC}"
echo " 1. Clear browser cache (Ctrl+Shift+Delete)"
echo " 2. Visit: https://ai-sandbox.oliver.solutions/lux-studio/"
echo " 3. Login with Microsoft SSO"
echo " 4. Create a project and test image/video generation"
echo ""
if [ "$BACKEND_OK" = "✓" ] && [ "$FRONTEND_OK" = "✓" ]; then
echo -e "${GREEN}✓ Deployment successful!${NC}"
else
echo -e "${YELLOW}⚠ Deployment completed with warnings. Please review above.${NC}"
fi
echo ""

View file

@ -26,7 +26,7 @@ VITE_BASE_PATH=/lux-studio/
# Backend API URL (REQUIRED)
# ----------------------------------------------------------------------------
# PRODUCTION: Use Apache proxy
VITE_API_URL=https://ai-sandbox.oliver.solutions/lux-studio-back
VITE_API_URL=https://ai-sandbox.oliver.solutions/lux-studio/api
# ----------------------------------------------------------------------------
# Google Gemini API Key

View file

@ -1,168 +0,0 @@
# Lux Studio - AI Cinematography Suite
## Overview
Lux Studio is a comprehensive AI-powered creative suite for filmmakers and visual artists. It combines professional cinematography prompt generation, AI video generation (via Google Veo 3.1), and project management with storyboarding capabilities.
## Key Features
### Image Generation
- **27 Cinematography Presets**: Documentary, Drama, Auteur, and Commercial styles
- **Professional Equipment**: 6 cinema cameras, 7 cinema lenses with compatibility matrix
- **Film Stock & Texture Engine**: Deep texture generation for photorealistic materials
- **AI-Optimized Prompts**: Powered by Google Gemini for precise prompt engineering
### Video Generation
- **Google Veo 3.1 Integration**: Generate 4-8 second AI videos
- **Model Options**: Standard (higher quality) and Fast (50% cost savings)
- **Image-to-Video (I2V)**: Use reference images to guide video generation
- **Audio Generation**: Optional AI-generated audio tracks
- **Frame Extraction**: Extract frames from videos and save to library
### Project Management
- **Organize Work**: Create projects to organize generated images and videos
- **Library**: Store and browse all generated assets
- **Re-run Videos**: Regenerate videos with saved settings and reference images
### Storyboarding
- **Create Storyboards**: Select images from library to build visual sequences
- **Drag-to-Reorder**: Arrange frames with intuitive drag-and-drop
- **Frame Annotations**: Add scene notes and descriptions
- **Generate Video per Frame**: Send frames directly to Video Gen
- **Export Options**: PDF and PNG export for sharing
## Data Storage
### Where is data stored?
All project data is stored locally in your browser using **IndexedDB**, a client-side database. This means:
- **Projects, images, and videos** are stored on your device
- **Data persists** between browser sessions
- **No server uploads** for library content (videos are generated server-side but stored locally)
- **Device-specific**: Data doesn't sync between devices
### Database Structure
```
IndexedDB: CinemaStudioPro
├── projects # Project metadata (name, dates, userId)
├── items # Images and videos (base64 data, prompts, settings)
└── storyboards # Storyboard configurations (frames, annotations)
```
### Storage Considerations
- Large video files are stored as URLs pointing to the server
- Images are stored as base64-encoded data
- Browser storage limits apply (typically 50-100MB+)
- Clear browser data will remove all projects
### Production Migration Path
The current IndexedDB storage is ideal for development but not suitable for production deployment. For hosted environments, migrate to server-side storage:
**Recommended Architecture:**
```
Development (Current):
Browser IndexedDB → base64 images stored locally
Production:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Frontend │ ──► │ Backend │ ──► │ S3/Cloud │
│ (React) │ │ API │ │ Storage │
└─────────────┘ └─────────────┘ └─────────────┘
┌─────────────┐
│ PostgreSQL │
│ (metadata) │
└─────────────┘
```
**Migration Steps:**
1. **Cloud Storage**: Store images/videos in AWS S3, Google Cloud Storage, or similar
2. **Backend API**: Create REST endpoints for CRUD operations
3. **Database**: PostgreSQL/MySQL for project metadata, user data, and asset references
4. **Update Hooks**: Modify `useProjects.js` to call API endpoints instead of IndexedDB
**API Endpoint Examples:**
```
POST /api/projects → createProject()
GET /api/projects → loadProjects()
DELETE /api/projects/:id → deleteProject()
POST /api/projects/:id/items → addItemToProject()
GET /api/projects/:id/items → getProjectItems()
```
The hook abstraction (`useProjects`, `useIndexedDB`) makes this migration clean - swap the implementation without changing UI components.
## User Isolation (SSO Ready)
The application is prepared for multi-user support via SSO integration:
- Each project includes a `userId` field
- Projects are filtered by user ID when loading
- Currently uses `'local'` as placeholder until SSO is implemented
### SSO Integration
To add SSO authentication, update the `getCurrentUserId()` function in `src/hooks/useProjects.js`:
```javascript
const getCurrentUserId = () => {
// Replace with your auth provider
return authContext.user?.id || 'local';
};
```
## Installation
### Prerequisites
- Node.js 18.0+
- Google Gemini API key
- PHP backend for video generation (Veo 3.1 API)
### Setup
1. **Install dependencies**
```bash
cd Prompt_Studio
npm install
```
2. **Configure environment**
```env
VITE_GEMINI_API_KEY=your_gemini_api_key
```
3. **Start development server**
```bash
npm run dev
```
4. **Build for production**
```bash
npm run build
```
## Technology Stack
- **Frontend**: React 18, Vite, Tailwind CSS
- **AI Services**: Google Gemini (prompts), Google Veo 3.1 (video)
- **Storage**: IndexedDB (client-side)
- **Drag & Drop**: @dnd-kit
- **Export**: jsPDF, html2canvas
## API Keys Required
| Service | Purpose | Environment Variable |
|---------|---------|---------------------|
| Google Gemini | Prompt optimization | `VITE_GEMINI_API_KEY` |
| Google Veo 3.1 | Video generation | Configured in PHP backend |
## License
Proprietary - All rights reserved

View file

@ -3,6 +3,7 @@
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/LUX_STUDIO_LOGO.svg" />
<link rel="icon" type="image/png" href="/LUX_STUDIO_LOGO.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lux Studio - AI Cinematography</title>
</head>

View file

@ -52,6 +52,7 @@
"resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.30.0.tgz",
"integrity": "sha512-I0XlIGVdM4E9kYP5eTjgW8fgATdzwxJvQ6bm2PNiHaZhEuUz47NYw1xHthC9R+lXz4i9zbShS0VdLyxd7n0GGA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@azure/msal-common": "14.16.1"
},
@ -112,6 +113,7 @@
"integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.28.6",
"@babel/generator": "^7.28.6",
@ -389,6 +391,7 @@
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@dnd-kit/accessibility": "^3.1.1",
"@dnd-kit/utilities": "^3.2.2",
@ -1181,9 +1184,9 @@
"license": "MIT"
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz",
"integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
"integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
"cpu": [
"arm"
],
@ -1195,9 +1198,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz",
"integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
"integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
"cpu": [
"arm64"
],
@ -1209,9 +1212,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz",
"integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
"integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
"cpu": [
"arm64"
],
@ -1223,9 +1226,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz",
"integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
"integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
"cpu": [
"x64"
],
@ -1237,9 +1240,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz",
"integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
"integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
"cpu": [
"arm64"
],
@ -1251,9 +1254,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz",
"integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
"integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
"cpu": [
"x64"
],
@ -1265,9 +1268,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz",
"integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
"integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
"cpu": [
"arm"
],
@ -1279,9 +1282,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz",
"integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
"integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
"cpu": [
"arm"
],
@ -1293,9 +1296,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz",
"integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
"integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
"cpu": [
"arm64"
],
@ -1307,9 +1310,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz",
"integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
"integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
"cpu": [
"arm64"
],
@ -1321,9 +1324,9 @@
]
},
"node_modules/@rollup/rollup-linux-loong64-gnu": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz",
"integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
"integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
"cpu": [
"loong64"
],
@ -1335,9 +1338,9 @@
]
},
"node_modules/@rollup/rollup-linux-loong64-musl": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz",
"integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
"integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
"cpu": [
"loong64"
],
@ -1349,9 +1352,9 @@
]
},
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz",
"integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
"integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
"cpu": [
"ppc64"
],
@ -1363,9 +1366,9 @@
]
},
"node_modules/@rollup/rollup-linux-ppc64-musl": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz",
"integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
"integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
"cpu": [
"ppc64"
],
@ -1377,9 +1380,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz",
"integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
"integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
"cpu": [
"riscv64"
],
@ -1391,9 +1394,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz",
"integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
"integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
"cpu": [
"riscv64"
],
@ -1405,9 +1408,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz",
"integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
"integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
"cpu": [
"s390x"
],
@ -1419,9 +1422,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz",
"integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
"integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
"cpu": [
"x64"
],
@ -1433,9 +1436,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz",
"integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
"integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
"cpu": [
"x64"
],
@ -1447,9 +1450,9 @@
]
},
"node_modules/@rollup/rollup-openbsd-x64": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz",
"integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
"integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
"cpu": [
"x64"
],
@ -1461,9 +1464,9 @@
]
},
"node_modules/@rollup/rollup-openharmony-arm64": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz",
"integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
"integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
"cpu": [
"arm64"
],
@ -1475,9 +1478,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz",
"integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
"integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
"cpu": [
"arm64"
],
@ -1489,9 +1492,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz",
"integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
"integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
"cpu": [
"ia32"
],
@ -1503,9 +1506,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-gnu": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz",
"integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
"integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
"cpu": [
"x64"
],
@ -1517,9 +1520,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz",
"integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
"integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
"cpu": [
"x64"
],
@ -1615,6 +1618,7 @@
"integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.2.2"
@ -1664,6 +1668,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@ -1682,9 +1687,9 @@
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1869,6 +1874,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@ -2226,6 +2232,7 @@
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@ -2792,6 +2799,7 @@
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"jiti": "bin/jiti.js"
}
@ -2863,19 +2871,19 @@
}
},
"node_modules/jspdf": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.0.0.tgz",
"integrity": "sha512-w12U97Z6edKd2tXDn3LzTLg7C7QLJlx0BPfM3ecjK2BckUl9/81vZ+r5gK4/3KQdhAcEZhENUxRhtgYBj75MqQ==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.2.0.tgz",
"integrity": "sha512-hR/hnRevAXXlrjeqU5oahOE+Ln9ORJUB5brLHHqH67A+RBQZuFr5GkbI9XQI8OUFSEezKegsi45QRpc4bGj75Q==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.28.4",
"@babel/runtime": "^7.28.6",
"fast-png": "^6.2.0",
"fflate": "^0.8.1"
},
"optionalDependencies": {
"canvg": "^3.0.11",
"core-js": "^3.6.0",
"dompurify": "^3.2.4",
"dompurify": "^3.3.1",
"html2canvas": "^1.0.0-rc.5"
}
},
@ -3002,9 +3010,9 @@
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
"license": "ISC",
"dependencies": {
@ -3259,6 +3267,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@ -3458,6 +3467,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@ -3470,6 +3480,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@ -3571,9 +3582,9 @@
}
},
"node_modules/rollup": {
"version": "4.55.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz",
"integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==",
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
"integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -3587,31 +3598,31 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.55.1",
"@rollup/rollup-android-arm64": "4.55.1",
"@rollup/rollup-darwin-arm64": "4.55.1",
"@rollup/rollup-darwin-x64": "4.55.1",
"@rollup/rollup-freebsd-arm64": "4.55.1",
"@rollup/rollup-freebsd-x64": "4.55.1",
"@rollup/rollup-linux-arm-gnueabihf": "4.55.1",
"@rollup/rollup-linux-arm-musleabihf": "4.55.1",
"@rollup/rollup-linux-arm64-gnu": "4.55.1",
"@rollup/rollup-linux-arm64-musl": "4.55.1",
"@rollup/rollup-linux-loong64-gnu": "4.55.1",
"@rollup/rollup-linux-loong64-musl": "4.55.1",
"@rollup/rollup-linux-ppc64-gnu": "4.55.1",
"@rollup/rollup-linux-ppc64-musl": "4.55.1",
"@rollup/rollup-linux-riscv64-gnu": "4.55.1",
"@rollup/rollup-linux-riscv64-musl": "4.55.1",
"@rollup/rollup-linux-s390x-gnu": "4.55.1",
"@rollup/rollup-linux-x64-gnu": "4.55.1",
"@rollup/rollup-linux-x64-musl": "4.55.1",
"@rollup/rollup-openbsd-x64": "4.55.1",
"@rollup/rollup-openharmony-arm64": "4.55.1",
"@rollup/rollup-win32-arm64-msvc": "4.55.1",
"@rollup/rollup-win32-ia32-msvc": "4.55.1",
"@rollup/rollup-win32-x64-gnu": "4.55.1",
"@rollup/rollup-win32-x64-msvc": "4.55.1",
"@rollup/rollup-android-arm-eabi": "4.59.0",
"@rollup/rollup-android-arm64": "4.59.0",
"@rollup/rollup-darwin-arm64": "4.59.0",
"@rollup/rollup-darwin-x64": "4.59.0",
"@rollup/rollup-freebsd-arm64": "4.59.0",
"@rollup/rollup-freebsd-x64": "4.59.0",
"@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
"@rollup/rollup-linux-arm-musleabihf": "4.59.0",
"@rollup/rollup-linux-arm64-gnu": "4.59.0",
"@rollup/rollup-linux-arm64-musl": "4.59.0",
"@rollup/rollup-linux-loong64-gnu": "4.59.0",
"@rollup/rollup-linux-loong64-musl": "4.59.0",
"@rollup/rollup-linux-ppc64-gnu": "4.59.0",
"@rollup/rollup-linux-ppc64-musl": "4.59.0",
"@rollup/rollup-linux-riscv64-gnu": "4.59.0",
"@rollup/rollup-linux-riscv64-musl": "4.59.0",
"@rollup/rollup-linux-s390x-gnu": "4.59.0",
"@rollup/rollup-linux-x64-gnu": "4.59.0",
"@rollup/rollup-linux-x64-musl": "4.59.0",
"@rollup/rollup-openbsd-x64": "4.59.0",
"@rollup/rollup-openharmony-arm64": "4.59.0",
"@rollup/rollup-win32-arm64-msvc": "4.59.0",
"@rollup/rollup-win32-ia32-msvc": "4.59.0",
"@rollup/rollup-win32-x64-gnu": "4.59.0",
"@rollup/rollup-win32-x64-msvc": "4.59.0",
"fsevents": "~2.3.2"
}
},
@ -3884,6 +3895,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@ -3993,6 +4005,7 @@
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.27.0",
"fdir": "^6.5.0",
@ -4086,6 +4099,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@ -4145,6 +4159,7 @@
"integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==",
"dev": true,
"license": "MIT",
"peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}

View file

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 118.87 50.32">
<defs>
<style>
.cls-1 {
fill: #f90;
}
.cls-2 {
fill: #fff;
}
.cls-3 {
fill: none;
stroke: #f90;
stroke-miterlimit: 10;
}
</style>
</defs>
<g id="Layer_1-2" data-name="Layer 1">
<g>
<g>
<path class="cls-2" d="M16.77,14.11h2.01l-2.83,20.12h4.53l-.24,1.67h-6.54l3.06-21.79Z"/>
<path class="cls-2" d="M31.75,14.11h2.01l-2.35,16.82c-.37,2.45.1,3.61,1.19,3.61s1.87-1.16,2.25-3.61l2.35-16.82h2.01l-2.28,16.31c-.54,3.85-2.18,5.79-4.56,5.79s-3.44-1.94-2.89-5.79l2.28-16.31Z"/>
<path class="cls-2" d="M51.93,24.9l1.33,11h-2.01l-.88-9.16-3.4,9.16h-2.01l4.43-10.96-1.06-10.83h2.01l.58,8.85,3.06-8.85h2.01l-4.05,10.79Z"/>
</g>
<g>
<path class="cls-1" d="M63.2,22.14c.95,0,1.39.71,1.21,2l-1.04.33.07-.57c.09-.64-.03-.93-.34-.93-.37,0-.63.43-.63,1.09,0,1.39,1.4,2.01,1.4,3.63,0,1.24-.63,2.09-1.73,2.09-.94,0-1.38-.71-1.2-2l1.04-.33-.07.57c-.09.64.02.93.34.93.37,0,.59-.42.59-1.07,0-1.32-1.4-1.96-1.4-3.62,0-1.21.66-2.12,1.75-2.12Z"/>
<path class="cls-1" d="M72.83,23.07h-.96l-.93,6.61h-1l.93-6.61h-.96l.13-.82h2.91l-.12.82Z"/>
<path class="cls-1" d="M78.54,22.24h1l-.8,5.78c-.09.64.02.93.34.93s.51-.29.6-.93l.81-5.78h1l-.78,5.5c-.2,1.38-.82,2.03-1.75,2.03s-1.38-.65-1.18-2.03l.77-5.5Z"/>
<path class="cls-1" d="M89.96,24.59l-.38,2.74c-.21,1.57-.94,2.35-2.16,2.35h-1.06l1.04-7.43h1.06c1.22,0,1.71.78,1.5,2.35ZM89.02,24.18c.1-.77-.13-1.11-.59-1.11h-.16l-.8,5.78h.15c.46,0,.8-.35.91-1.11l.5-3.55Z"/>
<path class="cls-1" d="M97.31,23.07l-.81,5.78h.5l-.12.82h-2l.12-.82h.5l.81-5.78h-.5l.12-.82h2l-.12.82h-.5Z"/>
<path class="cls-1" d="M105.05,22.14c.93,0,1.38.65,1.18,2.03l-.5,3.58c-.2,1.38-.82,2.03-1.75,2.03s-1.38-.65-1.18-2.03l.5-3.58c.19-1.38.82-2.03,1.75-2.03ZM104.93,22.96c-.3,0-.51.29-.6.93l-.57,4.13c-.09.64.02.93.34.93s.51-.29.6-.93l.57-4.13c.1-.64-.02-.93-.34-.93Z"/>
</g>
<rect class="cls-3" x=".5" y=".5" width="117.87" height="49.32"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View file

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 50">
<defs>
<style>
.border { fill: none; stroke: #f59e0b; stroke-miterlimit: 10; }
.text-white { fill: #fff; }
.text-gray { fill: #64748b; }
.gold { fill: #f59e0b; }
</style>
</defs>
<rect class="border" x="0.5" y="0.5" width="179" height="49"/>
<!-- CINEMA text -->
<text class="text-white" x="12" y="28" font-family="system-ui, -apple-system, sans-serif" font-size="18" font-weight="bold" letter-spacing="1">CINEMA</text>
<!-- STUDIO text -->
<text class="text-gray" x="88" y="28" font-family="system-ui, -apple-system, sans-serif" font-size="18" font-weight="bold" letter-spacing="1">STUDIO</text>
<!-- PRO badge -->
<rect class="gold" x="155" y="15" width="18" height="18" rx="3"/>
<text class="text-white" x="159" y="28" font-family="system-ui, -apple-system, sans-serif" font-size="9" font-weight="bold">P</text>
</svg>

Before

Width:  |  Height:  |  Size: 975 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB