neokit

module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 2, 2026 License: MIT

README

neokit

Composable Go building blocks for small services. Neokit does not replace the standard library or a web framework; it is the operational layer around them — safe HTTP clients, structured errors and logs, health checks, ordered shutdown, observability, caching, and optional integrations.

Take one package at a time, or start with app when a service wants the whole boot sequence from one constructor. There is no service container and no lookup by string: every dependency app builds is an exported field on it, and a handler stays an ordinary Fiber handler over ordinary types. Reflection is confined to the two places Go offers no alternative — decoding the environment in config, and validator tags in fiberx. Nothing reaches a binary unless its package is imported.

The one global: app.New installs its logger as slog.Default(), unless you pass your own through Options.Log.

Pre-1.0: the API may change between v0.x releases.

Packages

Package What
logx slog context handler, canonical Err attribute, request-id propagation
httpc NewHTTPClient, BaseClient, retry transport, APIError, Classify, SSRF guard
fiberx {"error": …} envelope, bind+validate, metrics/logging middleware, rate limiters
cache stale-while-revalidate GetOrFetch
sqlitex PRAGMA user_version append-only migration runner, VACUUM INTO snapshot backup
tracing metrics OpenTelemetry and Prometheus wiring
debugserver /metrics and opt-in pprof on a listener of their own, off the application's port
safe ids clock goroutine recovery, id/token generation, injectable clock
netx AddrInUseHint — a readable message for a listener already bound
disk Usage — free/total filesystem space via syscall.Statfs
oidcauth provider-agnostic OpenID Connect relying party: PKCE, nonce, typed error sentinels
oidcauth/fiberauth the browser half — handshake routes, __Host- cookies, session middleware, guards
jobs Job{Every, Timeout, RunAtStart, Do} — periodic work that is bounded and panic-guarded
lifecycle Signals context + a LIFO named shutdown Stack
pubsub Bus[T] — keyed fan-out for SSE/WebSocket, drop-on-slow
capset generic capability resolution by type assertion, memoised
notify Sender — webhook, ntfy, Apprise, and a Multi fan-out
webpush VAPID keypair generation and sub normalisation (no dependencies)
buildinfo version/commit/date with Go's embedded VCS metadata as the fallback

Every package is independent: importing one never drags in another's dependencies. A binary that does not import oidcauth links neither go-oidc nor oauth2.

Start here

Need Example
A small HTTP service examples/minimal-api
HTTP, health, metrics, shutdown, and SQLite examples/production-service
A bounded, retrying external API client examples/external-client

Run one from the repository root with go run ./examples/minimal-api. They are ordinary Go types and constructors: copy the pieces your service needs rather than adopting the whole thing.

A new project

There is no generator. A service starts as one file — copy the shape from app's package documentation, embed config.Base in your own config struct, and add what you need:

cfg, err := config.Load[Config]()
a, err := app.New(app.Options{Name: "okstables", Version: version, Base: cfg.Base})
defer a.Close()

a.HTTP.Get("/api/v1/hello", func(c fiber.Ctx) error {
    return c.JSON(fiber.Map{"hello": "okstables"})
})
return a.Run()

That is the whole boot. A scaffolding command would only write this out for you and then need a template set kept in step with the API forever.

The diagnostics port

app serves Prometheus metrics, /healthz and /readyz on a second listener, bound to 127.0.0.1:9090. Loopback is the default because a readiness body names your dependencies and their errors — operational detail, not public API. A scrape from another container needs METRICS_BIND_ADDR=0.0.0.0. pprof is off unless ENABLE_PPROF=true, because a heap profile carries whatever secrets are live in the process.

Neither fact is one you should have to infer from a default, so the boot report states both before the listeners come up:

production-service 1.4.0 · :8080
  ✓ database        ./data/app.db
  ✓ diagnostics     127.0.0.1:9090 · metrics, health
  ✗ metrics export  OTEL_EXPORTER_OTLP_ENDPOINT unset
  ✗ tracing         OTEL_EXPORTER_OTLP_ENDPOINT unset

That block is generated from the same app.Subsystem declarations that register the /readyz checks, so it cannot drift from what the process actually is.

Login gate in ten lines

authn, ok := oidcauth.New(oidcauth.Config{
    Issuer:   os.Getenv("OIDC_ISSUER"),   ClientID:     os.Getenv("OIDC_CLIENT_ID"),
    BaseURL:  os.Getenv("OIDC_BASE_URL"), ClientSecret: os.Getenv("OIDC_CLIENT_SECRET"),
})
gate := fiberauth.New(fiberauth.Options{
    Provider:     func() *oidcauth.Provider { if !ok { return nil }; return authn },
    Sessions:     store,      // your own storage; neokit ships none
    CookiePrefix: "myapp",
})
app.Use(gate.ResolveIdentity())
gate.Register(app)
admin := app.Group("/api/v1/admin", gate.RequireOwner())

ok == false (no credentials configured) means the gate is off: the middleware returns immediately, the guards pass through, and the handshake routes 404 — so an app can ship open and close later without a second feature flag.

MIT.

Directories

Path Synopsis
Package app is neokit's application builder: the boot sequence every service would otherwise retype, performed once in a documented order.
Package app is neokit's application builder: the boot sequence every service would otherwise retype, performed once in a documented order.
Package backup turns a snapshot primitive into the two things an application needs: a fresh copy streamed on demand, and a dated copy written to disk on a schedule.
Package backup turns a snapshot primitive into the two things an application needs: a fresh copy streamed on demand, and a dated copy written to disk on a schedule.
Package buildinfo reports the identity of the running binary: the version, commit and build date baked in at link time, plus the Go toolchain and target it was built for.
Package buildinfo reports the identity of the running binary: the version, commit and build date baked in at link time, plus the Go toolchain and target it was built for.
Package cache provides a tiny in-memory TTL cache with per-key single-flight and stale-while-revalidate refreshes.
Package cache provides a tiny in-memory TTL cache with per-key single-flight and stale-while-revalidate refreshes.
Package capset resolves optional capabilities out of a set of named components by type assertion, and memoises the answer.
Package capset resolves optional capabilities out of a set of named components by type assertion, and memoises the answer.
Package config holds the environment settings every service has, and the one call that parses them.
Package config holds the environment settings every service has, and the one call that parses them.
Package debugserver puts a process's diagnostics — Prometheus metrics and, optionally, pprof — on a listener of their own.
Package debugserver puts a process's diagnostics — Prometheus metrics and, optionally, pprof — on a listener of their own.
Package disk reports free and total space on the filesystem holding a path.
Package disk reports free and total space on the filesystem holding a path.
examples
external-client command
External-client calls a fixed upstream with a bounded timeout, idempotent retry policy, optional tracing, and structured errors.
External-client calls a fixed upstream with a bounded timeout, idempotent retry policy, optional tracing, and structured errors.
minimal-api command
Minimal-api is the smallest service built with app: configuration, standard middleware, structured errors, and graceful shutdown with one constructor.
Minimal-api is the smallest service built with app: configuration, standard middleware, structured errors, and graceful shutdown with one constructor.
production-service command
Production-service wires an application-owned SQLite database into app's readiness and ordered shutdown without introducing a service container.
Production-service wires an application-owned SQLite database into app's readiness and ordered shutdown without introducing a service container.
Package fiberx holds cross-cutting Fiber v3 HTTP helpers: the error envelope, request binding/validation, metrics+logging middleware, rate limiting and optimistic-concurrency helpers.
Package fiberx holds cross-cutting Fiber v3 HTTP helpers: the error envelope, request binding/validation, metrics+logging middleware, rate limiting and optimistic-concurrency helpers.
Package health answers the two questions an orchestrator asks, and keeps them apart.
Package health answers the two questions an orchestrator asks, and keeps them apart.
Package httpc is the HTTP client core: a BaseClient for JSON APIs with built-in retries, bearer-token injection/refresh, and bounded reads; a Fault classification (see fault.go) that turns an error into "what should the caller do about it" instead of a status code to grep; and an SSRF-guarded transport (see ssrf.go) for fetching URLs a caller only partly controls.
Package httpc is the HTTP client core: a BaseClient for JSON APIs with built-in retries, bearer-token injection/refresh, and bounded reads; a Fault classification (see fault.go) that turns an error into "what should the caller do about it" instead of a status code to grep; and an SSRF-guarded transport (see ssrf.go) for fetching URLs a caller only partly controls.
Package ids generates identifiers and secrets: UUIDGenerator for v4 UUIDs and CryptoTokenGenerator (see tokengen.go) for crypto-random tokens and passwords.
Package ids generates identifiers and secrets: UUIDGenerator for v4 UUIDs and CryptoTokenGenerator (see tokengen.go) for crypto-random tokens and passwords.
Package jobs runs periodic background work correctly.
Package jobs runs periodic background work correctly.
Package lifecycle owns process startup and shutdown: a context cancelled by the usual termination signals, and an ordered stack of teardown steps.
Package lifecycle owns process startup and shutdown: a context cancelled by the usual termination signals, and an ordered stack of teardown steps.
Package logx holds the small slog helpers that make logs correlatable and consistent: a request-ID carried on the context, a handler decorator that stamps it onto every record, and a canonical error attribute.
Package logx holds the small slog helpers that make logs correlatable and consistent: a request-ID carried on the context, a handler decorator that stamps it onto every record, and a canonical error attribute.
Package metrics wires the OpenTelemetry metrics pillar — the sibling of package tracing, and the third leg (with tracing plus the trace-correlated logs logx already emits) of a full traces + metrics + logs setup.
Package metrics wires the OpenTelemetry metrics pillar — the sibling of package tracing, and the third leg (with tracing plus the trace-correlated logs logx already emits) of a full traces + metrics + logs setup.
Package netx holds small network helpers.
Package netx holds small network helpers.
Package notify sends short operational notifications to the places a self-hosted deployment already has: a generic JSON webhook, an ntfy topic, or an Apprise API server.
Package notify sends short operational notifications to the places a self-hosted deployment already has: a generic JSON webhook, an ntfy topic, or an Apprise API server.
Package oidcauth is a provider-agnostic OpenID Connect relying party: the half of a login that talks to an identity provider.
Package oidcauth is a provider-agnostic OpenID Connect relying party: the half of a login that talks to an identity provider.
fiberauth
Package fiberauth is the browser-facing half of oidcauth: the Fiber v3 routes, cookies and middleware that turn a verified identity into a session and back again.
Package fiberauth is the browser-facing half of oidcauth: the Fiber v3 routes, cookies and middleware that turn a verified identity into a session and back again.
Package pubsub is an in-process, topic-keyed fan-out for pushing events at connected clients — Server-Sent Events and WebSocket streams, where each browser subscribes to one topic (a user id, a job token, a room) and wants only that topic's events.
Package pubsub is an in-process, topic-keyed fan-out for pushing events at connected clients — Server-Sent Events and WebSocket streams, where each browser subscribes to one topic (a user id, a job token, a room) and wants only that topic's events.
Package safe guards background work that runs outside a request's own recover middleware — schedulers, event hooks, detached goroutines — so a panic there is logged with a stack trace and contained, rather than crashing the whole process or silently ending that one goroutine forever.
Package safe guards background work that runs outside a request's own recover middleware — schedulers, event hooks, detached goroutines — so a panic there is logged with a stack trace and contained, rather than crashing the whole process or silently ending that one goroutine forever.
Package sqlitex provides SQLite operational helpers — a forward-only migration runner and a consistent snapshot — with no schema of its own.
Package sqlitex provides SQLite operational helpers — a forward-only migration runner and a consistent snapshot — with no schema of its own.
Package tracing wires OpenTelemetry distributed tracing for the HTTP server.
Package tracing wires OpenTelemetry distributed tracing for the HTTP server.
Package webpush holds the parts of Web Push (RFC 8030) that are pure key handling: generating a VAPID keypair (RFC 8292) and normalising the `sub` contact that rides in every VAPID JWT.
Package webpush holds the parts of Web Push (RFC 8030) that are pure key handling: generating a VAPID keypair (RFC 8292) and normalising the `sub` contact that rides in every VAPID JWT.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL