#!/usr/bin/env bash set -Eeuo pipefail ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" BACKEND_HOST="${BACKEND_HOST:-127.0.0.1}" BACKEND_PORT="${BACKEND_PORT:-8000}" FRONTEND_HOST="${FRONTEND_HOST:-127.0.0.1}" FRONTEND_PORT="${FRONTEND_PORT:-5173}" PYTHON_BIN="${PYTHON_BIN:-python3}" BACKEND_VENV="${ROOT_DIR}/backend/.venv" BACKEND_PYTHON="${BACKEND_VENV}/bin/python" cleanup() { local pids pids="$(jobs -pr || true)" if [[ -n "${pids}" ]]; then kill ${pids} 2>/dev/null || true fi } trap cleanup INT TERM EXIT if [[ ! -f "${ROOT_DIR}/backend/app/main.py" ]]; then echo "Backend entrypoint not found: backend/app/main.py" exit 1 fi if [[ ! -f "${ROOT_DIR}/frontend/package.json" ]]; then echo "Frontend package manifest not found: frontend/package.json" exit 1 fi if [[ ! -f "${ROOT_DIR}/backend/requirements.txt" ]]; then echo "Backend requirements not found: backend/requirements.txt" exit 1 fi command -v "${PYTHON_BIN}" >/dev/null 2>&1 || { echo "Python executable not found: ${PYTHON_BIN}" exit 1 } command -v npm >/dev/null 2>&1 || { echo "npm is required to start the frontend" exit 1 } if [[ ! -x "${BACKEND_PYTHON}" ]]; then echo "Creating backend virtual environment..." "${PYTHON_BIN}" -m venv "${BACKEND_VENV}" fi if ! "${BACKEND_PYTHON}" -c 'import build123d, dotenv, fastapi, httpx, jsonschema, multipart, uvicorn' >/dev/null 2>&1; then echo "Installing backend dependencies..." "${BACKEND_PYTHON}" -m pip install -r "${ROOT_DIR}/backend/requirements.txt" fi if [[ ! -d "${ROOT_DIR}/frontend/node_modules/next" ]]; then echo "Installing frontend dependencies..." ( cd "${ROOT_DIR}/frontend" if [[ -f package-lock.json ]]; then npm ci else npm install fi ) fi echo "Starting backend on ${BACKEND_HOST}:${BACKEND_PORT}" ( cd "${ROOT_DIR}/backend" "${BACKEND_PYTHON}" -m uvicorn app.main:app \ --host "${BACKEND_HOST}" \ --port "${BACKEND_PORT}" \ --reload ) & echo "Starting frontend on ${FRONTEND_HOST}:${FRONTEND_PORT}" ( cd "${ROOT_DIR}/frontend" npm run dev -- \ -H "${FRONTEND_HOST}" \ -p "${FRONTEND_PORT}" ) & echo "Frontend: http://${FRONTEND_HOST}:${FRONTEND_PORT}" echo "Backend: http://${BACKEND_HOST}:${BACKEND_PORT}" echo "Press Ctrl+C to stop both services." wait