handterm-assets (0.0.3)

Published 2026-07-27 10:50:06 +02:00 by alex

Installation

[registries.forgejo]
index = "sparse+" # Sparse index
# index = "" # Git

[net]
git-fetch-with-cli = true
cargo add handterm-assets@0.0.3 --registry forgejo

About this package

The built handterm CSS and custom elements, embedded for Rust consumers.

handterm-assets

The built handterm CSS and custom elements, embedded for Rust consumers.

handterm-leptos writes the markup and ships no styles, which is right — the CSS is the product and a binding should not fork it. But that leaves a Rust consumer with a delivery problem a JavaScript one does not have: the packages live in an npm registry, and reaching them means a Node toolchain, a lockfile and a registry token in a repository that may have none of those. A cargo build should be enough to build a site made of handterm.

So this crate carries the bytes.

# .cargo/config.toml
[registries.handterm]
index = "sparse+https://git.shiverpeak.xyz/api/packages/alex/cargo/"
# Cargo.toml
[dependencies]
handterm-assets = { version = "0.0.1", registry = "handterm" }

Reading the registry needs no token — see Publishing.

// Whatever "GET /handterm/{path}" means in your web framework.
fn serve(path: &str) -> Option<(&'static str, &'static [u8])> {
    handterm_assets::get(path).map(|asset| (asset.content_type, asset.bytes))
}

And in the document, in this order:

handterm_assets::STYLESHEETS  // ["tokens.css", "handterm.css"] — link in this order
handterm_assets::ELEMENTS_ENTRY  // "elements/index.js" — <script type="module">

Link STYLESHEETS rather than naming the files: the ordering is knowledge, not convention — handterm.css resolves the semantic tokens tokens.css defines — and a future split into more files then is not a breaking change.

What it does not do

It names no web framework. No Axum feature, no tower service, no dependencies at all. A component library that pulls a server in behind it is a component library you cannot use, and get() plus twenty lines is the whole integration.

It ships no fonts. The token stacks name Chakra Petch and Martian Mono, but handterm redistributes neither and this changes nothing about that. Loading them stays the consumer's job, exactly as it is from npm. Without them the type falls back to system-ui / ui-monospace; everything still works, it just stops looking like handterm.

It ships no source maps unless asked. The maps outweigh the modules they map several times over and embed the TypeScript those were built from. From npm that costs little, because a bundler drops them before anything is served; a binary has no such step, so here they would be permanent weight in every consumer. Turn them on to debug handterm itself:

handterm-assets = { version = "0.0.1", registry = "handterm", features = ["source-maps"] }

Without it the browser's request for a .js.map 404s — a devtools warning, nothing more.

It replaces nothing. A consumer who already has npm in the build should keep using the packages. This is for the ones who do not.

Caching

Every asset changes only when the crate version does, so serve them under a path containing handterm_assets::VERSION and answer cache-control: public, max-age=31536000, immutable. Whatever prefix is chosen, elements/ has to stay a directory beneath it — the modules resolve each other by relative path.

Build

build.rs reads the packages' built output and generates a table of include_bytes! calls pointing at it. Nothing is copied, so what a consumer serves is exactly what pnpm run build produced, and a stale rebuild is not possible. The whole elements directory is a rerun trigger and every module in it is picked up, so adding a custom element never means editing this crate.

It looks in two places, in this order:

crates/handterm-assets/assets/ A staged copy, present only in a published package.
packages/{tokens,css,elements}/dist The real build output, two levels up.

A cargo build in a fresh checkout therefore fails until the packages are built. It says so, and it says which of the two it was looking for:

packages/tokens/dist/tokens.css is missing — run `pnpm install && pnpm run build`
in the repository root first

It fails the same way if the elements directory is there but has no index.js in it — a half-finished build otherwise yields a crate that carries the stylesheets, compiles clean and 404s every element in the browser.

pnpm run ci:rust already builds the packages before it touches Cargo, for the same reason the wrapper codegen check does.

Publishing

Released to the cargo registry alongside the npm packages, by tools/publish-crates.mjs. Cargo packs only files beneath the package directory, so the script copies each package's dist into assets/ first and the build script prefers it — that copy is what the published crate carries. It is gitignored and removed again when the run ends, so a build here never quietly serves the bytes of whichever release last staged them; include in Cargo.toml is what makes cargo pack a directory git is told to ignore, and anything the build script reads has to be listed there.

Reads are unauthenticated. Publishing needs a Forgejo access token with write:package, which CI holds — a version is immutable once uploaded, so bumping version in Cargo.toml is what releases; the script asks the registry what it already has and skips the rest.

pnpm run publish:crates:check   # pack and build the packed copy, upload nothing (CI runs this)

That check is a gate rather than a formality: a crate can pass cargo build here, upload fine, and be unbuildable for everyone else, because the files it embeds only exist in a staged package.

A git dependency still does not work, and cannot: dist/ is not committed, so a git checkout of this repository has nothing for include_bytes! to point at. Use the registry, or a path dependency into a checkout where pnpm run build has run.

Details
Cargo
2026-07-27 10:50:06 +02:00
1
MIT
101 KiB
Assets (1)
Versions (4) View all
0.0.4 2026-07-27
0.0.3 2026-07-27
0.0.2 2026-07-26
0.0.1 2026-07-25