chartlet 0.20.0

Compile structured data into deterministic, accessible static charts
Documentation
1
<div class="chartlet-wrapper"><style>.chartlet-stage{position:relative;display:inline-block;max-width:100%;vertical-align:top}.chartlet-stage>svg{display:block}.chartlet-hotspot{position:absolute;border-radius:8px;cursor:pointer}.chartlet-focus{margin:0 0 12px 0;font-size:13px}.chartlet-focus summary{cursor:pointer;min-height:24px}.chartlet-focus fieldset{border:none;padding:0;margin:4px 0 0 0}.chartlet-focus label{display:inline-flex;align-items:center;min-height:44px;margin-right:14px;cursor:pointer;white-space:nowrap}.chartlet-focus input{margin-right:4px}.chartlet-focus input:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.chartlet-wrapper:has(.chartlet-focus-node:checked) #chartlet-00195d7e9e740778 .chartlet-f{opacity:.18}#chartlet-00195d7e9e740778-hs-0{left:43.944%;top:2.308%;width:12.111%;height:9.231%}#chartlet-00195d7e9e740778-hs-1{left:44.322%;top:29.231%;width:11.357%;height:11.154%}#chartlet-00195d7e9e740778-hs-2{left:44.8%;top:58.077%;width:10.4%;height:9.615%}#chartlet-00195d7e9e740778-hs-3{left:44.8%;top:85.385%;width:10.4%;height:11.538%}.chartlet-wrapper:has(#chartlet-00195d7e9e740778-focus-0:checked) #chartlet-00195d7e9e740778 .chartlet-f-0{opacity:1}.chartlet-wrapper:has(#chartlet-00195d7e9e740778-focus-0:checked) #chartlet-00195d7e9e740778 .chartlet-n-0 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-00195d7e9e740778-focus-0:checked) #chartlet-00195d7e9e740778 .chartlet-n-0 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-00195d7e9e740778-focus-1:checked) #chartlet-00195d7e9e740778 .chartlet-f-1{opacity:1}.chartlet-wrapper:has(#chartlet-00195d7e9e740778-focus-1:checked) #chartlet-00195d7e9e740778 .chartlet-n-1 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-00195d7e9e740778-focus-1:checked) #chartlet-00195d7e9e740778 .chartlet-n-1 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-00195d7e9e740778-focus-2:checked) #chartlet-00195d7e9e740778 .chartlet-f-2{opacity:1}.chartlet-wrapper:has(#chartlet-00195d7e9e740778-focus-2:checked) #chartlet-00195d7e9e740778 .chartlet-n-2 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-00195d7e9e740778-focus-2:checked) #chartlet-00195d7e9e740778 .chartlet-n-2 .chartlet-seq-box{stroke-width:3}.chartlet-wrapper:has(#chartlet-00195d7e9e740778-focus-3:checked) #chartlet-00195d7e9e740778 .chartlet-f-3{opacity:1}.chartlet-wrapper:has(#chartlet-00195d7e9e740778-focus-3:checked) #chartlet-00195d7e9e740778 .chartlet-n-3 .chartlet-flow-node,.chartlet-wrapper:has(#chartlet-00195d7e9e740778-focus-3:checked) #chartlet-00195d7e9e740778 .chartlet-n-3 .chartlet-seq-box{stroke-width:3}</style><details class="chartlet-focus"><summary>Focus</summary><fieldset><label><input type="radio" name="chartlet-00195d7e9e740778-focus" checked> Show all</label><label><input type="radio" name="chartlet-00195d7e9e740778-focus" class="chartlet-focus-node" id="chartlet-00195d7e9e740778-focus-0"> Shop front end</label><label><input type="radio" name="chartlet-00195d7e9e740778-focus" class="chartlet-focus-node" id="chartlet-00195d7e9e740778-focus-1"> Load balancer</label><label><input type="radio" name="chartlet-00195d7e9e740778-focus" class="chartlet-focus-node" id="chartlet-00195d7e9e740778-focus-2"> Orders API</label><label><input type="radio" name="chartlet-00195d7e9e740778-focus" class="chartlet-focus-node" id="chartlet-00195d7e9e740778-focus-3"> Orders</label></fieldset></details><figure class="chartlet-figure" data-viz="chart"><figcaption>Orders API: components</figcaption><div class="chartlet-stage"><svg xmlns="http://www.w3.org/2000/svg" width="1000" height="520" viewBox="0 0 1000 520" id="chartlet-00195d7e9e740778" role="img" aria-labelledby="chartlet-00195d7e9e740778-title chartlet-00195d7e9e740778-description" class="chartlet-root"><title id="chartlet-00195d7e9e740778-title">Orders API: components</title><desc id="chartlet-00195d7e9e740778-description">Architecture diagram with 4 components and 3 connections. Shop front end (frontend): connects to Load balancer (places orders, via HTTPS). Load balancer (service, load balancer): connects to Orders API (routes, via HTTP). Orders API (service): connects to Orders (reads, writes, via SQL). Orders (database): no outgoing connection.</desc><style>.chartlet-root{--chartlet-text:#172033;--chartlet-muted:#344054;--chartlet-grid:#d9dee8;--chartlet-zero:#667085;--chartlet-accent:#2563eb;--chartlet-background:#fff;--chartlet-color-1:#2563eb;--chartlet-color-2:#c2410c;--chartlet-color-3:#475569;--chartlet-color-4:#111827;max-width:100%;height:auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif;color:var(--chartlet-text)}#chartlet-00195d7e9e740778 .chartlet-title{font-size:22px;font-weight:650;fill:var(--chartlet-text)}#chartlet-00195d7e9e740778 .chartlet-label,#chartlet-00195d7e9e740778 .chartlet-tick,#chartlet-00195d7e9e740778 .chartlet-value,#chartlet-00195d7e9e740778 .chartlet-value-inverse,#chartlet-00195d7e9e740778 .chartlet-axis-title{font-size:12px;fill:var(--chartlet-muted)}#chartlet-00195d7e9e740778 .chartlet-value,#chartlet-00195d7e9e740778 .chartlet-value-inverse{font-weight:600}#chartlet-00195d7e9e740778 .chartlet-value{fill:var(--chartlet-text)}#chartlet-00195d7e9e740778 .chartlet-value-inverse{fill:var(--chartlet-background)}#chartlet-00195d7e9e740778 .chartlet-axis-title{font-weight:600}#chartlet-00195d7e9e740778 .chartlet-grid{stroke:var(--chartlet-grid);stroke-width:1}#chartlet-00195d7e9e740778 .chartlet-zero{stroke:var(--chartlet-zero);stroke-width:1.5}#chartlet-00195d7e9e740778 .chartlet-bar,#chartlet-00195d7e9e740778 .chartlet-point{fill:var(--chartlet-accent)}#chartlet-00195d7e9e740778 .chartlet-line{fill:none;stroke:var(--chartlet-accent);stroke-width:3;stroke-linecap:round;stroke-linejoin:round}#chartlet-00195d7e9e740778 .chartlet-background{fill:var(--chartlet-background)}.chartlet-root{--chartlet-node:#eef3fd;--chartlet-lane:#f7f9fc;--chartlet-lane-head:#eef1f6;--chartlet-shadow:rgba(16,24,40,.09);--chartlet-role-blue:#2563eb;--chartlet-role-blue-fill:#eef3fd;--chartlet-role-green:#15803d;--chartlet-role-green-fill:#ecfdf3;--chartlet-role-amber:#b45309;--chartlet-role-amber-fill:#fff7e8;--chartlet-role-teal:#0f766e;--chartlet-role-teal-fill:#e9faf7;--chartlet-role-violet:#6d28d9;--chartlet-role-violet-fill:#f3efff;--chartlet-role-gray:#667085;--chartlet-role-gray-fill:#f7f8fa;--chartlet-role-red:#b42318;--chartlet-role-red-fill:#fef3f2}.chartlet-root.chartlet-theme-dark{--chartlet-node:#1a2436;--chartlet-lane:#121925;--chartlet-lane-head:#18212f;--chartlet-shadow:rgba(0,0,0,.45);--chartlet-role-blue:#7ea6ff;--chartlet-role-blue-fill:#1a2436;--chartlet-role-green:#4ade80;--chartlet-role-green-fill:#132a1d;--chartlet-role-amber:#fbbf24;--chartlet-role-amber-fill:#2b2210;--chartlet-role-teal:#2dd4bf;--chartlet-role-teal-fill:#0f2a27;--chartlet-role-violet:#b69cff;--chartlet-role-violet-fill:#231c38;--chartlet-role-gray:#9aa7bd;--chartlet-role-gray-fill:#161d29;--chartlet-role-red:#f97066;--chartlet-role-red-fill:#2d1616}#chartlet-00195d7e9e740778 .chartlet-role-blue{fill:var(--chartlet-role-blue-fill);stroke:var(--chartlet-role-blue)}#chartlet-00195d7e9e740778 .chartlet-role-green{fill:var(--chartlet-role-green-fill);stroke:var(--chartlet-role-green)}#chartlet-00195d7e9e740778 .chartlet-role-amber{fill:var(--chartlet-role-amber-fill);stroke:var(--chartlet-role-amber)}#chartlet-00195d7e9e740778 .chartlet-role-teal{fill:var(--chartlet-role-teal-fill);stroke:var(--chartlet-role-teal)}#chartlet-00195d7e9e740778 .chartlet-role-violet{fill:var(--chartlet-role-violet-fill);stroke:var(--chartlet-role-violet)}#chartlet-00195d7e9e740778 .chartlet-role-gray{fill:var(--chartlet-role-gray-fill);stroke:var(--chartlet-role-gray)}#chartlet-00195d7e9e740778 .chartlet-role-red{fill:var(--chartlet-role-red-fill);stroke:var(--chartlet-role-red)}#chartlet-00195d7e9e740778 .chartlet-diagram-rim{fill:none;stroke:var(--chartlet-role-teal);stroke-width:1.5}#chartlet-00195d7e9e740778 .chartlet-diagram-shadow{fill:var(--chartlet-shadow);stroke:none;rx:7px}#chartlet-00195d7e9e740778 .chartlet-diagram-chip{fill:var(--chartlet-background);stroke:var(--chartlet-grid);stroke-width:1;rx:4px}#chartlet-00195d7e9e740778 .chartlet-diagram-chip-text{font-size:12px;fill:var(--chartlet-text)}#chartlet-00195d7e9e740778 .chartlet-diagram-badge{fill:var(--chartlet-accent);stroke:var(--chartlet-background);stroke-width:2}#chartlet-00195d7e9e740778 .chartlet-diagram-badge-text{font-size:10px;font-weight:700;fill:var(--chartlet-background)}#chartlet-00195d7e9e740778 .chartlet-flow-node{stroke-width:1.5;stroke-linejoin:round;rx:7px}#chartlet-00195d7e9e740778 .chartlet-flow-start{stroke-width:2}#chartlet-00195d7e9e740778 .chartlet-flow-end{stroke-width:3}#chartlet-00195d7e9e740778 .chartlet-flow-external{stroke-dasharray:5 3}#chartlet-00195d7e9e740778 .chartlet-flow-inner{stroke:var(--chartlet-role-blue);stroke-width:1}#chartlet-00195d7e9e740778 .chartlet-flow-label{font-size:13px;font-weight:600;fill:var(--chartlet-text)}#chartlet-00195d7e9e740778 .chartlet-flow-sublabel{font-size:11px;fill:var(--chartlet-muted)}#chartlet-00195d7e9e740778 .chartlet-flow-edge{fill:none;stroke:var(--chartlet-zero);stroke-width:1.4;stroke-linejoin:round}#chartlet-00195d7e9e740778 .chartlet-flow-dashed{stroke-dasharray:5 4}#chartlet-00195d7e9e740778 .chartlet-flow-dotted{stroke-dasharray:1 4;stroke-linecap:round}#chartlet-00195d7e9e740778 .chartlet-flow-main{stroke:var(--chartlet-accent);stroke-width:2.2}#chartlet-00195d7e9e740778 .chartlet-flow-head{fill:var(--chartlet-zero);stroke:var(--chartlet-zero);stroke-width:1;stroke-linejoin:round}#chartlet-00195d7e9e740778 .chartlet-flow-main-head{fill:var(--chartlet-accent);stroke:var(--chartlet-accent)}#chartlet-00195d7e9e740778 .chartlet-flow-lane{fill:var(--chartlet-lane);stroke:var(--chartlet-grid);stroke-width:1}#chartlet-00195d7e9e740778 .chartlet-flow-lane-alt{fill:var(--chartlet-background)}#chartlet-00195d7e9e740778 .chartlet-flow-lane-head{fill:var(--chartlet-lane-head);stroke:none}#chartlet-00195d7e9e740778 .chartlet-flow-lane-label{font-size:11px;font-weight:650;fill:var(--chartlet-muted);letter-spacing:.04em}#chartlet-00195d7e9e740778 .chartlet-flow-group{fill:var(--chartlet-accent);fill-opacity:.04;stroke:var(--chartlet-zero);stroke-width:1;stroke-dasharray:4 3;rx:10px}#chartlet-00195d7e9e740778 .chartlet-flow-group-label{font-size:11px;font-weight:600;fill:var(--chartlet-muted)}#chartlet-00195d7e9e740778 .chartlet-arch-head{fill:var(--chartlet-role-violet-fill);stroke:var(--chartlet-role-violet);stroke-width:1.5}#chartlet-00195d7e9e740778 .chartlet-arch-dot{fill:var(--chartlet-role-blue);stroke:none}#chartlet-00195d7e9e740778 .chartlet-arch-symbol{fill:none;stroke:var(--chartlet-muted);stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}</style><defs><symbol id="chartlet-00195d7e9e740778-symbol-load-balancer" viewBox="0 0 24 24"><path d="M3 12h5M8 12l4-6h7M8 12h11M8 12l4 6h7M17 4l2 2-2 2M17 10l2 2-2 2M17 16l2 2-2 2"/></symbol></defs><g class="chartlet-f chartlet-f-0 chartlet-f-1"><polyline points="500,60 500,144" class="chartlet-flow-edge"><title>Shop front end → Load balancer: places orders [HTTPS]</title></polyline><polyline points="496.5,144 500,152 503.5,144 496.5,144" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-f-1 chartlet-f-2"><polyline points="500,210 500,294" class="chartlet-flow-edge"><title>Load balancer → Orders API: routes [HTTP]</title></polyline><polyline points="496.5,294 500,302 503.5,294 496.5,294" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-f-2 chartlet-f-3"><polyline points="500,352 500,436" class="chartlet-flow-edge"><title>Orders API → Orders: reads, writes [SQL]</title></polyline><polyline points="496.5,436 500,444 503.5,436 496.5,436" class="chartlet-flow-head"/></g><g class="chartlet-f chartlet-n-0 chartlet-f-0 chartlet-f-1"></g><g class="chartlet-f chartlet-n-1 chartlet-f-0 chartlet-f-1 chartlet-f-2"></g><g class="chartlet-f chartlet-n-2 chartlet-f-1 chartlet-f-2 chartlet-f-3"></g><g class="chartlet-f chartlet-n-3 chartlet-f-2 chartlet-f-3"></g><g class="chartlet-f chartlet-f-0 chartlet-f-1"><rect x="504" y="65" width="91.36" height="36" class="chartlet-diagram-chip"/><text x="509" y="79" text-anchor="start" class="chartlet-diagram-chip-text">places orders</text><text x="509" y="94" text-anchor="start" class="chartlet-diagram-chip-text">[HTTPS]</text></g><g class="chartlet-f chartlet-f-1 chartlet-f-2"><rect x="504" y="215" width="55.6" height="36" class="chartlet-diagram-chip"/><text x="509" y="229" text-anchor="start" class="chartlet-diagram-chip-text">routes</text><text x="509" y="244" text-anchor="start" class="chartlet-diagram-chip-text">[HTTP]</text></g><g class="chartlet-f chartlet-f-2 chartlet-f-3"><rect x="504" y="357" width="92.32" height="36" class="chartlet-diagram-chip"/><text x="509" y="371" text-anchor="start" class="chartlet-diagram-chip-text">reads, writes</text><text x="509" y="386" text-anchor="start" class="chartlet-diagram-chip-text">[SQL]</text></g><g class="chartlet-f chartlet-n-0 chartlet-f-0 chartlet-f-1"><rect x="439.445" y="14.5" width="121.11" height="48" class="chartlet-diagram-shadow"/><rect x="439.445" y="12" width="121.11" height="48" class="chartlet-flow-node chartlet-role-blue"><title>Shop front end</title></rect><line x1="439.445" y1="24" x2="560.555" y2="24" class="chartlet-flow-inner"/><circle cx="447.445" cy="18" r="1.8" class="chartlet-arch-dot"/><circle cx="453.445" cy="18" r="1.8" class="chartlet-arch-dot"/><circle cx="459.445" cy="18" r="1.8" class="chartlet-arch-dot"/><text x="500" y="46.5" text-anchor="middle" class="chartlet-flow-label">Shop front end</text></g><g class="chartlet-f chartlet-n-1 chartlet-f-0 chartlet-f-1 chartlet-f-2"><rect x="443.215" y="154.5" width="113.57" height="58" class="chartlet-diagram-shadow"/><rect x="443.215" y="152" width="113.57" height="58" class="chartlet-flow-node chartlet-role-blue"><title>Load balancer</title></rect><use href="#chartlet-00195d7e9e740778-symbol-load-balancer" x="491" y="164.5" width="18" height="18" class="chartlet-arch-symbol"/><text x="500" y="196.5" text-anchor="middle" class="chartlet-flow-label">Load balancer</text></g><g class="chartlet-f chartlet-n-2 chartlet-f-1 chartlet-f-2 chartlet-f-3"><rect x="448" y="304.5" width="104" height="50" class="chartlet-diagram-shadow"/><rect x="448" y="302" width="104" height="50" class="chartlet-flow-node chartlet-role-blue"><title>Orders API – Node.js</title></rect><text x="500" y="324.5" text-anchor="middle" class="chartlet-flow-label">Orders API</text><text x="500" y="338.5" text-anchor="middle" class="chartlet-flow-sublabel">Node.js</text></g><g class="chartlet-f chartlet-n-3 chartlet-f-2 chartlet-f-3"><polyline points="448,451.5 448,501.5 449.772,502.794 454.967,504 463.23,505.036 474,505.83 486.541,506.33 500,506.5 513.459,506.33 526,505.83 536.77,505.036 545.033,504 550.228,502.794 552,501.5 552,451.5 550.228,450.206 545.033,449 536.77,447.964 526,447.17 513.459,446.67 500,446.5 486.541,446.67 474,447.17 463.23,447.964 454.967,449 449.772,450.206 448,451.5 448,451.5" class="chartlet-diagram-shadow"/><polyline points="448,449 448,499 449.772,500.294 454.967,501.5 463.23,502.536 474,503.33 486.541,503.83 500,504 513.459,503.83 526,503.33 536.77,502.536 545.033,501.5 550.228,500.294 552,499 552,449 550.228,447.706 545.033,446.5 536.77,445.464 526,444.67 513.459,444.17 500,444 486.541,444.17 474,444.67 463.23,445.464 454.967,446.5 449.772,447.706 448,449 448,449" class="chartlet-flow-node chartlet-role-teal"><title>Orders – Postgres</title></polyline><polyline points="448,449 449.772,450.294 454.967,451.5 463.23,452.536 474,453.33 486.541,453.83 500,454 513.459,453.83 526,453.33 536.77,452.536 545.033,451.5 550.228,450.294 552,449" class="chartlet-diagram-rim"/><text x="500" y="474.5" text-anchor="middle" class="chartlet-flow-label">Orders</text><text x="500" y="488.5" text-anchor="middle" class="chartlet-flow-sublabel">Postgres</text></g></svg><label class="chartlet-hotspot" id="chartlet-00195d7e9e740778-hs-0" for="chartlet-00195d7e9e740778-focus-0"></label><label class="chartlet-hotspot" id="chartlet-00195d7e9e740778-hs-1" for="chartlet-00195d7e9e740778-focus-1"></label><label class="chartlet-hotspot" id="chartlet-00195d7e9e740778-hs-2" for="chartlet-00195d7e9e740778-focus-2"></label><label class="chartlet-hotspot" id="chartlet-00195d7e9e740778-hs-3" for="chartlet-00195d7e9e740778-focus-3"></label></div><p class="chartlet-source">Source: Operations handbook, orders model</p><details class="chartlet-data" data-viz-text><summary>Show chart data</summary><table><caption>Data for Orders API: components</caption><thead><tr><th scope="col">Component</th><th scope="col">Kind</th><th scope="col">Connects to</th></tr></thead><tbody><tr><th scope="row">Shop front end</th><td>frontend</td><td>Load balancer (places orders, via HTTPS)</td></tr><tr><th scope="row">Load balancer</th><td>service, load balancer</td><td>Orders API (routes, via HTTP)</td></tr><tr><th scope="row">Orders API</th><td>service</td><td>Orders (reads, writes, via SQL)</td></tr><tr><th scope="row">Orders</th><td>database</td><td></td></tr></tbody></table></details></figure></div>