feat(quixzoom-asia): Full rebuild v1.0.0 — 9 languages, Landvex auth, light theme
- Rebuilt all 9 Asian language landing pages (zh-CN, zh-TW, ja, ko, th, vi, id, ms, hi) - Switched from dark to light theme per MOBILE_FIRST_STANDARD - Added Landvex Authorization section (VW-style certification flow) - Added full copy: hero, stats, how-it-works, missions, earnings, FAQ, footer - Localized currencies and payment methods per market - Build system: template + JSON translations → static HTML - Validation script ensures no missing translations or placeholder leaks - CI/CD pipeline: GitHub Actions → S3 + CloudFront - Version management: npm version patch/minor/major BREAKING CHANGE: Old placeholder pages replaced with full content
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Deploy to S3 + CloudFront
|
||||
* Usage: node scripts/deploy.js --env=staging|production
|
||||
*/
|
||||
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ENVIRONMENTS = {
|
||||
staging: {
|
||||
bucket: 'quixzoom-asia-staging',
|
||||
region: 'ap-southeast-1',
|
||||
distributionId: process.env.CF_DIST_STAGING,
|
||||
url: 'https://staging.quixzoom.asia',
|
||||
},
|
||||
production: {
|
||||
bucket: 'quixzoom-asia',
|
||||
region: 'ap-southeast-1',
|
||||
distributionId: process.env.CF_DIST_PRODUCTION,
|
||||
url: 'https://quixzoom.asia',
|
||||
},
|
||||
};
|
||||
|
||||
const [, , envArg] = process.argv;
|
||||
const env = envArg?.replace('--env=', '') || 'staging';
|
||||
|
||||
if (!ENVIRONMENTS[env]) {
|
||||
console.error(`❌ Unknown environment: ${env}`);
|
||||
console.error('Usage: node scripts/deploy.js --env=staging|production');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const config = ENVIRONMENTS[env];
|
||||
const distDir = path.join(__dirname, '../dist');
|
||||
const manifestPath = path.join(distDir, 'manifest.json');
|
||||
|
||||
if (!fs.existsSync(distDir)) {
|
||||
console.error('❌ No dist/ directory. Run: npm run build');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
||||
|
||||
console.log(`🚀 Deploying quiXzoom Asia v${manifest.version} to ${env}...`);
|
||||
console.log(` Bucket: ${config.bucket}`);
|
||||
console.log(` Region: ${config.region}`);
|
||||
console.log(` Commit: ${manifest.gitCommit}`);
|
||||
console.log('');
|
||||
|
||||
// Sync to S3
|
||||
const syncCmd = `aws s3 sync ${distDir}/ s3://${config.bucket}/ \
|
||||
--delete \
|
||||
--cache-control "max-age=3600" \
|
||||
--region ${config.region}`;
|
||||
|
||||
console.log('📤 Uploading...');
|
||||
execSync(syncCmd, { stdio: 'inherit' });
|
||||
|
||||
// Set content types
|
||||
console.log('\n📝 Setting content types...');
|
||||
execSync(`aws s3 cp s3://${config.bucket}/ s3://${config.bucket}/ \
|
||||
--recursive --exclude "*" --include "*.html" \
|
||||
--content-type "text/html; charset=utf-8" \
|
||||
--metadata-directive REPLACE --region ${config.region}`, { stdio: 'inherit' });
|
||||
|
||||
// Invalidate CloudFront
|
||||
if (config.distributionId) {
|
||||
console.log('\n🔄 Invalidating CloudFront...');
|
||||
execSync(`aws cloudfront create-invalidation \
|
||||
--distribution-id ${config.distributionId} \
|
||||
--paths "/*" --region ${config.region}`, { stdio: 'inherit' });
|
||||
}
|
||||
|
||||
console.log(`\n✅ Deployed to ${config.url}`);
|
||||
console.log(` Version: ${manifest.version}`);
|
||||
console.log(` Build: ${manifest.buildTime}`);
|
||||
Reference in New Issue
Block a user