tpt-marketplace-nz
GoOpen-source peer-to-peer marketplace for New Zealand, built with Go and Next.js. All users authenticate via RealMe (NZ Government SAML 2.0). High-value listings (vehicles, property, services) require verified identity. Full-text search, private messaging, reviews, and a seller dashboard.
Languages
TPT Marketplace NZ
A verified peer-to-peer marketplace for New Zealand. All users authenticate via RealMe — the NZ Government identity service. High-value categories (vehicles, property, services) require RealMe Verified identity. No payment processing is involved; the platform facilitates discovery and communication only.
Features
- RealMe Authentication — all users must log in via RealMe SAML 2.0. Session cookies are HMAC-signed with a configurable
SESSION_SECRET. - Tiered Verification — vehicles, property, and services require RealMe Verified identity (Assurance Level 3+); other categories require login only.
- Browse & Search — full-text trigram search (PostgreSQL
pg_trgm) with filters for category, region, and price range. - Private Messaging — authenticated buyers can contact sellers via an in-app inbox.
- Reviews & Ratings — verified buyers can leave a star rating and comment on any listing they did not create. One review per user per listing enforced at the database level.
- Seller Dashboard — sellers can view, edit, change the status of, and delete their own listings.
- Pagination — 20 listings per page.
Tech Stack
| Layer | Technology |
|---|---|
| Backend | Go 1.23, chi router, pgx v5 |
| Frontend | Next.js 14, TypeScript, App Router |
| Auth | RealMe SAML 2.0 via packages/realme-go |
| Database | PostgreSQL 16, pg_trgm for full-text search |
| Infrastructure | Docker Compose (PostgreSQL, Redis, NATS) |
Quick Start
Prerequisites
- Go 1.23+
- Node.js 18+
- Docker & Docker Compose
- RealMe certificates, or the included mock IdP for local development
1 — Start infrastructure
docker compose up -d db
2 — Generate a local SP certificate
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"
3 — Configure environment
cp .env.example .env
# Edit .env — at minimum set DATABASE_URL and SESSION_SECRET
See .env.example for all variables and their descriptions.
4 — Run the database migration
psql $DATABASE_URL -f migrations/001_init.sql
5 — Start the mock RealMe IdP (development only)
go run ./packages/realme-go/testenv/ -addr :8081
6 — Start the API server
go run ./cmd/server
The API server starts on http://localhost:8080.
7 — Start the frontend
cd web
npm install
npm run dev
The frontend starts on http://localhost:3000.
API Reference
Auth
| Method | Path | Description |
|---|---|---|
| GET | /health | Health check |
| GET | /auth/login | Initiate RealMe login |
| GET | /auth/callback | RealMe SAML callback |
| GET | /auth/logout | Logout |
| GET | /auth/metadata | SAML SP metadata XML |
| GET | /auth/status | Current user identity (unauthenticated returns {}) |
Listings
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /listings | No | Browse / search listings |
| GET | /listings/categories | No | Available categories |
| GET | /listings/{id} | No | Listing detail |
| POST | /listings | Required | Create listing |
| PUT | /listings/{id} | Owner | Full listing update |
| PUT | /listings/{id}/status | Owner | Update listing status |
| DELETE | /listings/{id} | Owner | Delete listing |
| POST | /listings/{id}/reviews | Required | Submit a review |
| GET | /my-listings | Required | Authenticated user's listings |
Messages
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /messages | Required | Inbox |
| POST | /messages | Required | Send message |
| GET | /messages/conversation/{listingId}/{otherUserId} | Required | Conversation thread |
Verification Gates
| Action | Requirement | |---|---| | Browse listings | None — public | | Send messages | RealMe login | | Submit a review | RealMe login, not the seller, one review per listing | | Create a listing | RealMe login | | Create in high-value category | RealMe Verified (Assurance Level 3+) | | Edit / delete own listing | RealMe login + ownership |
High-Value Categories
| Category | Requires Verification | |---|---| | Vehicles | Yes | | Property | Yes | | Services | Yes | | Electronics | No | | Agriculture | No | | Jobs | No | | Other | No |
RealMe Setup
Local Development (mock IdP)
The repository includes a mock RealMe IdP in packages/realme-go/testenv/. Start it on :8081 and set:
REALME_ENVIRONMENT=mts
REALME_IDP_METADATA_URL=http://localhost:8081/metadata
ITE (Integration Test Environment)
- Log in to the RealMe Developer Portal and register a new service.
- Submit your SP metadata (
GET /auth/metadata) to DIA. - DIA provides the ITE IdP metadata URL.
- Set:
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
Same as ITE with REALME_ENVIRONMENT=production and the DIA production metadata URL.
Project Structure
tpt-marketplace-nz/
├── cmd/server/ # Main entrypoint
├── internal/
│ ├── handlers/ # HTTP handlers
│ ├── services/ # Business logic
│ ├── repository/ # Database access
│ └── models/ # Shared types
├── migrations/ # SQL migration files
├── packages/
│ └── realme-go/ # RealMe SAML 2.0 SP library
├── web/ # Next.js 14 frontend
│ ├── app/ # App Router pages
│ ├── components/ # Shared components
│ └── lib/ # api.ts, categories.ts
├── docker-compose.yml
├── Dockerfile
└── .env.example
Contributing
See CONTRIBUTING.md.