diff --git a/README.md b/README.md
index 9c396971..d290676a 100644
--- a/README.md
+++ b/README.md
@@ -16,5 +16,8 @@ Run both application services from the repository root with:
./run.sh
```
-The startup script expects `backend/app/main.py` and
-`frontend/package.json` to be added by the implementation phase.
+On Windows, run `run.bat` instead.
+
+Python 3 and Node.js (including npm) must be installed first. Both startup
+scripts create `backend/.venv` and install the backend and frontend
+dependencies automatically when they are missing.
diff --git a/frontend/next-env.d.ts b/frontend/next-env.d.ts
index 9edff1c7..c4b7818f 100644
--- a/frontend/next-env.d.ts
+++ b/frontend/next-env.d.ts
@@ -1,6 +1,6 @@
///
///
-import "./.next/types/routes.d.ts";
+import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/run.bat b/run.bat
new file mode 100644
index 00000000..b6393e08
--- /dev/null
+++ b/run.bat
@@ -0,0 +1,94 @@
+@echo off
+setlocal EnableExtensions
+
+set "ROOT_DIR=%~dp0"
+set "BACKEND_HOST=%BACKEND_HOST%"
+set "BACKEND_PORT=%BACKEND_PORT%"
+set "FRONTEND_HOST=%FRONTEND_HOST%"
+set "FRONTEND_PORT=%FRONTEND_PORT%"
+
+if not defined BACKEND_HOST set "BACKEND_HOST=127.0.0.1"
+if not defined BACKEND_PORT set "BACKEND_PORT=8000"
+if not defined FRONTEND_HOST set "FRONTEND_HOST=127.0.0.1"
+if not defined FRONTEND_PORT set "FRONTEND_PORT=5173"
+if not defined PYTHON_BIN set "PYTHON_BIN=python"
+
+call "%PYTHON_BIN%" --version >nul 2>&1
+if errorlevel 1 (
+ if /i "%PYTHON_BIN%"=="python" (
+ call py --version >nul 2>&1
+ if not errorlevel 1 set "PYTHON_BIN=py"
+ )
+)
+set "BACKEND_VENV=%ROOT_DIR%backend\.venv"
+set "BACKEND_PYTHON=%BACKEND_VENV%\Scripts\python.exe"
+
+if not exist "%ROOT_DIR%backend\app\main.py" (
+ echo Backend entrypoint not found: backend\app\main.py
+ exit /b 1
+)
+
+if not exist "%ROOT_DIR%frontend\package.json" (
+ echo Frontend package manifest not found: frontend\package.json
+ exit /b 1
+)
+
+if not exist "%ROOT_DIR%backend\requirements.txt" (
+ echo Backend requirements not found: backend\requirements.txt
+ exit /b 1
+)
+
+call "%PYTHON_BIN%" --version >nul 2>&1
+if errorlevel 1 (
+ echo Python executable not found: %PYTHON_BIN%
+ echo Set PYTHON_BIN to the Python executable path and run this script again.
+ exit /b 1
+)
+
+where npm >nul 2>&1
+if errorlevel 1 (
+ echo npm is required to start the frontend.
+ exit /b 1
+)
+
+if not exist "%BACKEND_PYTHON%" (
+ echo Creating backend virtual environment...
+ call "%PYTHON_BIN%" -m venv "%BACKEND_VENV%"
+ if errorlevel 1 exit /b 1
+)
+
+call "%BACKEND_PYTHON%" -c "import build123d, dotenv, fastapi, httpx, jsonschema, multipart, uvicorn" >nul 2>&1
+if errorlevel 1 (
+ echo Installing backend dependencies...
+ call "%BACKEND_PYTHON%" -m pip install -r "%ROOT_DIR%backend\requirements.txt"
+ if errorlevel 1 exit /b 1
+)
+
+if not exist "%ROOT_DIR%frontend\node_modules\next" (
+ echo Installing frontend dependencies...
+ pushd "%ROOT_DIR%frontend"
+ if exist package-lock.json (
+ call npm ci
+ ) else (
+ call npm install
+ )
+ if errorlevel 1 (
+ popd
+ exit /b 1
+ )
+ popd
+)
+
+echo Starting backend on %BACKEND_HOST%:%BACKEND_PORT%
+start "CAD CDSL Backend" /D "%ROOT_DIR%backend" cmd /k call "%BACKEND_PYTHON%" -m uvicorn app.main:app --host %BACKEND_HOST% --port %BACKEND_PORT% --reload
+
+echo Starting frontend on %FRONTEND_HOST%:%FRONTEND_PORT%
+start "CAD CDSL Frontend" /D "%ROOT_DIR%frontend" cmd /k call npm run dev -- -H %FRONTEND_HOST% -p %FRONTEND_PORT%
+
+echo.
+echo Frontend: http://%FRONTEND_HOST%:%FRONTEND_PORT%
+echo Backend: http://%BACKEND_HOST%:%BACKEND_PORT%
+echo The backend and frontend are running in separate command windows.
+echo Close those windows to stop the services.
+
+endlocal
diff --git a/run.sh b/run.sh
index 6feca844..d45995ad 100755
--- a/run.sh
+++ b/run.sh
@@ -7,6 +7,8 @@ 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
@@ -28,6 +30,11 @@ if [[ ! -f "${ROOT_DIR}/frontend/package.json" ]]; then
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
@@ -38,10 +45,32 @@ command -v npm >/dev/null 2>&1 || {
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"
- "${PYTHON_BIN}" -m uvicorn app.main:app \
+ "${BACKEND_PYTHON}" -m uvicorn app.main:app \
--host "${BACKEND_HOST}" \
--port "${BACKEND_PORT}" \
--reload