#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" RUN_DIR="$ROOT_DIR/.run" LOG_DIR="$RUN_DIR/logs" BACKEND_PID_FILE="$RUN_DIR/backend.pid" FRONTEND_PID_FILE="$RUN_DIR/frontend.pid" BACKEND_LOG="$LOG_DIR/backend.log" FRONTEND_LOG="$LOG_DIR/frontend.log" BACKEND_HOST="${BACKEND_HOST:-127.0.0.1}" BACKEND_PORT="${BACKEND_PORT:-8001}" FRONTEND_HOST="${FRONTEND_HOST:-127.0.0.1}" FRONTEND_PORT="${FRONTEND_PORT:-3001}" API_BASE_URL="${NEXT_PUBLIC_API_BASE_URL:-http://${BACKEND_HOST}:${BACKEND_PORT}}" mkdir -p "$LOG_DIR" is_running() { local pid_file="$1" if [[ -f "$pid_file" ]]; then local pid pid="$(cat "$pid_file")" if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then return 0 fi rm -f "$pid_file" fi return 1 } require_file() { local path="$1" local label="$2" if [[ ! -e "$path" ]]; then echo "$label not found: $path" >&2 exit 1 fi } require_file "$ROOT_DIR/backend/.venv/bin/uvicorn" "Backend virtualenv executable" require_file "$ROOT_DIR/frontend/node_modules" "Frontend dependencies" if is_running "$BACKEND_PID_FILE"; then echo "Backend already running on PID $(cat "$BACKEND_PID_FILE")" else ( cd "$ROOT_DIR/backend" exec .venv/bin/uvicorn app.main:app --reload --host "$BACKEND_HOST" --port "$BACKEND_PORT" ) >"$BACKEND_LOG" 2>&1 & echo $! >"$BACKEND_PID_FILE" echo "Started backend on http://${BACKEND_HOST}:${BACKEND_PORT} (PID $(cat "$BACKEND_PID_FILE"))" fi if is_running "$FRONTEND_PID_FILE"; then echo "Frontend already running on PID $(cat "$FRONTEND_PID_FILE")" else ( cd "$ROOT_DIR/frontend" export NEXT_PUBLIC_API_BASE_URL="$API_BASE_URL" exec npm run dev -- --hostname "$FRONTEND_HOST" --port "$FRONTEND_PORT" ) >"$FRONTEND_LOG" 2>&1 & echo $! >"$FRONTEND_PID_FILE" echo "Started frontend on http://${FRONTEND_HOST}:${FRONTEND_PORT} (PID $(cat "$FRONTEND_PID_FILE"))" fi cat <