tpt-biz-incorporate-nz
GoRegister a New Zealand company instantly via MBIE Companies Office API, authenticated with RealMe Verified Identity. Go backend + Next.js frontend.
Languages
Instant Business Incorporation — App 5
Register a new New Zealand company instantly using your RealMe verified identity. Direct integration with the MBIE Companies Office API.
Architecture
┌─────────────────────────────────────────────────────┐
│ Next.js Frontend │
│ (TypeScript, React Server Components, Tailwind) │
└──────────────────┬──────────────────────────────────┘
│ HTTP (JSON API)
┌──────────────────▼──────────────────────────────────┐
│ Go Backend (Chi) │
│ ┌─────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ Auth │ │ Service │ │ Repository│ │
│ │ Handlers │ │ Layer │ │ (pgx) │ │
│ └──────┬──────┘ └──────┬───────┘ └─────┬─────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ RealMe SAML MBIE API PostgreSQL │
│ (Provider) (companies) (pgxpool) │
└─────────────────────────────────────────────────────┘
Tech Stack
- Backend: Go 1.23, Chi router, pgx (PostgreSQL), RealMe SAML
- Frontend: Next.js 14, TypeScript, Tailwind CSS
- Database: PostgreSQL 16 (via docker-compose)
- External API: MBIE Companies Office (
api.business.govt.nz) - Identity: RealMe Verified Identity (SAML 2.0)
Quick Start
Prerequisites
- Go 1.23+
- Node.js 20+ (with pnpm)
- Docker and Docker Compose
- RealMe certificates (for production, see below for dev)
1. Start Infrastructure
From the project root:
# Start PostgreSQL, Redis, NATS
make dev
2. Database Migration
# Run the initial schema migration
DATABASE_URL="postgres://tptnz:tptnz_dev@localhost:5432/tptnz?sslmode=disable" \
atlas schema apply --dir "file://packages/app-biz-incorporate/migrations" \
--url "$DATABASE_URL" --auto-approve
Or apply manually:
psql "postgres://tptnz:tptnz_dev@localhost:5432/tptnz?sslmode=disable" \
-f packages/app-biz-incorporate/migrations/001_init.sql
3. Run the Backend
cd packages/app-biz-incorporate
DATABASE_URL="postgres://tptnz:tptnz_dev@localhost:5432/tptnz?sslmode=disable" \
go run ./cmd/server
The server starts on http://localhost:8080.
4. Run the Frontend (optional, for development)
cd packages/app-biz-incorporate/web
pnpm install
pnpm dev
The frontend starts on http://localhost:3005.
5. Docker Compose (all-in-one)
# From project root
docker compose -f docker-compose.yml \
-f packages/app-biz-incorporate/docker-compose.yml up
API Endpoints
All protected endpoints require a RealMe Verified Identity session.
Authentication
| Method | Path | Description | |--------|-------------------|---------------------------------| | GET | /auth/login | Initiate RealMe login | | GET | /auth/callback | RealMe SAML callback | | GET | /auth/logout | Clear session | | GET | /auth/metadata | SAML SP metadata XML | | GET | /auth/status | Current auth status (requires login) |
Incorporation (requires RealMe Verified)
| Method | Path | Description | |--------|-------------------------|---------------------------------| | POST | /incorporate | Submit incorporation request | | GET | /companies | List user's companies | | GET | /companies/search?q= | Search companies by name | | GET | /companies/{id} | Get company details |
POST /incorporate
Request body:
{
"companyName": "Acme Technologies NZ Ltd",
"entityType": "NZLIMITED",
"registeredOffice": {
"streetAddress": "123 Queen Street",
"city": "Auckland",
"postcode": "1010",
"country": "New Zealand"
},
"addressForService": {
"streetAddress": "123 Queen Street",
"city": "Auckland",
"postcode": "1010",
"country": "New Zealand"
},
"directors": [
{
"fullName": "John Smith",
"email": "john@example.com",
"dateOfBirth": "1980-01-15",
"address": {
"streetAddress": "45 High Street",
"city": "Wellington",
"postcode": "6011",
"country": "New Zealand"
},
"consent": true,
"realMeHash": "abc123hash"
}
],
"shareholders": [
{
"fullName": "John Smith",
"shareClass": "Ordinary",
"numberOfShares": 100,
"email": "john@example.com",
"isEntity": false
}
]
}
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>
Environment Variables
| Variable | Default | Description | |-----------------------------|----------------------------------------------|------------------------------------| | LISTEN_ADDR | :8080 | Server listen address | | DATABASE_URL | postgres://tptnz:tptnz_dev@localhost:5432/...| PostgreSQL connection string | | MBIE_API_KEY | dev-api-key | MBIE API key | | MBIE_BASE_URL | (empty, uses default) | Override MBIE API base URL | | REALME_ENVIRONMENT | mts | mts, ite, or production | | REALME_CERT_FILE | certs/sp.crt | Path to SP certificate | | REALME_KEY_FILE | certs/sp.key | Path to SP private key | | REALME_ENTITY_ID | http://localhost:8080/auth/metadata | SAML entity ID | | REALME_ACS_URL | http://localhost:8080/auth/callback | SAML ACS URL | | REALME_IDP_METADATA_FILE | (empty) | Local IdP metadata file | | REALME_IDP_METADATA_URL | http://localhost:8081/metadata (default) | IdP metadata URL |
Testing
# From the app directory
go test ./...
# With race detection
go test -race ./...
# Run specific test
go test -v ./internal/handlers/ -run TestValidateIncorporationRequest
Database Schema
The schema (migrations/001_init.sql) consists of three core tables:
- companies — Tracks the full incorporation lifecycle (draft, submitting, registered, rejected, error)
- directors — RealMe-verified natural persons with expressed consent
- shareholders — Natural or corporate entities holding shares