| 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 : |
1:"$Sreact.fragment"
2:I[79404,["/_next/static/chunks/3u-4v10_yuvs8.js","/_next/static/chunks/31jk64s9j6agx.js"],"default"]
3:I[88287,["/_next/static/chunks/3u-4v10_yuvs8.js","/_next/static/chunks/31jk64s9j6agx.js"],"default"]
4:I[74895,["/_next/static/chunks/3u-4v10_yuvs8.js","/_next/static/chunks/31jk64s9j6agx.js"],"default"]
5:I[4561,["/_next/static/chunks/3u-4v10_yuvs8.js","/_next/static/chunks/31jk64s9j6agx.js","/_next/static/chunks/04th6t7cqv9wf.js"],""]
6:I[70805,["/_next/static/chunks/3u-4v10_yuvs8.js","/_next/static/chunks/31jk64s9j6agx.js"],"default"]
e:I[52576,["/_next/static/chunks/3u-4v10_yuvs8.js","/_next/static/chunks/31jk64s9j6agx.js"],"default",1]
:HL["/_next/static/chunks/002zte3riz0h6.css","style"]
0:{"P":null,"c":["",""],"q":"","i":false,"f":[[["",{"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":[["$","div",null,{"className":"space-y-20","children":[["$","section",null,{"className":"space-y-6 pt-6","children":[["$","div",null,{"className":"inline-block rounded-full border border-(--color-paper-dim) px-3 py-1 text-xs text-(--color-ink-dim)","children":"A portfolio demonstration · production-shaped, not production-grade"}],["$","h1",null,{"className":"max-w-3xl text-5xl font-bold tracking-tight leading-tight","children":"A/B testing that doesn't lie about the math."}],["$","p",null,{"className":"max-w-2xl text-lg text-(--color-ink-dim)","children":["Splitstream is an experimentation platform with sticky bucketing, mutex experiment groups, Sample Ratio Mismatch detection, guardrail metrics, and a Bayesian stats engine whose decision rule is"," ",["$","em",null,{"children":"empirically calibrated"}],", not asserted. Pair with"," ",["$","$L5",null,{"href":"/with-pennant","className":"underline","children":"Pennant"}]," for the full experimentation stack."]}],["$","div",null,{"className":"flex flex-wrap items-center gap-4 pt-2","children":[["$","$L5",null,{"href":"/docs","className":"rounded-md bg-(--color-accent) px-5 py-2.5 text-sm font-medium text-white no-underline hover:bg-emerald-800","children":"Read the docs"}],["$","$L5",null,{"href":"/reference","className":"rounded-md border border-(--color-paper-dim) px-5 py-2.5 text-sm font-medium text-(--color-ink) no-underline hover:bg-(--color-paper-dim)","children":"API reference"}],["$","a",null,{"href":"https://github.com/philiprehberger/splitstream","className":"text-sm text-(--color-ink-dim)","children":"Source on GitHub →"}]]}]]}],"$L7","$L8","$L9","$La"]}],["$Lb"],"$Lc"]}],{},null,false,null]},null,false,null],"$Ld",false]],"m":"$undefined","G":["$e",["$Lf"]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"d4p1Nsp7dnkNrIm-L0oJl"}
10:I[6437,["/_next/static/chunks/3u-4v10_yuvs8.js","/_next/static/chunks/31jk64s9j6agx.js","/_next/static/chunks/04th6t7cqv9wf.js"],"CodeTabs"]
13:I[51858,["/_next/static/chunks/3u-4v10_yuvs8.js","/_next/static/chunks/31jk64s9j6agx.js"],"OutletBoundary"]
14:"$Sreact.suspense"
16:I[51858,["/_next/static/chunks/3u-4v10_yuvs8.js","/_next/static/chunks/31jk64s9j6agx.js"],"ViewportBoundary"]
18:I[51858,["/_next/static/chunks/3u-4v10_yuvs8.js","/_next/static/chunks/31jk64s9j6agx.js"],"MetadataBoundary"]
7:["$","section",null,{"className":"rounded-lg border border-(--color-paper-dim) bg-(--color-paper) p-8 shadow-sm","children":[["$","h2",null,{"className":"text-2xl font-bold tracking-tight","children":["The plan's draft defaults delivered ",["$","span",null,{"className":"text-(--color-bad)","children":"66% empirical false-positive rate"}],"."]}],["$","p",null,{"className":"mt-4 text-(--color-ink-dim) leading-relaxed","children":["Bayesian threshold-stopping at ",["$","code",null,{"children":"posterior_threshold=0.95"}]," ","isn't safe under continuous peeking. We ran 360,000 null-effect simulations across a 36-cell grid before shipping. The calibrated tuple — the one Splitstream ships as the default — is"," ",["$","code",null,{"children":"0.995 / 20,000 / 240 min"}],", which lands at"," ",["$","strong",null,{"className":"text-(--color-good)","children":"4.77% empirical FP."}]," ","The calibration is what lets the docs claim the math is right."]}],["$","div",null,{"className":"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-4","children":[["$","div","Original draft",{"className":"rounded-md border border-(--color-paper-dim) p-4","children":[["$","div",null,{"className":"text-xs uppercase tracking-wide text-(--color-ink-dim)","children":"Original draft"}],["$","div",null,{"className":"mt-2 text-2xl font-bold font-(--font-mono) text-(--color-bad)","children":"66%"}]]}],["$","div","Threshold 0.99",{"className":"rounded-md border border-(--color-paper-dim) p-4","children":[["$","div",null,{"className":"text-xs uppercase tracking-wide text-(--color-ink-dim)","children":"Threshold 0.99"}],["$","div",null,{"className":"mt-2 text-2xl font-bold font-(--font-mono) text-(--color-warn)","children":"~15%"}]]}],["$","div","Threshold 0.995",{"className":"rounded-md border border-(--color-paper-dim) p-4","children":[["$","div",null,{"className":"text-xs uppercase tracking-wide text-(--color-ink-dim)","children":"Threshold 0.995"}],["$","div",null,{"className":"mt-2 text-2xl font-bold font-(--font-mono) text-(--color-good)","children":"4.77%"}]]}],["$","div","Threshold 0.999",{"className":"rounded-md border border-(--color-paper-dim) p-4","children":[["$","div",null,{"className":"text-xs uppercase tracking-wide text-(--color-ink-dim)","children":"Threshold 0.999"}],["$","div",null,{"className":"mt-2 text-2xl font-bold font-(--font-mono) ","children":"1.4%"}]]}]]}],["$","$L5",null,{"href":"/docs/concepts/bayesian-inference","className":"mt-6 inline-block text-sm","children":"Read the calibration table →"}]]}]
8:["$","section",null,{"className":"space-y-6","children":[["$","h2",null,{"className":"text-3xl font-bold tracking-tight","children":"Five lines per stack."}],["$","p",null,{"className":"max-w-2xl text-(--color-ink-dim)","children":"Splitstream ships SDKs for TypeScript, React, PHP (Laravel-ready), and Python (Django + FastAPI adapters). The bucketing function is guarded by a shared corpus — every SDK matches byte-for-byte."}],["$","$L10",null,{}]]}]
9:["$","section",null,{"className":"space-y-6","children":[["$","h2",null,{"className":"text-3xl font-bold tracking-tight","children":"What ships in v0.1."}],["$","div",null,{"className":"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3","children":[["$","div","Sticky-forever assignment",{"className":"rounded-lg border border-(--color-paper-dim) p-5","children":[["$","h3",null,{"className":"font-semibold","children":"Sticky-forever assignment"}],["$","p",null,{"className":"mt-2 text-sm text-(--color-ink-dim) leading-relaxed","children":"First /v1/assign call writes the variant to a PostgreSQL row partitioned by experiment_id. Subsequent calls — same user, same variant, same forever."}]]}],["$","div","Empirically calibrated defaults",{"className":"rounded-lg border border-(--color-paper-dim) p-5","children":[["$","h3",null,{"className":"font-semibold","children":"Empirically calibrated defaults"}],["$","p",null,{"className":"mt-2 text-sm text-(--color-ink-dim) leading-relaxed","children":"360k null-effect simulations picked the threshold/sample/cadence tuple. No hand-waved priors. The calibration JSON ships in the repo."}]]}],["$","div","Mutex experiment groups",{"className":"rounded-lg border border-(--color-paper-dim) p-5","children":[["$","h3",null,{"className":"font-semibold","children":"Mutex experiment groups"}],["$","p",null,{"className":"mt-2 text-sm text-(--color-ink-dim) leading-relaxed","children":"A unit assigned to one experiment in the group cannot be assigned to another. SELECT FOR UPDATE race-protects simultaneous calls; holdouts are surfaced."}]]}],["$","div","Sample Ratio Mismatch detection",{"className":"rounded-lg border border-(--color-paper-dim) p-5","children":[["$","h3",null,{"className":"font-semibold","children":"Sample Ratio Mismatch detection"}],["$","p",null,{"className":"mt-2 text-sm text-(--color-ink-dim) leading-relaxed","children":"Chi-squared test on observed vs declared weights, every 5 minutes. p < 0.001 raises a banner — most SRM is a bug, not a real traffic skew."}]]}],["$","div","Guardrail metrics",{"className":"rounded-lg border border-(--color-paper-dim) p-5","children":[["$","h3",null,{"className":"font-semibold","children":"Guardrail metrics"}],["$","p",null,{"className":"mt-2 text-sm text-(--color-ink-dim) leading-relaxed","children":"Lower bound on the 95% credible interval of the relative difference. If the regression bound crosses the threshold, the experiment auto-stops with reason \"lost.\""}]]}],["$","div","Peek-event audit",{"className":"rounded-lg border border-(--color-paper-dim) p-5","children":[["$","h3",null,{"className":"font-semibold","children":"Peek-event audit"}],["$","p",null,{"className":"mt-2 text-sm text-(--color-ink-dim) leading-relaxed","children":"Every dashboard open is logged. The audit log surfaces \"you peeked 12 times before calling this experiment\" alongside the outcome."}]]}],["$","div","Octane hot-path carve-out",{"className":"rounded-lg border border-(--color-paper-dim) p-5","children":[["$","h3",null,{"className":"font-semibold","children":"Octane hot-path carve-out"}],["$","p",null,{"className":"mt-2 text-sm text-(--color-ink-dim) leading-relaxed","children":"/v1/assign and /v1/events run on Laravel Octane (RoadRunner) under an Apache mod_proxy split. mod_php handles low-volume admin + management routes."}]]}],["$","div","Redis-buffered ingest",{"className":"rounded-lg border border-(--color-paper-dim) p-5","children":[["$","h3",null,{"className":"font-semibold","children":"Redis-buffered ingest"}],["$","p",null,{"className":"mt-2 text-sm text-(--color-ink-dim) leading-relaxed","children":"Synchronous endpoint, async persistence via COPY. Cross-partition dedup via SETNX with a 30-day TTL. Backpressure 429 with Retry-After."}]]}],["$","div","Cross-SDK bucketing corpus",{"className":"rounded-lg border border-(--color-paper-dim) p-5","children":["$L11","$L12"]}]]}]]}]
a:["$","section",null,{"className":"rounded-lg bg-(--color-ink) px-8 py-12 text-center text-white","children":[["$","h2",null,{"className":"text-3xl font-bold tracking-tight","children":"Built by Philip Rehberger."}],["$","p",null,{"className":"mt-3 text-(--color-paper-dim)","children":"This is a portfolio demo, not a hosted service. The code is the artifact."}],["$","div",null,{"className":"mt-6 flex flex-wrap justify-center gap-4","children":[["$","a",null,{"href":"https://philiprehberger.com","className":"rounded-md bg-(--color-accent) px-5 py-2.5 text-sm font-medium no-underline text-white hover:bg-emerald-800","children":"About Philip"}],["$","a",null,{"href":"https://github.com/philiprehberger/splitstream","className":"rounded-md border border-emerald-300 px-5 py-2.5 text-sm font-medium text-emerald-200 no-underline hover:bg-emerald-950","children":"GitHub repo"}]]}]]}]
b:["$","script","script-0",{"src":"/_next/static/chunks/04th6t7cqv9wf.js","async":true,"nonce":"$undefined"}]
c:["$","$L13",null,{"children":["$","$14",null,{"name":"Next.MetadataOutlet","children":"$@15"}]}]
d:["$","$1","h",{"children":[null,["$","$L16",null,{"children":"$L17"}],["$","div",null,{"hidden":true,"children":["$","$L18",null,{"children":["$","$14",null,{"name":"Next.Metadata","children":"$L19"}]}]}],null]}]
f:["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/002zte3riz0h6.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]
11:["$","h3",null,{"className":"font-semibold","children":"Cross-SDK bucketing corpus"}]
12:["$","p",null,{"className":"mt-2 text-sm text-(--color-ink-dim) leading-relaxed","children":"TS, PHP, and Python SDKs round-trip the same bucketing corpus in CI. Drift between any implementation silently poisons experiments — the corpus catches it."}]
17:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
15:null
19:[["$","title","0",{"children":"Splitstream — A/B testing API with empirically calibrated Bayesian inference"}],["$","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."}]]