- Web
- AI
TenderPilot
Procurement intelligence for public tenders: it collects public procurement notices, scores them against a company's own profile, and walks a bid team from "is this worth it?" to a submitted bid.
- Personal project, full-stack
- v1.0.0, certified by local release gates
- At least 222 backend tests, 26 of them release-contract tests
- Java, Spring Boot, PostgreSQL, OpenSearch, Liquibase, Ollama, Next.js, React, TypeScript, Tailwind CSS

The problem
Public tenders are published on several portals, in different shapes, and a small bid team cannot read them all. Time goes into notices that were never a good fit. Once a team commits to a bid, requirements, tasks and deadlines live in separate documents and are easy to lose track of.
The approach
I organized the product around the way a bid team works: find the tenders, decide which ones are worth it, prepare the bid, understand the market, and keep the data flowing. The dashboard links every number to the page where you can act on it, and links carry their state, so a list can open already filtered by a grade or a CPV code.
Two rules run through it. Every score explains itself: a match, a decision and a data-quality grade all show the parts they are made of. And a person makes every decision: alerts, AI findings and recommendations never change a Go / No-Go decision, a compliance verdict, a task or the submission state.
The backend was frozen at v1.0.0 while I refined the interface, so every frontend change had to work with the existing API, and features that need new endpoints were moved to v1.1. A demo mode that serves synthetic data let me build and photograph every screen without the backend, a database, a search index or a local AI.
Who uses it
- Bid managers
- Decide GO, HOLD or NO-GO, plan the work and authorize the final submission.
- Analysts
- Search and compare tenders, and study buyers, suppliers and whole markets.
- Contributors
- Work through their own tasks across every active bid, from one list sorted by due date.
- Owners
- Set up the organization, its members and the company profile that drives matching.
- Operators
- Watch the health of the TED, BOAMP and DECP ingestion without reading logs.
What it does
- Tenders from TED, BOAMP and DECP in one model, with full-text search, saved views and up to three tenders compared side by side
- Company-to-tender matching with a score out of 100 broken down by criterion, and a notice when the matches are out of date
- A Go / No-Go workspace per tender, with a six-part scorecard, a recommendation and a decision history
- Bid workspaces with documents, requirements, a compliance matrix and a printable bid brief
- Planning with tasks, a drag-and-drop board, a submission checklist and an authorization step before a bid is marked submitted
- My tasks across every active bid, and a deadline calendar that exports to Outlook, Google or Apple Calendar
- Questions answered only from a bid's own documents, with exact citations, and document analysis by a local AI model
- Market, buyer and supplier intelligence from public award notices, and a data-quality score for the whole catalogue
- Notifications and watchlists for tenders, buyers, CPV codes and bid execution
- Data-source and ingestion monitoring for the people who run the system
- Light, dark and system themes, a command palette, keyboard shortcuts and a phone layout for every page
Where the engineering is
A match score that explains itself
Each tender gets a score out of 100 against the company's private profile, and the card breaks it down: CPV fit, geography, contract value, buyer preference, capabilities, timing and data quality, each with its own score and its weight.
Matches are stored rather than recalculated on every visit, so the page says when the company profile has changed since the last run and offers to recalculate. From a match, one click opens the Go / No-Go workspace.
, Open the full-size image (opens in a new tab)Go, hold or no-go, with a record of why
The decision workspace rates six dimensions from 0 to 5: strategic fit, capability confidence, commercial attractiveness, delivery feasibility, resource capacity and risk confidence. It asks for the rationale, the key risks and the assumptions, and produces a decision score with a recommendation.
The person then records GO, HOLD or NO-GO, and every change lands in the decision history with who made it and when. The rationale flows into the printable bid brief, and the plan locks by itself after a No-Go or a submission.
, Open the full-size image (opens in a new tab)AI that reads the documents but never decides
The AI assistant is optional and runs locally through Ollama, so bid documents never leave the machine. It pulls requirements, deadlines, risks and deliverables out of each document, with a confidence for each finding, and a finding becomes a requirement with one click.
Questions about a bid are answered only from that bid's own documents, with exact source citations, and the history keeps the cited excerpts as they were at the time. The compliance matrix states that AI may not make compliance decisions: every requirement is reviewed by a person.
, Open the full-size image (opens in a new tab)Public market data and private bid data, kept apart
Public procurement intelligence is shared: notices, buyers, observed suppliers and market analytics come from one corpus. Each organization's profile, matches, decisions, documents, compliance and planning stay private, and the public market view never receives any of them.
PostgreSQL is the source of truth. OpenSearch holds public procurement data only, as a search projection that can be rebuilt at any time, with a PostgreSQL fallback for search.
Built for keyboards, phones and bad connections
A command palette opens with Cmd or Ctrl+K, or /, and finds pages, actions, recent items and live tenders; shortcuts such as G then T jump to a page. Every page has a phone layout, with the navigation in a drawer.
When the server cannot be reached, the app says so, says that you have not been signed out, and retries until the connection returns. A failed refresh ends the session only when the server answers 401 or 403, and nothing is deleted without a confirmation.
, Open the full-size image (opens in a new tab)Screens
, Open the full-size image (opens in a new tab)Tenders from three sources in one list.
, Open the full-size image (opens in a new tab)Tenders side by side, with the best values marked.
, Open the full-size image (opens in a new tab)Every submission deadline, ready to export.
, Open the full-size image (opens in a new tab)A bid's tasks as a board.
, Open the full-size image (opens in a new tab)Every requirement reviewed by a person.
, Open the full-size image (opens in a new tab)How a market is shaped, from public data only.
, Open the full-size image (opens in a new tab)Source health for the people who run the system.
, Open the full-size image (opens in a new tab)The dashboard in the dark theme.
How it's built
| Layer | Technology |
|---|---|
| Backend | Java 21, Spring Boot 4.1 and Maven, with one package per module: procurement, matching, bid decisions, planning, compliance, intelligence, search, local AI and more |
| Data | PostgreSQL 17 as the source of truth with 15 Liquibase migrations, and OpenSearch 3.8 as a search projection that can be rebuilt |
| Local AI | Optional: Ollama with qwen3:4b and nomic-embed-text-v2-moe by default, so bid documents never leave the machine |
| Frontend | Next.js 16 App Router, React 19, TypeScript and Tailwind CSS 4 |
| Quality | Local release and v1 readiness gates, and a frontend gate for dark-theme freshness, ESLint, TypeScript and the production build |
, Open the full-size image (opens in a new tab)Testing
There is no CI/CD pipeline by design: every check runs on a developer machine with one command. A local release gate and a v1 readiness gate, with a release manifest, expect at least 222 backend tests, 26 of them release-contract tests. A frontend gate checks dark-theme freshness, ESLint, TypeScript and the production build.
A capture script builds the demo, opens every page in light, dark and phone views, and writes the pictures and an explanation of each screen. The pictures on this page come from it, on synthetic data.
Results
- v1.0.0, certified by the local release and readiness gates.
- Tenders from three public sources, TED, BOAMP and DECP, in one model.
- 48 documented screens, captured in light, dark and phone views.
- At least 222 backend tests, including 26 release-contract tests.
What I would build next
- Password reset, profile editing, and invitations with roles.
- Win and loss tracking.
- Email alerts, and saved views stored on the server instead of the browser.
- Search results beyond the first 100 hits.
- An audit feed, comments, and one endpoint for tasks across bids.
Built with
- Java
- Spring Boot
- PostgreSQL
- OpenSearch
- Liquibase
- Ollama
- Next.js
- React
- TypeScript
- Tailwind CSS