Diagrams that keep their shape.

A small text language with a constraint solver. When a preference is dropped, the editor marks the statement's source span with a warning.

use icons aws

Users: icon aws:users "Users"
ChatClient: icon aws:client "Chat client"

MainRegion: [
  ApiGateway: icon aws:amazon-api-gateway "Amazon\nAPI Gateway"
  Lambda: icon aws:aws-lambda "AWS\nLambda"
  Rekognition: icon aws:amazon-rekognition "Amazon\nRekognition"
] "AWS Region"

Users -> ChatClient "(1)"
ChatClient -> ApiGateway "(2)"
ApiGateway -> Lambda "(3)"
Lambda <-> Rekognition "(4)"
Lambda -> ChatClient "(5)"

One language, every shape of diagram

Combine icons from ten packs, styled fills, nested groups, and routed connectors while a constraint solver lays it all out for you.

Styling 1 of 6

// The load balancer only talks to the app server; the app server owns both stores.
// Ideal rendering: tiers side by side, LB above App, and App's two outbound
// edges reaching the data tier as separate, non-crossing runs.

column Web: LB App
column Data: PG Cache

Web: [
  LB:  box "Load Balancer" fill #dbeafe stroke #2563eb
  App: box "App Server" fill #dbeafe stroke #2563eb
] "Web Tier" fill #2563eb bold

Data: [
  PG:    box "Postgres" fill #dcfce7 stroke #16a34a
  Cache: box "Redis" fill #fef9c3 stroke #ca8a04
] "Data Tier" fill #16a34a bold

LB -> App
App -> PG "SQL"
App -> Cache "cache"
A two-tier architecture diagram: a Web Tier group where a load balancer feeds an app server, and a Data Tier group with Postgres and Redis; the app server reaches Postgres over a labelled SQL edge and Redis over a labelled cache edge
Style fills and strokes, and nest related nodes into labelled groups.
Open this source in the editor →

Decision flow 2 of 6

direction down
require column MainSpine: Start Authn Authz Ok
require row AuthenticationReject: Authn Unauth
require row AuthorizationReject: Authz Forbid

// Two gates that fail differently: 401 means "we don't know who you are",
// 403 means "we know, and no". Collapsing them into one check is the usual
// bug in a hand-drawn auth flow.
//
// A column keeps the successful path easy to scan; two rows peel each rejection
// away from the main decision spine.

Start: box "Request"
Authn: box "Authenticated?" fill #fef08a
Authz: box "Authorized?" fill #fef08a

Out: [
  Unauth: box "401 Unauthorized" fill #fee2e2
  Forbid: box "403 Forbidden" fill #fee2e2
  Ok:     box "200 OK" fill #dcfce7
] "Outcomes"

Start -> Authn
Authn -> Unauth "no"
Authn -> Authz "yes"
Authz -> Forbid "no"
Authz -> Ok "yes"
A manually constrained authentication decision flow: request, authentication, authorization, successful response, and distinct unauthorized and forbidden branches
Add only the rows and column that communicate the decision structure; the remaining placement and routing is solved.
Open this source in the editor →

Incident response 3 of 6

direction right
group EscalationTeam "Human escalation": EscalationLead SeniorAnalyst ForensicsAnalyst CommsLead
row MainFlow: Sensors DetectionHub Triage

Sensors: box "Telemetry\nsensors"
DetectionHub: box "Detection hub"
Triage: box "Automated triage"
AutoContain: box "Automated\ncontainment"
EscalationLead: box "Escalation lead"
SeniorAnalyst: box "Senior incident analyst"
ForensicsAnalyst: box "Forensics and evidence analyst"
CommsLead: box "Communications and stakeholder lead"

Sensors -> DetectionHub "alerts"
DetectionHub -> Triage "auto triage"
DetectionHub -> AutoContain "contain"
DetectionHub -> EscalationLead "escalate"
EscalationLead -> SeniorAnalyst "assign"
EscalationLead -> ForensicsAnalyst "collect evidence"
EscalationLead -> CommsLead "notify stakeholders"
An incident-response flow: telemetry sensors alert a detection hub, which triages automatically, contains automatically, and escalates to an escalation lead inside a Human escalation group who assigns a senior analyst, a forensics analyst and a communications lead
A detection-to-escalation flow fanning into a human escalation team.
Open this source in the editor →

Checkout fan-out 4 of 6

direction right

Checkout: box "Checkout API"
Payment: box "Payment service"
Inventory: box "Inventory service"
Fraud: box "Fraud screening"
Notify: box "Notification service"

Checkout -> Payment "authorize"
Payment -> Checkout "auth result"
Checkout -> Inventory "reserve"
Inventory -> Checkout "stock result"
Checkout -> Fraud "screen"
Fraud -> Checkout "risk score"
Checkout -> Notify "enqueue"
Notify -> Checkout "receipt sent"
A checkout API fanning out to a payment service, an inventory service, fraud screening and a notification service, each request paired with a labelled reply route back to the checkout API
A checkout API fanning out to four services with reply routes.
Open this source in the editor →

CI loop 5 of 6

direction right
row Pipeline: Commit Build Test Review Merge

Commit: box "Commit"
Build: box "Build"
Test: box "Test suite"
Review: box "Code review"
Merge: box "Merge"

Commit -> Build "trigger"
Build -> Test "artifacts"
Test -> Review "report"
Review -> Merge "approve"
Test -> Commit "failures" route above
Review -> Commit "changes requested" route above
A delivery pipeline in one row from commit through build, test suite and code review to merge, with two failure routes drawn above the row that return from the test suite and the review to the commit
A delivery pipeline whose failure routes return to earlier stages.
Open this source in the editor →

Compiler pipeline 6 of 6

direction down
column CompilerPath: Source LA P Sem
column Correctors: LC Syn DMP
row LexicalRepair: LA LC
row SyntaxRepair: P Syn
row Diagnostics: Sem DMP ST

Source: text "source\ncode"
LA: box "lexical\nanalyzer"
P: box "parser"
Sem: box "semantic\nchecker"
LC: box "lexical\ncorrector"
Syn: box "syntactic\ncorrector"
DMP: box "diagnostic\nmessage\nprinter"
ST: box "symbol\ntable"

Source -> LA "source"
LA -> P "tokens"
P -> Sem "AST"
LC <-> LA "lexical repair"
Syn <-> P "syntax repair"
Syn -> DMP "diagnostics"
DMP <-> ST "lookup"
LC -> DMP "messages"
Sem -> DMP "messages"
Sem <-> ST "symbols"
A compiler front end in a column from source code through lexical analyzer, parser and semantic checker, beside a column of lexical and syntactic correctors joined to it by bidirectional repair routes, ending at a diagnostic message printer and a symbol table
A compiler front end with correctors and bidirectional repair routes.
Open this source in the editor →

Constraints, not coordinates

Say what is in the diagram and how it connects; the solver places it. Write a constraint only where you mean one; when two of them cannot both hold, SheepText tells you which.