<CodeBlock> puts its code prop into a client script unconditionally, which makes it unusable for any snippet that is not safe to ship to the browser as data.
The component
src/components/CodeBlock.stx:
<script client>
const code = {{ code }}
const copied = state(false)
async function copyToClipboard() {
await navigator.clipboard.writeText(code)
...
}
</script>The block is top-level. copyable only gates the button in the template:
@if(copyable)
<button @click="copyToClipboard()" ...>
@endifSo :copyable="false" still emits const code = ... with the full content. There is no way to render a highlighted block without also shipping its text into page JavaScript.
Why that blocks adoption
A status-page app has five code blocks, all of them install or ping snippets that embed a per-resource credential. The app keeps those bindings behind a __ prefix specifically because stx's extractBridgeData skips __ and $ names, and it has a test enforcing that no server binding reaches page HTML through the bridge, written after raw rows carrying a token leaked into dashboard HTML once.
:code="__agentInstall.install" routes straight around that. The snippet is already visible as rendered text, so this is not a new disclosure to a third party, but it does defeat an invariant the app deliberately maintains, and a component should not force that choice on a consumer who has explicitly turned the copy button off.
It is also dead weight in the ordinary case: a block with copyable: false ships a duplicate of its own content for no reader-visible benefit.
Suggested
Emit the client script only when copyable is true. If the current single-block form has to stay, reading the text from the DOM at click time rather than from an interpolated constant would also work, and would drop the duplicate payload for every consumer.
Two smaller things found alongside
The copy button is invisible to keyboard and touch. It is opacity-0 group-hover:opacity-100 with no focus variant, so a keyboard user who tabs to it sees nothing, and on a touch device it never appears at all. focus-visible:opacity-100 would fix the keyboard half; the touch half needs the button not to depend on hover.
highlightCss is exported but never rendered, with a source comment explaining that a <style> in a component is extracted before interpolation. That is stacksjs/stx#1990, which is now closed, so this may be ready to un-work-around: if it is, the component can ship its own theme CSS and consumers stop having to plumb it by hand.