Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/elecodes/TenderCheck-AI/llms.txt

Use this file to discover all available pages before exploring further.

TenderCheck AI ships with a Docker Compose configuration that makes it straightforward to spin up the backend service in an isolated container — ideal for local development or self-hosted production deployments on any Linux server. The Compose file mounts the backend source directory as a volume so that code changes are picked up without rebuilding the image.

Prerequisites

Docker 24+

Install Docker Desktop (Mac/Windows) or Docker Engine (Linux). Compose v2 is bundled with Docker 24+.

Turso Credentials

A Turso database URL and auth token. See Environment Variables for details.

Google AI Studio Key

A Gemini API key from Google AI Studio for the AI analysis pipeline.

Git

The repository cloned locally so Docker can build from the source tree.

Docker Compose Configuration

The docker-compose.yml at the repository root defines the backend service for local development:
services:
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
      target: builder
    image: tendercheck-backend-dev
    ports:
      - "3000:3000"
    volumes:
      - ./backend:/app
      - /app/node_modules
    command: npm run dev
    environment:
      - NODE_ENV=development
      - PORT=3000
Service breakdown:
  • build.context: ./backend — Docker uses backend/ as the build context, so the backend/Dockerfile is resolved relative to that directory.
  • build.target: builder — Uses only the first (builder) stage of the multi-stage Dockerfile, which retains dev dependencies so that hot-reload tooling is available.
  • ports: "3000:3000" — Maps container port 3000 to host port 3000.
  • volumes: ./backend:/app — Bind-mounts the local backend/ directory into /app inside the container, enabling live code reloading without image rebuilds.
  • /app/node_modules — An anonymous volume shadows the bind-mounted node_modules directory so the container’s installed packages are not overwritten by the host directory.
  • command: npm run dev — Overrides the Dockerfile CMD and starts the backend in watch mode.

Running with Docker Compose

1

Clone the repository

git clone https://github.com/elecodes/TenderCheck-AI.git
cd TenderCheck-AI
2

Create the backend environment file

Copy the example and fill in your credentials:
cp backend/.env.example backend/.env
At minimum, set the following variables in backend/.env:
TURSO_DB_URL=libsql://your-db-name.turso.io
TURSO_AUTH_TOKEN=your_turso_auth_token
GOOGLE_GENAI_API_KEY=your_gemini_api_key
GOOGLE_API_KEY=your_gemini_api_key
JWT_SECRET=your_strong_random_secret
ALLOWED_ORIGINS=http://localhost:3000
See Environment Variables for the full variable reference.
3

Build and start the containers

docker-compose up --build
Docker will build the tendercheck-backend-dev image from backend/Dockerfile (builder stage) and start the container. The backend starts in watch mode and reloads on file changes.
4

Verify the services are running

Once the containers are up, you can reach:
ServiceURL
Backend APIhttp://localhost:3000
Health endpointhttp://localhost:3000/health
The Docker Compose file only defines the backend service. To run the frontend locally, start it separately with npm run dev inside the frontend/ directory. The Vite dev server is configured in frontend/vite.config.ts to run on http://localhost:3000, with API requests proxied to the backend at http://localhost:3001.
5

Stop the containers

Press Ctrl+C in the terminal where Compose is running, or from a separate terminal:
docker-compose down

Individual Dockerfiles

Backend Dockerfile (backend/Dockerfile)

The backend uses a two-stage multi-stage build based on the official node:20-alpine image:
# Build Stage
FROM node:20-alpine AS builder

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build \
    && npm prune --production

# Production Stage
FROM node:20-alpine AS runner

WORKDIR /app

ENV NODE_ENV=production

COPY --from=builder --chown=node:node /app/package*.json ./
COPY --from=builder --chown=node:node /app/node_modules ./node_modules
COPY --from=builder --chown=node:node /app/dist ./dist

USER node

EXPOSE 3000

CMD ["node", "dist/index.js"]
Key details:
  • Node.js 20 on Alpine — Produces a small, security-hardened image.
  • npm ci — Installs exact locked versions from package-lock.json for reproducible builds.
  • npm run build + npm prune --production — Compiles TypeScript to dist/ then strips dev dependencies before the final image copy, minimizing image size.
  • USER node — Runs the process as the unprivileged node user rather than root.
  • EXPOSE 3000 — Documents the port; the actual binding is controlled by the PORT environment variable at runtime.

Root Dockerfile (Dockerfile)

The repository root also contains a Dockerfile targeting GPU-accelerated deployments (e.g. Hugging Face Spaces). It uses nvidia/cuda:12.1.0-base-ubuntu22.04 as both the builder and runtime base, installs Node.js 20 from NodeSource, builds both the backend and frontend, and additionally installs and pre-pulls Ollama models (mistral and nomic-embed-text) for local inference. This Dockerfile is used by the start.sh script. It is not required for standard Vercel or Render deployments.

Production Docker Deployment

When running containers on your own server, apply the following configuration adjustments:
  • Set NODE_ENV=production in the backend container’s environment so that secure cookie flags and strict CORS enforcement are active.
  • Set TURSO_DB_URL to your production Turso database URL. Use https:// if your runtime environment does not support WebSocket connections (see the warning below).
  • Set ALLOWED_ORIGINS to your production frontend domain (e.g. https://yourdomain.com), without a trailing slash.
  • Place a reverse proxy such as Nginx or Caddy in front of the containers to handle TLS termination. Expose only the frontend port publicly and proxy /api/* requests to the backend container internally.
A minimal Caddy configuration example:
yourdomain.com {
    reverse_proxy /api/* backend:3000
    reverse_proxy * frontend:80
}

Quick Start Script

The repository root contains a start.sh script used by the GPU (Dockerfile) runtime image:
#!/bin/bash
set -e

# Verify frontend build exists
if [ -d "frontend/dist" ]; then
  echo "Frontend build found at frontend/dist"
else
  echo "ERROR: frontend/dist NOT FOUND!"
fi

# Start Ollama in background
nohup ollama serve > /dev/null 2>&1 &
sleep 5

# Start backend
cd backend
export PORT=3000
exec npm start
This script verifies that the frontend static assets were built, starts the Ollama inference server in the background, waits for it to initialize, then hands off to the Node.js backend process. It is only relevant when using the root Dockerfile (GPU/Ollama deployment). Standard Docker Compose and Vercel deployments do not use this script.
The backend validates the TURSO_DB_URL protocol at startup. On platforms that block WebSocket connections (including Vercel serverless functions), you must set TURSO_DB_URL to https://your-db.turso.io rather than libsql://your-db.turso.io. Using the wrong protocol will cause the database connection to fail silently or throw on the first query.
Stream the backend container logs in real time during development to watch for startup errors, CORS warnings, and AI pipeline output:
docker-compose logs -f backend

Build docs developers (and LLMs) love