| Server IP : 35.80.110.71 / Your IP : 216.73.216.221 Web Server : Apache/2.4.58 (Ubuntu) System : Linux ip-172-31-21-44 6.17.0-1019-aws #19~24.04.1-Ubuntu SMP Tue Jun 23 18:53:06 UTC 2026 x86_64 User : ubuntu ( 1000) PHP Version : 8.3.31 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/splitstream-web/.next/server/app/ |
Upload File : |
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/002zte3riz0h6.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/2xx73w8k5o69w.js"/><script src="/_next/static/chunks/0_bmh1s0g_5m3.js" async=""></script><script src="/_next/static/chunks/390e59xl7grtx.js" async=""></script><script src="/_next/static/chunks/3ss6b_eo0gpqh.js" async=""></script><script src="/_next/static/chunks/turbopack-0frl60onblppy.js" async=""></script><script src="/_next/static/chunks/3u-4v10_yuvs8.js" async=""></script><script src="/_next/static/chunks/31jk64s9j6agx.js" async=""></script><link rel="preload" href="https://www.googletagmanager.com/gtag/js?id=G-HZ8Z4XP611" as="script"/><title>SDKs — Splitstream</title><meta name="description" content="Production-shaped A/B testing platform: sticky bucketing, mutex experiment groups, Sample Ratio Mismatch detection, guardrail metrics, an Octane carve-out for the hot path, and a Bayesian stats engine whose decision rule is empirically calibrated — not asserted."/><script src="/_next/static/chunks/0cz1d0mv5g_q7.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><header class="border-b border-(--color-paper-dim) bg-(--color-paper)"><div class="mx-auto flex max-w-6xl items-center justify-between px-6 py-5"><a class="text-lg font-bold tracking-tight text-(--color-ink) no-underline" href="/">Splitstream<span class="ml-2 rounded-full bg-(--color-accent-soft) px-2 py-0.5 text-xs font-medium text-(--color-accent) align-middle">portfolio demo</span></a><nav class="hidden md:flex items-center gap-5 text-sm text-(--color-ink-dim)"><a href="/docs">Docs</a><a href="/reference">API reference</a><a href="/sdks">SDKs</a><a href="/bucketing">Bucketing</a><a href="/stats-playground">Stats playground</a><a href="/with-pennant">With Pennant</a><a href="/about">About</a></nav><button type="button" aria-label="Open menu" aria-expanded="false" aria-controls="site-mobile-nav" class="md:hidden inline-flex items-center justify-center rounded-md border border-(--color-paper-dim) p-2 text-(--color-ink) cursor-pointer"><svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg></button></div></header><main class="mx-auto max-w-6xl px-6 py-10"><div class="space-y-10"><section><h1 class="text-3xl font-bold">SDKs</h1><p class="mt-3 max-w-2xl text-(--color-ink-dim)">Five SDK packages in v0.1 — TypeScript, React, PHP (Laravel-ready), Python (Django + FastAPI), and the growth umbrella. Every SDK that ships a port of the bucketing function round-trips the same<!-- --> <a href="/docs/concepts/bucketing">corpus</a> in CI. Drift is a build failure.</p></section><section class="space-y-6"><div class="rounded-lg border border-(--color-paper-dim) p-6"><div class="flex flex-wrap items-baseline justify-between gap-4"><h2 class="text-xl font-bold font-(--font-mono)">@philiprehberger/splitstream</h2><a href="https://github.com/philiprehberger/splitstream/tree/main/sdks/typescript" class="text-sm">Source ↗</a></div><p class="mt-3 text-sm text-(--color-ink-dim)">TypeScript core client. Sticky-assignment cache, buffered tracking, runs in Node or the browser. Pure-TS SHA-256 keeps bucket() synchronous everywhere.</p><pre class="mt-4 text-[13px]"><code>npm install @philiprehberger/splitstream</code></pre><div class="mt-4 flex flex-wrap gap-x-6 gap-y-2 text-xs text-(--color-ink-dim)"><span><strong class="text-(--color-ink)">Bundle:</strong> <!-- -->11.6 KB ESM</span><span><strong class="text-(--color-ink)">Tests:</strong> <!-- -->11 vitest tests · bucketing corpus drift catcher</span></div></div><div class="rounded-lg border border-(--color-paper-dim) p-6"><div class="flex flex-wrap items-baseline justify-between gap-4"><h2 class="text-xl font-bold font-(--font-mono)">@philiprehberger/splitstream-react</h2><a href="https://github.com/philiprehberger/splitstream/tree/main/sdks/react" class="text-sm">Source ↗</a></div><p class="mt-3 text-sm text-(--color-ink-dim)">React adapter — SplitstreamProvider + useExperiment hook with per-experiment subscription (changing one experiment’s variant doesn’t re-render the others).</p><pre class="mt-4 text-[13px]"><code>npm install @philiprehberger/splitstream-react</code></pre><div class="mt-4 flex flex-wrap gap-x-6 gap-y-2 text-xs text-(--color-ink-dim)"><span><strong class="text-(--color-ink)">Bundle:</strong> <!-- -->1.4 KB ESM</span><span><strong class="text-(--color-ink)">Tests:</strong> <!-- -->typecheck-clean, peer dep on react>=18</span></div></div><div class="rounded-lg border border-(--color-paper-dim) p-6"><div class="flex flex-wrap items-baseline justify-between gap-4"><h2 class="text-xl font-bold font-(--font-mono)">@philiprehberger/growth</h2><a href="https://github.com/philiprehberger/splitstream/tree/main/sdks/growth" class="text-sm">Source ↗</a></div><p class="mt-3 text-sm text-(--color-ink-dim)">Umbrella for Pennant + Splitstream. Reads the Pennant kill-switch flag, gates Splitstream.assign() if on. Same five-line shape on both docs sites.</p><pre class="mt-4 text-[13px]"><code>npm install @philiprehberger/growth</code></pre><div class="mt-4 flex flex-wrap gap-x-6 gap-y-2 text-xs text-(--color-ink-dim)"><span><strong class="text-(--color-ink)">Bundle:</strong> <!-- -->3.6 KB ESM + /react 0.6 KB</span><span><strong class="text-(--color-ink)">Tests:</strong> <!-- -->9 vitest tests</span></div></div><div class="rounded-lg border border-(--color-paper-dim) p-6"><div class="flex flex-wrap items-baseline justify-between gap-4"><h2 class="text-xl font-bold font-(--font-mono)">philiprehberger/splitstream (Packagist)</h2><a href="https://github.com/philiprehberger/splitstream/tree/main/sdks/php" class="text-sm">Source ↗</a></div><p class="mt-3 text-sm text-(--color-ink-dim)">PHP SDK with Laravel service provider, Splitstream facade, @experiment Blade directive. Session-backed sticky cache via LaravelSessionStorage.</p><pre class="mt-4 text-[13px]"><code>composer require philiprehberger/splitstream</code></pre><div class="mt-4 flex flex-wrap gap-x-6 gap-y-2 text-xs text-(--color-ink-dim)"><span><strong class="text-(--color-ink)">Bundle:</strong> <!-- -->Guzzle-backed; ext-intl + ext-curl</span><span><strong class="text-(--color-ink)">Tests:</strong> <!-- -->9 PHPUnit tests, 332 assertions</span></div></div><div class="rounded-lg border border-(--color-paper-dim) p-6"><div class="flex flex-wrap items-baseline justify-between gap-4"><h2 class="text-xl font-bold font-(--font-mono)">splitstream-sdk (PyPI)</h2><a href="https://github.com/philiprehberger/splitstream/tree/main/sdks/python" class="text-sm">Source ↗</a></div><p class="mt-3 text-sm text-(--color-ink-dim)">Python SDK with optional Django middleware and FastAPI dependency factory. Thread-safe via threading.Lock. Context-manager support.</p><pre class="mt-4 text-[13px]"><code>pip install splitstream-sdk</code></pre><div class="mt-4 flex flex-wrap gap-x-6 gap-y-2 text-xs text-(--color-ink-dim)"><span><strong class="text-(--color-ink)">Bundle:</strong> <!-- -->httpx-backed; pure Python</span><span><strong class="text-(--color-ink)">Tests:</strong> <!-- -->10 pytest tests</span></div></div></section><section class="rounded-lg border border-(--color-paper-dim) p-6"><h2 class="text-xl font-bold">v2 SDK roadmap</h2><p class="mt-2 text-sm text-(--color-ink-dim)">Vue 3, Svelte, Go, and Mobile (iOS / Android) SDKs are deferred to v2 — same posture as Pennant. The bucketing corpus is the machine-checkable contract; whichever language ports next inherits it.</p></section></div><!--$--><!--/$--></main><footer class="border-t border-(--color-paper-dim) mt-20"><div class="mx-auto flex max-w-6xl items-center justify-between px-6 py-8 text-sm text-(--color-ink-dim)"><div>Splitstream is a portfolio demonstration by<!-- --> <a href="https://philiprehberger.com">Philip Rehberger</a>.</div><div class="flex flex-wrap gap-4"><a href="https://github.com/philiprehberger/splitstream">GitHub</a><a href="/pricing">Pricing</a><a href="/downloads">Downloads</a><a href="/status">Status</a><a href="/about">About this demo</a></div></div></footer><script src="/_next/static/chunks/2xx73w8k5o69w.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[79404,[\"/_next/static/chunks/3u-4v10_yuvs8.js\",\"/_next/static/chunks/31jk64s9j6agx.js\"],\"default\"]\n3:I[88287,[\"/_next/static/chunks/3u-4v10_yuvs8.js\",\"/_next/static/chunks/31jk64s9j6agx.js\"],\"default\"]\n4:I[74895,[\"/_next/static/chunks/3u-4v10_yuvs8.js\",\"/_next/static/chunks/31jk64s9j6agx.js\"],\"default\"]\n5:I[4561,[\"/_next/static/chunks/3u-4v10_yuvs8.js\",\"/_next/static/chunks/31jk64s9j6agx.js\"],\"\"]\n6:I[70805,[\"/_next/static/chunks/3u-4v10_yuvs8.js\",\"/_next/static/chunks/31jk64s9j6agx.js\"],\"default\"]\n10:I[52576,[\"/_next/static/chunks/3u-4v10_yuvs8.js\",\"/_next/static/chunks/31jk64s9j6agx.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/002zte3riz0h6.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"sdks\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"sdks\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/002zte3riz0h6.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/3u-4v10_yuvs8.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/31jk64s9j6agx.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"children\":[[\"$\",\"$L2\",null,{}],[\"$\",\"main\",null,{\"className\":\"mx-auto max-w-6xl px-6 py-10\",\"children\":[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}],[\"$\",\"footer\",null,{\"className\":\"border-t border-(--color-paper-dim) mt-20\",\"children\":[\"$\",\"div\",null,{\"className\":\"mx-auto flex max-w-6xl items-center justify-between px-6 py-8 text-sm text-(--color-ink-dim)\",\"children\":[[\"$\",\"div\",null,{\"children\":[\"Splitstream is a portfolio demonstration by\",\" \",[\"$\",\"a\",null,{\"href\":\"https://philiprehberger.com\",\"children\":\"Philip Rehberger\"}],\".\"]}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap gap-4\",\"children\":[[\"$\",\"a\",null,{\"href\":\"https://github.com/philiprehberger/splitstream\",\"children\":\"GitHub\"}],[\"$\",\"$L5\",null,{\"href\":\"/pricing\",\"children\":\"Pricing\"}],[\"$\",\"$L5\",null,{\"href\":\"/downloads\",\"children\":\"Downloads\"}],[\"$\",\"$L5\",null,{\"href\":\"/status\",\"children\":\"Status\"}],[\"$\",\"$L5\",null,{\"href\":\"/about\",\"children\":\"About this demo\"}]]}]]}]}],[\"$\",\"$L6\",null,{}]]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"div\",null,{\"className\":\"space-y-10\",\"children\":[[\"$\",\"section\",null,{\"children\":[[\"$\",\"h1\",null,{\"className\":\"text-3xl font-bold\",\"children\":\"SDKs\"}],[\"$\",\"p\",null,{\"className\":\"mt-3 max-w-2xl text-(--color-ink-dim)\",\"children\":[\"Five SDK packages in v0.1 — TypeScript, React, PHP (Laravel-ready), Python (Django + FastAPI), and the growth umbrella. Every SDK that ships a port of the bucketing function round-trips the same\",\" \",[\"$\",\"$L5\",null,{\"href\":\"/docs/concepts/bucketing\",\"children\":\"corpus\"}],\" in CI. Drift is a build failure.\"]}]]}],[\"$\",\"section\",null,{\"className\":\"space-y-6\",\"children\":[[\"$\",\"div\",\"@philiprehberger/splitstream\",{\"className\":\"rounded-lg border border-(--color-paper-dim) p-6\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-baseline justify-between gap-4\",\"children\":[[\"$\",\"h2\",null,{\"className\":\"text-xl font-bold font-(--font-mono)\",\"children\":\"@philiprehberger/splitstream\"}],[\"$\",\"a\",null,{\"href\":\"https://github.com/philiprehberger/splitstream/tree/main/sdks/typescript\",\"className\":\"text-sm\",\"children\":\"Source ↗\"}]]}],[\"$\",\"p\",null,{\"className\":\"mt-3 text-sm text-(--color-ink-dim)\",\"children\":\"TypeScript core client. Sticky-assignment cache, buffered tracking, runs in Node or the browser. Pure-TS SHA-256 keeps bucket() synchronous everywhere.\"}],[\"$\",\"pre\",null,{\"className\":\"mt-4 text-[13px]\",\"children\":[\"$\",\"code\",null,{\"children\":\"npm install @philiprehberger/splitstream\"}]}],\"$L7\"]}],\"$L8\",\"$L9\",\"$La\",\"$Lb\"]}],\"$Lc\"]}],null,\"$Ld\"]}],{},null,false,null]},null,false,\"$@e\"]},null,false,null],\"$Lf\",false]],\"m\":\"$undefined\",\"G\":[\"$10\",[\"$L11\"]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"d4p1Nsp7dnkNrIm-L0oJl\"}\n"])</script><script>self.__next_f.push([1,"12:I[51858,[\"/_next/static/chunks/3u-4v10_yuvs8.js\",\"/_next/static/chunks/31jk64s9j6agx.js\"],\"OutletBoundary\"]\n13:\"$Sreact.suspense\"\n16:I[51858,[\"/_next/static/chunks/3u-4v10_yuvs8.js\",\"/_next/static/chunks/31jk64s9j6agx.js\"],\"ViewportBoundary\"]\n18:I[51858,[\"/_next/static/chunks/3u-4v10_yuvs8.js\",\"/_next/static/chunks/31jk64s9j6agx.js\"],\"MetadataBoundary\"]\n7:[\"$\",\"div\",null,{\"className\":\"mt-4 flex flex-wrap gap-x-6 gap-y-2 text-xs text-(--color-ink-dim)\",\"children\":[[\"$\",\"span\",null,{\"children\":[[\"$\",\"strong\",null,{\"className\":\"text-(--color-ink)\",\"children\":\"Bundle:\"}],\" \",\"11.6 KB ESM\"]}],[\"$\",\"span\",null,{\"children\":[[\"$\",\"strong\",null,{\"className\":\"text-(--color-ink)\",\"children\":\"Tests:\"}],\" \",\"11 vitest tests · bucketing corpus drift catcher\"]}]]}]\n8:[\"$\",\"div\",\"@philiprehberger/splitstream-react\",{\"className\":\"rounded-lg border border-(--color-paper-dim) p-6\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-baseline justify-between gap-4\",\"children\":[[\"$\",\"h2\",null,{\"className\":\"text-xl font-bold font-(--font-mono)\",\"children\":\"@philiprehberger/splitstream-react\"}],[\"$\",\"a\",null,{\"href\":\"https://github.com/philiprehberger/splitstream/tree/main/sdks/react\",\"className\":\"text-sm\",\"children\":\"Source ↗\"}]]}],[\"$\",\"p\",null,{\"className\":\"mt-3 text-sm text-(--color-ink-dim)\",\"children\":\"React adapter — SplitstreamProvider + useExperiment hook with per-experiment subscription (changing one experiment’s variant doesn’t re-render the others).\"}],[\"$\",\"pre\",null,{\"className\":\"mt-4 text-[13px]\",\"children\":[\"$\",\"code\",null,{\"children\":\"npm install @philiprehberger/splitstream-react\"}]}],[\"$\",\"div\",null,{\"className\":\"mt-4 flex flex-wrap gap-x-6 gap-y-2 text-xs text-(--color-ink-dim)\",\"children\":[[\"$\",\"span\",null,{\"children\":[[\"$\",\"strong\",null,{\"className\":\"text-(--color-ink)\",\"children\":\"Bundle:\"}],\" \",\"1.4 KB ESM\"]}],[\"$\",\"span\",null,{\"children\":[[\"$\",\"strong\",null,{\"className\":\"text-(--color-ink)\",\"children\":\"Tests:\"}],\" \",\"typecheck-clean, peer dep on react\u003e=18\"]}]]}]]}]\n9:[\"$\",\"div\",\"@philiprehberger/growth\",{\"className\":\"rounded-lg border border-(--color-paper-dim) p-6\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-baseline justify-between gap-4\",\"children\":[[\"$\",\"h2\",null,{\"className\":\"text-xl font-bold font-(--font-mono)\",\"children\":\"@philiprehberger/growth\"}],[\"$\",\"a\",null,{\"href\":\"https://github.com/philiprehberger/splitstream/tree/main/sdks/growth\",\"className\":\"text-sm\",\"children\":\"Source ↗\"}]]}],[\"$\",\"p\",null,{\"className\":\"mt-3 text-sm text-(--color-ink-dim)\",\"children\":\"Umbrella for Pennant + Splitstream. Reads the Pennant kill-switch flag, gates Splitstream.assign() if on. Same five-line shape on both docs sites.\"}],[\"$\",\"pre\",null,{\"className\":\"mt-4 text-[13px]\",\"children\":[\"$\",\"code\",null,{\"children\":\"npm install @philiprehberger/growth\"}]}],[\"$\",\"div\",null,{\"className\":\"mt-4 flex flex-wrap gap-x-6 gap-y-2 text-xs text-(--color-ink-dim)\",\"children\":[[\"$\",\"span\",null,{\"children\":[[\"$\",\"strong\",null,{\"className\":\"text-(--color-ink)\",\"children\":\"Bundle:\"}],\" \",\"3.6 KB ESM + /react 0.6 KB\"]}],[\"$\",\"span\",null,{\"children\":[[\"$\",\"strong\",null,{\"className\":\"text-(--color-ink)\",\"children\":\"Tests:\"}],\" \",\"9 vitest tests\"]}]]}]]}]\na:[\"$\",\"div\",\"philiprehberger/splitstream (Packagist)\",{\"className\":\"rounded-lg border border-(--color-paper-dim) p-6\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-baseline justify-between gap-4\",\"children\":[[\"$\",\"h2\",null,{\"className\":\"text-xl font-bold font-(--font-mono)\",\"children\":\"philiprehberger/splitstream (Packagist)\"}],[\"$\",\"a\",null,{\"href\":\"https://github.com/philiprehberger/splitstream/tree/main/sdks/php\",\"className\":\"text-sm\",\"children\":\"Source ↗\"}]]}],[\"$\",\"p\",null,{\"className\":\"mt-3 text-sm text-(--color-ink-dim)\",\"children\":\"PHP SDK with Laravel service provider, Splitstream facade, @experiment Blade directive. Session-backed sticky cache via LaravelSessionStorage.\"}],[\"$\",\"pre\",null,{\"className\":\"mt-4 text-[13px]\",\"children\":[\"$\",\"code\",null,{\"children\":\"composer require philiprehberger/splitstream\"}]}],[\"$\",\"div\",null,{"])</script><script>self.__next_f.push([1,"\"className\":\"mt-4 flex flex-wrap gap-x-6 gap-y-2 text-xs text-(--color-ink-dim)\",\"children\":[[\"$\",\"span\",null,{\"children\":[[\"$\",\"strong\",null,{\"className\":\"text-(--color-ink)\",\"children\":\"Bundle:\"}],\" \",\"Guzzle-backed; ext-intl + ext-curl\"]}],[\"$\",\"span\",null,{\"children\":[[\"$\",\"strong\",null,{\"className\":\"text-(--color-ink)\",\"children\":\"Tests:\"}],\" \",\"9 PHPUnit tests, 332 assertions\"]}]]}]]}]\nb:[\"$\",\"div\",\"splitstream-sdk (PyPI)\",{\"className\":\"rounded-lg border border-(--color-paper-dim) p-6\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex flex-wrap items-baseline justify-between gap-4\",\"children\":[[\"$\",\"h2\",null,{\"className\":\"text-xl font-bold font-(--font-mono)\",\"children\":\"splitstream-sdk (PyPI)\"}],[\"$\",\"a\",null,{\"href\":\"https://github.com/philiprehberger/splitstream/tree/main/sdks/python\",\"className\":\"text-sm\",\"children\":\"Source ↗\"}]]}],[\"$\",\"p\",null,{\"className\":\"mt-3 text-sm text-(--color-ink-dim)\",\"children\":\"Python SDK with optional Django middleware and FastAPI dependency factory. Thread-safe via threading.Lock. Context-manager support.\"}],[\"$\",\"pre\",null,{\"className\":\"mt-4 text-[13px]\",\"children\":[\"$\",\"code\",null,{\"children\":\"pip install splitstream-sdk\"}]}],[\"$\",\"div\",null,{\"className\":\"mt-4 flex flex-wrap gap-x-6 gap-y-2 text-xs text-(--color-ink-dim)\",\"children\":[[\"$\",\"span\",null,{\"children\":[[\"$\",\"strong\",null,{\"className\":\"text-(--color-ink)\",\"children\":\"Bundle:\"}],\" \",\"httpx-backed; pure Python\"]}],[\"$\",\"span\",null,{\"children\":[[\"$\",\"strong\",null,{\"className\":\"text-(--color-ink)\",\"children\":\"Tests:\"}],\" \",\"10 pytest tests\"]}]]}]]}]\nc:[\"$\",\"section\",null,{\"className\":\"rounded-lg border border-(--color-paper-dim) p-6\",\"children\":[[\"$\",\"h2\",null,{\"className\":\"text-xl font-bold\",\"children\":\"v2 SDK roadmap\"}],[\"$\",\"p\",null,{\"className\":\"mt-2 text-sm text-(--color-ink-dim)\",\"children\":\"Vue 3, Svelte, Go, and Mobile (iOS / Android) SDKs are deferred to v2 — same posture as Pennant. The bucketing corpus is the machine-checkable contract; whichever language ports next inherits it.\"}]]}]\nd:[\"$\",\"$L12\",null,{\"children\":[\"$\",\"$13\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@14\"}]}]\n15:[]\ne:\"$W15\"\nf:[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L16\",null,{\"children\":\"$L17\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L18\",null,{\"children\":[\"$\",\"$13\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L19\"}]}]}],null]}]\n11:[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/002zte3riz0h6.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]\n"])</script><script>self.__next_f.push([1,"17:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"14:null\n19:[[\"$\",\"title\",\"0\",{\"children\":\"SDKs — Splitstream\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Production-shaped A/B testing platform: sticky bucketing, mutex experiment groups, Sample Ratio Mismatch detection, guardrail metrics, an Octane carve-out for the hot path, and a Bayesian stats engine whose decision rule is empirically calibrated — not asserted.\"}]]\n"])</script></body></html>