Skip to content

Latest commit

History

1,312 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ZigCSS — Native by design. Correct by contract.

ZigCSS

BuildnpmLicense: MIT

Native by design. Fast on purpose. Correct by contract.

Compile CSS. Keep the meaning.

Five languages in. One deterministic compiler out.

ZigCSS is a self-contained native Zig compiler for CSS, SCSS, indented Sass, Less, and Stylus. It is built for a low-overhead execution path, deterministic output, and semantics-preserving transforms. It treats CSS like a language—not a string to rewrite until it looks smaller.

The current source snapshot compiles CSS, SCSS, indented Sass, Less, and Stylus through self-contained native Zig paths. All five machine rows are native-graduated; executable plugin parity remains outside the contract.

Website · Input/output lab · Get started · Documentation · npm · Releases

Stable package identity: 0.6.0 — published. npm latest serves zigcss@0.6.0, and the matching non-prerelease GitHub Release carries 25 signed release assets. The immutable 0.6.0-rc.2 prerelease remains on next as historical release evidence.

Native dependency-free migration

Publication of the provider-backed 0.5 candidate was cancelled before tagging. Dart Sass 1.101.0, Less 4.6.7, and Stylus 0.64.0 remain development-only reference oracles. They judge differential tests but do not enter the compiler, release archives, installed production graph, or compilation runtime.

The current native package contract has zero dependencies and zero optionalDependencies. The compiler itself starts no child process, performs no network access, and requires no runtime download. Five archive and offline-package jobs cover Linux x64/arm64, macOS x64/arm64, and Windows x64.

The native implementation was first proven on immutable 0.6.0-rc.2: its historical machine contract records nativeReleaseReady: true, and all nine pre-tag evidence surfaces, five signed target archives, offline consumers, and provenance passed. GitHub prerelease and npm next publication are verified for that immutable RC. Stable 0.6.0 then passed its separate ten-gate terminal and was published from immutable tag v0.6.0; it does not rewrite the RC or loosen any gate.

NATIVE-008 closed the finite source-capability inventory. NATIVE-009 graduated the four preprocessor machine rows together and closed the exact prerelease terminal with five native archives, 25 release assets, one GitHub prerelease, and npm next; executable plugin parity remains outside the contract. REL-010 owns the separate stable tag, npm latest, Pages, and public readback.

Why ZigCSS

What mattersZigCSS contract
Native executionAll five source inputs share native Zig compilation paths; the JavaScript delivery shim only invokes the binary.
Semantic safetyTransform classes stay unavailable until equivalence, idempotence, and independent-parser gates pass.
Failure behaviorCompilation is atomic. An error, cancellation, limit, or allocation failure returns no partial CSS.
DeterminismReplay, batch order, parallel workers, source maps, diagnostics, and packaging have executable checks.
OwnershipCSS, diagnostics, dependencies, source maps, module exports, and profile data share one explicit result lifetime.
DeliveryLinux x64/arm64, macOS x64/arm64, and Windows x64 archive paths are tested.

Your CSS deserves a real compiler: bounded input, a recovery-disabled parser, explicit transforms, strict output validation, and an atomic write at the end.

Install

Install the published stable five-language release:

npm install --save-dev zigcss

Compile CSS:

npx zigcss input.css -o dist/output.css --minify

Input:

.button {
color:#08100b;
background:#c8ff55;
}

Output:

.button{color:#08100b;background:#c8ff55}

Successful commands exit 0; compilation and I/O failures exit 1; usage or configuration failures exit 2.

Five syntaxes, one CSS destination

The stable package exposes explicit native CLI selection while keeping executable plugin boundaries separate from language graduation.

InputSource snapshot execution pathMachine migration state
CSS (.css)Native ZigCSS tokenizer/parsernative-graduated
SCSS (.scss)Native Sass-family parser/evaluatornative-graduated
Sass (.sass)Native Sass-family parser/evaluatornative-graduated
Less (.less)Native Less parser/evaluatornative-graduated
Stylus (.styl)Native Stylus parser/evaluatornative-graduated

native-graduated means the pinned corpus, negative/resource, deterministic, generated-CSS, product-routing, package, five-target, documentation, release, and publication gates passed for the immutable release line. It does not grant executable provider or plugin extension points.

To build the stable five-language source snapshot locally:

git clone https://github.com/vyakymenko/zigcss.git
cd zigcss
zig build
zig-out/bin/zigcss --syntax css styles.css -o dist/styles.css --minify
zig-out/bin/zigcss --syntax scss styles.scss -o dist/styles.css --minify
zig-out/bin/zigcss --syntax sass styles.sass -o dist/styles.css --minify
zig-out/bin/zigcss --syntax less styles.less -o dist/styles.css --minify
zig-out/bin/zigcss --syntax stylus styles.styl -o dist/styles.css --minify

--syntax is deliberate: the compiler does not infer a native preprocessor route from the filename alone. Imports stay inside the entry directory and explicitly admitted load paths.

Arbitrary Sass plugins, custom functions and importers, Less JavaScript and plugins, Stylus plugins and evaluator hooks, and executable project code remain outside the native product contract.

zig-out/bin/zigcss --syntax scss src/app.scss \
--load-path src/tokens \
--source-map \
--minify \
-o dist/app.css

See the format compatibility matrix, CSS compatibility matrix, and current capability status.

Benchmarks

ZigCSS is engineered for a low-overhead native path, but this project does not turn a laptop stopwatch into a marketing multiplier.

The benchmark program is already executable and publication-gated:

Evidence gateRequired proof
Semantic equivalenceEvery timed output must pass independent CSS admission before its timing is accepted.
Workload coverageSmall, medium, and large deterministic corpora are versioned and checksum-bound.
Execution modesCold CLI, warm CLI, in-process API, allocator memory, and throughput stay separately labeled.
Statistics43 ordered series and 860 raw observations are retained—never only the winning median.
HardwareThe publishable archive must come from dedicated Linux x64 bare metal. The runner records systemd-detect-virt, CPU-flag, sysfs, container-marker, cgroup, and bounded DMI evidence; any ambiguous or virtualized result fails closed.
ReproductionSource SHA, runner identity, tool versions, raw report, manifest, digest, and artifact link are sealed together.

Current status: the pipeline is ready, but the final controlled runner archive does not exist yet. Timing, ranking, throughput, memory, and ratio numbers remain unpublished until that evidence lands.

Read the benchmark report and publication contract. When the controlled archive passes, the report and this section can be generated from retained evidence instead of hand-edited hype.

Compiler pipeline

source bytes
↓
bounded lexer and parser
↓
typed, safety-classed transforms
↓
recovery-disabled CSS validation
↓
owned result + atomic output

The source-built executable is written to zig-out/bin/zigcss and routes all five inputs through native Zig code. The package JavaScript wrapper only locates and invokes the installed native binary; it does not host language semantics. Reference providers and their host remain development-only differential tools.

JavaScript wrapper

The installed package exports a thin launcher. It forwards the closed CLI arguments to the packaged binary, preserves exit and signal behavior, and implements no parser, evaluator, provider host, or fallback. A public programmatic JavaScript preprocessor API is not claimed by this snapshot.

Tooling integration

ZigCSS 0.6.0 ships a native CLI and a thin npm launcher. It does not currently ship a JavaScript bundler plugin, loader, or Nx executor. Calling the CLI from a build script is portable, but that alone is not evidence for a tool-specific integration.

SurfaceWhat is actually verified
npm scripts, CI, and shell build stepsThe installed launcher invokes the checksum-verified native binary and preserves its exit or signal result.
Zig Buildhelpers.addCssCompile passes fresh consumer builds in Debug and ReleaseSafe.
ViteThe website itself builds with Vite. Its local development middleware can invoke the CLI, but it is not a shipped stylesheet plugin and does not prove general Vite integration.
WebpackNo official loader or end-to-end consumer test yet.
RollupNo official plugin or end-to-end consumer test yet; Vite using Rollup internally does not count.
esbuildUsed as a benchmark comparator and to bundle the VS Code extension, not as a tested ZigCSS plugin.
NxNo official executor, generator, or workspace consumer test yet.

The same unverified boundary currently applies to Rspack, Turbopack, Parcel, Next.js, Nuxt, Astro, Angular, and SvelteKit. Until a real adapter and CI consumer exist, these integrations are intentionally documented as unavailable rather than implied by generic CLI compatibility.

Zig API

The stable zigcss.compile example remains CSS-only. It returns one owned compile result; call deinit exactly once.

conststd=@import("std");
constzigcss=@import("zigcss");
pubfnmain() !void {
vargpa=std.heap.GeneralPurposeAllocator(.{}){};
defer_=gpa.deinit();
varresult=tryzigcss.compile(
gpa.allocator(),
"input.css",
".notice { color: red; }",
.{ .format=.minified },
);
deferresult.deinit();
if (result.diagnostics.len!=0) returnerror.InvalidCss;
varbuffer: [1024]u8=undefined;
varwriter=std.fs.File.stdout().writer(&buffer);
trywriter.interface.writeAll(result.css);
trywriter.interface.flush();
}

The explicitly experimental zigcss.experimental_native namespace covers the finite SCSS, indented Sass, Less, and Stylus source set. This compiled example parameterizes all four rows, keeps resolver roots explicit, checks exact deterministic CSS, and deinitializes every owned result:

conststd=@import("std");
constzigcss=@import("zigcss");
constnative=zigcss.experimental_native;
constExample=struct {
syntax: native.Syntax,
filename: []constu8,
source: []constu8,
expected: []constu8,
};
constexamples= [_]Example{
.{ .syntax=.scss, .filename="example.scss", .source="$color: red; .card { color: $color; }", .expected=".card{color:red}" },
.{ .syntax=.sass, .filename="example.sass", .source="$color: red\n.card\n color: $color\n", .expected=".card{color:red}" },
.{ .syntax=.less, .filename="example.less", .source="@color: red; .card { color: @color; }", .expected=".card{color:red}" },
.{ .syntax=.stylus, .filename="example.styl", .source="color = red\n.card\n color color\n", .expected=".card{color:#f00}" },
};
pubfnmain() !void {
vargpa=std.heap.GeneralPurposeAllocator(.{}){};
defer_=gpa.deinit();
constallocator=gpa.allocator();
constroot=trystd.fs.cwd().realpathAlloc(allocator, ".");
deferallocator.free(root);
varbuffer: [1024]u8=undefined;
varwriter=std.fs.File.stdout().writer(&buffer);
inlinefor (examples) |example| {
constentry=trystd.fs.path.join(allocator, &.{ root, example.filename });
deferallocator.free(entry);
varresult=trynative.compile(allocator, entry, example.source, .{
.syntax=example.syntax,
.root_paths= &.{root},
.format=.minified,
});
deferresult.deinit();
if (result.diagnostics.len!=0or!std.mem.eql(u8, result.css, example.expected)) {
returnerror.UnexpectedNativeResult;
}
trywriter.interface.print("{s}\n", .{result.css});
}
trywriter.interface.flush();
}

The same documentation gate executes the five committed files under examples/native through the source-built binary with explicit --syntax. Neither example invokes a provider, child language engine, plugin, network service, or runtime download.

build.zig.zon gives the source package stable identity zigcss. The build module exposes helpers.addCssCompile for declared CSS inputs and generated outputs. See examples/build-integration.

Build and verify

Use Zig 0.15.2:

npm ci
zig build
zig build test --summary all
zig build test -Doptimize=ReleaseSafe --summary all
npm run test:preprocessor-product
npm run test:formats

The native migration boundary is machine-readable and fail-closed:

npm run test:native-contract
npm run check:native-contract

ADR-013 defines the self-contained native frontend contract.

Editor integration

The experimental CSS LSP covers bounded JSON-RPC framing, full document sync, UTF-16 positions, pull diagnostics, and syntax-aware open-document features.

Its release checks pass large-document, Unicode, malformed-request, leak, and editor-integration gates.

  • The VS Code preview uses Marketplace version 0.6.0 for the current CSS core mapping and requires a separately installed ZigCSS binary.
  • The Neovim configuration uses the built-in LSP client and an explicit trusted executable path.

Neither integration bundles a compiler binary.

Editor integrations remain CSS-only today. They do not silently execute preprocessor plugins or project code.

Project status

  • Stable package identity: 0.6.0; the exact GitHub tag, signed assets, npm latest package, Pages deployment, and public readback share one fail-closed promotion terminal.
  • CSS core: native-graduated.
  • SCSS, indented Sass, Less, and Stylus: native-graduated after parser/evaluator, pinned conformance, native product-routing, package, five-target, and pre-tag release gates.
  • Production package closure: verified with zero production dependencies and no provider or host bytes; the compiler itself starts no child process and performs no network access.
  • Reference engines: retained only as exact development oracles and excluded from production bytes and runtime execution.
  • Public capability graduation: all seven predeclared NATIVE-008 surfaces match native evidence; NATIVE-009 binds the immutable prerelease evidence and REL-010 binds the stable identity.
  • Controlled comparative benchmark: the machine-verifiable bare-metal gate is implemented; publication is waiting for the dedicated Linux x64 runner and its scheduled archive.
  • Stable publication: verified on immutable tag v0.6.0 at commit 6786655d66ca65c5a06421c8ed70d84183722dce; GitHub Release, 25 signed assets, npm latest, SLSA provenance, preserved next, and anonymous five-syntax installation all passed exact readback. The immutable RC remains separate.

The completed recovery plan and its verbose execution ledger were retired after stable publication. Git history preserves the audit trail; accepted architecture decisions, machine-readable native and stable-release contracts, release metadata, and executable tests remain the maintained evidence.

Contributing

Bring a minimal source input, expected semantics, actual output or diagnostic, and the relevant language-engine version. Run the focused language gate plus Debug and ReleaseSafe before opening a pull request.

High-value contributions include reduced compatibility cases, independent CSS validation, fuzz seeds, controlled benchmark runner capacity, and integrations that preserve the closed execution boundary.

License

MIT. See LICENSE.

About

Fast, zero-dependency CSS compiler built with Zig. Compile-time optimizations and minimal runtime overhead.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages