538 lines
No EOL
18 KiB
Bash
Executable file
538 lines
No EOL
18 KiB
Bash
Executable file
#!/bin/bash
|
|
# filepath: /Users/tbehrend/Repositories/thatsme/deploy-shared-no-db.sh
|
|
|
|
echo "🚀 Creating deployment packages for 'That's Me' development structure..."
|
|
|
|
# Clean up previous deployment
|
|
rm -rf development
|
|
mkdir -p development/{frontend,backend}
|
|
|
|
echo "📦 Building frontend..."
|
|
cd frontend
|
|
npm install
|
|
quasar build
|
|
cd ..
|
|
|
|
echo "🔧 Preparing backend..."
|
|
cd backend
|
|
composer install --optimize-autoloader --no-dev --no-interaction
|
|
|
|
if [ -f "package.json" ]; then
|
|
npm install
|
|
NODE_ENV=production npm run build
|
|
fi
|
|
cd ..
|
|
|
|
echo "📂 Creating FRONTEND deployment structure..."
|
|
|
|
# Frontend deployment - complete Quasar SPA
|
|
cp -r frontend/dist/spa/* development/frontend/
|
|
cp -r frontend/public/images development/frontend/
|
|
cp -r frontend/public/videos development/frontend/
|
|
if [ -d "frontend/public/audio" ]; then
|
|
cp -r frontend/public/audio development/frontend/
|
|
fi
|
|
|
|
# Create frontend config for development deployment
|
|
cat > development/frontend/config.js << 'EOF'
|
|
// Frontend configuration for development deployment
|
|
window.APP_CONFIG = {
|
|
API_BASE_URL: '/api',
|
|
APP_URL: window.location.origin,
|
|
environment: 'development',
|
|
database: false
|
|
};
|
|
EOF
|
|
|
|
# Update frontend index.html to include config
|
|
sed -i.bak 's|</head>| <script src="/config.js"></script>\n </head>|' development/frontend/index.html
|
|
|
|
# Create frontend .htaccess for SPA routing
|
|
cat > development/frontend/.htaccess << 'EOF'
|
|
<IfModule mod_rewrite.c>
|
|
<IfModule mod_negotiation.c>
|
|
Options -MultiViews -Indexes
|
|
</IfModule>
|
|
|
|
RewriteEngine On
|
|
|
|
# Handle client-side routing for Vue SPA
|
|
RewriteCond %{REQUEST_FILENAME} !-f
|
|
RewriteCond %{REQUEST_FILENAME} !-d
|
|
RewriteRule . /index.html [L]
|
|
</IfModule>
|
|
|
|
# Cache static assets
|
|
<IfModule mod_expires.c>
|
|
ExpiresActive on
|
|
ExpiresByType text/css "access plus 1 year"
|
|
ExpiresByType application/javascript "access plus 1 year"
|
|
ExpiresByType image/png "access plus 1 year"
|
|
ExpiresByType image/jpg "access plus 1 year"
|
|
ExpiresByType image/jpeg "access plus 1 year"
|
|
ExpiresByType image/gif "access plus 1 year"
|
|
ExpiresByType image/webp "access plus 1 year"
|
|
ExpiresByType video/mp4 "access plus 1 month"
|
|
</IfModule>
|
|
|
|
# Security headers
|
|
<IfModule mod_headers.c>
|
|
Header always set X-Content-Type-Options nosniff
|
|
Header always set X-Frame-Options SAMEORIGIN
|
|
Header always set X-XSS-Protection "1; mode=block"
|
|
</IfModule>
|
|
EOF
|
|
|
|
echo "📂 Creating BACKEND deployment structure..."
|
|
|
|
# Backend deployment - Laravel application
|
|
mkdir -p development/backend/{app,bootstrap,config,database,resources,routes,storage,vendor,public}
|
|
|
|
# Copy Laravel core files
|
|
cp -r backend/app development/backend/
|
|
cp -r backend/bootstrap development/backend/
|
|
cp -r backend/config development/backend/
|
|
cp -r backend/database development/backend/
|
|
cp -r backend/resources development/backend/
|
|
cp -r backend/routes development/backend/
|
|
cp -r backend/storage development/backend/
|
|
cp -r backend/vendor development/backend/
|
|
|
|
# Copy backend root files
|
|
cp backend/artisan development/backend/
|
|
cp backend/composer.json development/backend/
|
|
cp backend/composer.lock development/backend/
|
|
if [ -f "backend/vite.config.js" ]; then
|
|
cp backend/vite.config.js development/backend/
|
|
fi
|
|
|
|
# Copy built assets to public
|
|
if [ -d "backend/public/build" ]; then
|
|
cp -r backend/public/build development/backend/public/
|
|
fi
|
|
|
|
# Copy other public assets
|
|
if [ -d "backend/public" ]; then
|
|
rsync -av --exclude='build' backend/public/ development/backend/public/
|
|
fi
|
|
|
|
# Create backend index.php for development structure
|
|
cat > development/backend/public/index.php << 'EOF'
|
|
<?php
|
|
/**
|
|
* Laravel Backend for That's Me Development
|
|
*/
|
|
|
|
use Illuminate\Contracts\Http\Kernel;
|
|
use Illuminate\Http\Request;
|
|
|
|
define('LARAVEL_START', microtime(true));
|
|
|
|
require_once __DIR__.'/../vendor/autoload.php';
|
|
|
|
$app = require_once __DIR__.'/../bootstrap/app.php';
|
|
|
|
$kernel = $app->make(Kernel::class);
|
|
|
|
$response = $kernel->handle(
|
|
$request = Request::capture()
|
|
);
|
|
|
|
$response->send();
|
|
|
|
$kernel->terminate($request, $response);
|
|
EOF
|
|
|
|
# Create backend .htaccess
|
|
cat > development/backend/public/.htaccess << 'EOF'
|
|
<IfModule mod_rewrite.c>
|
|
<IfModule mod_negotiation.c>
|
|
Options -MultiViews -Indexes
|
|
</IfModule>
|
|
|
|
RewriteEngine On
|
|
|
|
# Handle Authorization Header
|
|
RewriteCond %{HTTP:Authorization} .
|
|
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
|
|
|
# Redirect Trailing Slashes If Not A Folder
|
|
RewriteCond %{REQUEST_FILENAME} !-d
|
|
RewriteCond %{REQUEST_URI} (.+)/$
|
|
RewriteRule ^ %1 [L,R=301]
|
|
|
|
# Send Requests To Front Controller
|
|
RewriteCond %{REQUEST_FILENAME} !-d
|
|
RewriteCond %{REQUEST_FILENAME} !-f
|
|
RewriteRule ^ index.php [L]
|
|
</IfModule>
|
|
|
|
# Security headers
|
|
<IfModule mod_headers.c>
|
|
Header always set X-Content-Type-Options nosniff
|
|
Header always set X-Frame-Options DENY
|
|
Header always set X-XSS-Protection "1; mode=block"
|
|
|
|
# CORS for development
|
|
Header always set Access-Control-Allow-Origin "*"
|
|
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
|
|
Header always set Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With"
|
|
</IfModule>
|
|
EOF
|
|
|
|
# Create API routes for backend (database-free)
|
|
cat > development/backend/routes/web.php << 'EOF'
|
|
<?php
|
|
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
// API routes for Quasar frontend (no database needed)
|
|
Route::prefix('api')->group(function () {
|
|
Route::middleware(['web'])->group(function () {
|
|
|
|
Route::get('/health', function () {
|
|
return response()->json([
|
|
'status' => 'ok',
|
|
'app' => 'That\'s Me Backend API',
|
|
'version' => '1.0.0',
|
|
'mode' => 'development-no-database',
|
|
'timestamp' => now()->toISOString()
|
|
]);
|
|
});
|
|
|
|
// Mock LifeWave data for anime.js visualizations
|
|
Route::get('/life-events', function () {
|
|
return response()->json([
|
|
'events' => [
|
|
[
|
|
'id' => 1,
|
|
'title' => 'Schulanfang',
|
|
'value' => 0.8,
|
|
'x' => 0.1,
|
|
'imageUrl' => '/images/thumbs/aaron-huber-RLs8LZcONCA-unsplash.jpg',
|
|
'date' => '2010-09-01',
|
|
'description' => 'Mein erster Schultag war aufregend und voller neuer Erfahrungen.',
|
|
'animationDelay' => 100
|
|
],
|
|
[
|
|
'id' => 2,
|
|
'title' => 'Erster Job',
|
|
'value' => 0.9,
|
|
'x' => 0.3,
|
|
'imageUrl' => '/images/thumbs/andrew-bui-z7rzbFHXym0-unsplash.jpg',
|
|
'date' => '2020-03-15',
|
|
'description' => 'Der Beginn meiner beruflichen Laufbahn in einem tollen Team.',
|
|
'animationDelay' => 200
|
|
],
|
|
[
|
|
'id' => 3,
|
|
'title' => 'Umzug nach München',
|
|
'value' => 0.6,
|
|
'x' => 0.5,
|
|
'imageUrl' => '/images/thumbs/becca-tapert--A_Sx8GrRWg-unsplash.jpg',
|
|
'date' => '2022-06-20',
|
|
'description' => 'Ein großer Schritt in eine neue Stadt und neue Möglichkeiten.',
|
|
'animationDelay' => 300
|
|
],
|
|
[
|
|
'id' => 4,
|
|
'title' => 'Hochzeit',
|
|
'value' => 1.0,
|
|
'x' => 0.7,
|
|
'imageUrl' => '/images/thumbs/fuu-j-r2nJPbEYuSQ-unsplash.jpg',
|
|
'date' => '2023-08-12',
|
|
'description' => 'Der schönste Tag meines Lebens mit der Person, die ich liebe.',
|
|
'isFavorite' => true,
|
|
'animationDelay' => 400
|
|
],
|
|
[
|
|
'id' => 5,
|
|
'title' => 'Neues Projekt',
|
|
'value' => 0.85,
|
|
'x' => 0.9,
|
|
'imageUrl' => '/images/thumbs/ian-dooley-hpTH5b6mo2s-unsplash.jpg',
|
|
'date' => '2024-01-10',
|
|
'description' => 'Start eines spannenden neuen Projekts mit großem Potenzial.',
|
|
'isFavorite' => true,
|
|
'animationDelay' => 500
|
|
]
|
|
],
|
|
'waveConfig' => [
|
|
'amplitude' => 0.3,
|
|
'frequency' => 2,
|
|
'animationDuration' => 2000,
|
|
'easingFunction' => 'easeInOutQuad'
|
|
]
|
|
]);
|
|
});
|
|
|
|
// Mock entry detail for LifeWave interaction
|
|
Route::get('/entries/{id}', function ($id) {
|
|
$events = [
|
|
1 => [
|
|
'id' => 1,
|
|
'title' => 'Schulanfang',
|
|
'subtitle' => 'Ein wichtiger Meilenstein',
|
|
'date' => '2010-09-01',
|
|
'time' => '08:00',
|
|
'location' => 'Grundschule am Park',
|
|
'level' => 2,
|
|
'keyImage' => '/images/thumbs/aaron-huber-RLs8LZcONCA-unsplash.jpg',
|
|
'description' => 'Mein erster Schultag war aufregend und voller neuer Erfahrungen. Die Schultüte war schwer und ich war gleichzeitig nervös und neugierig.',
|
|
'additionalImages' => [
|
|
['url' => '/images/thumbs/andrew-bui-z7rzbFHXym0-unsplash.jpg', 'caption' => 'Vorbereitung am Morgen'],
|
|
['url' => '/images/thumbs/becca-tapert--A_Sx8GrRWg-unsplash.jpg', 'caption' => 'Mit der Familie']
|
|
],
|
|
'audioRecordings' => [
|
|
['name' => 'Erinnerungen', 'url' => '/audio/sample.mp3']
|
|
],
|
|
'videoRecordings' => [
|
|
['name' => 'Einschulungsfeier', 'url' => '/videos/3191901-uhd_3840_2160_25fps.mp4']
|
|
],
|
|
'relatedPersons' => [
|
|
['id' => 1, 'name' => 'Mama', 'relation' => 'Mutter', 'avatar' => null],
|
|
['id' => 2, 'name' => 'Papa', 'relation' => 'Vater', 'avatar' => null]
|
|
],
|
|
'categories' => [
|
|
['id' => 1, 'name' => 'Bildung', 'icon' => 'school'],
|
|
['id' => 2, 'name' => 'Familie', 'icon' => 'family_restroom']
|
|
],
|
|
'tags' => [
|
|
['id' => 1, 'name' => 'Aufregend', 'icon' => 'emoji_emotions'],
|
|
['id' => 2, 'name' => 'Neuanfang', 'icon' => 'new_releases']
|
|
]
|
|
]
|
|
];
|
|
|
|
$event = $events[$id] ?? [
|
|
'id' => (int)$id,
|
|
'title' => 'Sample Entry ' . $id,
|
|
'subtitle' => 'Ein wichtiger Meilenstein',
|
|
'date' => '2023-08-12',
|
|
'time' => '14:30',
|
|
'location' => 'München, Deutschland',
|
|
'level' => 2,
|
|
'keyImage' => '/images/familie2.png',
|
|
'description' => 'Eine detaillierte Beschreibung dieses wichtigen Lebensereignisses.'
|
|
];
|
|
|
|
return response()->json($event);
|
|
});
|
|
});
|
|
});
|
|
|
|
// Simple API info page
|
|
Route::get('/', function () {
|
|
return response()->json([
|
|
'app' => 'That\'s Me Backend API (Development)',
|
|
'frontend_path' => '../frontend/',
|
|
'api_endpoints' => [
|
|
'health' => '/api/health',
|
|
'life_events' => '/api/life-events',
|
|
'entry_detail' => '/api/entries/{id}'
|
|
],
|
|
'note' => 'Database-free development mode with mock LifeWave data'
|
|
]);
|
|
});
|
|
EOF
|
|
|
|
# Create backend environment file for development
|
|
cat > development/backend/.env.production << 'EOF'
|
|
APP_NAME="That's Me Backend (Development)"
|
|
APP_ENV=production
|
|
APP_KEY=
|
|
APP_DEBUG=false
|
|
APP_URL=http://localhost
|
|
|
|
LOG_CHANNEL=single
|
|
LOG_DEPRECATIONS_CHANNEL=null
|
|
LOG_LEVEL=error
|
|
|
|
# NO DATABASE CONFIGURATION
|
|
# Database is disabled for this development deployment
|
|
|
|
# Cache Configuration (file-based, no database)
|
|
BROADCAST_DRIVER=log
|
|
CACHE_DRIVER=file
|
|
FILESYSTEM_DISK=local
|
|
QUEUE_CONNECTION=sync
|
|
SESSION_DRIVER=file
|
|
SESSION_LIFETIME=120
|
|
|
|
# Mail Configuration (optional)
|
|
MAIL_MAILER=log
|
|
EOF
|
|
|
|
# Create root .htaccess for combined deployment
|
|
cat > development/.htaccess << 'EOF'
|
|
<IfModule mod_rewrite.c>
|
|
<IfModule mod_negotiation.c>
|
|
Options -MultiViews -Indexes
|
|
</IfModule>
|
|
|
|
RewriteEngine On
|
|
|
|
# API routes to backend
|
|
RewriteCond %{REQUEST_URI} ^/api/
|
|
RewriteRule ^api/(.*)$ /backend/public/index.php [L,QSA]
|
|
|
|
# Backend admin routes
|
|
RewriteCond %{REQUEST_URI} ^/admin/
|
|
RewriteRule ^admin/(.*)$ /backend/public/index.php [L,QSA]
|
|
|
|
# Frontend SPA (default)
|
|
RewriteCond %{REQUEST_FILENAME} !-f
|
|
RewriteCond %{REQUEST_FILENAME} !-d
|
|
RewriteCond %{REQUEST_URI} !^/backend/
|
|
RewriteRule ^(.*)$ /frontend/index.html [L]
|
|
</IfModule>
|
|
|
|
# Security headers
|
|
<IfModule mod_headers.c>
|
|
Header always set X-Content-Type-Options nosniff
|
|
Header always set X-Frame-Options SAMEORIGIN
|
|
Header always set X-XSS-Protection "1; mode=block"
|
|
</IfModule>
|
|
|
|
# Cache static assets
|
|
<IfModule mod_expires.c>
|
|
ExpiresActive on
|
|
ExpiresByType text/css "access plus 1 year"
|
|
ExpiresByType application/javascript "access plus 1 year"
|
|
ExpiresByType image/png "access plus 1 year"
|
|
ExpiresByType image/jpg "access plus 1 year"
|
|
ExpiresByType image/jpeg "access plus 1 year"
|
|
ExpiresByType image/gif "access plus 1 year"
|
|
ExpiresByType image/webp "access plus 1 year"
|
|
ExpiresByType video/mp4 "access plus 1 month"
|
|
</IfModule>
|
|
EOF
|
|
|
|
# Create combined deployment instructions
|
|
cat > development/README.md << 'EOF'
|
|
# That's Me - Development Deployment
|
|
|
|
## Structure
|
|
```
|
|
development/
|
|
├── frontend/ # Quasar SPA build
|
|
│ ├── index.html
|
|
│ ├── js/
|
|
│ ├── css/
|
|
│ ├── images/
|
|
│ ├── videos/
|
|
│ └── .htaccess
|
|
├── backend/ # Laravel API
|
|
│ ├── app/
|
|
│ ├── public/
|
|
│ │ └── index.php
|
|
│ ├── routes/
|
|
│ ├── .env.production
|
|
│ └── ...
|
|
├── .htaccess # Root routing
|
|
└── README.md
|
|
```
|
|
|
|
## Deployment Instructions
|
|
|
|
### Option 1: Combined Deployment (Single Domain)
|
|
1. Upload entire `development/` folder contents to web root
|
|
2. Configure backend:
|
|
- Rename `backend/.env.production` to `backend/.env`
|
|
- Generate APP_KEY (see below)
|
|
- Set permissions: 755 for `backend/storage/` and `backend/bootstrap/cache/`
|
|
|
|
### Option 2: Separate Subdomains
|
|
- Frontend: Upload `frontend/` contents to frontend subdomain
|
|
- Backend: Upload `backend/` contents to backend subdomain
|
|
|
|
## Generate Laravel APP_KEY
|
|
Create temporary file in web root:
|
|
```php
|
|
<?php
|
|
// generate-key.php - DELETE AFTER USE!
|
|
require_once 'backend/vendor/autoload.php';
|
|
echo 'APP_KEY=' . 'base64:' . base64_encode(random_bytes(32));
|
|
?>
|
|
```
|
|
|
|
## URL Structure (Combined)
|
|
- **Frontend**: `yourdomain.com/` (Quasar LifeWave SPA)
|
|
- **API**: `yourdomain.com/api/health`, `/api/life-events`, `/api/entries/{id}`
|
|
- **Backend Admin**: `yourdomain.com/admin/` (if Livewire/Volt components added)
|
|
|
|
## Features
|
|
- ✅ LifeWave visualization with anime.js
|
|
- ✅ Mock life events data for development
|
|
- ✅ Database-free operation
|
|
- ✅ CORS configured for cross-origin requests
|
|
- ✅ File-based sessions and cache
|
|
- ✅ SPA routing for Vue Router
|
|
|
|
## Testing
|
|
- Health check: `/api/health`
|
|
- Life events: `/api/life-events` (returns events with animation config)
|
|
- Entry detail: `/api/entries/1`
|
|
|
|
Perfect for development and demo environments!
|
|
EOF
|
|
|
|
# Create individual deployment instructions
|
|
cat > development/frontend/DEPLOYMENT_INSTRUCTIONS.md << 'EOF'
|
|
# Frontend Deployment
|
|
|
|
## Standalone Frontend Deployment
|
|
Upload contents of this folder to web root for frontend-only deployment.
|
|
|
|
## What's Included
|
|
- Complete Quasar SPA build with LifeWave visualization
|
|
- Images, videos, and audio assets
|
|
- SPA routing via .htaccess
|
|
- Development configuration
|
|
|
|
## Dependencies
|
|
- Backend API for data (configure API_BASE_URL in config.js)
|
|
- anime.js for wave animations (included in build)
|
|
EOF
|
|
|
|
cat > development/backend/DEPLOYMENT_INSTRUCTIONS.md << 'EOF'
|
|
# Backend Deployment
|
|
|
|
## Laravel API Deployment
|
|
Upload contents of this folder to web root for backend-only deployment.
|
|
|
|
## Setup Steps
|
|
1. Rename `.env.production` to `.env`
|
|
2. Generate APP_KEY using provided instructions
|
|
3. Set file permissions: 755 for storage/ and bootstrap/cache/
|
|
4. Test API endpoints
|
|
|
|
## API Endpoints
|
|
- Health: `/api/health`
|
|
- Life Events: `/api/life-events` (LifeWave data with animation config)
|
|
- Entry Details: `/api/entries/{id}`
|
|
|
|
## Features
|
|
- Database-free operation with mock data
|
|
- CORS configured for frontend integration
|
|
- Optimized for anime.js LifeWave visualizations
|
|
EOF
|
|
|
|
echo "✅ Development deployment structure created successfully!"
|
|
echo ""
|
|
echo "📁 Created development structure:"
|
|
echo " - development/frontend/ (Quasar SPA)"
|
|
echo " - development/backend/ (Laravel API)"
|
|
echo " - development/.htaccess (Combined routing)"
|
|
echo ""
|
|
echo "🎯 Deployment Options:"
|
|
echo " 1. Combined: Upload entire development/ folder"
|
|
echo " 2. Separate: Upload frontend/ and backend/ to different domains"
|
|
echo ""
|
|
echo "🌊 Features:"
|
|
echo " - LifeWave visualization ready"
|
|
echo " - Mock data with animation config"
|
|
echo " - Database-free operation"
|
|
echo " - anime.js integration support"
|
|
echo ""
|
|
echo "📋 Next: Follow README.md in development/ folder" |