Skip to content

Commit aff9dcf

Browse files
luanvdwankur-arch
andauthored
feat(blog): Compute pricing blog post (#7969)
* feat(blog): add Compute pricing post * feat(blog): polish Compute pricing post * feat(blog): address pricing post feedback * feat(blog): update pricing post preview copy * feat(blog): add pricing post cover image * fix(blog): update pricing post date * Update apps/blog/content/blog/price-the-work-not-the-workflow/index.mdx Co-authored-by: Ankur Datta <64993082+ankur-arch@users.noreply.github.com> * Update apps/blog/content/blog/price-the-work-not-the-workflow/index.mdx Co-authored-by: Ankur Datta <64993082+ankur-arch@users.noreply.github.com> * Update apps/blog/content/blog/price-the-work-not-the-workflow/index.mdx Co-authored-by: Ankur Datta <64993082+ankur-arch@users.noreply.github.com> * feat(blog): polish pricing post close * Update apps/blog/content/blog/price-the-work-not-the-workflow/index.mdx * Update apps/blog/content/blog/price-the-work-not-the-workflow/index.mdx --------- Co-authored-by: Ankur Datta <64993082+ankur-arch@users.noreply.github.com>
1 parent 0c40510 commit aff9dcf

4 files changed

Lines changed: 409 additions & 1 deletion

File tree

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
const LOOP_STEPS = ["intent", "change", "test", "preview", "retry"];
2+
const WORK_METERS = ["Requests", "Memory", "Active CPU", "Outbound data"];
3+
4+
function labelLines(label: string) {
5+
const parts = label.split(" ");
6+
7+
if (parts.length <= 1) return [label];
8+
9+
return [parts.slice(0, -1).join(" "), parts.at(-1) ?? ""];
10+
}
11+
12+
function Box({
13+
x,
14+
y,
15+
width,
16+
label,
17+
dashed = false,
18+
variant = "default",
19+
}: {
20+
x: number;
21+
y: number;
22+
width: number;
23+
label: string;
24+
dashed?: boolean;
25+
variant?: "default" | "meter";
26+
}) {
27+
const lines = labelLines(label);
28+
const meterStyle =
29+
variant === "meter"
30+
? {
31+
fill: "color-mix(in srgb, #6754e8 58%, var(--color-background-default))",
32+
stroke: "color-mix(in srgb, #a99cff 80%, transparent)",
33+
}
34+
: undefined;
35+
36+
return (
37+
<g>
38+
<rect
39+
x={x}
40+
y={y}
41+
width={width}
42+
height={42}
43+
rx={7}
44+
className="seq-box"
45+
strokeDasharray={dashed ? "5 4" : undefined}
46+
style={meterStyle}
47+
/>
48+
{lines.map((line, i) => (
49+
<text
50+
key={line}
51+
x={x + width / 2}
52+
y={y + 21 + (i - (lines.length - 1) / 2) * 12}
53+
textAnchor="middle"
54+
dominantBaseline="central"
55+
className="seq-box-text"
56+
>
57+
{line}
58+
</text>
59+
))}
60+
</g>
61+
);
62+
}
63+
64+
function Arrow({ d, dashed = false }: { d: string; dashed?: boolean }) {
65+
return (
66+
<path
67+
d={d}
68+
fill="none"
69+
markerEnd="url(#work-pricing-arrow)"
70+
className={`seq-arrow${dashed ? " seq-arrow-dashed" : ""}`}
71+
/>
72+
);
73+
}
74+
75+
export function WorkPricingDiagram() {
76+
return (
77+
<figure className="seq-diagram not-prose">
78+
<svg
79+
viewBox="0 0 760 372"
80+
width="100%"
81+
aria-label="The loop is not the bill. The work is. An agent-assisted loop can repeat many times, while observable application work becomes the bill."
82+
role="img"
83+
>
84+
<defs>
85+
<marker
86+
id="work-pricing-arrow"
87+
viewBox="0 0 8 8"
88+
refX="7"
89+
refY="4"
90+
markerWidth="5"
91+
markerHeight="5"
92+
orient="auto"
93+
>
94+
<path d="M0,0 L8,4 L0,8 Z" className="seq-arr-fill" />
95+
</marker>
96+
</defs>
97+
98+
<text x="18" y="28" className="seq-box-text" style={{ fontSize: 16, fontWeight: 700 }}>
99+
The loop is not the bill. The work is.
100+
</text>
101+
102+
<rect
103+
x="18"
104+
y="52"
105+
width="724"
106+
height="142"
107+
rx="10"
108+
className="seq-box"
109+
strokeDasharray="5 4"
110+
/>
111+
112+
<text x="42" y="82" className="seq-box-text" style={{ fontSize: 13, fontWeight: 700 }}>
113+
Agent-assisted loop
114+
</text>
115+
<text x="380" y="108" textAnchor="middle" className="seq-label">
116+
can repeat many times
117+
</text>
118+
119+
{LOOP_STEPS.map((label, i) => (
120+
<Box key={label} x={52 + i * 136} y={126} width={100} label={label} dashed />
121+
))}
122+
123+
{LOOP_STEPS.slice(0, -1).map((label, i) => {
124+
const start = 152 + i * 136;
125+
const end = 188 + i * 136;
126+
127+
return <Arrow key={label} d={`M${start} 147 L${end} 147`} />;
128+
})}
129+
130+
<Arrow d="M616 124 C 566 84, 194 84, 152 124" dashed />
131+
132+
<Arrow d="M380 194 L380 234" dashed />
133+
<text x="402" y="218" className="seq-label">
134+
observable application work becomes the bill
135+
</text>
136+
137+
<text x="18" y="272" className="seq-box-text" style={{ fontSize: 13, fontWeight: 700 }}>
138+
The bill, what the app actually did
139+
</text>
140+
141+
{WORK_METERS.map((label, i) => (
142+
<Box key={label} x={18 + i * 185} y={292} width={150} label={label} variant="meter" />
143+
))}
144+
145+
<text x="18" y="354" className="seq-label">
146+
Run the loop once or a thousand times, the bill counts the same four things.
147+
</text>
148+
</svg>
149+
</figure>
150+
);
151+
}

0 commit comments

Comments
 (0)