Compare commits
2 commits
feature/de
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25ab570aab | ||
|
|
ac275a9259 |
21 changed files with 883 additions and 3228 deletions
|
|
@ -28,7 +28,8 @@
|
|||
"Bash(bash:*)",
|
||||
"Bash(dos2unix:*)",
|
||||
"WebSearch",
|
||||
"WebFetch(domain:ai.google.dev)"
|
||||
"WebFetch(domain:ai.google.dev)",
|
||||
"Bash(cp:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
88
CLAUDE.md
88
CLAUDE.md
|
|
@ -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`)
|
||||
|
|
|
|||
937
DEPLOYMENT.md
937
DEPLOYMENT.md
|
|
@ -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
255
NEW_DEPLOYMENT.md
Normal 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 1–6 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
347
README.md
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
# ----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
# ----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
# ----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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
757
deploy.sh
|
|
@ -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 30–60 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 ""
|
||||
|
|
|
|||
|
|
@ -1,70 +1,40 @@
|
|||
# ============================================================================
|
||||
# Lux Studio Frontend Environment Configuration
|
||||
# Lux Studio Backend - LOCAL Development Environment Configuration
|
||||
# ============================================================================
|
||||
# IMPORTANT: After changing this file for production, rebuild the frontend:
|
||||
# cd frontend
|
||||
# npm run build
|
||||
# Then upload frontend/dist/* to the server
|
||||
# For production settings, see .env.production
|
||||
# This file is used by setup.sh for local development
|
||||
# ============================================================================
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Port Configuration
|
||||
# Backend Port Configuration
|
||||
# ----------------------------------------------------------------------------
|
||||
# Frontend development server port
|
||||
FRONTEND_PORT=3000
|
||||
# Backend API server port
|
||||
# Port on which the PHP backend server runs locally
|
||||
# Start backend with: php -S localhost:5015
|
||||
BACKEND_PORT=5015
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Base Path Configuration
|
||||
# API Base Path (for video/file streaming URLs)
|
||||
# ----------------------------------------------------------------------------
|
||||
# Base path for the application (used in vite build)
|
||||
# LOCAL DEVELOPMENT: Use root path
|
||||
VITE_BASE_PATH=/
|
||||
#
|
||||
# PRODUCTION: Use subdirectory path
|
||||
# VITE_BASE_PATH=/lux-studio/
|
||||
# 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=/
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Backend API URL (REQUIRED)
|
||||
# Google Gemini API Key (REQUIRED)
|
||||
# ----------------------------------------------------------------------------
|
||||
# LOCAL DEVELOPMENT (uncomment for local):
|
||||
VITE_API_URL=http://localhost:5015
|
||||
#
|
||||
# PRODUCTION (comment out for local - use Apache proxy):
|
||||
# VITE_API_URL=https://ai-sandbox.oliver.solutions/lux-studio-back
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Google Gemini API Key
|
||||
# ----------------------------------------------------------------------------
|
||||
# Used for client-side prompt enhancement
|
||||
# Get your API key from: https://aistudio.google.com/app/apikey
|
||||
VITE_GEMINI_API_KEY=your-api-key-here
|
||||
# GEMINI_API_KEY=AIzaSyCMKLSJJYEx4c6-TtBACnjdULrLzsr_fts
|
||||
GEMINI_API_KEY=AIzaSyDs7EKdC9NLM5UqWlGUqeQO96TmSA-kos8
|
||||
# ----------------------------------------------------------------------------
|
||||
# Frontend URL for CORS (REQUIRED)
|
||||
# ----------------------------------------------------------------------------
|
||||
# IMPORTANT: No trailing slash!
|
||||
# Local development frontend URL
|
||||
FRONTEND_URL=http://localhost:3000
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Azure AD / MSAL SSO Configuration
|
||||
# ----------------------------------------------------------------------------
|
||||
# Enable/Disable SSO authentication (true/false)
|
||||
VITE_SSO_ENABLED=true
|
||||
# Development credentials (use for local development)
|
||||
VITE_SSO_TENANT_ID=e519c2e6-bc6d-4fdf-8d9c-923c2f002385
|
||||
VITE_SSO_CLIENT_ID=15c0c4e2-bac0-4564-a3a6-c2717f00a6d9
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# SSO Redirect URI (REQUIRED if SSO enabled)
|
||||
# ----------------------------------------------------------------------------
|
||||
# LOCAL DEVELOPMENT (uncomment for local):
|
||||
VITE_SSO_REDIRECT_URI=http://localhost:3000
|
||||
#
|
||||
# PRODUCTION (comment out for local):
|
||||
# VITE_SSO_REDIRECT_URI=https://ai-sandbox.oliver.solutions/lux-studio
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Environment Mode
|
||||
# ----------------------------------------------------------------------------
|
||||
# LOCAL DEVELOPMENT:
|
||||
NODE_ENV=development
|
||||
#
|
||||
# PRODUCTION (comment out for local):
|
||||
# NODE_ENV=production
|
||||
# Backend authentication is DISABLED - Frontend handles SSO
|
||||
SSO_ENABLED=false
|
||||
SSO_TENANT_ID=e519c2e6-bc6d-4fdf-8d9c-923c2f002385
|
||||
SSO_CLIENT_ID=15c0c4e2-bac0-4564-a3a6-c2717f00a6d9
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
243
frontend/package-lock.json
generated
243
frontend/package-lock.json
generated
|
|
@ -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"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 |
|
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 |
|
|
@ -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 |
|
|
@ -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 |
Loading…
Add table
Reference in a new issue