Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .claude/CUSTOM-AGENTS-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Integration testing, contract testing, load testing for APIs.

### devops-automator (blue)
Docker, CI/CD pipeline generation, deployment automation.
- **When to use:** Setting up Docker, creating CI/CD, deploying to Cloudflare Workers, Node.js, or AWS Lambda
- **When to use:** Setting up Docker, creating CI/CD, deploying to Cloudflare Workers, Node.js, AWS Lambda, or Railway
- **Key capabilities:** Multi-stage Docker, GitHub Actions, wrangler deploy, PM2, health endpoints

---
Expand Down
2 changes: 1 addition & 1 deletion .claude/agents/devops-automator.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: devops-automator
description: API deployment and CI/CD specialist for Docker, GitHub Actions, Cloudflare Workers, Node.js, and AWS Lambda deployments. Use when setting up deployment pipelines, configuring Docker, managing Workers deployments, deploying with SAM, or automating build processes.
description: API deployment and CI/CD specialist for Docker, GitHub Actions, Cloudflare Workers, Node.js, AWS Lambda, and Railway deployments. Use when setting up deployment pipelines, configuring Docker, managing Workers deployments, deploying with SAM, configuring Railway services, or automating build processes.
color: blue
tools: Bash, Read, Write, Grep, MultiEdit
---
Expand Down
11 changes: 10 additions & 1 deletion .claude/pipeline.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"noAnyTypes": true
},
"deployment": {
"targets": ["cloudflare-workers", "node-docker", "aws-lambda"],
"targets": ["cloudflare-workers", "node-docker", "aws-lambda", "railway"],
"defaultTarget": "cloudflare-workers",
"cloudflareWorkers": {
"compatibilityDate": "2024-12-01",
Expand Down Expand Up @@ -96,6 +96,15 @@
"framework": "sam",
"provisionedConcurrency": 0
},
"railway": {
"builder": "dockerfile",
"healthcheckPath": "/health",
"healthcheckTimeoutSeconds": 300,
"restartPolicy": "on-failure",
"restartPolicyMaxRetries": 10,
"managedPostgres": true,
"autoDeployFromGitHub": true
},
"cicd": {
"provider": "github-actions",
"runTests": true,
Expand Down
79 changes: 73 additions & 6 deletions .claude/skills/deployment-config-generator/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ description: >
build-spec.json. For Cloudflare Workers, generates wrangler.toml with bindings.
For Node.js, generates Dockerfile and docker-compose.yml with PostgreSQL. For
AWS Lambda, generates a SAM template (API Gateway HTTP API), esbuild bundling
config, and an OIDC deploy workflow. Always generates GitHub Actions CI/CD
workflow and .env.example. Keywords: deploy, deployment, wrangler, cloudflare,
workers, docker, dockerfile, docker-compose, aws, lambda, sam, api-gateway,
serverless, esbuild, oidc, cold-start, github-actions, ci-cd, pipeline, env,
configuration, infrastructure
config, and an OIDC deploy workflow. For Railway, generates railway.toml
(Dockerfile build, health check, start command) and nixpacks.toml. Always
generates GitHub Actions CI/CD workflow and .env.example. Keywords: deploy,
deployment, wrangler, cloudflare, workers, docker, dockerfile, docker-compose,
aws, lambda, sam, api-gateway, serverless, esbuild, oidc, cold-start, railway,
nixpacks, paas, github-actions, ci-cd, pipeline, env, configuration,
infrastructure
---

# Deployment Config Generator (Phase 5)
Expand Down Expand Up @@ -45,7 +47,7 @@ const spec = JSON.parse(
await readFile('.claude/plans/build-spec.json', 'utf-8'),
);

const target = spec.deployment.target; // 'cloudflare-workers' | 'node' | 'aws-lambda'
const target = spec.deployment.target; // 'cloudflare-workers' | 'node' | 'aws-lambda' | 'railway'
const authStrategy = spec.auth.strategy;
```

Expand Down Expand Up @@ -347,6 +349,67 @@ permissions:
--parameter-overrides "DatabaseUrl=${{ secrets.DATABASE_URL }} JwtSecret=${{ secrets.JWT_SECRET }}"
```

### Step 2d -- Railway Configuration

If target is `railway`, reuse the Node.js Dockerfile from Step 2b and generate
Railway config-as-code. Canonical templates live in `templates/railway/`
(`railway.toml`, `nixpacks.toml`). Railway builds the service from the
Dockerfile, so the deployed image is identical to the local
`docker compose up` image.

```toml
# api/railway.toml
[build]
builder = "DOCKERFILE"
dockerfilePath = "Dockerfile"
watchPatterns = ["src/**", "package.json", "pnpm-lock.yaml", "Dockerfile"]

[deploy]
startCommand = "node dist/index.js"
healthcheckPath = "/health"
healthcheckTimeout = 300
restartPolicyType = "ON_FAILURE"
restartPolicyMaxRetries = 10
numReplicas = 1
```

No deploy workflow is generated: Railway auto-deploys the connected GitHub
repo on every push, gated by the `/health` check. (CLI deploys from CI are
possible with `railway up` and a `RAILWAY_TOKEN` secret, but not required.)

Environment variables live on the Railway service (Variables tab), not in
config files. Generate this reference table into the project README:

| Variable | Value |
|---|---|
| `DATABASE_URL` | `${{Postgres.DATABASE_URL}}` (reference to managed PostgreSQL) |
| `JWT_SECRET` | generated secret, 32+ chars |
| `NODE_ENV` | `production` |
| `LOG_LEVEL` | `info` |

`PORT` is injected by Railway; the Node.js entry point already binds it.
Remind the user of the one dashboard setting config-as-code cannot express:
service **Root Directory** must be `api` so Railway finds `railway.toml` and
the Dockerfile.

Nixpacks alternative (`builder = "NIXPACKS"`) for building without the
Dockerfile -- `nixpacks.toml` pins the toolchain:

```toml
# api/nixpacks.toml
[phases.setup]
nixPkgs = ["nodejs_22", "pnpm"]

[phases.install]
cmds = ["pnpm install --frozen-lockfile"]

[phases.build]
cmds = ["pnpm build"]

[start]
cmd = "node dist/index.js"
```

### Step 3 -- Generate GitHub Actions CI/CD

```yaml
Expand Down Expand Up @@ -449,6 +512,8 @@ jobs:
# role-to-assume: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
# aws-region: ${{ vars.AWS_REGION }}
# - run: cd api && pnpm run build:lambda && sam deploy --no-confirm-changeset
# For Railway: no deploy step -- Railway auto-deploys the connected
# GitHub repo on push, gated by the /health check (see Step 2d).

deploy-production:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -525,6 +590,8 @@ Ensure the API package.json has all necessary scripts:
| SAM template | `api/template.yaml` | AWS Lambda + API Gateway HTTP API stack |
| SAM config | `api/samconfig.toml` | Stack name, region, deploy defaults |
| esbuild config | `api/esbuild.config.mjs` | Single-file Lambda bundle build |
| Railway config | `api/railway.toml` | Build, health check, start command, restart policy |
| Nixpacks config | `api/nixpacks.toml` | Toolchain pins for the non-Docker Railway build |
| CI/CD workflow | `.github/workflows/ci.yml` | GitHub Actions pipeline |
| Deploy workflow | `.github/workflows/deploy.yml` | OIDC-based AWS Lambda deploy (Lambda target) |
| Env template | `.env.example` | Environment variable template |
Expand Down
6 changes: 3 additions & 3 deletions .claude/skills/schema-intake/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ continuing. Adapt follow-up questions based on responses.

**Question 6 -- Deployment Target**
> Where will this API be deployed?
> Options: Cloudflare Workers (default), Node.js / Docker, AWS Lambda
> Options: Cloudflare Workers (default), Node.js / Docker, AWS Lambda, Railway

**Question 7 -- Additional Requirements** (optional)
> Any special requirements? (pagination style, rate limiting, soft deletes, etc.)
Expand Down Expand Up @@ -294,7 +294,7 @@ interface BuildSpec {
sourceType: 'file' | 'interview';
};
deployment: {
target: 'cloudflare-workers' | 'node' | 'aws-lambda';
target: 'cloudflare-workers' | 'node' | 'aws-lambda' | 'railway';
runtime: string;
};
auth: {
Expand Down Expand Up @@ -553,7 +553,7 @@ function validateBuildSpec(spec: BuildSpec): string[] {
| `tdd-from-schema` (Phase 2) | Reads `endpoints` and `auth` to generate test cases |
| `route-generation` (Phase 3) | Reads `endpoints` to scaffold Hono route handlers |
| `api-authentication` | Reads `auth` to configure JWT/API key middleware |
| `deployment-config-generator` | Reads `deployment` to generate wrangler.toml, Dockerfile, or SAM template |
| `deployment-config-generator` | Reads `deployment` to generate wrangler.toml, Dockerfile, SAM template, or railway.toml |
| `api-documentation` | Reads the generated OpenAPI spec or regenerates from build-spec |

### Triggering the Next Phase
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ jobs:
fi
done

for dir in templates/shared templates/cloudflare-workers templates/node-server templates/docker templates/aws-lambda; do
for dir in templates/shared templates/cloudflare-workers templates/node-server templates/docker templates/aws-lambda templates/railway; do
if [ -d "$dir" ]; then
echo " $dir: OK"
else
Expand Down
10 changes: 6 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Project Overview

This is a **Claude Code-integrated API & backend development framework** providing specialized agents, skills, scripts, and schema-to-API conversion pipelines. Built with TypeScript, Hono (HTTP framework), Drizzle ORM, and PostgreSQL. Deployed to Cloudflare Workers, Node.js, or AWS Lambda.
This is a **Claude Code-integrated API & backend development framework** providing specialized agents, skills, scripts, and schema-to-API conversion pipelines. Built with TypeScript, Hono (HTTP framework), Drizzle ORM, and PostgreSQL. Deployed to Cloudflare Workers, Node.js, AWS Lambda, or Railway.

Nerva is the backend counterpart to **Aurelius** (frontend framework).

The framework is designed for:
- Schema-first API development (OpenAPI spec to working API)
- OpenAPI-to-working-API conversion with TDD-mandatory development
- Comprehensive testing (integration tests, contract tests, load tests with k6)
- Deployment to Cloudflare Workers, Node.js (Docker), or AWS Lambda (SAM)
- Deployment to Cloudflare Workers, Node.js (Docker), AWS Lambda (SAM), or Railway
- Full product lifecycle support (engineering, database, testing, DevOps, operations)

## Project Structure
Expand All @@ -39,6 +39,7 @@ project-root/
│ ├── cloudflare-workers/ # Wrangler config
│ ├── node-server/ # Node.js server config
│ ├── aws-lambda/ # SAM template, esbuild config, OIDC deploy workflow
│ ├── railway/ # Railway config-as-code (railway.toml, nixpacks.toml)
│ └── docker/ # Dockerfile, docker-compose
├── docs/
│ ├── schema-to-api/ # Pipeline guide
Expand All @@ -58,7 +59,7 @@ project-root/

```bash
# Setup a new API project
./scripts/setup-project.sh my-api --cloudflare # or --node / --lambda
./scripts/setup-project.sh my-api --cloudflare # or --node / --lambda / --railway

# Run tests with coverage
./scripts/run-tests.sh
Expand Down Expand Up @@ -233,7 +234,7 @@ Autonomous 10-phase pipeline that converts an OpenAPI specification into a worki
- **Schema-first** — OpenAPI spec drives database schema, types, handlers, and tests
- **Contract testing** — generated tests validate API responses against OpenAPI spec
- **Load testing** — k6 scripts generated for performance-critical endpoints
- **Multi-target deployment** — Cloudflare Workers, Node.js, Docker, AWS Lambda with single config change
- **Multi-target deployment** — Cloudflare Workers, Node.js, Docker, AWS Lambda, Railway with single config change
- **Type safety end-to-end** — Drizzle schema to Zod validators to TypeScript types
- Quality gate: 80%+ coverage, TypeScript strict, security audit, bundle analysis
- Resumable: TodoWrite tracks progress across interrupted sessions
Expand Down Expand Up @@ -489,6 +490,7 @@ pnpm drizzle-kit studio # Open database GUI
./scripts/setup-project.sh my-api --cloudflare # New Cloudflare Workers project
./scripts/setup-project.sh my-api --node # New Node.js project
./scripts/setup-project.sh my-api --lambda # New AWS Lambda (SAM) project
./scripts/setup-project.sh my-api --railway # New Railway project
```

---
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ A Claude Code-integrated API & backend development framework with TypeScript, Ho
- **12 Development Skills** — Automated workflows for schema parsing, TDD, route generation, authentication, validation, documentation
- **10-Phase Schema-to-API Pipeline** — Convert OpenAPI specs into fully working, tested API servers with a single command
- **TDD-Mandatory Development** — Integration tests written before route handlers, hard gate enforced
- **Three Deployment Targets** — Cloudflare Workers (edge), Node.js (Docker), or AWS Lambda (SAM) with one config change
- **Four Deployment Targets** — Cloudflare Workers (edge), Node.js (Docker), AWS Lambda (SAM), or Railway (PaaS) with one config change
- **Testing Stack** — Vitest, supertest, contract tests against OpenAPI, k6 load tests
- **Schema-First Design** — Database schemas, types, and validators all derived from your API spec

Expand All @@ -37,7 +37,7 @@ cd Nerva
pnpm install

# Initialize a new API project
./scripts/setup-project.sh my-api --cloudflare # or --node / --lambda
./scripts/setup-project.sh my-api --cloudflare # or --node / --lambda / --railway

# Start development
cd api && pnpm dev
Expand Down Expand Up @@ -176,6 +176,7 @@ Full catalog: [`.claude/CUSTOM-AGENTS-GUIDE.md`](.claude/CUSTOM-AGENTS-GUIDE.md)
| `templates/cloudflare-workers/` | Wrangler config with Hyperdrive |
| `templates/node-server/` | Dockerfile + docker-compose with PostgreSQL |
| `templates/aws-lambda/` | SAM template, esbuild config, OIDC deploy workflow |
| `templates/railway/` | Railway config-as-code + Nixpacks build config |
| `templates/docker/` | Extended Docker with Redis + pgAdmin |

## Part of the PMDS Framework Series
Expand Down
5 changes: 3 additions & 2 deletions docs/onboarding/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Shell scripts for common development tasks:

| Script | Purpose |
|--------|---------|
| `setup-project.sh` | Initialize a new API project (--cloudflare, --node, or --lambda) |
| `setup-project.sh` | Initialize a new API project (--cloudflare, --node, --lambda, or --railway) |
| `run-tests.sh` | Vitest test suite with coverage |
| `check-types.sh` | TypeScript strict mode checking |
| `security-scan.sh` | Dependency and code security audit |
Expand All @@ -71,7 +71,7 @@ Shell scripts for common development tasks:
| `generate-openapi-docs.sh` | Build API documentation |
| `generate-client.sh` | Generate typed API client for frontends |

### Templates (5 directories)
### Templates (6 directories)

Starter configurations for different deployment targets:

Expand All @@ -81,6 +81,7 @@ Starter configurations for different deployment targets:
| `templates/cloudflare-workers/` | Wrangler config with D1/KV/Hyperdrive bindings |
| `templates/node-server/` | Dockerfile + docker-compose with PostgreSQL |
| `templates/aws-lambda/` | SAM template (API Gateway HTTP API), esbuild config, OIDC deploy workflow |
| `templates/railway/` | Railway config-as-code (Docker build, health check) + Nixpacks config |
| `templates/docker/` | Extended Docker setup with Redis + pgAdmin |

## Pipelines
Expand Down
2 changes: 1 addition & 1 deletion docs/onboarding/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ If you have an OpenAPI specification file:

```bash
# Initialize the project structure
./scripts/setup-project.sh my-api --cloudflare # or --node / --lambda
./scripts/setup-project.sh my-api --cloudflare # or --node / --lambda / --railway

# Open Claude Code and run the pipeline
/build-from-schema path/to/openapi-spec.yaml
Expand Down
8 changes: 4 additions & 4 deletions docs/schema-to-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Convert an OpenAPI specification into a fully working, tested API server through
| 7 | Validation Layer | Generate Zod schemas for request/response validation |
| 8 | Auth & Security | Wire authentication middleware, CORS, rate limiting |
| 9 | Documentation | Generate API docs, Swagger UI config, example responses |
| 10 | Deployment Config | Produce Wrangler TOML, Dockerfile, or SAM template |
| 10 | Deployment Config | Produce Wrangler TOML, Dockerfile, SAM template, or Railway config |

## Phase-by-Phase Deep Dive

Expand Down Expand Up @@ -102,12 +102,12 @@ Convert an OpenAPI specification into a fully working, tested API server through

### Phase 10: Deployment Config

**What it does:** Produces deployment configuration files matching the target platform. For Cloudflare Workers: `wrangler.toml` with D1 bindings. For Node.js: `Dockerfile` with multi-stage build and `docker-compose.yml`. For AWS Lambda: `template.yaml` (SAM with an API Gateway HTTP API), `samconfig.toml`, esbuild bundle config, and an OIDC-based deploy workflow.
**What it does:** Produces deployment configuration files matching the target platform. For Cloudflare Workers: `wrangler.toml` with D1 bindings. For Node.js: `Dockerfile` with multi-stage build and `docker-compose.yml`. For AWS Lambda: `template.yaml` (SAM with an API Gateway HTTP API), `samconfig.toml`, esbuild bundle config, and an OIDC-based deploy workflow. For Railway: `railway.toml` (Dockerfile build, health check, start command) and `nixpacks.toml`.

- **Inputs:** Project structure, database config, environment variables
- **Outputs:** `wrangler.toml`, `Dockerfile` + `docker-compose.yml`, or `template.yaml` + `samconfig.toml` + `esbuild.config.mjs`
- **Outputs:** `wrangler.toml`, `Dockerfile` + `docker-compose.yml`, `template.yaml` + `samconfig.toml` + `esbuild.config.mjs`, or `railway.toml` + `nixpacks.toml`
- **Tools:** `deployment-config-generator` skill
- **Config:** `pipeline.config.json` -- `deployment.target` (cloudflare, node, aws-lambda, both)
- **Config:** `pipeline.config.json` -- `deployment.target` (cloudflare, node, aws-lambda, railway, both)

## Configuration

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"schema-first",
"tdd",
"cloudflare-workers",
"aws-lambda"
"aws-lambda",
"railway"
],
"author": "PAMulligan",
"license": "MIT",
Expand Down
Loading
Loading