diff --git a/dataflow.cabal b/dataflow.cabal
--- a/dataflow.cabal
+++ b/dataflow.cabal
@@ -1,5 +1,5 @@
 name:                dataflow
-version:             0.5.3.0
+version:             0.5.4.0
 synopsis:            Generate Graphviz documents from a Haskell representation.
 description:         Outputs .dot files that can be processed by the dot
                      command. Currently it only supports the DFD output format
diff --git a/examples/legend.svg b/examples/legend.svg
--- a/examples/legend.svg
+++ b/examples/legend.svg
@@ -4,49 +4,52 @@
 <!-- Generated by graphviz version 2.38.0 (20140413.2041)
  -->
 <!-- Title: Untitled Pages: 1 -->
-<svg width="370pt" height="300pt"
- viewBox="0.00 0.00 370.00 300.48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 296.481)">
+<svg width="406pt" height="308pt"
+ viewBox="0.00 0.00 406.00 308.32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 304.316)">
 <title>Untitled</title>
-<polygon fill="white" stroke="none" points="-4,4 -4,-296.481 366,-296.481 366,4 -4,4"/>
+<polygon fill="white" stroke="none" points="-4,4 -4,-304.316 402,-304.316 402,4 -4,4"/>
 <g id="clust1" class="cluster"><title>cluster_trust</title>
-<polygon fill="none" stroke="#595959" stroke-dasharray="5,2" points="8,-8 8,-284.481 354,-284.481 354,-8 8,-8"/>
-<text text-anchor="start" x="148.393" y="-273.481" font-family="Arial" font-style="italic" font-size="10.00" fill="#595959">TrustBoundary</text>
+<polygon fill="none" stroke="#595959" stroke-dasharray="5,2" points="8,-8 8,-292.316 390,-292.316 390,-8 8,-8"/>
+<text text-anchor="start" x="166.393" y="-281.316" font-family="Arial" font-style="italic" font-size="10.00" fill="#595959">TrustBoundary</text>
 </g>
 <!-- function -->
 <g id="node1" class="node"><title>function</title>
-<ellipse fill="none" stroke="black" cx="190" cy="-210.074" rx="46.8172" ry="46.8172"/>
-<text text-anchor="start" x="163.152" y="-207.923" font-family="Arial" font-weight="bold" font-size="14.00">Function</text>
+<ellipse fill="none" stroke="black" cx="208" cy="-217.908" rx="46.8172" ry="46.8172"/>
+<text text-anchor="start" x="181.152" y="-215.758" font-family="Arial" font-weight="bold" font-size="14.00">Function</text>
 </g>
 <!-- database -->
 <g id="node2" class="node"><title>database</title>
-<text text-anchor="start" x="58.5347" y="-58.3825" font-family="Arial" font-weight="bold" font-size="14.00">Database</text>
-<polyline fill="none" stroke="black" points="53.5,-47.5825 122.5,-47.5825 "/>
-<polyline fill="none" stroke="black" points="122.5,-73.5825 53.5,-73.5825 "/>
+<text text-anchor="start" x="58.5347" y="-62.3" font-family="Arial" font-weight="bold" font-size="14.00">Database</text>
+<polyline fill="none" stroke="black" points="53.5,-51.5 122.5,-51.5 "/>
+<polyline fill="none" stroke="black" points="122.5,-77.5 53.5,-77.5 "/>
 </g>
 <!-- function&#45;&gt;database -->
 <g id="edge3" class="edge"><title>function&#45;&gt;database</title>
-<path fill="none" stroke="black" d="M156.061,-177.629C146.51,-167.788 136.58,-156.519 128.664,-145.165 116.243,-127.349 105.643,-105.165 98.3825,-88.129"/>
-<polygon fill="black" stroke="black" points="101.565,-86.6655 94.5049,-78.7656 95.0974,-89.3438 101.565,-86.6655"/>
-<text text-anchor="start" x="129" y="-132.464" font-family="Arial" font-weight="bold" font-size="12.00">Flow</text>
+<path fill="none" stroke="black" d="M169.293,-191.395C155.216,-180.751 139.998,-167.488 128.664,-153 114.295,-134.632 103.528,-110.364 96.6951,-92.0459"/>
+<polygon fill="black" stroke="black" points="99.9655,-90.7966 93.3059,-82.5564 93.3733,-93.151 99.9655,-90.7966"/>
+<text text-anchor="start" x="129" y="-140.299" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(3) </text>
+<text text-anchor="start" x="147" y="-140.299" font-family="Arial" font-weight="bold" font-size="12.00">Flow</text>
 </g>
 <!-- io -->
 <g id="node3" class="node"><title>io</title>
-<polygon fill="none" stroke="black" stroke-width="2" points="313.665,-105.248 224.335,-105.248 224.335,-15.9173 313.665,-15.9173 313.665,-105.248"/>
-<text text-anchor="start" x="232.417" y="-58.4318" font-family="Arial" font-weight="bold" font-size="14.00">InputOutput</text>
+<polygon fill="none" stroke="black" stroke-width="2" points="337.5,-113 240.5,-113 240.5,-16 337.5,-16 337.5,-113"/>
+<text text-anchor="start" x="252.917" y="-62.3" font-family="Arial" font-weight="bold" font-size="14.00">InputOutput</text>
 </g>
 <!-- function&#45;&gt;io -->
 <g id="edge1" class="edge"><title>function&#45;&gt;io</title>
-<path fill="none" stroke="black" d="M173.056,-166.198C170.005,-151.853 169.686,-136.207 176.664,-123.165 185.251,-107.116 200.073,-94.5268 215.359,-85.0284"/>
-<polygon fill="black" stroke="black" points="217.483,-87.8421 224.369,-79.7904 213.965,-81.7904 217.483,-87.8421"/>
-<text text-anchor="start" x="177" y="-132.464" font-family="Arial" font-weight="bold" font-size="12.00">Flow</text>
+<path fill="none" stroke="black" d="M191.196,-174.107C188.156,-159.768 187.808,-144.107 194.664,-131 202.93,-115.197 216.936,-102.441 231.662,-92.5323"/>
+<polygon fill="black" stroke="black" points="233.794,-95.3258 240.378,-87.0254 230.054,-89.408 233.794,-95.3258"/>
+<text text-anchor="start" x="195" y="-140.299" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(1) </text>
+<text text-anchor="start" x="213" y="-140.299" font-family="Arial" font-weight="bold" font-size="12.00">Flow</text>
 </g>
 <!-- function&#45;&gt;io -->
 <g id="edge2" class="edge"><title>function&#45;&gt;io</title>
-<path fill="none" stroke="black" d="M216.6,-159.412C226.002,-141.858 236.5,-122.259 245.616,-105.241"/>
-<polygon fill="black" stroke="black" points="213.433,-157.913 211.796,-168.381 219.603,-161.218 213.433,-157.913"/>
-<text text-anchor="start" x="248.561" y="-136.565" font-family="Arial" font-weight="bold" font-size="12.00">Flow</text>
-<text text-anchor="start" x="234" y="-126.165" font-family="Arial" font-size="10.00">(backwards)</text>
+<path fill="none" stroke="black" d="M241.242,-170.972C245.053,-165.037 248.737,-158.952 252,-153 258.898,-140.418 265.381,-126.282 270.934,-113.101"/>
+<polygon fill="black" stroke="black" points="238.183,-169.252 235.599,-179.527 244.027,-173.106 238.183,-169.252"/>
+<text text-anchor="start" x="267.561" y="-144.4" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(2) </text>
+<text text-anchor="start" x="285.561" y="-144.4" font-family="Arial" font-weight="bold" font-size="12.00">Flow</text>
+<text text-anchor="start" x="262" y="-134" font-family="Arial" font-size="10.00">(backwards)</text>
 </g>
 </g>
 </svg>
diff --git a/examples/webapp.svg b/examples/webapp.svg
--- a/examples/webapp.svg
+++ b/examples/webapp.svg
@@ -4,68 +4,72 @@
 <!-- Generated by graphviz version 2.38.0 (20140413.2041)
  -->
 <!-- Title: Webapp Pages: 1 -->
-<svg width="333pt" height="450pt"
- viewBox="0.00 0.00 333.01 450.40" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<svg width="364pt" height="450pt"
+ viewBox="0.00 0.00 364.30 450.40" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 446.4)">
 <title>Webapp</title>
-<polygon fill="white" stroke="none" points="-4,4 -4,-446.4 329.01,-446.4 329.01,4 -4,4"/>
-<text text-anchor="start" x="125.44" y="-423.4" font-family="Arial" font-weight="bold" font-size="20.00">Webapp</text>
+<polygon fill="white" stroke="none" points="-4,4 -4,-446.4 360.298,-446.4 360.298,4 -4,4"/>
+<text text-anchor="start" x="141.084" y="-423.4" font-family="Arial" font-weight="bold" font-size="20.00">Webapp</text>
 <g id="clust1" class="cluster"><title>cluster_browser</title>
-<polygon fill="none" stroke="#595959" stroke-dasharray="5,2" points="115,-298.185 115,-403.402 201,-403.402 201,-298.185 115,-298.185"/>
-<text text-anchor="start" x="139.663" y="-392.402" font-family="Arial" font-style="italic" font-size="10.00" fill="#595959">Browser</text>
+<polygon fill="none" stroke="#595959" stroke-dasharray="5,2" points="124.298,-298.185 124.298,-403.402 210.298,-403.402 210.298,-298.185 124.298,-298.185"/>
+<text text-anchor="start" x="148.961" y="-392.402" font-family="Arial" font-style="italic" font-size="10.00" fill="#595959">Browser</text>
 </g>
 <g id="clust2" class="cluster"><title>cluster_aws</title>
-<polygon fill="none" stroke="#595959" stroke-dasharray="5,2" points="8,-8 8,-258.185 144,-258.185 144,-8 8,-8"/>
-<text text-anchor="start" x="45.3408" y="-247.185" font-family="Arial" font-style="italic" font-size="10.00" fill="#595959">Amazon AWS</text>
+<polygon fill="none" stroke="#595959" stroke-dasharray="5,2" points="75.2982,-8 75.2982,-258.185 211.298,-258.185 211.298,-8 75.2982,-8"/>
+<text text-anchor="start" x="112.639" y="-247.185" font-family="Arial" font-style="italic" font-size="10.00" fill="#595959">Amazon AWS</text>
 </g>
 <!-- client -->
 <g id="node1" class="node"><title>client</title>
-<ellipse fill="none" stroke="black" cx="158" cy="-341.044" rx="34.7182" ry="34.7182"/>
-<text text-anchor="start" x="140.104" y="-338.893" font-family="Arial" font-weight="bold" font-size="14.00">Client</text>
+<ellipse fill="none" stroke="black" cx="167.298" cy="-341.044" rx="34.7182" ry="34.7182"/>
+<text text-anchor="start" x="149.402" y="-338.893" font-family="Arial" font-weight="bold" font-size="14.00">Client</text>
 </g>
 <!-- server -->
 <g id="node2" class="node"><title>server</title>
-<ellipse fill="none" stroke="black" cx="76" cy="-170.343" rx="60.1865" ry="60.1865"/>
-<text text-anchor="start" x="39.1714" y="-168.192" font-family="Arial" font-weight="bold" font-size="14.00">Web Server</text>
+<ellipse fill="none" stroke="black" cx="143.298" cy="-170.343" rx="60.1865" ry="60.1865"/>
+<text text-anchor="start" x="106.47" y="-168.192" font-family="Arial" font-weight="bold" font-size="14.00">Web Server</text>
 </g>
 <!-- client&#45;&gt;server -->
 <g id="edge1" class="edge"><title>client&#45;&gt;server</title>
-<path fill="none" stroke="black" d="M123.059,-338.065C89.5097,-334.089 40.5091,-322.371 16.6367,-288.185 2.08217,-267.343 11.5388,-242.438 26.8205,-220.986"/>
-<polygon fill="black" stroke="black" points="29.6634,-223.03 32.9246,-212.949 24.0889,-218.796 29.6634,-223.03"/>
-<text text-anchor="start" x="17" y="-275.484" font-family="Arial" font-weight="bold" font-size="12.00">Request /</text>
+<path fill="none" stroke="black" d="M132.239,-339.791C94.5448,-337.407 36.2297,-327.148 7.93494,-288.185 -19.1714,-250.859 30.7957,-217.498 77.4951,-196.076"/>
+<polygon fill="black" stroke="black" points="79.0523,-199.214 86.7676,-191.953 76.2082,-192.817 79.0523,-199.214"/>
+<text text-anchor="start" x="8.29822" y="-275.484" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(1) </text>
+<text text-anchor="start" x="26.2982" y="-275.484" font-family="Arial" font-weight="bold" font-size="12.00">Request /</text>
 </g>
 <!-- client&#45;&gt;server -->
 <g id="edge3" class="edge"><title>client&#45;&gt;server</title>
-<path fill="none" stroke="black" d="M138.654,-300.242C127.716,-277.74 113.896,-249.306 102.019,-224.873"/>
-<polygon fill="black" stroke="black" points="135.631,-302.03 143.15,-309.493 141.927,-298.97 135.631,-302.03"/>
-<text text-anchor="start" x="132" y="-279.585" font-family="Arial" font-weight="bold" font-size="12.00">Response</text>
-<text text-anchor="start" x="132.899" y="-269.185" font-family="Arial" font-size="10.00">User Profile</text>
+<path fill="none" stroke="black" d="M156.033,-297.404C155.38,-294.295 154.78,-291.199 154.263,-288.185 151.076,-269.61 148.761,-249.204 147.103,-230.715"/>
+<polygon fill="black" stroke="black" points="152.647,-298.299 158.261,-307.284 159.475,-296.759 152.647,-298.299"/>
+<text text-anchor="start" x="154.298" y="-279.585" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(3) </text>
+<text text-anchor="start" x="172.298" y="-279.585" font-family="Arial" font-weight="bold" font-size="12.00">Response</text>
+<text text-anchor="start" x="164.198" y="-269.185" font-family="Arial" font-size="10.00">User Profile</text>
 </g>
 <!-- analytics -->
 <g id="node4" class="node"><title>analytics</title>
-<polygon fill="none" stroke="black" stroke-width="2" points="325.021,-206.364 252.979,-206.364 252.979,-134.323 325.021,-134.323 325.021,-206.364"/>
-<text text-anchor="start" x="266.428" y="-174.143" font-family="Arial" font-weight="bold" font-size="14.00">Google</text>
-<text text-anchor="start" x="260.99" y="-160.143" font-family="Arial" font-weight="bold" font-size="14.00">Analytics</text>
+<polygon fill="none" stroke="black" stroke-width="2" points="356.298,-210.343 276.298,-210.343 276.298,-130.343 356.298,-130.343 356.298,-210.343"/>
+<text text-anchor="start" x="293.726" y="-174.143" font-family="Arial" font-weight="bold" font-size="14.00">Google</text>
+<text text-anchor="start" x="288.288" y="-160.143" font-family="Arial" font-weight="bold" font-size="14.00">Analytics</text>
 </g>
 <!-- client&#45;&gt;analytics -->
 <g id="edge4" class="edge"><title>client&#45;&gt;analytics</title>
-<path fill="none" stroke="black" d="M181.196,-314.881C188.653,-306.533 196.835,-297.095 204,-288.185 223.027,-264.524 243.063,-237.118 258.9,-214.798"/>
-<polygon fill="black" stroke="black" points="261.843,-216.698 264.754,-206.51 256.126,-212.659 261.843,-216.698"/>
-<text text-anchor="start" x="248.681" y="-279.585" font-family="Arial" font-weight="bold" font-size="12.00">Log</text>
-<text text-anchor="start" x="222" y="-269.185" font-family="Arial" font-size="10.00">Page Navigation</text>
+<path fill="none" stroke="black" d="M196.993,-322.619C211.093,-313.472 227.595,-301.419 240.298,-288.185 259.899,-267.764 277.455,-241.61 290.743,-219.226"/>
+<polygon fill="black" stroke="black" points="293.797,-220.937 295.803,-210.534 287.747,-217.415 293.797,-220.937"/>
+<text text-anchor="start" x="275.979" y="-279.585" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(4) </text>
+<text text-anchor="start" x="293.979" y="-279.585" font-family="Arial" font-weight="bold" font-size="12.00">Log</text>
+<text text-anchor="start" x="258.298" y="-269.185" font-family="Arial" font-size="10.00">Page Navigation</text>
 </g>
 <!-- logs -->
 <g id="node3" class="node"><title>logs</title>
-<text text-anchor="start" x="72.8208" y="-31.8" font-family="Arial" font-weight="bold" font-size="14.00">Logs</text>
-<polyline fill="none" stroke="black" points="68,-21 108,-21 "/>
-<polyline fill="none" stroke="black" points="108,-47 68,-47 "/>
+<text text-anchor="start" x="140.119" y="-31.8" font-family="Arial" font-weight="bold" font-size="14.00">Logs</text>
+<polyline fill="none" stroke="black" points="135.298,-21 175.298,-21 "/>
+<polyline fill="none" stroke="black" points="175.298,-47 135.298,-47 "/>
 </g>
 <!-- server&#45;&gt;logs -->
 <g id="edge2" class="edge"><title>server&#45;&gt;logs</title>
-<path fill="none" stroke="black" d="M81.2983,-110.027C82.7846,-93.3881 84.3291,-76.0972 85.5602,-62.3138"/>
-<polygon fill="black" stroke="black" points="89.0697,-62.3631 86.4733,-52.0913 82.0974,-61.7403 89.0697,-62.3631"/>
-<text text-anchor="start" x="91.6592" y="-83.4" font-family="Arial" font-weight="bold" font-size="12.00">Log</text>
-<text text-anchor="start" x="85" y="-73" font-family="Arial" font-size="10.00">User IP</text>
+<path fill="none" stroke="black" d="M148.597,-110.027C150.083,-93.3881 151.627,-76.0972 152.858,-62.3138"/>
+<polygon fill="black" stroke="black" points="156.368,-62.3631 153.772,-52.0913 149.396,-61.7403 156.368,-62.3631"/>
+<text text-anchor="start" x="152.298" y="-83.4" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(2) </text>
+<text text-anchor="start" x="170.298" y="-83.4" font-family="Arial" font-weight="bold" font-size="12.00">Log</text>
+<text text-anchor="start" x="154.639" y="-73" font-family="Arial" font-size="10.00">User IP</text>
 </g>
 </g>
 </svg>
diff --git a/src/DataFlow/DFD.hs b/src/DataFlow/DFD.hs
--- a/src/DataFlow/DFD.hs
+++ b/src/DataFlow/DFD.hs
@@ -1,10 +1,24 @@
 module DataFlow.DFD where
 
 import Text.Printf
+import Control.Monad
+import Control.Monad.State
 import qualified DataFlow.Core as C
 import DataFlow.Graphviz
 import DataFlow.Graphviz.EdgeNormalization
 
+type Step = Int
+type DFD v = State Step v
+
+incrStep :: DFD ()
+incrStep = modify (+ 1)
+
+-- | Get the next \"step\" number (the order of flow arrows in the diagram).
+nextStep :: DFD Int
+nextStep = do
+  incrStep
+  get
+
 inQuotes :: String -> String
 inQuotes s = "\"" ++ s ++ "\""
 
@@ -25,21 +39,25 @@
 
 small :: String -> String
 small "" = ""
-small s = "<font point-size=\"10\">" ++ s ++ "</font>"
+small s = printf "<font point-size=\"10\">%s</font>" s
 
-convertObject :: C.Object -> StmtList
+color :: String -> String -> String
+color _ "" = ""
+color c s = printf "<font color=\"%s\">%s</font>" c s
 
-convertObject (C.InputOutput id' name) = [
+convertObject :: C.Object -> DFD StmtList
+
+convertObject (C.InputOutput id' name) = return [
     NodeStmt (ID id') [
       Attr (ID "shape") (ID "square"),
       Attr (ID "style") (ID "bold"),
-      label $ bold name
+      label $ printf "<table border=\"0\" cellborder=\"0\" cellpadding=\"2\"><tr><td>%s</td></tr></table>" (bold name)
     ]
   ]
 
-convertObject (C.TrustBoundary id' name objects) =
-  let sgId = (ID $ "cluster_" ++ id')
-      objectStmts = convertObjects objects
+convertObject (C.TrustBoundary id' name objects) = do
+  objectStmts <- convertObjects objects
+  let sgId = ID $ "cluster_" ++ id'
       sgAttrStmt = AttrStmt Graph [
           Attr (ID "fontsize") (ID "10"),
           Attr (ID "fontcolor") (ID "grey35"),
@@ -48,35 +66,35 @@
           label $ italic name
         ]
       stmts = sgAttrStmt : objectStmts
-  in [SubgraphStmt $ Subgraph sgId stmts]
+  return [SubgraphStmt $ Subgraph sgId stmts]
 
-convertObject (C.Function id' name) =
-  [
+convertObject (C.Function id' name) = return [
     NodeStmt (ID id') [
       Attr (ID "shape") (ID "circle"),
       label $ bold name
     ]
   ]
 
-convertObject (C.Database id' name) =
-  [
+convertObject (C.Database id' name) = return [
     NodeStmt (ID id') [
       Attr (ID "shape") (ID "none"),
       label $ printf "<table sides=\"TB\" cellborder=\"0\"><tr><td>%s</td></tr></table>" (bold name)
     ]
   ]
 
-convertObject (C.Flow i1 i2 op desc) =
-  [
-    EdgeStmt (EdgeExpr (IDOperand (NodeID (ID i1) Nothing))
-                       Arrow
-                       (IDOperand (NodeID (ID i2) Nothing))) [
-      label $ bold op ++ "<br/>" ++ small desc
-    ]
-  ]
+convertObject (C.Flow i1 i2 op desc) = do
+    step <- nextStep
+    let stepStr = color "#3184e4" $ bold $ printf "(%d) " step
+    return [
+        EdgeStmt (EdgeExpr (IDOperand (NodeID (ID i1) Nothing))
+                          Arrow
+                          (IDOperand (NodeID (ID i2) Nothing))) [
+          label $ stepStr ++ bold op ++ "<br/>" ++ small desc
+        ]
+      ]
 
-convertObjects :: [C.Object] -> StmtList
-convertObjects = concatMap convertObject
+convertObjects :: [C.Object] -> DFD StmtList
+convertObjects = liftM concat . mapM convertObject
 
 defaultGraphStmts :: StmtList
 defaultGraphStmts = [
@@ -99,11 +117,18 @@
     EqualsStmt (ID "rankdir") (ID "t")
   ]
 
+convertDiagram :: C.Diagram -> DFD Graph
+
+convertDiagram (C.Diagram (Just name) objects) = do
+  let lbl = EqualsStmt (ID "label") (ID $ inAngleBrackets $ bold name)
+  objs <- convertObjects objects
+  let stmts = lbl : defaultGraphStmts ++ objs
+  return $ normalize $ Digraph (ID $ inQuotes name) stmts
+
+convertDiagram (C.Diagram Nothing objects) = do
+  objs <- convertObjects objects
+  return $ normalize $ Digraph (ID "Untitled") $ defaultGraphStmts ++ objs
+
 asDFD :: C.Diagram -> Graph
-asDFD (C.Diagram (Just name) objects) =
-  normalize $ Digraph (ID $ inQuotes name) $
-    let lbl = EqualsStmt (ID "label") (ID $ inAngleBrackets $ bold name)
-    in lbl : defaultGraphStmts ++ convertObjects objects
-asDFD (C.Diagram Nothing objects) =
-  normalize $ Digraph (ID "Untitled") $
-    defaultGraphStmts ++ convertObjects objects
+asDFD d = evalState (convertDiagram d) 0
+
