summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler Hoang <tyler@tylerhoang.xyz>2026-05-19 00:38:46 -0700
committerTyler Hoang <tyler@tylerhoang.xyz>2026-05-19 00:38:46 -0700
commitdcb417cbf251a427861b2cbeb50e7f6a9f06f212 (patch)
treeb86d188f9f2860f186bf4e84b4b757ad5ac2219b
parent0c557f44b59d90900d6a2052a9d97c0266d8feb1 (diff)
unified start/stop script and included systemd files
-rw-r--r--README.md47
-rwxr-xr-xscripts/start-stack.sh80
-rwxr-xr-xscripts/stop-stack.sh42
3 files changed, 39 insertions, 130 deletions
diff --git a/README.md b/README.md
index 9f1de30..d41c8d6 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,8 @@ The implementation copies and adapts finance logic from Prism v1 into `backend/`
- `components/PriceChart.tsx` Plotly price chart
- `lib/api.ts` typed REST client
- `types/api.ts` shared frontend response types
+- `scripts/stack.sh` unified start/stop/restart/status script
+- `systemd/` systemd unit files for running as a system service
- `.env.example` optional environment variables
- `pytest.ini` backend pytest import path config
@@ -95,23 +97,52 @@ The UI stores the selected ticker in the URL, for example `/?ticker=AAPL`.
## Quick Start
-Start the whole local stack:
+`scripts/stack.sh` manages both services as a local development stack:
```bash
-./scripts/start-stack.sh
+./scripts/stack.sh start # start backend + frontend in background
+./scripts/stack.sh stop # stop both
+./scripts/stack.sh restart # stop then start
+./scripts/stack.sh status # show running PIDs and URLs
```
-Stop both services:
+Notes:
+
+- expects `backend/.venv` and `frontend/node_modules` to already exist
+- default ports are backend `8001` and frontend `3001`
+- logs are written to `.run/logs/`
+- override hosts/ports via env vars: `BACKEND_HOST`, `BACKEND_PORT`, `FRONTEND_HOST`, `FRONTEND_PORT`
+
+## Running as a systemd Service
+
+Unit files live in `systemd/`. Install them for the current user:
```bash
-./scripts/stop-stack.sh
+# Copy units
+cp systemd/prismv2-backend.service ~/.config/systemd/user/
+cp systemd/prismv2-frontend.service ~/.config/systemd/user/
+cp systemd/prismv2.target ~/.config/systemd/user/
+
+systemctl --user daemon-reload
+
+# Start both services via the target
+systemctl --user enable --now prismv2.target
+
+# Control individual services
+systemctl --user status prismv2-backend.service
+systemctl --user restart prismv2-frontend.service
+systemctl --user stop prismv2.target
+
+# View logs
+journalctl --user -u prismv2-backend.service -f
+journalctl --user -u prismv2-frontend.service -f
```
-Notes:
+To start automatically on login, enable lingering once:
-- the scripts expect `backend/.venv` and `frontend/node_modules` to already exist
-- default ports are backend `8001` and frontend `3001`
-- logs are written to `.run/logs/`
+```bash
+loginctl enable-linger $USER
+```
## Verification
diff --git a/scripts/start-stack.sh b/scripts/start-stack.sh
deleted file mode 100755
index 6324967..0000000
--- a/scripts/start-stack.sh
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/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 <<EOF
-
-Stack status
-- Frontend: http://${FRONTEND_HOST}:${FRONTEND_PORT}
-- Backend: http://${BACKEND_HOST}:${BACKEND_PORT}
-- API base: $API_BASE_URL
-- Logs: $LOG_DIR
-
-Stop both services with:
- ./scripts/stop-stack.sh
-EOF
diff --git a/scripts/stop-stack.sh b/scripts/stop-stack.sh
deleted file mode 100755
index 606de01..0000000
--- a/scripts/stop-stack.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
-RUN_DIR="$ROOT_DIR/.run"
-
-BACKEND_PID_FILE="$RUN_DIR/backend.pid"
-FRONTEND_PID_FILE="$RUN_DIR/frontend.pid"
-
-stop_process() {
- local name="$1"
- local pid_file="$2"
- if [[ ! -f "$pid_file" ]]; then
- echo "$name not running"
- return
- fi
-
- local pid
- pid="$(cat "$pid_file")"
-
- if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then
- kill "$pid" 2>/dev/null || true
- for _ in {1..20}; do
- if ! kill -0 "$pid" 2>/dev/null; then
- break
- fi
- sleep 0.25
- done
- if kill -0 "$pid" 2>/dev/null; then
- kill -9 "$pid" 2>/dev/null || true
- fi
- echo "Stopped $name (PID $pid)"
- else
- echo "$name pid file was stale"
- fi
-
- rm -f "$pid_file"
-}
-
-stop_process "frontend" "$FRONTEND_PID_FILE"
-stop_process "backend" "$BACKEND_PID_FILE"