Definition
Items at the start and end of a sequence are remembered better than items in the middle. The first items benefit from primacy (rehearsal into long-term memory), the last from recency (still active in working memory). The middle is where information goes to die.
Why it matters for ShurIQ reports
Stack-rank tables, navigation menus, and viewport tile orders all carry serial-position weight. The top row and the bottom row of a 21-company stack rank get re-read; rows 8–14 are the dropout zone. Action items at the top of a recommendation list and the closing line of a brief carry disproportionate memory weight.
Takeaways
- Place the most consequential items at the start and the end; bury caveats in the middle, never on the bookends.
- For navigation, anchor the most-used controls at the far left and far right, treating the middle as secondary territory.
Visual motion language
Sequence-reveal staggers entries with a slight color-emphasis on the first and last; the middle items fade in at lower contrast to acknowledge their lower memorability.
Origins
Hermann Ebbinghaus, late 19th century — coined the serial position effect in foundational memory research.
Cavalry scene
The script below builds this concept's motion in Cavalry through the Stallion bridge. Pipe to cavalry_run_script via MCP, or paste into Cavalry's JavaScript Editor.
// Laws of UX · serial-position-effect · Cavalry scene
// Motion family: grid-stagger (book-end highlight)
// Palette: plum-purple + cream
// To run: pipe to cavalry_run_script tool, or paste into Cavalry's JavaScript Editor
// Built 2026-04-30 by ShurAI
(function () {
var PREFIX = "claude_lawofux_serial-position-effect_";
var existing = api.getAllSceneLayers();
for (var i = 0; i < existing.length; i++) {
try {
var nm = api.getNiceName(existing[i]);
if (nm && nm.indexOf("claude_lawofux_") === 0) api.deleteLayer(existing[i]);
} catch (e) {}
}
var BG = "#4A2E5C";
var CREAM = "#D6CDB0";
var bg = api.primitive("rectangle", PREFIX + "bg");
api.set(bg, { "generator.dimensions": [1080, 1080] });
api.setFill(bg, true);
api.set(bg, { "material.materialColor": BG });
// 7 squares: 4 on top row, 3 on bottom row offset right
var SIZE = 60;
var GAP = 26;
var topY = 50, botY = -50;
var positions = [
{ x: -((4-1)/2) * (SIZE + GAP), y: topY }, // 0 top-left
{ x: -((4-1)/2) * (SIZE + GAP) + 1 * (SIZE + GAP), y: topY }, // 1
{ x: -((4-1)/2) * (SIZE + GAP) + 2 * (SIZE + GAP), y: topY }, // 2
{ x: -((4-1)/2) * (SIZE + GAP) + 3 * (SIZE + GAP), y: topY }, // 3
{ x: -((3-1)/2) * (SIZE + GAP) + 0 * (SIZE + GAP) + (SIZE/2 + GAP/2), y: botY },
{ x: -((3-1)/2) * (SIZE + GAP) + 1 * (SIZE + GAP) + (SIZE/2 + GAP/2), y: botY },
{ x: -((3-1)/2) * (SIZE + GAP) + 2 * (SIZE + GAP) + (SIZE/2 + GAP/2), y: botY }
];
var bookendIdxs = [0, 6]; // primacy + recency
for (var i = 0; i < positions.length; i++) {
var p = positions[i];
var sq = api.primitive("rectangle", PREFIX + "sq_" + i);
api.set(sq, {
"generator.dimensions": [SIZE, SIZE],
"position.x": p.x, "position.y": p.y,
"opacity": 0,
"scale.x": 1.0, "scale.y": 1.0
});
api.setFill(sq, true);
api.set(sq, { "material.materialColor": CREAM });
var inF = i * 4;
api.keyframe(sq, inF, { "opacity": 0 });
api.keyframe(sq, inF + 12, { "opacity": 70 });
if (bookendIdxs.indexOf(i) >= 0) {
// Boost
api.keyframe(sq, 36, { "opacity": 70, "scale.x": 1.0, "scale.y": 1.0 });
api.keyframe(sq, 52, { "opacity": 100, "scale.x": 1.4, "scale.y": 1.4 });
}
}
var layerCount = api.getAllSceneLayers().length;
console.log("scene built: serial-position-effect (" + layerCount + " layers)");
})();