Build Landingi
KINDAreplaces $29/mosaves $348/yrback to the verdict
A landing page builder whose interesting half is the experiment engine: consistent variant assignment, conversion attribution that survives a page reload, and a statistical method that does not let you stop a test the moment it looks good.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the server, the page generator and the statistics.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - installfree locally
Why Assignments and conversions are counts that have to be exact, with one assignment per visitor enforced.
Get it Docker or your package manager. open ↗
Verify
A unique constraint rejects a second assignment for one visitor - decidefree to read; a statistician's hour is worth it for a commercial site
Why Fixed horizon with hidden results and sequential testing lead to different interfaces, and retrofitting either onto the other is a rewrite of the decision path.
Get it Read how each handles continuous monitoring, pick one, and write down the parameters: your minimum detectable effect and acceptable error rate.
Verify
A written note names the method, the detectable effect and the error rate - have readyfree, and sometimes discouraging
Why A test needing forty thousand visitors per arm on a page receiving two hundred a week will never conclude, and knowing that before building saves the experiment.
Get it Compute the required sample from your detectable effect and compare it to your actual weekly traffic.
Verify
A calculation exists showing how long a test would take at your traffic - decidefree
Why It is fixed at experiment start and cannot change while running, so an imprecise definition invalidates the test rather than being tidied up later.
Get it Define the event precisely, including repeat and cross-device behaviour.
Verify
A written definition covers the event, repeats and cross-device cases
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- pages(id, slug, published_version_id, created_at) - versions(id, page_id, content_json, published_at) · immutable once published - experiments(id, page_id, method, target_sample_per_variant, min_detectable_effect, started_at, ended_at, stopped_reason) - variants(id, experiment_id, version_id, weight, label) - assignments(visitor_id, experiment_id, variant_id, assigned_at) · one per visitor, never reassigned - conversions(id, assignment_id, goal, at, value_minor) · attributed to the assignment - results(experiment_id, computed_at, per_variant_json, decision, valid_under_method) - An assignment is written once and never changed, because a visitor moved between variants mid-test corrupts both arms.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
DATABASE_URLsecret | required | postgres://localhost:5432/landing | Assignments and conversions. |
STATS_METHOD | required | fixed_horizon_hidden | Named in the interface. The other honest option is a sequential method. |
SHOW_RUNNING_SIGNIFICANCE | required | never | Present as a constant. A running figure invites the stopping that manufactures results. |
MIN_DETECTABLE_EFFECT | required | 0.05 | Drives the required sample size. Smaller effects need far more traffic. |
ACCEPTABLE_ERROR_RATE | required | 0.05 | Validated against a null simulation in the test suite. |
ASSIGNMENT_COOKIE_DAYS | required | 90 | How long a visitor keeps their variant. Shorter means more reassignment as new visitors. |
The build, in order
Pages that load fast enough to test
A landing page renders quickly and is versioned immutably once published.
An edited variant mid-test invalidates the whole experiment.
Files
src/versions.tsThe page is in the measurement path. Slow pages change what you measure.
Files
src/build.tsIt loads before assignment. Measure its size and hold it.
Files
runtime/assign.ts
done when · tick each as it passeswatch out- Editing a published page during a running experiment changes what the variant is halfway through, and the results describe two things that no longer exist. Snapshot the version at publish and bind the experiment to versions rather than to pages.
Assignment that stays put
A visitor sees the same variant every time, and you know they did.
From a stable identifier, written once and never updated.
Files
src/assign.tssrc/assign.test.tsNew weights apply to new visitors only.
Files
src/assign.tsRendering the control then swapping is visible and it biases the result.
Files
runtime/assign.ts
done when · tick each as it passeswatch out- Reassigning visitors when you adjust traffic weights moves people between arms mid-test, which contaminates both and produces a result describing neither. Keep existing assignments fixed and apply new weights only to visitors who have not been assigned.
Conversions attributed to what was seen
A conversion counts for the variant the visitor actually saw.
It is the only record of what the visitor actually saw.
Files
src/conversions.tsChanging what counts as success mid-test is choosing the answer.
Files
src/experiments.tsBoth happen. Both need an answer written down, not an accident.
Files
src/conversions.ts
done when · tick each as it passeswatch out- Attributing a conversion to whichever variant is current at conversion time rather than to the recorded assignment mixes the arms whenever anything about the test changes, and the corruption is invisible in the totals. Attribute to the assignment, which is the only thing that records what was actually seen.
Statistics that do not let you cheat
A winner is declared only when the method says it may be.
Fixed horizon with hidden results, or sequential. Not a running figure.
Files
src/stats.tsA thousand tests between identical variants. Count the false winners.
Files
src/stats.test.tsIn the decision path. The friction is the feature.
Files
src/decide.ts
done when · tick each as it passeswatch out- Displaying a running significance figure invites stopping the moment it crosses the line, and doing that on two identical pages produces a false winner a large fraction of the time. Either hide the numbers until the planned sample is reached, or use a method whose guarantee holds when you look continuously, and say which one you chose.
Reporting a result honestlyproduct builder
The report says what was found and what it does not support.
A single percentage implies precision the data does not have.
Files
src/report.tsOn the result itself, where someone reading it will see them.
Files
src/report.tsSo a claim made from one can be checked a year later.
Files
src/archive.ts
done when · tick each as it passeswatch out- Reporting a percentage improvement as a single number implies a precision the data does not support, and a fourteen percent lift with an interval spanning zero to thirty is a different finding from one spanning twelve to sixteen. Report the interval, always, and make the point estimate the smaller number on the page.
That is the whole plan for Landingi. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Multivariate testing.
- Personalisation engines.
- Template libraries and design assets.
- Any general claim about what converts.
- CMS collaboration and client handoff
- managed hosting, forms, and analytics
- general-purpose visual editing
- large template and component libraries
- Sample size guidance before a test starts, which prevents tests that cannot conclude
- Segment analysis with a correction for testing several segments, which is the next place people fool themselves
- Sequential monitoring with a proper spending function, if you started with fixed horizon
Need the files? The project pack on the verdict page hands your agent the whole brief · more website builders.