Features
- Daily ingestion of every competitive procurement type, with pagination, exponential backoff, Retry-After handling, and idempotent upserts.
- Accent-insensitive Portuguese full-text search with weighted ranking (Postgres unaccent + tsvector + GIN).
- Alerts with sector presets mapped to CNAE codes, region, procurement type, and value range; each tender is sent once per alert.
- AI tender summary with structured output validated by Zod, cached per tender, with a daily quota per user.
- Passwordless magic-link login with single-use hashed tokens and HMAC-signed sessions.
- 33 unit and integration tests against a real Postgres, CI on GitHub Actions, and a Docker Compose stack that runs in about 170 MB of RAM.
Technologies used
- Next.js 16 — App Router, Server Actions, and Partial Prerendering.
- PostgreSQL — Full-text search, idempotent upserts via jsonb_to_recordset.
- Claude API — PDF reading with structured outputs.
- PNCP API — Brazil's national public procurement portal.
- Docker Compose — Web, jobs scheduler, and database containers.
- Vitest — Unit and Postgres integration tests.
Build steps
Clone the repository
git clone https://github.com/giovaniohira/radar-licitacoes && cd radar-licitacoesStart Postgres and migrate
docker run -d -p 5544:5432 -e POSTGRES_USER=radar -e POSTGRES_PASSWORD=radar -e POSTGRES_DB=radar postgres:17-alpine cp .env.example .env.local && npm install && npm run db:migrateIngest one day and run
npm run ingest -- 2026-10-15 npm run dev
