Where Rhodd fits
Start with a greenfield baseline; grow into continuity, standardization, adoption and multi-repo planning. Every scenario produces the same inspectable .rhodd/ state.
A real system, compiled from one file
fullstack-saas is a four-service product — a React web app, a Nest API, a Go audit service and a Node worker, over postgres and redis, with presets, adapters, Docker and Kubernetes. One rhodd.yaml compiles it into a reproducible baseline with the graph, plan and lock already in place.
version: "0.1"
project:
name: fullstack-saas
description: Frontend, backend, a Go service, database, worker, adapters, Docker, and Kubernetes.
preset:
kind: fullstack-saas
quality: production-baseline
frontend:
framework: react
language: typescript
bundler: vite
validation: zod
componentLibrary: radix
state:
client: zustand
server: tanstack-query
backend:
language: typescript
framework: nest
transport: rest
orm: prisma
modules:
- name: postgres
- name: redis
services:
- name: web
kind: app
runtime: react-ts-zod
language: typescript
port: 5173
exposure: cluster
dependencies: [api]
consumes: [http]
env: { VITE_API_BASE_URL: http://api:3000 }
- name: api
kind: app
runtime: node-nest
language: typescript
port: 3000
replicas: 2
exposure: cluster
provides: [http]
dependencies: [postgres, redis]
consumes: [postgres, redis]
env: { DATABASE_HOST: postgres, CACHE_HOST: redis }
- name: audit
kind: app
runtime: go-http
port: 8081
exposure: cluster
provides: [http]
dependencies: [api]
consumes: [http]
env: { API_BASE_URL: http://api:3000 }
- name: jobs
kind: app
runtime: node-worker
language: typescript
port: 9100
exposure: none
dependencies: [api, postgres, redis]
consumes: [http, postgres, redis]
env: { QUEUE_NAME: billing-jobs }
database:
provider: postgres
orm: prisma
targets:
- { name: frontend-react }
- { name: backend-node-nest }
- { name: backend-go-rest }
- { name: prisma-db }
- { name: workers-node }
- { name: docker-compose }
- { name: kubernetes }
- { name: full-project }
infrastructure:
compose: true
kubernetes: true
docs: true
tests: true- Service node: web (runtime react-ts-zod).
- Service node: api (runtime node-nest).
- Service node: audit (runtime go-http).
- Service node: jobs (runtime node-worker).
- Module node: postgres.
- Module node: redis.
- Edge: web depends on api over http.
- Edge: audit depends on api over http.
- Edge: jobs depends on api over http.
- Edge: api owns postgres.
- Edge: api owns redis.
- Edge: jobs depends on postgres.
- Edge: jobs depends on redis.
- Graph is acyclic, proven by topological order.
AI project continuity across sessions
The .rhodd/ai handoff is a structured truth pack — context, model, graph, generation-plan, ownership, target-matrix, plus task-scoped prompts — that an agent reads to continue safely. It is lint-checked and secrets are redacted; providers never run by default (skipped unless you pass --include provider). Rhodd works without AI; AI becomes safer when Rhodd gives it explicit state, and stays bounded by it — it never drives the compile.
# Rhodd handoff — for humans and AI
Read order: context → model → graph → generation-plan → ownership → target-matrix
This system was compiled deterministically. Treat the artifacts under `.rhodd/`
as ground truth. Rhodd works without AI; AI becomes safer when it reads this
explicit state instead of guessing.
.rhodd/ai/
context.md system shape + read order (this file)
prompts/ task-scoped prompts, ready to paste
tasks/ bounded, checkable units of work
graph.json services, modules, edges (acyclic)
model.json the resolved system
generation-plan.json the write set (dry-run clean)
ownership.md generated vs user-owned paths
target-matrix.md targets → emitted files
Safety (code-enforced): the handoff is lint-checked and secrets are redacted —
the linter errors on api_key / token / secret / password patterns and never
prints the value. Providers (openai, anthropic, gemini) never run by default;
they are skipped unless you pass `--include provider`, and the run records
"no provider call was made". A deterministic local `fake` provider is available
for offline validation.Repeatable services from one definition
A team's services come out of the same definition the same way every time — identical scaffolds, wiring and compose, with ownership boundaries recorded. New service, same shape, no drift.
Adopt an existing project
Already have a codebase? Point Rhodd at it. `rhodd scan` detects services and infra and suggests a definition; `rhodd compare` reports drift before you commit. An advanced path — reach for it after you've compiled a greenfield baseline.
$ rhodd scan ./legacy-app
→ detected 3 services · 1 database · docker-compose.yml
→ suggested definition written to .rhodd/adoption/suggested.yaml
$ rhodd compare
→ 2 services match · 1 drift · 0 conflictsPlan across repositories
A single repo uses rhodd.yaml. Many repos use rhodd.system.yaml — it links the repositories, declares typed cross-repo contracts (OpenAPI producer → consumer), the runtime dependencies bound to them, environments, and release channels. Plan a coordinated change across the whole system. A deeper capability, not the first experience.
apiVersion: rhodd.dev/v1alpha1
kind: System
metadata:
name: example-system
version: 0.1.0
spec:
repositories:
- name: web-platform
path: repos/web-platform
spec: rhodd.yaml
role: web-platform
defaultBranch: main
managedByRhodd: true
- name: processing-platform
path: repos/processing-platform
spec: rhodd.yaml
role: backend-processing
defaultBranch: main
managedByRhodd: true
- name: deploy
path: repos/deploy
spec: rhodd.deploy.yaml
role: deployment
managedByRhodd: false
contracts:
- name: processing-api
kind: openapi
producer:
repo: processing-platform
service: api
consumers:
- repo: web-platform
app: web
schema:
path: repos/processing-platform/contracts/processing-api.openapi.yaml
dependencies:
- from:
repo: web-platform
app: web
to:
repo: processing-platform
service: api
kind: runtime-http
contract: processing-api
environments:
- name: local
kind: local-dev
deployRepo: deploy
- name: staging
kind: kubernetes
deployRepo: deploy
- name: production
kind: kubernetes
deployRepo: deploy
releaseChannels:
- name: stable
- name: canary
- name: ab-test
releaseSets:
path: releasesTwo services or a dozen
The same compiler and the same .rhodd/ state, whether the system is two services or a dozen. Complexity is additive — not a different tool.
Rung 1 · hello-platform — start tiny: two services, one file.
version: "0.1"
project:
name: hello-platform
description: Minimal multi-service system.
services:
- name: api
kind: http-api
language: go
port: 8080
env:
LOG_LEVEL: debug
- name: worker
kind: worker
language: go
port: 8090
env:
QUEUE_NAME: jobs
infrastructure:
compose: trueRung 2 · sqlite-prisma — add a framework and a database.
version: "0.1"
project:
name: sqlite-prisma
description: TypeScript/Nest service with SQLite + Prisma.
preset:
kind: fullstack-saas
quality: production-baseline
backend:
language: typescript
framework: nest
transport: rest
orm: prisma
services:
- name: api
kind: app
runtime: node-nest
language: typescript
port: 3000
exposure: cluster
provides: [http]
database:
provider: sqlite
orm: prisma
targets:
- { name: backend-node-nest }
- { name: prisma-db }
- { name: db-sqlite }
- { name: full-project }
infrastructure:
compose: true
envfiles: trueRung 3 · fullstack-saas — scale to a real system: frontend, services, workers, adapters, Kubernetes. See the flagship ↑
Pick a starting point.
Greenfield or brownfield, one repo or many — the output is always a locked, reproducible, inspectable baseline.