Skip to content

Commit 9b5fa97

Browse files
committed
lindy post
1 parent 1f79f1e commit 9b5fa97

4 files changed

Lines changed: 366 additions & 1 deletion

File tree

components/mdx/figures.tsx

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4038,3 +4038,183 @@ export function AeonGapFigure() {
40384038
</svg>
40394039
);
40404040
}
4041+
4042+
/** Lindy architecture — push email core surrounded by polling integrations. */
4043+
export function LindyArchFigure() {
4044+
return (
4045+
<svg viewBox="0 0 320 320" className="w-full" role="img" aria-labelledby="lindy-arch-title">
4046+
<title id="lindy-arch-title">Lindy architecture: push-based email core with polling integrations around it</title>
4047+
<defs>
4048+
<radialGradient id="lindy-core-grad" cx="50%" cy="45%" r="30%">
4049+
<stop offset="0%" stopColor={C.rose} stopOpacity="0.5" />
4050+
<stop offset="100%" stopColor={C.rose} stopOpacity="0.1" />
4051+
</radialGradient>
4052+
</defs>
4053+
{/* Central push core */}
4054+
<circle cx="160" cy="145" r="55" fill="url(#lindy-core-grad)" />
4055+
<circle cx="160" cy="145" r="55" fill="none" stroke={C.ink} strokeWidth="1.5" />
4056+
{/* Envelope icon */}
4057+
<rect x="140" y="130" width="40" height="28" rx="3" fill="none" stroke={C.ink} strokeWidth="1.4" />
4058+
<path d="M140 130 L160 148 L200 130" fill="none" stroke={C.ink} strokeWidth="1.4" strokeLinejoin="round" />
4059+
<text x="160" y="175" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="8" fill={C.ink}>push</text>
4060+
{/* Lightning bolt for real-time */}
4061+
<path d="M155 118 L159 126 L153 126 L157 134" fill="none" stroke={C.terracotta} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
4062+
{/* Outer polling ring */}
4063+
<circle cx="160" cy="145" r="110" fill="none" stroke={C.rule} strokeWidth="1" strokeDasharray="6 4" />
4064+
{/* Polling integration nodes */}
4065+
{[
4066+
{ label: "Notion", angle: -60 },
4067+
{ label: "Confluence", angle: -20 },
4068+
{ label: "Slack", angle: 20 },
4069+
{ label: "HubSpot", angle: 60 },
4070+
].map(({ label, angle }, i) => {
4071+
const rad = ((angle - 90) * Math.PI) / 180;
4072+
const x = 160 + Math.cos(rad) * 110;
4073+
const y = 145 + Math.sin(rad) * 110;
4074+
return (
4075+
<g key={i}>
4076+
<circle cx={x} cy={y} r="18" fill={C.butter} opacity="0.4" />
4077+
<circle cx={x} cy={y} r="18" fill="none" stroke={C.ink} strokeWidth="1.2" />
4078+
<text x={x} y={y + 3} textAnchor="middle" fontFamily="var(--font-mono)" fontSize="6.5" fill={C.ink}>{label}</text>
4079+
{/* Dashed line to core — poll */}
4080+
<line x1={x + (160 - x) * 0.18} y1={y + (145 - y) * 0.18} x2={160 + (x - 160) * 0.5} y2={145 + (y - 145) * 0.5} stroke={C.faint} strokeWidth="0.9" strokeDasharray="3 3" />
4081+
</g>
4082+
);
4083+
})}
4084+
{/* iMessage delivery arrow going down */}
4085+
<path d="M160 200 L160 265" stroke={C.ink} strokeWidth="1.4" fill="none" />
4086+
<path d="M155 260 L160 268 L165 260" fill="none" stroke={C.ink} strokeWidth="1.4" strokeLinejoin="round" />
4087+
{/* Phone icon */}
4088+
<rect x="148" y="270" width="24" height="36" rx="4" fill="none" stroke={C.ink} strokeWidth="1.3" />
4089+
<line x1="155" y1="298" x2="165" y2="298" stroke={C.ink} strokeWidth="1" strokeLinecap="round" />
4090+
<text x="160" y="318" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.faint}>iMessage</text>
4091+
<text x="280" y="50" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7.5" fill={C.faint}>poll every 10–15 min</text>
4092+
<path d="M265 53 L275 60" stroke={C.faint} strokeWidth="0.7" strokeDasharray="2 2" />
4093+
</svg>
4094+
);
4095+
}
4096+
4097+
/** Lindy polling trigger — clock ticking with a configurable interval field. */
4098+
export function LindyPollFigure() {
4099+
return (
4100+
<svg viewBox="0 0 320 320" className="w-full" role="img" aria-labelledby="lindy-poll-title">
4101+
<title id="lindy-poll-title">Lindy polling triggers: configurable intervals mask a poll-based architecture</title>
4102+
{/* Two trigger cards side by side */}
4103+
{/* Left card: Email — push */}
4104+
<rect x="20" y="30" width="125" height="140" rx="8" fill={C.sage} opacity="0.15" />
4105+
<rect x="20" y="30" width="125" height="140" rx="8" fill="none" stroke={C.ink} strokeWidth="1.4" />
4106+
<text x="82" y="55" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="9" fill={C.ink}>Gmail trigger</text>
4107+
{/* Lightning bolt */}
4108+
<path d="M75 70 L82 85 L72 85 L79 100" fill="none" stroke={C.moss} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
4109+
<text x="82" y="120" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="8" fill={C.moss}>push-based</text>
4110+
<text x="82" y="135" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.faint}>Pub/Sub</text>
4111+
<text x="82" y="150" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.faint}>fires instantly</text>
4112+
{/* Right card: Confluence — poll */}
4113+
<rect x="175" y="30" width="125" height="140" rx="8" fill={C.butter} opacity="0.15" />
4114+
<rect x="175" y="30" width="125" height="140" rx="8" fill="none" stroke={C.ink} strokeWidth="1.4" />
4115+
<text x="237" y="55" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="9" fill={C.ink}>Confluence trigger</text>
4116+
{/* Clock icon */}
4117+
<circle cx="237" cy="82" r="14" fill="none" stroke={C.terracotta} strokeWidth="1.5" />
4118+
<line x1="237" y1="82" x2="237" y2="73" stroke={C.terracotta} strokeWidth="1.5" strokeLinecap="round" />
4119+
<line x1="237" y1="82" x2="244" y2="85" stroke={C.terracotta} strokeWidth="1.2" strokeLinecap="round" />
4120+
<text x="237" y="120" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="8" fill={C.terracotta}>poll-based</text>
4121+
<text x="237" y="135" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.faint}>every 900s</text>
4122+
<text x="237" y="150" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.faint}>≈ 15 min delay</text>
4123+
{/* Divider */}
4124+
<line x1="160" y1="45" x2="160" y2="155" stroke={C.rule} strokeWidth="1" strokeDasharray="4 3" />
4125+
{/* Bottom: same UI, different architecture */}
4126+
<rect x="40" y="200" width="240" height="65" rx="6" fill={C.paper} stroke={C.rule} strokeWidth="1" />
4127+
<text x="160" y="222" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="8.5" fill={C.ink}>Agent Builder UI</text>
4128+
<text x="160" y="238" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7.5" fill={C.faint}>same interface, different latency</text>
4129+
<text x="160" y="252" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7.5" fill={C.faint}>user sees no distinction</text>
4130+
{/* Arrows from cards to UI */}
4131+
<path d="M82 170 L82 200" stroke={C.ink} strokeWidth="0.9" strokeDasharray="3 3" />
4132+
<path d="M237 170 L237 200" stroke={C.ink} strokeWidth="0.9" strokeDasharray="3 3" />
4133+
<text x="160" y="292" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="8" fill={C.terracotta}>
4134+
uniform UX hides the latency gap
4135+
</text>
4136+
</svg>
4137+
);
4138+
}
4139+
4140+
/** Lindy scorecard — three primitives with fill levels. */
4141+
export function LindyScorecardFigure() {
4142+
return (
4143+
<svg viewBox="0 0 320 320" className="w-full" role="img" aria-labelledby="lindy-score-title">
4144+
<title id="lindy-score-title">Lindy scorecard: clock full, listener half, inbox full</title>
4145+
{/* Three vertical bars */}
4146+
{[
4147+
{ label: "clock", fill: 1.0, color: C.sage, status: "✓" },
4148+
{ label: "listener", fill: 0.55, color: C.butter, status: "~" },
4149+
{ label: "inbox", fill: 1.0, color: C.rose, status: "✓" },
4150+
].map(({ label, fill, color, status }, i) => {
4151+
const x = 55 + i * 90;
4152+
const barH = 160;
4153+
const barY = 60;
4154+
const fillH = barH * fill;
4155+
return (
4156+
<g key={i}>
4157+
{/* Bar background */}
4158+
<rect x={x} y={barY} width="50" height={barH} rx="6" fill={C.rule} opacity="0.3" />
4159+
<rect x={x} y={barY} width="50" height={barH} rx="6" fill="none" stroke={C.ink} strokeWidth="1.3" />
4160+
{/* Fill from bottom */}
4161+
<rect x={x + 3} y={barY + barH - fillH + 3} width="44" height={fillH - 6} rx="4" fill={color} opacity="0.5" />
4162+
{/* Status badge */}
4163+
<circle cx={x + 25} cy={barY + 20} r="10" fill={fill >= 1 ? C.sage : C.butter} opacity="0.6" />
4164+
<text x={x + 25} y={barY + 24} textAnchor="middle" fontFamily="var(--font-mono)" fontSize="11" fill={C.ink}>{status}</text>
4165+
{/* Label */}
4166+
<text x={x + 25} y={barY + barH + 22} textAnchor="middle" fontFamily="var(--font-mono)" fontSize="9" fill={C.ink}>{label}</text>
4167+
</g>
4168+
);
4169+
})}
4170+
{/* Annotation for listener */}
4171+
<text x="160" y="270" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7.5" fill={C.faint}>
4172+
email: push · everything else: poll
4173+
</text>
4174+
<text x="160" y="300" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="9" fill={C.terracotta}>
4175+
≈ 2.5 / 3
4176+
</text>
4177+
</svg>
4178+
);
4179+
}
4180+
4181+
/** Lindy tradeoff — consumer polish on one side, infrastructure depth on the other. */
4182+
export function LindyTradeoffFigure() {
4183+
return (
4184+
<svg viewBox="0 0 320 320" className="w-full" role="img" aria-labelledby="lindy-trade-title">
4185+
<title id="lindy-trade-title">Lindy tradeoff: consumer polish versus infrastructure depth</title>
4186+
{/* Balance beam */}
4187+
<circle cx="160" cy="170" r="6" fill={C.ink} />
4188+
<line x1="160" y1="170" x2="160" y2="240" stroke={C.ink} strokeWidth="2" />
4189+
<rect x="130" y="240" width="60" height="8" rx="3" fill={C.ink} />
4190+
{/* Beam — tilted left (consumer polish heavier) */}
4191+
<line x1="50" y1="140" x2="270" y2="160" stroke={C.ink} strokeWidth="2" strokeLinecap="round" />
4192+
{/* Left pan — Consumer polish (lower = heavier) */}
4193+
<line x1="50" y1="140" x2="50" y2="145" stroke={C.ink} strokeWidth="1.2" />
4194+
<path d="M20 145 Q50 160 80 145" fill="none" stroke={C.ink} strokeWidth="1.4" />
4195+
<rect x="22" y="105" width="56" height="32" rx="5" fill={C.rose} opacity="0.3" />
4196+
<rect x="22" y="105" width="56" height="32" rx="5" fill="none" stroke={C.ink} strokeWidth="1" />
4197+
<text x="50" y="118" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.ink}>consumer</text>
4198+
<text x="50" y="130" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.ink}>polish</text>
4199+
{/* Right pan — Infrastructure depth (higher = lighter) */}
4200+
<line x1="270" y1="160" x2="270" y2="165" stroke={C.ink} strokeWidth="1.2" />
4201+
<path d="M240 165 Q270 180 300 165" fill="none" stroke={C.ink} strokeWidth="1.4" />
4202+
<rect x="242" y="125" width="56" height="32" rx="5" fill={C.lavender} opacity="0.3" />
4203+
<rect x="242" y="125" width="56" height="32" rx="5" fill="none" stroke={C.ink} strokeWidth="1" />
4204+
<text x="270" y="138" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.ink}>infra</text>
4205+
<text x="270" y="150" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.ink}>depth</text>
4206+
{/* Annotations */}
4207+
<text x="50" y="80" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.faint}>iMessage, onboarding</text>
4208+
<text x="50" y="91" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.faint}>2,500 integrations</text>
4209+
<text x="270" y="105" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.faint}>state opacity</text>
4210+
<text x="270" y="116" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7" fill={C.faint}>scoped auth gap</text>
4211+
{/* Bottom label */}
4212+
<text x="160" y="280" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="8" fill={C.terracotta}>
4213+
Lindy chose polish first, infrastructure second
4214+
</text>
4215+
<text x="160" y="296" textAnchor="middle" fontFamily="var(--font-mono)" fontSize="7.5" fill={C.faint}>
4216+
right call for the target user
4217+
</text>
4218+
</svg>
4219+
);
4220+
}

components/mdx/mdx-components.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ import {
8181
AeonArchFigure,
8282
AeonHealFigure,
8383
AeonGapFigure,
84+
LindyArchFigure,
85+
LindyPollFigure,
86+
LindyScorecardFigure,
87+
LindyTradeoffFigure,
8488
} from "./figures";
8589

8690
export const mdxComponents = {
@@ -167,6 +171,10 @@ export const mdxComponents = {
167171
AeonArchFigure,
168172
AeonHealFigure,
169173
AeonGapFigure,
174+
LindyArchFigure,
175+
LindyPollFigure,
176+
LindyScorecardFigure,
177+
LindyTradeoffFigure,
170178
LinkedInEmbed: () => (
171179
<iframe
172180
src="https://www.linkedin.com/embed/feed/update/urn:li:share:7429634994467414016?collapsed=1"

0 commit comments

Comments
 (0)