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
row Spine: Users Client Cloud

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

Cloud: [
  Gateway: icon aws:amazon-api-gateway "API Gateway"
  Fn:      icon aws:aws-lambda "Chatbot"
  Vision:  icon aws:amazon-rekognition "Rekognition"
] "AWS Cloud"

from Users   arrow "1. post image" to Client
from Client  arrow "2. API call"   to Gateway
from Gateway arrow "3. invoke"     to Fn
from Fn      arrow "4. moderate"   to Vision
from Fn      arrow "5. push via chat API" to Client route above

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.

// 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

arrow from LB to App
from App arrow "SQL" to PG
from App arrow "cache" to 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, nest related nodes into labelled groups.
Open this source in the editor →
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"

arrow from Start to Authn
from Authn arrow "no"  to Unauth
from Authn arrow "yes" to Authz
from Authz arrow "no"  to Forbid
from Authz arrow "yes" to Ok
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; SheepText handles the remaining placement and routing.
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.

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"

from Users arrow "(1)" to ChatClient
from ChatClient arrow "(2)" to ApiGateway
from ApiGateway arrow "(3)" to Lambda
from Lambda arrow "(4)" to Rekognition heads both
from Lambda arrow "(5)" to ChatClient
An image-moderation chat flow with no layout statements: users reach a chat client, which calls an API Gateway inside an AWS Region group; Lambda moderates with Rekognition and replies to the chat client, every arrow numbered and drawn with AWS icons
1. No layout statements at all: five services, five arrows, one region. Placement, routing and label clearance are the solver's job.
Open this source in the editor →