Getting Started
Getting Started
Section titled “Getting Started”Try it without installing anything
Section titled “Try it without installing anything”Open the reference service directly in a browser-based dev environment — no local Go install needed:
Inside the Codespace the Go toolchain is pre-installed. Run:
cd reference/standard-servicego run .Then open the forwarded port and verify:
curl http://localhost:8080/healthz# {"data":{"status":"ok","service":"plumego-reference","timestamp":"2026-06-08T00:00:00Z"}}Quickest start — add to any Go project
Section titled “Quickest start — add to any Go project”Requirements: Go 1.26+ and an existing Go module (go.mod).
go mod init myservice # skip if you already have a modulego get github.com/spcent/plumego@latestCreate main.go:
package main
import ( "net/http"
"github.com/spcent/plumego/contract" "github.com/spcent/plumego/core" plog "github.com/spcent/plumego/log")
func main() { app := core.New(core.DefaultConfig(), core.AppDependencies{Logger: plog.NewLogger()})
_ = app.Get("/ping", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _ = contract.WriteResponse(w, r, http.StatusOK, map[string]string{"status": "ok"}, nil) }))
app.Run() // combined prepare + listen on :8080}Run and verify:
go run .# 2026/06/06 00:00:00 server listening on :8080
curl http://localhost:8080/ping# {"data":{"status":"ok"},"request_id":""}The data wrapper and request_id field are part of the contract response envelope. Add middleware/requestid before app.Run() to populate the request ID on every response.
Two lifecycle patterns:
app.Run()is the combined path — prepare, wire, and start in one call. If you need to inspect or wrap the*http.Serverbefore it starts (custom TLS, connection tracking, or test embedding), useapp.Prepare()+app.Server()instead. See the core module primer for the full API.
What this proves
Section titled “What this proves”| Signal | Proves |
|---|---|
contract.WriteResponse wraps the map | Success responses use the stable transport contract |
app.Get(path, http.HandlerFunc(...)) | Route registration is explicit — no hidden init() |
app.Run() in one call | Lifecycle is explicit and composable — the server starts where you see it |
Want the full canonical service shape?
Section titled “Want the full canonical service shape?”Clone and run the reference app to see the complete directory layout — config loading, health endpoints, handler separation, and constructor-based dependency wiring.
git clone https://github.com/spcent/plumegocd plumego/reference/standard-servicego run .Verify:
curl http://localhost:8080/healthz# {"data":{"status":"ok","service":"plumego-reference","timestamp":"2026-06-08T00:00:00Z"}}
curl 'http://localhost:8080/api/v1/greet?name=Alice'# {"data":{"message":"hello, Alice"}}Four files cover the entire shape:
| File | What to inspect |
|---|---|
reference/standard-service/main.go | Bootstrap order |
reference/standard-service/internal/app/app.go | Explicit dependency wiring |
reference/standard-service/internal/app/routes.go | Route ownership in one place |
reference/standard-service/internal/handler/api.go | Handler shape: stdlib-compatible |
Choose Your Next Module
Section titled “Choose Your Next Module”After the smallest example works, keep the app layout from reference/standard-service and add only the capability family you need:
| Goal | First module |
|---|---|
| Standard JSON API with explicit handlers | stable roots: core, router, contract, middleware |
| Reusable CRUD and resource conventions | x/rest |
| Tenant resolution, policy, quota, and isolation | x/tenant |
| Reverse proxy, rewrite, balancing, and edge transport | x/gateway, then x/gateway/discovery only when dynamic backend lookup is required |
| WebSocket transport | x/websocket |
| Messaging workflows | x/messaging |
| Inbound webhook verification or outbound webhook delivery | x/messaging/webhook, starting from x/messaging when the task is broader than transport mechanics |
| File upload, download, and temporary URL transport | x/fileapi, with storage and metadata implementations in x/data/file |
| Reusable circuit breaker or rate-limit primitives | x/resilience |
| AI providers, sessions, streaming, and tools | x/ai/provider, x/ai/session, x/ai/streaming, x/ai/tool |
| Observability export, protected diagnostics, or local debug endpoints | x/observability, x/observability/ops, or x/observability/devtools depending on the surface |
| gRPC + HTTP service hosting or outbound RPC client pooling | x/rpc |
| OpenAPI 3.1 document generation from registered routes | x/openapi |
| Explicit JSON binding and caller-owned request validation | x/validate |
Do not start a new application layout from an x/* package. Extensions are explicit additions to the canonical app wiring in reference/standard-service.
Leave this page when
Section titled “Leave this page when”| Next question | Go to |
|---|---|
| Which files should I copy from? | Reference App |
| How does the request path work? | Request Flow |
Which stable root or x/* family should I open? | Modules Overview |
| Can I depend on this package long term? | Release Posture |
| Common questions (auth, database, comparison with Gin) | FAQ |