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 is built as a modular monolith following Clean Architecture principles. The codebase is divided into four concentric layers where dependencies only point inward — inner layers (Domain and Application) know nothing about outer layers (Infrastructure and Presentation). This design makes it straightforward to swap the database engine, replace the AI provider, or change the HTTP framework without touching core business logic. The entire backend is TypeScript, runs on Express, and is deployed as a Render web service alongside a static React frontend.

Layer Overview

LayerResponsibilityKey Files
DomainEntities, interfaces, validation rulesentities/, interfaces/, repositories/, validation/
ApplicationUse cases, orchestrationuse-cases/CreateTender.ts, ValidateProposal.ts, AuthService.ts
InfrastructureDB adapters, AI services, middlewareTursoDatabase.ts, GeminiGenkitService.ts, VectorSearchService.ts
PresentationExpress controllers and routesAuthController.ts, TenderController.ts, routes/
The Golden Rule: a layer may only depend on layers closer to the center. TursoDatabase.ts implements ITenderRepository; the Domain interface never imports from Infrastructure.

Directory Structure

├── backend/
│   └── src/
│       ├── domain/            # Entities, Repositories, Interfaces (Pure Logic)
│       │   ├── entities/
│       │   │   ├── ComparisonResult.ts
│       │   │   ├── Requirement.ts
│       │   │   ├── TenderAnalysis.ts
│       │   │   ├── User.ts
│       │   │   └── ValidationResult.ts
│       │   ├── errors/
│       │   │   └── AppError.ts
│       │   ├── interfaces/
│       │   │   ├── IPdfParser.ts
│       │   │   ├── IRule.ts
│       │   │   └── ITenderAnalyzer.ts
│       │   ├── repositories/
│       │   │   ├── ITenderRepository.ts
│       │   │   └── UserRepository.ts
│       │   └── validation/
│       │       ├── ValidationEngine.ts
│       │       ├── ValidationRuleFactory.ts
│       │       └── rules/ScopeValidationRule.ts
│       ├── application/       # Use Cases & Services (Orchestration)
│       │   ├── services/
│       │   │   └── AuthService.ts
│       │   └── use-cases/
│       │       ├── CreateTender.ts
│       │       └── ValidateProposal.ts
│       ├── infrastructure/    # DB Adapters (Turso), AI (Genkit), Middleware
│       │   ├── adapters/
│       │   │   └── PdfParserAdapter.ts
│       │   ├── database/
│       │   │   ├── TursoDatabase.ts
│       │   │   └── schema.sql
│       │   ├── middleware/
│       │   │   ├── authMiddleware.ts
│       │   │   └── errorHandler.ts
│       │   ├── repositories/
│       │   │   ├── InMemoryTenderRepository.ts
│       │   │   ├── InMemoryUserRepository.ts
│       │   │   ├── TursoTenderRepository.ts
│       │   │   └── TursoUserRepository.ts
│       │   └── services/
│       │       ├── GeminiGenkitService.ts
│       │       └── VectorSearchService.ts
│       ├── genkit/
│       │   └── flows/
│       │       ├── index.ts       # legalAuditorFlow, seniorEvaluatorFlow
│       │       └── embeddings.ts  # generateEmbeddingFlow, semanticSearchFlow
│       ├── config/
│       │   ├── constants.ts
│       │   └── genkit.config.ts
│       └── presentation/      # Express Controllers & Routes
│           ├── controllers/
│           │   ├── AuthController.ts
│           │   └── TenderController.ts
│           ├── routes/
│           │   ├── AuthRoutes.ts
│           │   └── TenderRoutes.ts
│           └── server.ts
├── frontend/
│   └── src/
│       ├── components/        # UI, Auth, Dashboard, Layout
│       ├── context/           # AuthContext, ThemeContext
│       ├── services/          # api.ts, auth.service.ts, export.service.ts
│       └── pages/             # LandingPage and main views
└── tests/
    ├── e2e/                   # Playwright end-to-end flows
    └── fixtures/              # Mock PDFs for testing

Request Flow

The following steps trace a complete tender analysis request from the browser to the database and back.
1

Upload

The React frontend POSTs a multipart form (PDF file) to POST /api/tenders/analyze. The request includes either an HttpOnly cookie (token) or an Authorization: Bearer <jwt> header.
2

Authentication

authMiddleware intercepts the request. It first reads the JWT from the cookie; if absent, it falls back to the Authorization header. The JWT is verified with jsonwebtoken. Invalid or missing tokens return 401.
3

Controller dispatch

TenderController receives the validated request, extracts the file buffer and user identity from req.user, and delegates to the CreateTender use case.
4

Use case orchestration

CreateTender calls the injected dependencies in sequence:
  1. PdfParserAdapter.parsePages() extracts page-delimited text from the PDF buffer using pdf-parse.
  2. GeminiGenkitService.analyze() (or analyzeChunks() for large PDFs) sends the text to Gemini 2.5 Flash and receives a structured list of Requirement objects.
  3. VectorSearchService.generateEmbedding() produces a Float32Array for each requirement and serialises it to a Buffer for storage.
5

Persistence

TursoTenderRepository.save() writes the TenderAnalysis record — including all requirements and their embedding BLOBs — to the Turso (LibSQL) database.
6

Response

A TenderAnalysis JSON object is returned to the frontend with status: "COMPLETED", a summary, and the full requirements array including pageNumber and sourceText for clickable citations.

Frontend Architecture

The frontend is a React + Vite + Tailwind CSS single-page application. Key dashboard components are:
  • Dashboard — root layout that composes all other dashboard components.
  • TenderUpload — drag-and-drop file input that triggers the analysis API call.
  • AnalysisResults — renders the extracted requirements list with confidence badges.
  • ValidationSummary — aggregated compliance scores after proposal validation.
  • HistorySidebar — browsable list of past analyses fetched from the API.
  • CitationPreview — modal that shows the full page text with the AI-identified source fragment highlighted.
Global state is managed through two React contexts:
  • AuthContext — holds the authenticated user, JWT, and login/logout actions.
  • ThemeContext — drives the dual light (Beige/Gold) and dark (Charcoal/Emerald) theme toggle applied across the entire application.

Deployment Architecture

ComponentServiceNotes
FrontendRender (Static Site)Static site with SPA rewrites; also accessible via a Vercel deployment (vercel.json)
BackendRender (Node.js Web Service)Express app running on a persistent Node.js process; defined in render.yaml
DatabaseTurso (LibSQL)Edge SQLite, serverless, always-on; TURSO_DB_URL uses https:// in production
AIGoogle AI StudioGemini 2.5 Flash via @genkit-ai/google-genai plugin

AI Pipeline

How Gemini 2.5 Flash, Google Genkit flows, and gemini-embedding-001 vector embeddings work together to extract requirements and validate proposals.

Database

The full Turso (LibSQL) schema, repository pattern, and how vector embeddings are stored and queried in SQLite.

Build docs developers (and LLMs) love