Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions services/api/.golangci-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
run:
timeout: 5m

linters:
enable:
- govet
- revive
- staticcheck
- errcheck
- ineffassign

issues:
exclude-use-default: false
12 changes: 12 additions & 0 deletions services/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Builder
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY . .
RUN go mod tidy
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o server ./cmd/server

# Runtime
FROM gcr.io/distroless/base-debian12
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
16 changes: 16 additions & 0 deletions services/api/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
BINARY=server

build:
go build -o bin/$(BINARY) ./cmd/server

run:
go run ./cmd/server

test:
go test ./...

fmt:
go fmt ./...

lint:
golangci-lint run
125 changes: 125 additions & 0 deletions services/api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Nester API

Production-grade Go backend service with clean architecture foundations.

## Overview

The Nester backend is transitioning from Node.js/Express to Go to support long-term scalability and align with ecosystem standards. This service serves as the authoritative API layer for vault, user, and offramp domains.

## Directory Structure

### `cmd/`
**Entrypoints only.** Contains `server/main.go` — application bootstrap and port resolution. No domain logic here.

### `internal/`
**Private domain logic.** Not importable by external packages.

- `config/` — configuration loading and validation
- `domain/` — domain entities and business logic
- `vault/` — vault operations and state
- `user/` — user identity and auth
- `offramp/` — off-ramp transaction processing
- `handler/` — HTTP request handlers
- `middleware/` — request/response middleware
- `repository/` — data access layer
- `service/` — business logic orchestration

### `pkg/`
**Reusable utilities.** Importable by external packages.

- `response/` — standard HTTP response formatting
- `validator/` — input validation helpers

### `migrations/`
**Database schema evolution.** Version-controlled SQL or Go migration scripts.

## Local Development

### Prerequisites
- Go 1.22+
- golangci-lint (optional, for linting)

### Running the server

```bash
make run
```

Server starts on `http://localhost:8080` (or `$PORT` if set).

### Health check

```bash
curl http://localhost:8080/healthz
# Returns: ok (200)
```

### Building

```bash
make build
```

Binary written to `bin/server`.

### Testing

```bash
make test
```

### Code quality

Format code:
```bash
make fmt
```

Lint:
```bash
make lint
```

## Docker

### Build

```bash
docker build -t nester-api .
```

Multi-stage build ensures minimal runtime image (~15MB).

### Run

```bash
docker run -p 8080:8080 nester-api
```

Set port with environment variable:
```bash
docker run -p 9000:9000 -e PORT=9000 nester-api
```

## Architecture Philosophy

**Clean Architecture.** Domain logic is isolated from HTTP, database, and framework concerns. Changes to the web layer do not cascade into domain code.

**Domain Isolation.** `internal/domain/*` packages own their boundaries. Cross-domain dependencies flow only through service/handler layers.

**Minimal Abstraction.** Uses `net/http` directly instead of frameworks. Avoids premature indirection. Repository pattern introduced only where data access is complex.

**Simplicity First.** No dependency injection containers, no global singletons, no reflection-based magic. Code is explicit and traceable.

## Future Phases

1. **Database layer** — PostgreSQL integration via `internal/repository`
2. **Auth middleware** — JWT validation in `internal/middleware`
3. **Vault domain** — Core business logic in `internal/domain/vault`
4. **API v1** — Public endpoints in `internal/handler`
5. **Integration tests** — End-to-end validation

---

*Go version: 1.22+*
*Module: github.com/Suncrest-Labs/nester*
Binary file added services/api/bin/server
Binary file not shown.
37 changes: 37 additions & 0 deletions services/api/cmd/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package main

import (
"log"
"net/http"
"os"
)

func main() {
port := resolvePort()

mux := http.NewServeMux()
mux.HandleFunc("/healthz", healthHandler)

server := &http.Server{
Addr: ":" + port,
Handler: mux,
}

log.Printf("server starting on :%s", port)

if err := server.ListenAndServe(); err != nil {
log.Fatalf("server failed: %v", err)
}
}

func resolvePort() string {
if p := os.Getenv("PORT"); p != "" {
return p
}
return "8080"
}

func healthHandler(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("ok"))
}
3 changes: 3 additions & 0 deletions services/api/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/Suncrest-Labs/nester

go 1.22
Binary file added services/api/server.exe
Binary file not shown.
Loading