update
This commit is contained in:
parent
361e476d2c
commit
e1067b551e
11 changed files with 536 additions and 1646 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -67,3 +67,10 @@ debug*.php
|
|||
|
||||
# Session files
|
||||
sess_*
|
||||
|
||||
# Development server files (created by setup.sh)
|
||||
.backend.pid
|
||||
.frontend.pid
|
||||
backend-server.log
|
||||
frontend-server.log
|
||||
stop.sh
|
||||
|
|
|
|||
11
CLAUDE.md
11
CLAUDE.md
|
|
@ -183,7 +183,7 @@ All managed by `useProjects.js` hook.
|
|||
- Reference images (up to 2: first frame + optional last frame for interpolation)
|
||||
- Veo 3.1 Standard or Fast model selection
|
||||
- Creative Freedom levels (auto-adjusts guidance strength)
|
||||
- Duration constraints: 4s (any), 6s (T2V only), 8s (T2V only)
|
||||
- Duration options: 4s, 6s, 8s (all available for both T2V and I2V)
|
||||
- Async polling for video completion
|
||||
- Frame extraction from generated videos
|
||||
|
||||
|
|
@ -376,13 +376,8 @@ if ((tabId === 'image' || tabId === 'video') && !activeProjectId) {
|
|||
}
|
||||
```
|
||||
|
||||
### 4. Video Duration Constraints
|
||||
Veo 3.1 I2V (image-to-video) only supports 4 seconds:
|
||||
```javascript
|
||||
if (referenceImages.length > 0 && duration > 4) {
|
||||
duration = 4; // Force to 4s for I2V
|
||||
}
|
||||
```
|
||||
### 4. Video Generation Settings
|
||||
All durations (4s, 6s, 8s) work for both T2V and I2V modes. Resolution (720p/1080p) is a UI-only setting - only aspectRatio and durationSeconds are sent to the Veo 3.1 API.
|
||||
|
||||
### 5. MIME Type Handling
|
||||
Always store and use dynamic MIME type from API response:
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@
|
|||
# Start backend with: php -S localhost:${BACKEND_PORT}
|
||||
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)
|
||||
# ----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@
|
|||
# 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)
|
||||
# ----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -14,11 +14,19 @@
|
|||
# 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)
|
||||
# ----------------------------------------------------------------------------
|
||||
# Get your API key from: https://aistudio.google.com/app/apikey
|
||||
GEMINI_API_KEY=AIzaSyCMKLSJJYEx4c6-TtBACnjdULrLzsr_fts
|
||||
GEMINI_API_KEY=AIzaSyDs7EKdC9NLM5UqWlGUqeQO96TmSA-kos8
|
||||
# AIzaSyCMKLSJJYEx4c6-TtBACnjdULrLzsr_fts
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Frontend URL for CORS (REQUIRED)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# ==============================================================================
|
||||
# VIDEO OPTIMIZER - FRONTEND SECURITY CONFIGURATION
|
||||
# LUX STUDIO BACKEND - SECURITY CONFIGURATION
|
||||
# ==============================================================================
|
||||
# Location: /var/www/html/lux-studio/.htaccess
|
||||
# Purpose: Security hardening for frontend static files
|
||||
# Location: /opt/lux-studio-back/.htaccess
|
||||
# Purpose: Prevent direct browser access, allow only API endpoints
|
||||
# ==============================================================================
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
@ -12,20 +12,68 @@
|
|||
# Disable directory browsing
|
||||
Options -Indexes
|
||||
|
||||
# Follow symbolic links (required for some servers)
|
||||
Options +FollowSymLinks
|
||||
|
||||
# Disable server signature
|
||||
ServerSignature Off
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# FILE ACCESS CONTROL
|
||||
# BLOCK ROOT AND INDEX ACCESS
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Default: Allow access to all files (will be restricted below)
|
||||
# Block access to index.php (prevents browsing backend UI)
|
||||
<Files "index.php">
|
||||
Require all denied
|
||||
</Files>
|
||||
|
||||
# Deny access to sensitive files and patterns
|
||||
<FilesMatch "^\.">
|
||||
# Block access to test files
|
||||
<FilesMatch "^(test|auth-test|server-check)\.php$">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
# Block access to configuration files
|
||||
<FilesMatch "^(config|config\.example)\.php$">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# API ENDPOINT ACCESS CONTROL
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Only allow POST requests to API endpoints
|
||||
# GET is allowed only for stream_video.php (video streaming)
|
||||
|
||||
<FilesMatch "^(api|video_api|enhance_prompt|auth|webhook_logger)\.php$">
|
||||
<RequireAll>
|
||||
Require all granted
|
||||
<RequireAny>
|
||||
Require method POST OPTIONS
|
||||
</RequireAny>
|
||||
</RequireAll>
|
||||
</FilesMatch>
|
||||
|
||||
# Allow GET and POST for video streaming
|
||||
<Files "stream_video.php">
|
||||
Require all granted
|
||||
</Files>
|
||||
|
||||
# Allow POST for cleanup and session management
|
||||
<FilesMatch "^(cleanup|clear_session|session_manager)\.php$">
|
||||
<RequireAll>
|
||||
Require all granted
|
||||
Require method POST OPTIONS
|
||||
</RequireAll>
|
||||
</FilesMatch>
|
||||
|
||||
# Allow get_config.php and get_logs.php for debugging (consider disabling in production)
|
||||
<FilesMatch "^(get_config|get_logs|get_current_image)\.php$">
|
||||
Require all granted
|
||||
</FilesMatch>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# PROTECT SENSITIVE FILES
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Deny access to environment files
|
||||
<FilesMatch "^\.env">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
|
|
@ -34,86 +82,60 @@ ServerSignature Off
|
|||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
# Deny access to version control files
|
||||
<FilesMatch "(^\.git|^\.svn|^\.hg|^\.bzr)">
|
||||
# Deny access to version control
|
||||
<FilesMatch "(^\.git|^\.svn|^\.hg|composer\.)">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
# Deny access to environment and configuration files
|
||||
<FilesMatch "^(\.env|\.env\.|config\.json|package\.json|package-lock\.json|composer\.json|composer\.lock)">
|
||||
# Deny access to class files (should only be included, not accessed directly)
|
||||
<FilesMatch "^(AuthMiddleware|JWTValidator|SessionManager)\.php$">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
# Deny access to PHP files (if any exist - security measure)
|
||||
<FilesMatch "\.php">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
# <FilesMatch "\.php$">
|
||||
# Require all denied
|
||||
# </FilesMatch>
|
||||
|
||||
# Deny access to Python files (should not be in frontend)
|
||||
<FilesMatch "\.py$">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
# Deny access to README and documentation that shouldn't be public
|
||||
<FilesMatch "^(README|INSTALL|CHANGELOG|LICENSE|CONTRIBUTING)">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ALLOWED FILE TYPES (Explicitly allow necessary files)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Allow HTML files (main application pages)
|
||||
<FilesMatch "\.(html|htm)$">
|
||||
Require all granted
|
||||
</FilesMatch>
|
||||
|
||||
# Allow JavaScript files
|
||||
<FilesMatch "\.(js|mjs)$">
|
||||
Require all granted
|
||||
</FilesMatch>
|
||||
|
||||
# Allow CSS files
|
||||
<FilesMatch "\.css$">
|
||||
Require all granted
|
||||
</FilesMatch>
|
||||
|
||||
# Allow images
|
||||
<FilesMatch "\.(jpg|jpeg|png|gif|ico|svg|webp)$">
|
||||
Require all granted
|
||||
</FilesMatch>
|
||||
|
||||
# Allow fonts
|
||||
<FilesMatch "\.(woff|woff2|ttf|otf|eot)$">
|
||||
Require all granted
|
||||
</FilesMatch>
|
||||
|
||||
# Allow JSON files (only if needed for app functionality)
|
||||
<FilesMatch "\.json$">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ERROR DOCUMENTS
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Custom error pages (optional - create these files if needed)
|
||||
# ErrorDocument 403 /video-optimizer/error/403.html
|
||||
# ErrorDocument 404 /video-optimizer/error/404.html
|
||||
# ErrorDocument 500 /video-optimizer/error/500.html
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ADDITIONAL SECURITY
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Prevent access to .htaccess itself
|
||||
# Deny access to .htaccess itself
|
||||
<Files ".htaccess">
|
||||
Require all denied
|
||||
</Files>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# UPLOADS DIRECTORY PROTECTION
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Block direct access to uploads directory (videos/images should be streamed via PHP)
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
|
||||
# Block direct access to uploads folder
|
||||
RewriteRule ^uploads/ - [F,L]
|
||||
</IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# SECURITY HEADERS (if not set by Apache)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
<IfModule mod_headers.c>
|
||||
# Prevent MIME type sniffing
|
||||
Header set X-Content-Type-Options "nosniff"
|
||||
|
||||
# Prevent clickjacking
|
||||
Header set X-Frame-Options "DENY"
|
||||
|
||||
# XSS Protection
|
||||
Header set X-XSS-Protection "1; mode=block"
|
||||
</IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ERROR HANDLING
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Return 403 Forbidden instead of showing file listings
|
||||
<IfModule mod_autoindex.c>
|
||||
Options -Indexes
|
||||
</IfModule>
|
||||
|
||||
# Custom error document (returns JSON for API errors)
|
||||
ErrorDocument 403 "Forbidden: Direct access to backend is not allowed. Use API endpoints only."
|
||||
ErrorDocument 404 "Not Found: API endpoint does not exist."
|
||||
|
||||
# ==============================================================================
|
||||
# END OF CONFIGURATION
|
||||
|
|
|
|||
1513
backend/index.php
1513
backend/index.php
File diff suppressed because it is too large
Load diff
|
|
@ -439,7 +439,7 @@ try {
|
|||
'video' => [
|
||||
'filename' => $filename,
|
||||
'mime_type' => $videoData['mime_type'],
|
||||
'url' => '/api/stream_video.php?file=' . urlencode($filename)
|
||||
'url' => ($_ENV['API_BASE_PATH'] ?? '') . '/stream_video.php?file=' . urlencode($filename)
|
||||
]
|
||||
]);
|
||||
} else if ($videoData['type'] === 'uri') {
|
||||
|
|
@ -481,7 +481,7 @@ try {
|
|||
'video' => [
|
||||
'filename' => $filename,
|
||||
'mime_type' => $videoData['mime_type'],
|
||||
'url' => '/api/stream_video.php?file=' . urlencode($filename)
|
||||
'url' => ($_ENV['API_BASE_PATH'] ?? '') . '/stream_video.php?file=' . urlencode($filename)
|
||||
]
|
||||
]);
|
||||
} else {
|
||||
|
|
@ -561,7 +561,7 @@ try {
|
|||
echo json_encode([
|
||||
'success' => true,
|
||||
'video' => [
|
||||
'url' => '/api/stream_video.php?file=' . urlencode($filename),
|
||||
'url' => ($_ENV['API_BASE_PATH'] ?? '') . '/stream_video.php?file=' . urlencode($filename),
|
||||
'filename' => $filename,
|
||||
'mime_type' => 'video/mp4'
|
||||
]
|
||||
|
|
|
|||
|
|
@ -129,10 +129,9 @@ const VideoGenTab = ({ activeProjectId, rerunData, onRerunLoaded }) => {
|
|||
// Check if already added
|
||||
if (referenceImages.some(img => img.projectItemId === item.id)) return;
|
||||
|
||||
// Auto-set constraints when adding first reference image (I2V requirements)
|
||||
// Auto-set aspect ratio when adding first reference image
|
||||
if (referenceImages.length === 0) {
|
||||
setDuration(8);
|
||||
setAspectRatio('16:9'); // Reference images only support 16:9
|
||||
setAspectRatio('16:9');
|
||||
}
|
||||
|
||||
setReferenceImages(prev => [...prev, {
|
||||
|
|
@ -185,10 +184,9 @@ const VideoGenTab = ({ activeProjectId, rerunData, onRerunLoaded }) => {
|
|||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
setReferenceImages(prev => {
|
||||
// Auto-set constraints when adding first reference image (I2V requirements)
|
||||
// Auto-set aspect ratio when adding first reference image
|
||||
if (prev.length === 0) {
|
||||
setDuration(8);
|
||||
setAspectRatio('16:9'); // Reference images only support 16:9
|
||||
setAspectRatio('16:9');
|
||||
}
|
||||
return [...prev, {
|
||||
data: reader.result.split(',')[1],
|
||||
|
|
@ -615,25 +613,16 @@ OUTPUT ONLY THE PROMPT - no explanations, no labels, no formatting.`;
|
|||
</label>
|
||||
<div className="flex gap-2">
|
||||
{durationOptions.map((opt) => {
|
||||
const isDisabledByI2V = referenceImages.length > 0 && opt.value !== 8;
|
||||
const isDisabledByI2V = false;
|
||||
return (
|
||||
<button
|
||||
key={opt.value}
|
||||
onClick={() => {
|
||||
if (isDisabledByI2V) return;
|
||||
setDuration(opt.value);
|
||||
// Auto-downgrade resolution if not 8s (1080p requires 8s)
|
||||
if (opt.value !== 8 && resolution === '1080p') {
|
||||
setResolution('720p');
|
||||
}
|
||||
}}
|
||||
disabled={isDisabledByI2V}
|
||||
title={isDisabledByI2V ? 'I2V requires 8s duration' : ''}
|
||||
onClick={() => setDuration(opt.value)}
|
||||
className={`flex-1 px-3 py-2 rounded-lg font-medium transition-all text-sm ${
|
||||
duration === opt.value
|
||||
? 'bg-cinema-gold text-slate-950'
|
||||
: 'bg-slate-800 text-slate-400 hover:bg-slate-700'
|
||||
} ${isDisabledByI2V ? 'opacity-50 cursor-not-allowed' : ''}`}
|
||||
}`}
|
||||
>
|
||||
<div>{opt.label}</div>
|
||||
<div className="text-xs opacity-70">{getDurationCost(opt.value)}</div>
|
||||
|
|
@ -641,9 +630,6 @@ OUTPUT ONLY THE PROMPT - no explanations, no labels, no formatting.`;
|
|||
);
|
||||
})}
|
||||
</div>
|
||||
{referenceImages.length > 0 && (
|
||||
<p className="text-xs text-slate-500">I2V mode requires 8s duration</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Aspect Ratio */}
|
||||
|
|
@ -655,13 +641,7 @@ OUTPUT ONLY THE PROMPT - no explanations, no labels, no formatting.`;
|
|||
{['16:9', '9:16'].map((ratio) => (
|
||||
<button
|
||||
key={ratio}
|
||||
onClick={() => {
|
||||
setAspectRatio(ratio);
|
||||
if (ratio === '9:16') {
|
||||
// Auto-downgrade resolution (1080p not supported in portrait)
|
||||
setResolution('720p');
|
||||
}
|
||||
}}
|
||||
onClick={() => setAspectRatio(ratio)}
|
||||
className={`flex-1 px-4 py-2 rounded-lg font-medium transition-all ${
|
||||
aspectRatio === ratio
|
||||
? 'bg-cinema-gold text-slate-950'
|
||||
|
|
@ -681,27 +661,22 @@ OUTPUT ONLY THE PROMPT - no explanations, no labels, no formatting.`;
|
|||
</label>
|
||||
<div className="flex gap-2">
|
||||
{['720p', '1080p'].map((res) => {
|
||||
const is1080pDisabled = res === '1080p' && (duration !== 8 || aspectRatio !== '16:9');
|
||||
const is1080pDisabled = false;
|
||||
return (
|
||||
<button
|
||||
key={res}
|
||||
onClick={() => !is1080pDisabled && setResolution(res)}
|
||||
disabled={is1080pDisabled}
|
||||
title={is1080pDisabled ? '1080p requires 8s duration + 16:9 aspect ratio' : ''}
|
||||
onClick={() => setResolution(res)}
|
||||
className={`flex-1 px-4 py-2 rounded-lg font-medium transition-all ${
|
||||
resolution === res
|
||||
? 'bg-cinema-gold text-slate-950'
|
||||
: 'bg-slate-800 text-slate-400 hover:bg-slate-700'
|
||||
} ${is1080pDisabled ? 'opacity-50 cursor-not-allowed' : ''}`}
|
||||
}`}
|
||||
>
|
||||
{res}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{(duration !== 8 || aspectRatio !== '16:9') && (
|
||||
<p className="text-xs text-slate-500">1080p requires 8s + 16:9</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Audio Toggle */}
|
||||
|
|
|
|||
284
setup.sh
284
setup.sh
|
|
@ -1,9 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
# ============================================================================
|
||||
# Lux Studio - Local Development Setup Script
|
||||
# Lux Studio - Local Development Setup & Start Script
|
||||
# ============================================================================
|
||||
# This script sets up both frontend and backend for LOCAL development
|
||||
# This script sets up AND starts both frontend and backend for LOCAL development
|
||||
# For production deployment, use deploy.sh instead
|
||||
# ============================================================================
|
||||
|
||||
|
|
@ -19,6 +19,9 @@ YELLOW='\033[1;33m'
|
|||
RED='\033[0;31m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Get the absolute path of the project root
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# ============================================================================
|
||||
# 1. CHECK PREREQUISITES
|
||||
# ============================================================================
|
||||
|
|
@ -125,7 +128,20 @@ cd ..
|
|||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# 4. READ PORT CONFIGURATION
|
||||
# 4. CREATE REQUIRED DIRECTORIES
|
||||
# ============================================================================
|
||||
|
||||
echo "${BLUE}Step 4: Creating required directories...${NC}"
|
||||
|
||||
# Create backend upload directory with proper permissions
|
||||
mkdir -p backend/uploads/sessions
|
||||
chmod -R 755 backend/uploads 2>/dev/null || true
|
||||
|
||||
echo "${GREEN}✓ Required directories created${NC}"
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# 5. READ PORT CONFIGURATION
|
||||
# ============================================================================
|
||||
|
||||
# Read ports from .env files
|
||||
|
|
@ -145,38 +161,262 @@ BACKEND_PORT=${BACKEND_PORT:-5015}
|
|||
FRONTEND_PORT=${FRONTEND_PORT:-3000}
|
||||
|
||||
# ============================================================================
|
||||
# 5. FINAL INSTRUCTIONS
|
||||
# 6. CHECK FOR PORT CONFLICTS
|
||||
# ============================================================================
|
||||
|
||||
echo "${BLUE}Step 5: Checking for port conflicts...${NC}"
|
||||
|
||||
# Function to check if a port is in use
|
||||
check_port() {
|
||||
local port=$1
|
||||
if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1 ; then
|
||||
return 0 # Port is in use
|
||||
else
|
||||
return 1 # Port is free
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to kill process on port
|
||||
kill_port() {
|
||||
local port=$1
|
||||
local pid=$(lsof -ti:$port)
|
||||
if [ ! -z "$pid" ]; then
|
||||
echo " → Killing process $pid on port $port..."
|
||||
kill -9 $pid 2>/dev/null || true
|
||||
sleep 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check backend port
|
||||
if check_port $BACKEND_PORT; then
|
||||
echo "${YELLOW} ⚠ Port $BACKEND_PORT is already in use${NC}"
|
||||
read -p " Kill the process and continue? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
kill_port $BACKEND_PORT
|
||||
echo "${GREEN} ✓ Port $BACKEND_PORT is now free${NC}"
|
||||
else
|
||||
echo "${RED} ✗ Cannot start backend - port in use${NC}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "${GREEN} ✓ Port $BACKEND_PORT is available${NC}"
|
||||
fi
|
||||
|
||||
# Check frontend port
|
||||
if check_port $FRONTEND_PORT; then
|
||||
echo "${YELLOW} ⚠ Port $FRONTEND_PORT is already in use${NC}"
|
||||
read -p " Kill the process and continue? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
kill_port $FRONTEND_PORT
|
||||
echo "${GREEN} ✓ Port $FRONTEND_PORT is now free${NC}"
|
||||
else
|
||||
echo "${RED} ✗ Cannot start frontend - port in use${NC}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "${GREEN} ✓ Port $FRONTEND_PORT is available${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# 7. START BACKEND SERVER
|
||||
# ============================================================================
|
||||
|
||||
echo "${BLUE}Step 6: Starting backend server...${NC}"
|
||||
|
||||
cd "$PROJECT_ROOT/backend"
|
||||
|
||||
# Start PHP server in background
|
||||
nohup php -S localhost:${BACKEND_PORT} > "${PROJECT_ROOT}/backend-server.log" 2>&1 &
|
||||
BACKEND_PID=$!
|
||||
|
||||
# Wait a moment and check if server started
|
||||
sleep 2
|
||||
|
||||
if ps -p $BACKEND_PID > /dev/null; then
|
||||
echo "${GREEN}✓ Backend server started on port ${BACKEND_PORT}${NC}"
|
||||
echo " PID: $BACKEND_PID"
|
||||
echo " Logs: ${PROJECT_ROOT}/backend-server.log"
|
||||
|
||||
# Save PID for later shutdown
|
||||
echo $BACKEND_PID > "${PROJECT_ROOT}/.backend.pid"
|
||||
else
|
||||
echo "${RED}✗ Failed to start backend server${NC}"
|
||||
echo " Check ${PROJECT_ROOT}/backend-server.log for errors"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# 8. START FRONTEND SERVER
|
||||
# ============================================================================
|
||||
|
||||
echo "${BLUE}Step 7: Starting frontend dev server...${NC}"
|
||||
|
||||
cd "$PROJECT_ROOT/frontend"
|
||||
|
||||
# Start Vite dev server in background
|
||||
nohup npm run dev > "${PROJECT_ROOT}/frontend-server.log" 2>&1 &
|
||||
FRONTEND_PID=$!
|
||||
|
||||
# Wait for Vite to start (it takes a bit longer)
|
||||
echo " → Waiting for Vite dev server to start..."
|
||||
sleep 5
|
||||
|
||||
if ps -p $FRONTEND_PID > /dev/null; then
|
||||
echo "${GREEN}✓ Frontend server started on port ${FRONTEND_PORT}${NC}"
|
||||
echo " PID: $FRONTEND_PID"
|
||||
echo " Logs: ${PROJECT_ROOT}/frontend-server.log"
|
||||
|
||||
# Save PID for later shutdown
|
||||
echo $FRONTEND_PID > "${PROJECT_ROOT}/.frontend.pid"
|
||||
else
|
||||
echo "${RED}✗ Failed to start frontend server${NC}"
|
||||
echo " Check ${PROJECT_ROOT}/frontend-server.log for errors"
|
||||
|
||||
# Clean up backend server
|
||||
kill $BACKEND_PID 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# 9. VERIFY SERVERS ARE RUNNING
|
||||
# ============================================================================
|
||||
|
||||
echo "${BLUE}Step 8: Verifying servers...${NC}"
|
||||
|
||||
# Wait a moment for servers to fully initialize
|
||||
sleep 3
|
||||
|
||||
# Check if backend responds
|
||||
if curl -s http://localhost:${BACKEND_PORT}/server-check.php > /dev/null 2>&1; then
|
||||
echo "${GREEN} ✓ Backend is responding${NC}"
|
||||
else
|
||||
echo "${YELLOW} ⚠ Backend may not be fully ready yet${NC}"
|
||||
fi
|
||||
|
||||
# Check if frontend responds
|
||||
if curl -s http://localhost:${FRONTEND_PORT} > /dev/null 2>&1; then
|
||||
echo "${GREEN} ✓ Frontend is responding${NC}"
|
||||
else
|
||||
echo "${YELLOW} ⚠ Frontend may not be fully ready yet${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================================================
|
||||
# 10. CREATE STOP SCRIPT
|
||||
# ============================================================================
|
||||
|
||||
# Create a stop script for easy shutdown
|
||||
cat > "${PROJECT_ROOT}/stop.sh" << 'EOF'
|
||||
#!/bin/bash
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${YELLOW}🛑 Stopping Lux Studio servers...${NC}"
|
||||
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Stop backend
|
||||
if [ -f "${PROJECT_ROOT}/.backend.pid" ]; then
|
||||
BACKEND_PID=$(cat "${PROJECT_ROOT}/.backend.pid")
|
||||
if ps -p $BACKEND_PID > /dev/null 2>&1; then
|
||||
kill $BACKEND_PID 2>/dev/null
|
||||
echo -e "${GREEN}✓ Backend server stopped (PID: $BACKEND_PID)${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠ Backend server not running${NC}"
|
||||
fi
|
||||
rm "${PROJECT_ROOT}/.backend.pid"
|
||||
fi
|
||||
|
||||
# Stop frontend
|
||||
if [ -f "${PROJECT_ROOT}/.frontend.pid" ]; then
|
||||
FRONTEND_PID=$(cat "${PROJECT_ROOT}/.frontend.pid")
|
||||
if ps -p $FRONTEND_PID > /dev/null 2>&1; then
|
||||
kill $FRONTEND_PID 2>/dev/null
|
||||
echo -e "${GREEN}✓ Frontend server stopped (PID: $FRONTEND_PID)${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠ Frontend server not running${NC}"
|
||||
fi
|
||||
rm "${PROJECT_ROOT}/.frontend.pid"
|
||||
fi
|
||||
|
||||
# Also kill any remaining processes on the ports (cleanup)
|
||||
BACKEND_PORT=$(grep -E "^BACKEND_PORT=" backend/.env 2>/dev/null | cut -d'=' -f2 | tr -d ' ')
|
||||
FRONTEND_PORT=$(grep -E "^FRONTEND_PORT=" frontend/.env 2>/dev/null | cut -d'=' -f2 | tr -d ' ')
|
||||
|
||||
BACKEND_PORT=${BACKEND_PORT:-5015}
|
||||
FRONTEND_PORT=${FRONTEND_PORT:-3000}
|
||||
|
||||
# Kill any remaining processes on ports
|
||||
for port in $BACKEND_PORT $FRONTEND_PORT; do
|
||||
pid=$(lsof -ti:$port 2>/dev/null)
|
||||
if [ ! -z "$pid" ]; then
|
||||
kill -9 $pid 2>/dev/null || true
|
||||
echo -e "${GREEN}✓ Cleaned up process on port $port${NC}"
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "${GREEN}✅ All servers stopped${NC}"
|
||||
EOF
|
||||
|
||||
chmod +x "${PROJECT_ROOT}/stop.sh"
|
||||
|
||||
# ============================================================================
|
||||
# 11. SUCCESS MESSAGE
|
||||
# ============================================================================
|
||||
|
||||
echo "${GREEN}════════════════════════════════════════════════════════════${NC}"
|
||||
echo "${GREEN}🎉 Setup Complete! Ready for Local Development${NC}"
|
||||
echo "${GREEN}🎉 Lux Studio is Running!${NC}"
|
||||
echo "${GREEN}════════════════════════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
|
||||
echo "${BLUE}📋 Next Steps:${NC}"
|
||||
echo "${BLUE}🌐 Application URLs:${NC}"
|
||||
echo " • Frontend: ${GREEN}http://localhost:${FRONTEND_PORT}${NC}"
|
||||
echo " • Backend API: ${GREEN}http://localhost:${BACKEND_PORT}${NC}"
|
||||
echo ""
|
||||
echo "1. ${YELLOW}Start Backend Server${NC} (Terminal 1):"
|
||||
echo " ${GREEN}cd backend && php -S localhost:${BACKEND_PORT}${NC}"
|
||||
|
||||
echo "${BLUE}📊 Server Status:${NC}"
|
||||
echo " • Backend PID: $BACKEND_PID (port $BACKEND_PORT)"
|
||||
echo " • Frontend PID: $FRONTEND_PID (port $FRONTEND_PORT)"
|
||||
echo ""
|
||||
echo "2. ${YELLOW}Start Frontend Dev Server${NC} (Terminal 2):"
|
||||
echo " ${GREEN}cd frontend && npm run dev${NC}"
|
||||
|
||||
echo "${BLUE}📝 Log Files:${NC}"
|
||||
echo " • Backend: ${PROJECT_ROOT}/backend-server.log"
|
||||
echo " • Frontend: ${PROJECT_ROOT}/frontend-server.log"
|
||||
echo " • View backend: ${GREEN}tail -f ${PROJECT_ROOT}/backend-server.log${NC}"
|
||||
echo " • View frontend: ${GREEN}tail -f ${PROJECT_ROOT}/frontend-server.log${NC}"
|
||||
echo ""
|
||||
echo "3. ${YELLOW}Open in Browser:${NC}"
|
||||
echo " ${GREEN}http://localhost:${FRONTEND_PORT}${NC}"
|
||||
|
||||
echo "${BLUE}🛑 Stop Servers:${NC}"
|
||||
echo " ${GREEN}./stop.sh${NC}"
|
||||
echo ""
|
||||
|
||||
echo "${BLUE}⚙️ Configuration:${NC}"
|
||||
echo " • Backend Port: ${BACKEND_PORT} (change in backend/.env)"
|
||||
echo " • Frontend Port: ${FRONTEND_PORT} (change in frontend/.env)"
|
||||
echo " • SSO: Enabled (disable by setting VITE_SSO_ENABLED=false in frontend/.env)"
|
||||
echo " • SSO: Enabled with LOCAL credentials"
|
||||
echo " • SSO Client ID: 15c0c4e2-bac0-4564-a3a6-c2717f00a6d9 (local dev)"
|
||||
echo " • API Key: Configured in .env files"
|
||||
echo ""
|
||||
|
||||
echo "${BLUE}📚 Documentation:${NC}"
|
||||
echo " • README.md - User guide and features"
|
||||
echo " • CLAUDE.md - Developer guide for AI assistants"
|
||||
echo " • DEPLOYMENT.md - Production deployment guide"
|
||||
echo " • CLAUDE.md - Developer guide"
|
||||
echo " • MDFiles/README.md - User guide"
|
||||
echo " • MDFiles/AUTH_README.md - SSO guide"
|
||||
echo ""
|
||||
echo "${BLUE}💡 Useful Commands:${NC}"
|
||||
echo " • Build for production: ${GREEN}cd frontend && npm run build${NC}"
|
||||
echo " • Run linter: ${GREEN}cd frontend && npm run lint${NC}"
|
||||
echo " • View logs: Check terminal output and browser console (F12)"
|
||||
|
||||
echo "${YELLOW}💡 Tip: Open http://localhost:${FRONTEND_PORT} in your browser!${NC}"
|
||||
echo ""
|
||||
echo "Happy coding! 🚀"
|
||||
|
|
|
|||
108
status.sh
Normal file
108
status.sh
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
#!/bin/bash
|
||||
|
||||
# ============================================================================
|
||||
# Lux Studio - Server Status Check Script
|
||||
# ============================================================================
|
||||
|
||||
# Colors
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Read ports from .env files
|
||||
BACKEND_PORT=5015
|
||||
FRONTEND_PORT=3000
|
||||
|
||||
if [ -f "backend/.env" ]; then
|
||||
BACKEND_PORT=$(grep -E "^BACKEND_PORT=" backend/.env | cut -d'=' -f2 | tr -d ' ')
|
||||
fi
|
||||
|
||||
if [ -f "frontend/.env" ]; then
|
||||
FRONTEND_PORT=$(grep -E "^FRONTEND_PORT=" frontend/.env | cut -d'=' -f2 | tr -d ' ')
|
||||
fi
|
||||
|
||||
BACKEND_PORT=${BACKEND_PORT:-5015}
|
||||
FRONTEND_PORT=${FRONTEND_PORT:-3000}
|
||||
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${BLUE}📊 Lux Studio Server Status${NC}"
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
|
||||
# Check Backend
|
||||
echo -e "${BLUE}🔧 Backend Server (Port ${BACKEND_PORT}):${NC}"
|
||||
if [ -f "${PROJECT_ROOT}/.backend.pid" ]; then
|
||||
BACKEND_PID=$(cat "${PROJECT_ROOT}/.backend.pid")
|
||||
if ps -p $BACKEND_PID > /dev/null 2>&1; then
|
||||
echo -e " Status: ${GREEN}✓ Running${NC}"
|
||||
echo -e " PID: $BACKEND_PID"
|
||||
if curl -s http://localhost:${BACKEND_PORT}/server-check.php > /dev/null 2>&1; then
|
||||
echo -e " Health: ${GREEN}✓ Responding${NC}"
|
||||
else
|
||||
echo -e " Health: ${YELLOW}⚠ Not responding${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e " Status: ${RED}✗ Not running (stale PID file)${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e " Status: ${RED}✗ Not running${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Check Frontend
|
||||
echo -e "${BLUE}🎨 Frontend Server (Port ${FRONTEND_PORT}):${NC}"
|
||||
if [ -f "${PROJECT_ROOT}/.frontend.pid" ]; then
|
||||
FRONTEND_PID=$(cat "${PROJECT_ROOT}/.frontend.pid")
|
||||
if ps -p $FRONTEND_PID > /dev/null 2>&1; then
|
||||
echo -e " Status: ${GREEN}✓ Running${NC}"
|
||||
echo -e " PID: $FRONTEND_PID"
|
||||
if curl -s http://localhost:${FRONTEND_PORT} > /dev/null 2>&1; then
|
||||
echo -e " Health: ${GREEN}✓ Responding${NC}"
|
||||
else
|
||||
echo -e " Health: ${YELLOW}⚠ Not responding${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e " Status: ${RED}✗ Not running (stale PID file)${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e " Status: ${RED}✗ Not running${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# URLs
|
||||
echo -e "${BLUE}🌐 Application URLs:${NC}"
|
||||
echo -e " • Frontend: ${GREEN}http://localhost:${FRONTEND_PORT}${NC}"
|
||||
echo -e " • Backend API: ${GREEN}http://localhost:${BACKEND_PORT}${NC}"
|
||||
echo ""
|
||||
|
||||
# Log files
|
||||
echo -e "${BLUE}📝 Log Files:${NC}"
|
||||
if [ -f "${PROJECT_ROOT}/backend-server.log" ]; then
|
||||
echo -e " • Backend: ${GREEN}${PROJECT_ROOT}/backend-server.log${NC}"
|
||||
echo -e " Last 3 lines:"
|
||||
tail -3 "${PROJECT_ROOT}/backend-server.log" | sed 's/^/ /'
|
||||
else
|
||||
echo -e " • Backend: ${YELLOW}No log file${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
if [ -f "${PROJECT_ROOT}/frontend-server.log" ]; then
|
||||
echo -e " • Frontend: ${GREEN}${PROJECT_ROOT}/frontend-server.log${NC}"
|
||||
echo -e " Last 3 lines:"
|
||||
tail -3 "${PROJECT_ROOT}/frontend-server.log" | sed 's/^/ /'
|
||||
else
|
||||
echo -e " • Frontend: ${YELLOW}No log file${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Commands
|
||||
echo -e "${BLUE}💡 Useful Commands:${NC}"
|
||||
echo -e " • View backend logs: ${GREEN}tail -f backend-server.log${NC}"
|
||||
echo -e " • View frontend logs: ${GREEN}tail -f frontend-server.log${NC}"
|
||||
echo -e " • Stop servers: ${GREEN}./stop.sh${NC}"
|
||||
echo -e " • Restart: ${GREEN}./stop.sh && ./setup.sh${NC}"
|
||||
echo ""
|
||||
Loading…
Add table
Reference in a new issue