tpt-marketplace-nz

Go

Open-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.

0 stars0 forks0 watchersMIT License
golangidentity-verificationmarketplacenew-zealandnextjsopen-sourcepeer-to-peerpostgresqlrealmesaml

Languages

Go55.9%TypeScript43.6%Dockerfile0.3%Makefile0.2%
README

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.

License: MIT

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)

  1. Log in to the RealMe Developer Portal and register a new service.
  2. Submit your SP metadata (GET /auth/metadata) to DIA.
  3. DIA provides the ITE IdP metadata URL.
  4. 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.

License

MIT