diff --git a/.dockerignore b/.dockerignore
index cf5282e..6f0d9c3 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,9 +1,9 @@
+npm-debug.log
node_modules
dist
-.git
-npm-debug.log
Dockerfile
+Dockerfile.dev
.dockerignore
-.git
.gitignore
-.env
\ No newline at end of file
+.env
+.env.example
\ No newline at end of file
diff --git a/.env.development b/.env.development
deleted file mode 100644
index 02d4367..0000000
--- a/.env.development
+++ /dev/null
@@ -1,10 +0,0 @@
-# These variables are used for development environment
-VITE_SOARCA_URI=http://localhost:8080 # for vite each env var must start with VITE_ otherwise it won't be exposed to the client side
-VITE_SOARCA_GUI_DOMAIN=http://localhost
-VITE_PORT="3000"
-VITE_OIDC_ISSUER="https://localhost:9443/application/u/test/"
-VITE_OIDC_CLIENT_ID="SOME_CLIENT_ID"
-VITE_OIDC_CLIENT_SECRET="SOME_CLIENT_SECRET"
-VITE_OIDC_REDIRECT_URL="http://localhost:3000/auth/soarca_gui/callback"
-VITE_COOKIE_SECRET_KEY="SOME_COOKIE_SECRET" #openssl rand -base64 32 or head -c 32 /dev/urandom | base64
-VITE_OIDC_SKIP_TLS_VERIFY=true
\ No newline at end of file
diff --git a/.env.example b/.env.example
index 490ec00..a5297b7 100644
--- a/.env.example
+++ b/.env.example
@@ -1 +1,27 @@
-VITE_SOARCA_URI=http://localhost:8080 # for vite each env var must start with VITE_ otherwise it won't be exposed to the client side
\ No newline at end of file
+# .env.example — example environment variables for SOARCA-GUI
+# Copy this file to `.env.development` for local dev or to `.env` for Docker Compose
+# Notes:
+# - Vite exposes ONLY variables prefixed with `VITE_` to the client (import.meta.env).
+# - Client-visible `VITE_` values are embedded at *build time* (rebuild to change).
+# - Docker Compose reads the project `.env` for substitution and container envs.
+# - We also follow a consumer based prefix convention for clarity, so variables used by nginx start with NGINX_, those used by the dev server start with VITE_ etc.
+
+########## Development (Vite) ##########
+# Used by `npm run dev` / Vite dev server. Client-facing variables MUST start with VITE_.
+# copy these lines into `.env.development` or `.env` (see Vite docs at https://vite.dev/guide/env-and-mode) and adjust as needed for local development
+VITE_BACKEND_URL=http://localhost:8080 # backend API URL used by the frontend (dev server proxy target)
+VITE_SERVER_PORT=5173 # dev server port
+
+########## Docker Compose (dev) ##########
+# Values used by `docker-compose.dev.yml`. Compose will substitute ${VAR} from the
+# project `.env` or the shell environment when you run `docker compose`.
+VITE_APP_VERSION=development
+VITE_BACKEND_URL=http://host.docker.internal:8080 # backend API URL used by the frontend inside the container (host.docker.internal points to the host machine)
+VITE_SERVER_PORT=5173 # dev server port inside the container
+DOCKER_HOST_PORT=5173 # port on the host machine mapped to the container's VITE_SERVER_PORT (for browser access)
+
+########## Production (nginx) ##########
+# Values used at container runtime by nginx to proxy /api/
+NGINX_BACKEND_URL=http://host.docker.internal:8080/ # backend API URL used by nginx inside the container (host.docker.internal points to the host machine)
+NGINX_SERVER_PORT=8081 # port nginx listens on inside the container
+DOCKER_HOST_PORT=8081 # port on the host machine mapped to the container's NGINX_SERVER_PORT (for browser access)
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index deb2e95..6afb121 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,19 +1,15 @@
-# Stage 1: Development environment
-FROM node:24-alpine AS development
+# Install dependencies and build the application
+FROM node:24-alpine AS builder
RUN apk add --no-cache git
WORKDIR /app
COPY package*.json ./
-RUN npm install --include=dev
-EXPOSE 3000
-CMD ["npm", "run", "dev"]
-
-# Stage 2: Build for production
-FROM development AS builder
+RUN npm install
COPY . .
RUN npm run build
-# Stage 3: Production environment
+# Serve with nginx
FROM nginx:alpine AS production
+COPY nginx.conf /etc/nginx/templates/default.conf.template
COPY --from=builder /app/dist /usr/share/nginx/html
-EXPOSE 80
+EXPOSE 8081
CMD ["nginx", "-g", "daemon off;"]
\ No newline at end of file
diff --git a/Dockerfile.dev b/Dockerfile.dev
new file mode 100644
index 0000000..ffd98f2
--- /dev/null
+++ b/Dockerfile.dev
@@ -0,0 +1,9 @@
+# Install (dev) dependencies and run development server
+# NOTE: we install git to allow the versioning of the application to be included in the build (e.g., for display in the UI)
+FROM node:24-alpine
+RUN apk add --no-cache git
+WORKDIR /app
+COPY package*.json ./
+RUN npm install --include=dev
+EXPOSE 5173
+CMD ["npm", "run", "dev"]
\ No newline at end of file
diff --git a/README.md b/README.md
index 50fbbac..3229e2d 100644
--- a/README.md
+++ b/README.md
@@ -5,56 +5,317 @@
# SOARCA-GUI
[](https://cossas.github.io/SOARCA/docs/)
+[](https://github.com/cossas/soarca-gui/releases)
[](https://github.com/COSSAS/SOARCA/actions)
[](https://opensource.org/licenses/Apache-2.0)
Modern [React](https://react.dev) + [Vite](https://vitejs.dev) frontend for the [SOARCA](https://github.com/COSSAS/SOARCA) platform, providing a lightweight UI to interact with SOARCA services. The app uses [TypeScript](https://www.typescriptlang.org/), [styled-components](https://styled-components.com/) for theming, [React Router](https://reactrouter.com/) for navigation, and [React Query](https://tanstack.com/query) for data fetching.
> [!WARNING]
-> SOARCA-GUI is still in development and features for the base version v0.1 are still being added.
+> SOARCA-GUI is still in development and features and look may change with time.
-## Requirements for running
+## Requirements
-- [Node.js](https://nodejs.org/) 20+
-- [npm](https://www.npmjs.com/) 10+
-- (Optional) [Docker](https://www.docker.com/) and [Docker Compose](https://docs.docker.com/compose/) for running the full stack locally
+- [Node.js](https://nodejs.org/) 20+ (if runned locally)
+- [npm](https://www.npmjs.com/) 10+ (if runned locally)
+- [Docker](https://www.docker.com/) and [Docker Compose](https://docs.docker.com/compose/) (for building/running from docker image)
-## Getting Started (Development)
+## Running the Project
+
+### Development Mode
+
+Development mode provides hot-reload capabilities and a proxy server for API requests to the SOARCA backend. In order to provide an enjoyable development experience, we provide both a local environment and a Docker setup. In order to accomodate both scenarios and provided minimal user configuration needed, we opted for the architecture shown below.
+
+#### Development Architecture
+
+Development can happen in two ways: locally running Vite on your machine or in a Docker container.
+
+```mermaid
+flowchart TB
+ subgraph User[" "]
+ direction TB
+ UserLabel["User Machine"]
+ Browser["Browser
localhost:HOST_PORT"]
+ end
+
+ subgraph LocalDev["Local Development Mode"]
+ direction TB
+ LocalLabel["Local Development"]
+ LocalVite["Vite Dev Server
Port: VITE_SERVER_PORT"]
+ LocalProxy["Vite Proxy
/api → VITE_BACKEND_URL"]
+ LocalHMR["Hot Module
Replacement"]
+ end
+
+ subgraph DockerDev["Docker Container Mode"]
+ direction TB
+ ContainerLabel["Development Container"]
+ ContainerVite["Vite Dev Server
Port: VITE_SERVER_PORT"]
+ ContainerProxy["Vite Proxy
/api → VITE_BACKEND_URL"]
+ ContainerHMR["Hot Module
Replacement"]
+ end
+
+ subgraph Backend[" "]
+ direction TB
+ BackendLabel["SOARCA Backend"]
+ API["API Endpoints"]
+ end
+
+ UserLabel ~~~ Browser
+ LocalLabel ~~~ LocalVite
+ ContainerLabel ~~~ ContainerVite
+ BackendLabel ~~~ API
+
+ %% Local development flow
+ Browser -->|Local Mode| LocalVite
+ LocalVite -->|Source Files| LocalHMR
+ LocalHMR -->|Live Updates| Browser
+ Browser -->|"/api/*"| LocalProxy
+ LocalProxy -->|"Rewrite & Forward"| API
+
+ %% Docker development flow
+ Browser -->|Container Mode| ContainerVite
+ ContainerVite -->|Source Files| ContainerHMR
+ ContainerHMR -->|Live Updates| Browser
+ Browser -->|"/api/*"| ContainerProxy
+ ContainerProxy -->|"Rewrite & Forward"| API
+
+ %% Backend responses
+ API -->|Response| LocalProxy
+ LocalProxy -->|Response| Browser
+ API -->|Response| ContainerProxy
+ ContainerProxy -->|Response| Browser
+
+ style LocalVite fill:#C5E1FF,stroke:#4A90E2,color:#000
+ style ContainerVite fill:#C5E1FF,stroke:#4A90E2,color:#000
+ style Browser fill:#B8F5D3,stroke:#2ECC71,color:#000
+ style API fill:#FFE5CC,stroke:#E67E22,color:#000
+ style LocalHMR fill:#FFD1DC,stroke:#E74C3C,color:#000
+ style ContainerHMR fill:#FFD1DC,stroke:#E74C3C,color:#000
+ style LocalProxy fill:#C2F0F0,stroke:#16A085,color:#000
+ style ContainerProxy fill:#C2F0F0,stroke:#16A085,color:#000
+
+ style UserLabel fill:#F0F0F0,stroke:#999,color:#333
+ style LocalLabel fill:#F0F0F0,stroke:#999,color:#333
+ style ContainerLabel fill:#F0F0F0,stroke:#999,color:#333
+ style BackendLabel fill:#F0F0F0,stroke:#999,color:#333
+
+ classDef envVar fill:#D4F1D4,stroke:#27AE60,stroke-width:2px,color:#000
+ class VITE_SERVER_PORT envVar
+ class HOST_PORT envVar
+ class VITE_BACKEND_URL envVar
+```
+
+**Environment variables involved:**
+
+- `VITE_BACKEND_URL` - Backend API URL (proxied by Vite dev server)
+- `VITE_SERVER_PORT` - Port where Vite dev server listens
+- `DOCKER_HOST_PORT` - The port of the host machine that is mapped to the `VITE_SERVER_PORT` of the Vite dev server running in the container. This is only relevant when running the Development Container.
+- `HOST_PORT` - is the same of the `VITE_SERVER_PORT` if run locally or `DOCKER_HOST_PORT` if running the Development Container.
+
+#### Running Locally (recommended for development)
+
+1. **Install (dev)dependencies:**
-1. Install dependencies:
```bash
- npm install
+ npm install -D
```
-2. Start the dev server (Vite):
+
+2. **Configure environment variables:**
+ Optionally create a `.env` file (explanation and defaults can be found in `.env.example`). Vite will load `*.env` files for the active mode and only expose variables that begin with `VITE_` to the browser (see https://vite.dev/guide/env-and-mode).
+
+ If no enviroment variables are provided, the defaults are:
+ - `VITE_BACKEND_URL`: `http://localhost:8080` - (SOARCA default)
+ - `VITE_SERVER_PORT`: `5713` - (Vite default)
+
+3. **Start the dev server:**
+
```bash
npm run dev
```
- The dev server runs at http://localhost:3000 but the port can be modified in the `vite.config.ts` and `Dockerfile`.
-## NPM Scripts
+ The app will be available at `http://localhost:HOST_PORT` with hot-reload enabled. You will see in the terminal where exactly the app is being served.
-- `npm run dev` — start Vite dev server
-- `npm run lint` — run ESLint
-- `npm run build` — type-check and create production bundle
-- `npm run preview` — serve the production build locally
+#### Running in Docker Container (reccomended for development without Node/npm setup)
-## Running with Docker (optional)
+1. **Configure environment variables:**
+ Optionally provide values via the shell, a project `.env`, or `--env-file` when starting Compose (explanation and defaults can be found in `.env.example`).
-Currently the docker image in not published yet, so you will have to buid your own
+ If no enviroment variables are provided, the defaults are:
+ - `VITE_BACKEND_URL`: `http://host.docker.internal:8080` - (The `localhost:8080` equivalent of the Container internal network)
+ - `VITE_SERVER_PORT`: `5173`
+ - `DOCKER_HOST_PORT` — port on the host mapped to the `VITE_SERVER_PORT` (default: `5173`)
-```bash
-docker build -t soarca-ui-react-dev --target development .
-```
+2. **Start the container:**
+ ```bash
+ docker compose -f docker-compose.dev.yml up
+ ```
+ The app will be available at `http://localhost:HOST_PORT` with hot-reload enabled.
+
+### Production Mode
+
+Production mode builds optimized static assets and serves them via Nginx. We use this mode to publish Docker images and make releases, but it can be useful to run a production build locally through Vite as well by building the project locally and previewing it. Also this mode is supported for both local and Docker Container environment.
+As before, a diagram of the architecture is shown down below.
+
+#### Production Architecture
+
+Production deployment can happen in two ways: locally using Vite's preview server or in a Docker container using Nginx.
+
+```mermaid
+flowchart TB
+ subgraph User[" "]
+ direction TB
+ UserLabel["User Machine"]
+ Browser["Browser
localhost:HOST_PORT"]
+ end
-To spin up the UI with the included compose setup:
+ subgraph LocalProd["Local Production Mode"]
+ direction TB
+ LocalLabel["Local Build & Preview"]
+ LocalBuild["npm run build"]
+ LocalDist["dist/
Static Assets"]
+ VitePreview["Vite Preview Server
Port: 3000
Proxy: VITE_BACKEND_URL"]
+ end
-```bash
-docker compose up -d
+ subgraph DockerProd["Docker Container Mode"]
+ direction TB
+ ContainerLabel["Multi-stage Docker Build"]
+
+ subgraph BuildStage[" "]
+ direction TB
+ BuildLabel["Build Stage"]
+ NPM["npm install"]
+ Build["npm run build"]
+ Dist["dist/"]
+ end
+
+ subgraph ProdStage[" "]
+ direction TB
+ ProdLabel["Production Stage"]
+ StaticFiles["Static Files
/usr/share/nginx/html"]
+ NginxConf["Nginx Config
Port: NGINX_SERVER_PORT
Proxy: NGINX_BACKEND_URL"]
+ Nginx["Nginx Server"]
+ end
+ end
+
+ subgraph Backend[" "]
+ direction TB
+ BackendLabel["SOARCA Backend"]
+ API["API Endpoints"]
+ end
+
+ UserLabel ~~~ Browser
+ LocalLabel ~~~ LocalBuild
+ ContainerLabel ~~~ BuildStage
+ BuildLabel ~~~ NPM
+ ProdLabel ~~~ StaticFiles
+ BackendLabel ~~~ API
+
+ %% Local production flow
+ LocalBuild --> LocalDist
+ LocalDist --> VitePreview
+ Browser -->|Local Mode| VitePreview
+ VitePreview -->|"/api/*"| API
+
+ %% Docker production flow
+ NPM --> Build
+ Build --> Dist
+ Dist -->|Copy| StaticFiles
+ StaticFiles --> Nginx
+ Nginx --> NginxConf
+ Browser -->|Container Mode| Nginx
+ NginxConf -->|"/api/*"| API
+ API -->|Response| NginxConf
+ NginxConf -->|Response| Browser
+ API -->|Response| VitePreview
+ VitePreview -->|Response| Browser
+
+ style LocalBuild fill:#C5E1FF,stroke:#4A90E2,color:#000
+ style Build fill:#C5E1FF,stroke:#4A90E2,color:#000
+ style Browser fill:#B8F5D3,stroke:#2ECC71,color:#000
+ style API fill:#FFE5CC,stroke:#E67E22,color:#000
+ style VitePreview fill:#C2F0F0,stroke:#16A085,color:#000
+ style Nginx fill:#C2F0F0,stroke:#16A085,color:#000
+ style NginxConf fill:#C2F0F0,stroke:#16A085,color:#000
+ style LocalDist fill:#FFF4CC,stroke:#F39C12,color:#000
+ style Dist fill:#FFF4CC,stroke:#F39C12,color:#000
+ style StaticFiles fill:#FFF4CC,stroke:#F39C12,color:#000
+ style NPM fill:#E8D4FF,stroke:#9B59B6,color:#000
+
+ style UserLabel fill:#F0F0F0,stroke:#999,color:#333
+ style LocalLabel fill:#F0F0F0,stroke:#999,color:#333
+ style ContainerLabel fill:#F0F0F0,stroke:#999,color:#333
+ style BuildLabel fill:#F0F0F0,stroke:#999,color:#333
+ style ProdLabel fill:#F0F0F0,stroke:#999,color:#333
+ style BackendLabel fill:#F0F0F0,stroke:#999,color:#333
+
+ classDef envVar fill:#D4F1D4,stroke:#27AE60,stroke-width:2px,color:#000
+ class VITE_BACKEND_URL envVar
+ class NGINX_BACKEND_URL envVar
+ class NGINX_SERVER_PORT envVar
+ class HOST_PORT envVar
```
-## Hot-reload
+**Environment variables involved:**
+
+- `VITE_BACKEND_URL` - Backend API URL embedded into the client bundle at build time (must be set before running `npm run build`)
+- `VITE_APP_VERSION` - Application version embedded into the client bundle at build time (optional, falls back to git describe or "development")
+- `NGINX_BACKEND_URL` - Backend API URL used by Nginx at runtime to proxy `/api/*` requests. This is only relevant when running in Docker Container Mode.
+- `NGINX_SERVER_PORT` - Port where Nginx listens inside the container. This is only relevant when running in Docker Container Mode.
+- `DOCKER_HOST_PORT` - The port of the host machine that is mapped to the `NGINX_SERVER_PORT` of the Nginx server running in the container. This is only relevant when running in Docker Container Mode.
+- `HOST_PORT` - Port 4173 (Vite default) for local preview mode (`npm run preview`) or `DOCKER_HOST_PORT` when running in Docker Container Mode.
+
+#### Running Locally (recommended for preview)
+
+1. **Install dependencies:**
+
+ ```bash
+ npm install
+ ```
+
+2. **Configure environment variables:**
+ Optionally create a `.env` file (explanation and defaults can be found in `.env.example`). Note that `VITE_` variables must be set at _build time_ to be embedded into the static bundle.
+
+ If no environment variables are provided, the defaults are:
+ - `VITE_BACKEND_URL`: `http://localhost:8080` - (SOARCA default)
+
+3. **Build and preview:**
+
+ ```bash
+ npm run build
+ npm run preview
+ ```
+
+ The app will be available at `http://localhost:4173` (Vite preview server default).
+
+ > [!WARNING]
+ > For actual production deployment, use a proper web server like Nginx (see Docker section below).
+
+#### Running in Docker Container (recommended for production)
+
+1. **Configure environment variables:**
+ Optionally provide values via the shell, a project `.env`, or `--env-file` when starting Compose (explanation and defaults can be found in `.env.example`). Note that `VITE_` variables are build-time only (embedded at image build), while `NGINX_` variables are runtime (used by the running container).
+
+ If no environment variables are provided, the defaults are:
+ - `VITE_BACKEND_URL`: `http://localhost:8080` - embedded at build time
+ - `NGINX_BACKEND_URL`: `http://host.docker.internal:8080/` - used at runtime
+ - `NGINX_SERVER_PORT`: `8081`
+ - `DOCKER_HOST_PORT`: `8081` — port on the host mapped to the `NGINX_SERVER_PORT`
+
+2. **Build and start the container:**
+
+ ```bash
+ docker compose up --build
+ ```
+
+ The app will be available at `http://localhost:DOCKER_HOST_PORT`.
+
+### NPM Scripts for local run
-In both the local and Docker dev environment, Vite provides instant hot reload, so any change to the files will be reflected in the browser upon saving.
+- `npm run dev` - Start Vite dev server with hot-reload
+- `npm run build` - Type-check and create production bundle
+- `npm run preview` - Serve the production build locally (Vite preview server)
+- `npm run lint` - Run ESLint
+- `npm test` - Run unit tests (Vitest)
## Documentation
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
new file mode 100644
index 0000000..da5ea2d
--- /dev/null
+++ b/docker-compose.dev.yml
@@ -0,0 +1,23 @@
+services:
+ soarca-gui-dev:
+ container_name: soarca-gui-dev
+ image: soarca-gui:dev
+ build:
+ context: .
+ dockerfile: Dockerfile.dev
+ args:
+ VITE_BACKEND_URL: ${VITE_BACKEND_URL:-http://host.docker.internal:8080}
+ VITE_SERVER_PORT: ${VITE_SERVER_PORT:-5173}
+ ports:
+ - "${DOCKER_HOST_PORT:-5173}:${VITE_SERVER_PORT:-5173}"
+ environment:
+ - NODE_ENV=development
+ - VITE_BACKEND_URL=${VITE_BACKEND_URL:-http://host.docker.internal:8080}
+ - VITE_SERVER_PORT=${VITE_SERVER_PORT:-5173}
+ volumes:
+ - .:/app
+ - node_modules_volume:/app/node_modules
+ command: sh -c "npm install && npm run dev"
+
+volumes:
+ node_modules_volume:
diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml
deleted file mode 100644
index 5e74080..0000000
--- a/docker-compose.prod.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-services:
- soarca-ui-react:
- image: soarca-ui-react:latest
- build:
- context: .
- target: production
- ports:
- - "80:80"
- environment:
- - NODE_ENV=production
- restart: unless-stopped
diff --git a/docker-compose.yml b/docker-compose.yml
index 29d3a09..c84a4ba 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,17 +1,18 @@
services:
- soarca-ui-react:
- image: soarca-ui-react:development
+ soarca-gui:
+ container_name: soarca-gui
+ image: soarca-gui:latest
build:
context: .
- target: development
+ dockerfile: Dockerfile
+ args:
+ VITE_APP_VERSION: ${VITE_APP_VERSION:-development}
+ NGINX_BACKEND_URL: ${NGINX_BACKEND_URL:-http://host.docker.internal:8080/}
+ NGINX_SERVER_PORT: ${NGINX_SERVER_PORT:-8081}
ports:
- - "3000:3000"
+ - "${DOCKER_HOST_PORT:-8081}:${NGINX_SERVER_PORT:-8081}"
environment:
- - NODE_ENV=development
- volumes:
- - .:/app
- - node_modules_volume:/app/node_modules
- command: sh -c "npm install && npm run dev"
-
-volumes:
- node_modules_volume:
+ - NODE_ENV=production
+ - NGINX_BACKEND_URL=${NGINX_BACKEND_URL:-http://host.docker.internal:8080/}
+ - NGINX_SERVER_PORT=${NGINX_SERVER_PORT:-8081}
+ restart: unless-stopped
diff --git a/nginx.conf b/nginx.conf
new file mode 100644
index 0000000..372c1f2
--- /dev/null
+++ b/nginx.conf
@@ -0,0 +1,24 @@
+# Nginx template: variables are substituted at container start (envsubst)
+# Variables expected:
+# - ${NGINX_SERVER_PORT} (default: 8081): port nginx will listen on inside the container
+# - ${NGINX_BACKEND_URL} (default: http://host.docker.internal:8080/): backend to proxy /api/ to (include trailing slash)
+server {
+ listen ${NGINX_SERVER_PORT};
+ server_name localhost;
+
+ location / {
+ root /usr/share/nginx/html;
+ index index.html;
+ try_files $uri /index.html;
+ }
+
+ location /api/ {
+ proxy_pass ${NGINX_BACKEND_URL};
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $http_connection;
+ }
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 213ff04..f31aacf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,11 +1,11 @@
{
- "name": "soarca-ui-react",
+ "name": "soarca-ui",
"version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "soarca-ui-react",
+ "name": "soarca-ui",
"version": "0.0.0",
"dependencies": {
"@tanstack/react-query": "^4.42.0",
@@ -68,6 +68,7 @@
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/code-frame": "^7.29.0",
"@babel/generator": "^7.29.0",
diff --git a/package.json b/package.json
index ee07c4e..6a91d27 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "name": "soarca-ui-react",
+ "name": "soarca-ui",
"private": true,
"version": "0.0.0",
"type": "module",
diff --git a/src/api/manual.ts b/src/api/manual.ts
index e003cf2..e3d7146 100644
--- a/src/api/manual.ts
+++ b/src/api/manual.ts
@@ -1,9 +1,9 @@
import { Execution, ManualOutArgsUpdatePayload } from "@/types";
-import { HttpMutationMethod, mutationToApi, SOARCA_URI } from "./utils";
+import { HttpMutationMethod, mutationToApi } from "./utils";
export const postStepActionResult = (data: ManualOutArgsUpdatePayload) =>
mutationToApi(
HttpMutationMethod.POST,
- `${SOARCA_URI}/manual/continue`,
+ `/api/manual/continue`,
data,
);
diff --git a/src/api/playbooks.ts b/src/api/playbooks.ts
index d58d936..212e333 100644
--- a/src/api/playbooks.ts
+++ b/src/api/playbooks.ts
@@ -4,28 +4,22 @@ import {
fetchFromApi,
HttpMutationMethod,
mutationToApi,
- SOARCA_URI,
} from "./utils";
-export const getPlaybooks = () =>
- fetchFromApi(`${SOARCA_URI}/playbook/`);
+export const getPlaybooks = () => fetchFromApi(`/api/playbook/`);
export const getPlaybookById = (playbookId: string) =>
- fetchFromApi(`${SOARCA_URI}/playbook/${playbookId}`);
+ fetchFromApi(`/api/playbook/${playbookId}`);
export const createPlaybook = (playbook: Partial) =>
- mutationToApi(
- HttpMutationMethod.POST,
- `${SOARCA_URI}/playbook/`,
- playbook,
- );
+ mutationToApi(HttpMutationMethod.POST, `/api/playbook/`, playbook);
export const updatePlaybook = (playbookId: string, patch: Partial) =>
mutationToApi(
HttpMutationMethod.PUT,
- `${SOARCA_URI}/playbook/${playbookId}`,
+ `/api/playbook/${playbookId}`,
patch,
);
export const deletePlaybook = (playbookId: string) =>
- deleteToApi(`${SOARCA_URI}/playbook/${playbookId}`);
+ deleteToApi(`/api/playbook/${playbookId}`);
diff --git a/src/api/reporter.ts b/src/api/reporter.ts
index f225a2c..763ad4b 100644
--- a/src/api/reporter.ts
+++ b/src/api/reporter.ts
@@ -1,10 +1,8 @@
import { PlaybookExecutionReport } from "@/types";
-import { fetchFromApi, SOARCA_URI } from "./utils";
+import { fetchFromApi } from "./utils";
export const getReporterState = () =>
- fetchFromApi(`${SOARCA_URI}/reporter/`);
+ fetchFromApi(`/api/reporter/`);
export const getReportOfExecutionById = (executionId: string) =>
- fetchFromApi(
- `${SOARCA_URI}/reporter/${executionId}`,
- );
+ fetchFromApi(`/api/reporter/${executionId}`);
diff --git a/src/api/status.ts b/src/api/status.ts
index dc52f37..5ea4a3b 100644
--- a/src/api/status.ts
+++ b/src/api/status.ts
@@ -1,7 +1,6 @@
import { Status } from "@/types";
-import { fetchFromApi, SOARCA_URI } from "./utils";
+import { fetchFromApi } from "./utils";
-export const getPingStatus = async () => fetch(`${SOARCA_URI}/status/ping`);
+export const getPingStatus = async () => fetch(`/api/status/ping`);
-export const getSystemStatus = async () =>
- fetchFromApi(`${SOARCA_URI}/status/`);
+export const getSystemStatus = async () => fetchFromApi(`/api/status/`);
diff --git a/src/api/trigger.ts b/src/api/trigger.ts
index 108e31d..da900bd 100644
--- a/src/api/trigger.ts
+++ b/src/api/trigger.ts
@@ -1,10 +1,10 @@
import { Execution } from "@/types";
-import { HttpMutationMethod, mutationToApi, SOARCA_URI } from "./utils";
+import { HttpMutationMethod, mutationToApi } from "./utils";
export const triggerPlaybookById = (playbookId: string) => {
return mutationToApi(
HttpMutationMethod.POST,
- `${SOARCA_URI}/trigger/playbook/${playbookId}`,
+ `/api/trigger/playbook/${playbookId}`,
{},
);
};
diff --git a/src/api/utils.ts b/src/api/utils.ts
index a498ff9..4beb986 100644
--- a/src/api/utils.ts
+++ b/src/api/utils.ts
@@ -1,7 +1,5 @@
import { ErrorResponse } from "@/types";
-export const SOARCA_URI = import.meta.env.VITE_SOARCA_URI;
-
/**
* Fetches from the API and handles errors uniformly.
* @param url - API endpoint URL
diff --git a/vite.config.ts b/vite.config.ts
index a555aad..73a10ee 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -4,29 +4,43 @@ import sbom from "rollup-plugin-sbom";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
-// Get version from git describe --tags (tag name only, without hash/dirty suffix)
-const getGitVersion = () => {
+/**
+ * Resolve the app version.
+ */
+const getAppVersion = (): string => {
+ // Explicit env var (ideal for CI and Docker builds)
+ if (process.env.VITE_APP_VERSION) {
+ return process.env.VITE_APP_VERSION;
+ }
+
+ // Git tag (works locally; fails in Docker where .git is excluded)
try {
- // Try to get the most recent tag
const tag = execSync("git describe --tags --abbrev=0", {
encoding: "utf-8",
- stdio: ["pipe", "pipe", "ignore"], // Suppress stderr
+ stdio: ["pipe", "pipe", "ignore"],
}).trim();
- return tag;
+ if (tag) return tag;
} catch {
- // If no tags exist, fall back to development
- return "development";
+ // .git not available — continue to fallback
}
+ // Fallback for local development without .git or CI/CD environment
+ return "development";
};
export default defineConfig({
plugins: [react(), tsconfigPaths(), sbom()],
define: {
- __APP_VERSION__: JSON.stringify(getGitVersion()),
+ __APP_VERSION__: JSON.stringify(getAppVersion()),
},
server: {
+ proxy: {
+ "/api": {
+ target: process.env.VITE_BACKEND_URL || "http://localhost:8080",
+ rewrite: (path) => path.replace(/^\/api/, ""),
+ },
+ },
host: true,
- port: 3000,
+ port: Number(process.env.VITE_SERVER_PORT) || 5173,
strictPort: true, // Fail if port is already in use, as the docker container won't be able to use a different one
watch: {
usePolling: true,
@@ -34,6 +48,6 @@ export default defineConfig({
},
preview: {
host: true,
- port: 3000,
+ port: 4173,
},
});