diff --git a/capacitor.config.ts b/capacitor.config.ts index 2355a0a..ce08a6a 100644 --- a/capacitor.config.ts +++ b/capacitor.config.ts @@ -1,12 +1,22 @@ import type { CapacitorConfig } from '@capacitor/cli'; +// Live reload configuration +// Set CAPACITOR_LIVE_RELOAD=true and CAPACITOR_SERVER_URL to enable +const isLiveReload = process.env.CAPACITOR_LIVE_RELOAD === 'true'; +const serverUrl = process.env.CAPACITOR_SERVER_URL || 'http://192.168.1.100:5000'; + const config: CapacitorConfig = { appId: 'com.aethex.os', appName: 'AeThex OS', webDir: 'dist/public', server: { androidScheme: 'https', - iosScheme: 'https' + iosScheme: 'https', + // Live reload: point to dev server instead of bundled assets + ...(isLiveReload && { + url: serverUrl, + cleartext: true, // Allow HTTP for local development + }), }, plugins: { SplashScreen: { @@ -42,8 +52,18 @@ const config: CapacitorConfig = { android: { allowMixedContent: true, captureInput: true, - webContentsDebuggingEnabled: true - } + webContentsDebuggingEnabled: true, + // Allow cleartext (HTTP) for live reload + ...(isLiveReload && { + allowMixedContent: true, + }), + }, + ios: { + // iOS-specific live reload settings + ...(isLiveReload && { + limitsNavigationsToAppBoundDomains: false, + }), + }, }; export default config; diff --git a/package.json b/package.json index 5912f7d..d76fd2c 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,11 @@ "build:mobile": "npm run build && npx cap sync", "android": "npx cap open android", "ios": "npx cap open ios", + "cap:live-reload": "tsx script/capacitor-live-reload.ts", + "cap:live-reload:android": "tsx script/capacitor-live-reload.ts --android", + "cap:live-reload:ios": "tsx script/capacitor-live-reload.ts --ios", + "cap:production": "tsx script/capacitor-production.ts", + "dev:mobile": "npm run cap:live-reload && concurrently \"npm run dev\" \"echo 'Dev server started. Open Android Studio or Xcode to run the app.'\"", "start": "NODE_ENV=production node dist/index.js", "check": "tsc", "db:push": "drizzle-kit push", diff --git a/script/capacitor-live-reload.ts b/script/capacitor-live-reload.ts new file mode 100644 index 0000000..55fcd67 --- /dev/null +++ b/script/capacitor-live-reload.ts @@ -0,0 +1,130 @@ +#!/usr/bin/env tsx +/** + * Capacitor Live Reload Setup Script + * + * This script configures Capacitor for live reload development by: + * 1. Detecting the local network IP address + * 2. Setting environment variables for the Capacitor config + * 3. Running cap sync to update native projects + * + * Usage: + * npx tsx script/capacitor-live-reload.ts [--port 5000] [--ip 192.168.1.100] + * npm run cap:live-reload + */ + +import { execSync, spawn } from 'child_process'; +import { networkInterfaces } from 'os'; + +interface Options { + port: number; + ip?: string; + platform?: 'android' | 'ios' | 'all'; +} + +function getLocalIP(): string { + const nets = networkInterfaces(); + const results: string[] = []; + + for (const name of Object.keys(nets)) { + const netList = nets[name]; + if (!netList) continue; + + for (const net of netList) { + // Skip internal and non-IPv4 addresses + if (net.family === 'IPv4' && !net.internal) { + results.push(net.address); + } + } + } + + // Prefer common local network ranges + const preferred = results.find(ip => + ip.startsWith('192.168.') || + ip.startsWith('10.') || + ip.startsWith('172.') + ); + + return preferred || results[0] || 'localhost'; +} + +function parseArgs(): Options { + const args = process.argv.slice(2); + const options: Options = { + port: 5000, + platform: 'all' + }; + + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + const next = args[i + 1]; + + if (arg === '--port' && next) { + options.port = parseInt(next, 10); + i++; + } else if (arg === '--ip' && next) { + options.ip = next; + i++; + } else if (arg === '--android') { + options.platform = 'android'; + } else if (arg === '--ios') { + options.platform = 'ios'; + } + } + + return options; +} + +function run(command: string, env?: Record): void { + console.log(`\n> ${command}\n`); + execSync(command, { + stdio: 'inherit', + env: { ...process.env, ...env } + }); +} + +async function main() { + const options = parseArgs(); + const ip = options.ip || getLocalIP(); + const serverUrl = `http://${ip}:${options.port}`; + + console.log('========================================'); + console.log(' Capacitor Live Reload Setup'); + console.log('========================================'); + console.log(` Server URL: ${serverUrl}`); + console.log(` Platform: ${options.platform}`); + console.log('========================================\n'); + + // Set environment variables for Capacitor config + const env = { + CAPACITOR_LIVE_RELOAD: 'true', + CAPACITOR_SERVER_URL: serverUrl + }; + + // Sync Capacitor with live reload configuration + console.log('Syncing Capacitor with live reload configuration...'); + + if (options.platform === 'all') { + run('npx cap sync', env); + } else { + run(`npx cap sync ${options.platform}`, env); + } + + console.log('\n========================================'); + console.log(' Live Reload Setup Complete!'); + console.log('========================================'); + console.log('\nNext steps:'); + console.log(` 1. Start the dev server: npm run dev`); + console.log(` 2. Open your IDE:`); + console.log(` - Android Studio: npm run android`); + console.log(` - Xcode: npm run ios`); + console.log(` 3. Run the app on your device`); + console.log('\nThe app will connect to your dev server at:'); + console.log(` ${serverUrl}`); + console.log('\nMake sure:'); + console.log(' - Your device is on the same network as this machine'); + console.log(' - Firewall allows connections on port ' + options.port); + console.log(' - The dev server is running before launching the app'); + console.log('========================================\n'); +} + +main().catch(console.error); diff --git a/script/capacitor-production.ts b/script/capacitor-production.ts new file mode 100644 index 0000000..85ab47a --- /dev/null +++ b/script/capacitor-production.ts @@ -0,0 +1,59 @@ +#!/usr/bin/env tsx +/** + * Capacitor Production Sync Script + * + * Reverts Capacitor configuration from live reload mode back to production mode. + * This rebuilds the web assets and syncs them to native projects. + * + * Usage: + * npx tsx script/capacitor-production.ts [--android | --ios] + * npm run cap:production + */ + +import { execSync } from 'child_process'; + +function parseArgs(): { platform: 'android' | 'ios' | 'all' } { + const args = process.argv.slice(2); + + if (args.includes('--android')) return { platform: 'android' }; + if (args.includes('--ios')) return { platform: 'ios' }; + return { platform: 'all' }; +} + +function run(command: string): void { + console.log(`\n> ${command}\n`); + execSync(command, { stdio: 'inherit' }); +} + +async function main() { + const { platform } = parseArgs(); + + console.log('========================================'); + console.log(' Capacitor Production Build'); + console.log('========================================'); + console.log(` Platform: ${platform}`); + console.log('========================================\n'); + + // Build production assets + console.log('Building production assets...'); + run('npm run build'); + + // Sync without live reload environment variables + console.log('\nSyncing Capacitor (production mode)...'); + if (platform === 'all') { + run('npx cap sync'); + } else { + run(`npx cap sync ${platform}`); + } + + console.log('\n========================================'); + console.log(' Production Build Complete!'); + console.log('========================================'); + console.log('\nThe app is now configured to use bundled assets.'); + console.log('Open your IDE to build and run:'); + console.log(' - Android Studio: npm run android'); + console.log(' - Xcode: npm run ios'); + console.log('========================================\n'); +} + +main().catch(console.error); diff --git a/vite.config.ts b/vite.config.ts index defd881..b2eedf1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -44,11 +44,20 @@ export default defineConfig({ server: { cors: true, host: "0.0.0.0", - hmr: { - host: "orange-journey-wvwxgw4r6vrf577-5000.app.github.dev", - protocol: "wss", - clientPort: 443, - }, + port: 5000, + // HMR configuration - use different settings for Capacitor live reload vs cloud dev + hmr: process.env.CAPACITOR_LIVE_RELOAD === 'true' + ? { + // For Capacitor live reload: use default WebSocket on same host + protocol: 'ws', + host: undefined, // Uses request host automatically + } + : { + // For cloud development (GitHub Codespaces, Replit, etc.) + host: "orange-journey-wvwxgw4r6vrf577-5000.app.github.dev", + protocol: "wss", + clientPort: 443, + }, allowedHosts: true, fs: { strict: true,