Created
November 2, 2025 20:04
-
-
Save MonteLogic/2a0a90d4d2b77969cec57e9bc5cbd858 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // scripts/mobile-web-dev.js | |
| const { networkInterfaces } = require('os'); | |
| const { spawn } = require('child_process'); | |
| const net = require('net'); | |
| // --- 1. Find the local IP address --- | |
| const nets = networkInterfaces(); | |
| let localIp = 'localhost'; | |
| // Iterate over network interfaces to find the non-internal IPv4 address | |
| for (const name of Object.keys(nets)) { | |
| for (const netInterface of nets[name]) { | |
| // Skip over internal (e.g. 127.0.0.1) and non-IPv4 addresses | |
| if (netInterface.family === 'IPv4' && !netInterface.internal) { | |
| localIp = netInterface.address; | |
| break; | |
| } | |
| } | |
| } | |
| // --- 2. Function to check if a port is available --- | |
| function isPortAvailable(port) { | |
| return new Promise((resolve) => { | |
| const server = net.createServer(); | |
| server.once('error', (err) => { | |
| if (err.code === 'EADDRINUSE') { | |
| resolve(false); // Port is in use | |
| } else { | |
| resolve(false); // Other error, assume port not available | |
| } | |
| }); | |
| server.once('listening', () => { | |
| server.once('close', () => { | |
| resolve(true); // Port is available | |
| }); | |
| server.close(); | |
| }); | |
| server.listen(port); | |
| }); | |
| } | |
| // --- 3. Find an available port starting from 3000 --- | |
| async function findAvailablePort(startPort = 3000, maxAttempts = 100) { | |
| console.log(`\nπ Looking for an available port starting from ${startPort}...`); | |
| for (let port = startPort; port < startPort + maxAttempts; port++) { | |
| const available = await isPortAvailable(port); | |
| if (available) { | |
| console.log(`β Found available port: ${port}\n`); | |
| return port; | |
| } | |
| process.stdout.write(` Port ${port} is in use, trying ${port + 1}...\r`); | |
| } | |
| throw new Error(`Could not find an available port after ${maxAttempts} attempts`); | |
| } | |
| // --- 4. Main function to start the server --- | |
| async function startServer() { | |
| try { | |
| const port = await findAvailablePort(3000); | |
| // Print the mobile URL | |
| console.log(`\nπ Server starting on port ${port}...`); | |
| console.log(`π± Access on your phone at: http://${localIp}:${port}\n`); | |
| console.log(`π» Or on your computer at: http://localhost:${port}\n`); | |
| // Security warning | |
| console.log(`\nπ SECURITY WARNING:`); | |
| console.log(` This server is accessible to anyone on your local network (${localIp}:${port})`); | |
| console.log(` β οΈ Risks:`); | |
| console.log(` - Dev server may expose stack traces and debug info`); | |
| console.log(` - Public API endpoints: /api/generate-basic-siddur, /blog, /`); | |
| console.log(` - Could be exploited for DoS (resource exhaustion)`); | |
| console.log(` β Protections:`); | |
| console.log(` - Cannot directly hack your machine`); | |
| console.log(` - Clerk auth protects most routes`); | |
| console.log(` - Only accessible on local network (not internet)`); | |
| console.log(` π‘ Recommendations:`); | |
| console.log(` - Only use on trusted networks (home/work)`); | |
| console.log(` - Stop the server when not in use`); | |
| console.log(` - Don't use on public Wi-Fi\n`); | |
| console.log(`\nβ οΈ IMPORTANT: For Clerk to work on your phone, add this URL to your Clerk dashboard:`); | |
| console.log(` - Go to https://dashboard.clerk.com β Your App β Settings β Domains`); | |
| console.log(` - Add: ${localIp}:${port}`); | |
| console.log(` - Or add a wildcard pattern for your local network if needed\n`); | |
| // Set environment variables for Clerk to recognize the domain | |
| const env = { | |
| ...process.env, | |
| NEXT_PUBLIC_CLERK_FRONTEND_API: process.env.NEXT_PUBLIC_CLERK_FRONTEND_API || '', | |
| // Set the domain that Clerk will use for redirects | |
| CLERK_DOMAIN: `${localIp}:${port}`, | |
| }; | |
| // Start the Next.js dev server | |
| const child = spawn('npx', ['next', 'dev', '-H', '0.0.0.0', '-p', port.toString()], { | |
| // Pipe the server's output (logs, errors, etc.) to this script's console | |
| stdio: 'inherit', | |
| env: env, | |
| }); | |
| // Handle errors from the child process | |
| child.on('error', (err) => { | |
| console.error('Failed to start Next.js server:', err); | |
| process.exit(1); | |
| }); | |
| // Handle process exit | |
| child.on('exit', (code) => { | |
| if (code !== 0) { | |
| console.error(`Next.js server exited with code ${code}`); | |
| process.exit(code); | |
| } | |
| }); | |
| } catch (error) { | |
| console.error('Error starting server:', error.message); | |
| process.exit(1); | |
| } | |
| } | |
| // Start the server | |
| startServer(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment