tpt-gets-nz
GoNZ Government Electronic Tenders Service (GETS) platform — browse, filter, and bid on government procurement opportunities. Go + PostgreSQL backend with RealMe SAML 2.0 auth, Next.js 14 frontend.
Languages
app-gets — Government Electronic Tenders Service
A modern GETS tender management platform that connects New Zealand government agencies with verified suppliers through RealMe authentication.
Features
- Browse Tenders: Search and filter government procurement opportunities from the NZ GETS API
- Supplier Profiles: RealMe-verified supplier profiles with business details and specialities
- Bid Submission: Submit competitive bids on open tenders with proposal documents
- Alert Subscriptions: Get notified when new tenders match your criteria
- Saved Searches: Save and reuse complex search filters
- Supplier Dashboard: Central hub for alerts, bids, and profile management
Architecture
app-gets/
├── cmd/server/ # HTTP server entrypoint
├── internal/
│ ├── models/ # Domain types (Tender, Bid, Supplier, Award)
│ ├── repository/ # PostgreSQL data access layer
│ ├── services/ # Business logic (tender, bid, supplier services)
│ └── handlers/ # HTTP handlers with RealMe auth middleware
├── migrations/ # Database schema (Atlas-compatible)
├── web/ # Next.js 14 frontend
├── Dockerfile # Go backend container
└── docker-compose.yml # Service composition
Tech Stack
- Backend: Go 1.23, Chi router, pgx (PostgreSQL)
- Auth: RealMe (SAML 2.0) — login and verified identity
- Frontend: Next.js 14, React, TailwindCSS
- Data: PostgreSQL with JSONB for flexible arrays
- Infrastructure: Docker, docker-compose
Quick Start
Prerequisites
- Go 1.23+
- Node.js 20+
- Docker & docker-compose
- PostgreSQL (or Docker PostgreSQL)
- RealMe certificates (dev mock available)
Setup
-
Start the database:
docker compose up -d postgres -
Run database migrations:
atlas schema apply --dir file://migrations --url "postgres://tptnz:tptnz_dev@localhost:5432/tptnz?sslmode=disable"Or apply manually:
psql "postgres://tptnz:tptnz_dev@localhost:5432/tptnz?sslmode=disable" -f migrations/001_init.sql -
Start the backend:
go run ./cmd/serverThe API will be available at
http://localhost:8082. -
Start the frontend (in a separate terminal):
cd web npm install npm run devThe UI will be available at
http://localhost:3002.
Docker (full stack)
docker compose -f docker-compose.yml -f packages/app-gets/docker-compose.yml up
API Endpoints
Authentication (RealMe)
| Method | Path | Description |
|--------|------|-------------|
| GET | /auth/login | Initiate RealMe login |
| GET | /auth/callback | SAML callback handler |
| GET | /auth/logout | Logout and destroy session |
| GET | /auth/metadata | SAML metadata XML |
| GET | /auth/status | Current auth status |
Tenders (Public)
| Method | Path | Description |
|--------|------|-------------|
| GET | /tenders | List/search tenders |
| GET | /tenders/categories | Get tender categories |
| GET | /tenders/{id} | Get tender details |
| GET | /tenders/{id}/bids | List bids for a tender |
| POST | /tenders/sync | Sync from external GETS API |
Tenders (Authenticated)
| Method | Path | Description |
|--------|------|-------------|
| POST | /tenders/{id}/bids | Submit a bid (verified only) |
Suppliers
| Method | Path | Description |
|--------|------|-------------|
| GET | /suppliers/profile | Get/create own profile |
| PUT | /suppliers/profile | Update own profile |
| GET | /suppliers/{id} | Get supplier by ID |
Dashboard
| Method | Path | Description |
|--------|------|-------------|
| GET | /dashboard | User dashboard (profile, bids, alerts) |
Alerts & Saved Searches
| Method | Path | Description |
|--------|------|-------------|
| GET | /alerts | List alert subscriptions |
| POST | /alerts | Create alert subscription |
| DELETE | /alerts/{id} | Delete alert subscription |
| PUT | /alerts/{id}/toggle | Toggle alert active status |
| GET | /saved-searches | List saved searches |
| POST | /saved-searches | Save a search |
| DELETE | /saved-searches/{id} | Delete saved search |
Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| LISTEN_ADDR | :8082 | HTTP server listen address |
| DATABASE_URL | postgres://... | PostgreSQL connection string |
| FRONTEND_URL | http://localhost:3002 | CORS allowed origin |
| REALME_ENVIRONMENT | mts | RealMe environment |
| REALME_CERT_FILE | certs/sp.crt | Service provider cert |
| REALME_KEY_FILE | certs/sp.key | Service provider key |
| REALME_ENTITY_ID | http://localhost:8082/auth/metadata | SAML entity ID |
| REALME_ACS_URL | http://localhost:8082/auth/callback | SAML ACS URL |
| REALME_IDP_METADATA_URL | http://localhost:8081/metadata | IdP metadata URL |
Data Model
- tenders: Government procurement opportunities with budget ranges, categories, and regions
- suppliers: RealMe-verified business entities with service categories
- bids: Supplier proposals linked to tenders with lifecycle status tracking
- awards: Contract awards for winning bids
- alert_subscriptions: Supplier-configured keyword/category/region matching rules
- saved_searches: Persistent search queries for quick access
Security
- RealMe Login: Required for all authenticated endpoints
- RealMe Verified: Required for bid submission (high-value actions)
- CORS: Restricted to configured frontend origin
- Session: Server-side encrypted sessions with 30-minute expiry
- SAML: Signed authentication assertions via RealMe IdP
RealMe Registration
To use this app with real RealMe identities (ITE or Production environments), you must register a Service Provider with the Department of Internal Affairs.
MTS (Messaging Test Site) — Development
-
Generate a self-signed certificate and key:
mkdir -p certs openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout certs/sp.key -out certs/sp.crt \ -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost" -
In MTS, no formal registration is needed — use the mock IdP in
packages/realme-go/testenv/for local development. -
Start the mock IdP:
cd packages/realme-go go run ./testenv/ -addr :8081 -
Configure the app to use the mock IdP:
REALME_IDP_METADATA_URL=http://localhost:8081/metadata
ITE (Integration Test Environment) — Pre-Production
- Log in to the RealMe Developer Portal and register a new service.
- Submit your SP metadata XML (available at
GET /auth/metadata) to DIA. - DIA will provide the ITE IdP metadata URL.
- Generate a proper certificate (not self-signed) using the naming convention:
ite.{service-name}.{org-domain}.nz - Configure environment variables:
REALME_ENVIRONMENT=ite REALME_CERT_FILE=certs/ite.sp.crt REALME_KEY_FILE=certs/ite.sp.key REALME_IDP_METADATA_URL=<DIA-provided-ITE-url>
Production
Follow the ITE steps above, substituting:
REALME_ENVIRONMENT=production
REALME_CERT_FILE=certs/prod.sp.crt
REALME_KEY_FILE=certs/prod.sp.key
REALME_IDP_METADATA_URL=<DIA-provided-prod-url>