Reusable TypeScript service template for integration-facing services. This is a generic foundation — it contains no product logic, only service plumbing.
Intended for things like:
- Slack adapters
- MCP servers
- Webhook receivers
- Lightweight integration APIs
- Node 24+ (pinned in
.nvmrc)
# Install dependencies
npm install
# Copy env file and fill in values
cp .env.example .env
# Run the dev server (hot reload)
npm run devThe service is available at http://localhost:3001.
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch# Format, lint, typecheck, and test
npm run precommit| Method | Path | Description |
|---|---|---|
| GET | /healthz |
Health check |
- App factory:
buildApp(opts?)creates a configured Fastify instance — testable in isolation - Composition root:
server.tsis the only file that reads env vars - Env validation: Zod schema with fail-fast on startup
- Error handling:
AppErrorclass → consistent{ error: { code, message, details } }envelope - Request logging: Structured pino logs with request_id, method, url, status_code, duration_ms
- Core API client: Typed
CoreApiClientfor calling backend services (constructor injection, no env coupling)
See docs/ARCHITECTURE.md for detailed design and docs/DECISIONS.md for the decision log.
Copy .env.example to .env. Dev requires:
| Variable | Default | Description |
|---|---|---|
PORT |
3001 | HTTP port |
HOST |
0.0.0.0 | Bind address |
LOG_LEVEL |
info | Pino log level |
CORE_API_BASE_URL |
— | Backend API URL (required) |
CORE_API_TOKEN |
— | Bearer token for backend API (required) |
This is one of three reusable service templates. They share API conventions and response envelopes but are otherwise independent.
| Template | Purpose | Stack |
|---|---|---|
| elixir-api-core | Core backend APIs | Elixir, Phoenix, PostgreSQL |
| node-edge-core (this repo) | Edge/integration services | TypeScript, Fastify, Zod |
| web-app-core | Frontend SPA | TypeScript, React, Vite, Tailwind |
Product apps are created from these templates and then diverge freely with domain logic. They're designed to work together — a frontend built from web-app-core calls a backend API built from elixir-api-core, while edge services built from node-edge-core handle integrations.
See CHANGELOG.md for the versioned task tracker.