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.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.
Layer Overview
| Layer | Responsibility | Key Files |
|---|---|---|
| Domain | Entities, interfaces, validation rules | entities/, interfaces/, repositories/, validation/ |
| Application | Use cases, orchestration | use-cases/CreateTender.ts, ValidateProposal.ts, AuthService.ts |
| Infrastructure | DB adapters, AI services, middleware | TursoDatabase.ts, GeminiGenkitService.ts, VectorSearchService.ts |
| Presentation | Express controllers and routes | AuthController.ts, TenderController.ts, routes/ |
TursoDatabase.ts implements ITenderRepository; the Domain interface never imports from Infrastructure.
Directory Structure
Request Flow
The following steps trace a complete tender analysis request from the browser to the database and back.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.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.Controller dispatch
TenderController receives the validated request, extracts the file buffer and user identity from req.user, and delegates to the CreateTender use case.Use case orchestration
CreateTender calls the injected dependencies in sequence:PdfParserAdapter.parsePages()extracts page-delimited text from the PDF buffer usingpdf-parse.GeminiGenkitService.analyze()(oranalyzeChunks()for large PDFs) sends the text to Gemini 2.5 Flash and receives a structured list ofRequirementobjects.VectorSearchService.generateEmbedding()produces aFloat32Arrayfor each requirement and serialises it to aBufferfor storage.
Persistence
TursoTenderRepository.save() writes the TenderAnalysis record — including all requirements and their embedding BLOBs — to the Turso (LibSQL) database.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.
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
| Component | Service | Notes |
|---|---|---|
| Frontend | Render (Static Site) | Static site with SPA rewrites; also accessible via a Vercel deployment (vercel.json) |
| Backend | Render (Node.js Web Service) | Express app running on a persistent Node.js process; defined in render.yaml |
| Database | Turso (LibSQL) | Edge SQLite, serverless, always-on; TURSO_DB_URL uses https:// in production |
| AI | Google AI Studio | Gemini 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.