Skip to content

docs: teach agents to size an interactive island, not just place one - #1395

Merged
vivek7405 merged 1 commit into
mainfrom
docs/island-guidance
Aug 11, 2026
Merged

docs: teach agents to size an interactive island, not just place one#1395
vivek7405 merged 1 commit into
mainfrom
docs/island-guidance

Conversation

@vivek7405

Copy link
Copy Markdown
Collaborator

Problem

The skill told an agent where interactivity goes in eleven separate places. It never told it how much to put there.

Worse, the ownership rules in references/components.md pushed actively the wrong way, with no stopping rule. Rule 1 says: "If you are writing a selector to find markup that another file rendered, write the component that renders it instead." Followed literally that argument never terminates, because there is always more surrounding markup a component could render. Nothing anywhere said where to stop.

The one fact that would have stopped it was buried. components.md listed "being rendered by a component that itself ships" as the last bullet of the elidability blocker list, a place an agent reads when debugging a verdict, never while authoring. And the file went on to say elision is "inspectable rather than something to reason about from the rules above", which tells the agent not to think about island cost at all while writing the component.

Net effect: an agent had no reason not to promote a whole page section to a component so one button inside it could work, and no downstream check would flag it. All 19 bullets in the skill's "Common Mistakes To Avoid" pointed the other way, at under-componentizing.

The word "island" also appeared exactly twice in 3,440 lines and was never defined.

What this adds

The stopping rule. A component owns the markup its own behaviour reads or writes. Static markup that no handler touches, no state change re-renders, and no template hole depends on belongs to the page.

Why it is a byte rule and not a taste rule. A page never hydrates, so markup it renders is free in the browser. Markup an island renders is not: the module is fetched, @webjsdev/core comes with it, and on upgrade the component re-renders that subtree, replacing the server's DOM. Moving static markup across the boundary converts free HTML into shipped JavaScript that rebuilds what the server already sent.

The non-linear cost, promoted out of the blocker list. Elision propagates downward from whatever ships, so island size decides how much of the tree stays elidable. Ten display-only components rendered by a page are ten modules the browser never fetches. The same ten rendered by one oversized wrapper all ship, and nothing about any of them changed.

A too-big / right-size before-and-after, a <product-page> swallowing a whole article versus an <add-to-cart> that is one button.

A test an agent can run on a component it is about to write. Walk the template and ask of each element: does a handler touch it, does a state change alter it, does it sit in a hole? Three noes means that element is a passenger. A template that is mostly passengers wants splitting.

The exception, stated so the rule does not get over-applied. Markup that is static today but is what a near-term behaviour will read is fine to keep, since the alternative is a component reaching outward for it later, which rule 1 forbids. When ownership and bytes genuinely collide, ownership wins.

A definition of "island", in the SKILL.md execution-model block that already used the word.

Surfaces

Surface Change
.agents/skills/webjs/SKILL.md Islands defined in the execution model; sizing clause on workflow step 5; an over-componentizing bullet in Common Mistakes
.agents/skills/webjs/references/components.md New "Sizing an island" section, placed directly after the ownership rules that cause the pull; propagation fact promoted to a design consequence
.agents/skills/webjs/references/routing-and-pages.md Worked static-shell-plus-island example where the agent is told "put every interactive behaviour in a component"
AGENTS.md The rule in the execution-model section
website/app/docs/components/page.ts "How big should a component be?" for the human-facing docs

The scaffold needed no separate edit: packages/cli/lib/create.js:679 copies the repo-root skill verbatim into every generated app.

Verification

Generated a fresh app with the built CLI and confirmed all four additions are present in its .agents/skills/webjs/. test/repo-health/ + test/docs/ 149/149, test/scaffolds/ 65/65, website npm run typecheck clean, webjs check clean, website tests 471/471.

The skill said "all interactivity lives in a component" in eleven places
and never once said how much markup to put in it. Worse, the ownership
rules pushed the wrong way with no stopping rule: "if you are writing a
selector to find markup another file rendered, write the component that
renders it instead" never terminates, because there is always more
surrounding markup a component could render.

The fact that would have stopped it was buried as the last bullet of the
elidability blocker list, "being rendered by a component that itself
ships", and components.md explicitly told the reader elision was
"inspectable rather than something to reason about". So an agent had no
reason not to wrap a page section in a component to make one button work,
and nothing downstream would flag it.

Adds the stopping rule (a component owns the markup its own behaviour
reads or writes), the byte-cost argument behind it, a too-big/right-size
before-and-after, a walk-the-template test, and the ownership-wins
exception. Promotes the propagation fact from a blocker-list entry into a
stated design consequence, since it is the reason the cost of an oversized
island is not linear in what was moved. Also defines "island", which the
skill used twice and never explained.

Same guidance on the four surfaces that carry it: the skill (which
create.js copies verbatim, so every scaffolded app gets it), the root
AGENTS.md execution model, and /docs/components.
@vivek7405
vivek7405 merged commit 57cc0a3 into main Aug 11, 2026
10 checks passed
@vivek7405
vivek7405 deleted the docs/island-guidance branch August 11, 2026 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant