Part of [Ferramenta](https://ferramenta.dev), a family of Rust tools.
# Ferriki
[](https://oss.sebastian-software.com) [](https://github.com/sebastian-software/ferriki/actions/workflows/ci.yml)
[](./.github/workflows/ci.yml)
[](./LICENSE-MIT)
[](https://nodejs.org)
[](https://www.npmjs.com/package/@ferriki/core)
[](https://crates.io/crates/ferriki)
[](https://docs.rs/ferriki)
**Beautiful code. Optimization, delivered.** Ferriki brings editor-grade TextMate
highlighting to documentation, CMS content, and site builds. Its native Rust
engine works from Node.js and Rust, while Vite 8 macros prepare literal
component examples during the build. The Node API keeps
Shiki's familiar HTML call shape, backed by Ferriki's own curated grammar
catalog.
## Compile once. Start optimized.
Regex optimization can travel with your grammar. Powered by Ferroni 2.7,
Ferriki prepares regex programs and static scanner automata ahead of time and
delivers them as packages from the CDN. Your highlighter restores that work
and starts with Eager optimizations from the first static scan.
Keep the asset cache between builds and the same download serves fresh
processes, rebuilds, and deployments. Each process restores the prepared
automata instead of rebuilding them from regex source. Standard grammars use
these packages by default when prefiltering is on, with source fallback when
a package is unavailable. Dynamic patterns remain local.
In our local seven-grammar diagnostic, C++ tokenizer startup dropped from
**about 144 ms to 68 ms**, with execution comparable to ordinary Eager.
Startup includes restoration and the first document; network, file I/O, and
complete builds are outside the timer. See the
[measurements and limits](https://ferriki.dev/evidence/benchmarks#prepared-regex).
## Choose your path
| Node.js | `npm install @ferriki/core` | [Node.js package guide](node/ferriki/README.md) |
| Rust | `cargo add ferriki --features remote` | [Rust API guide](docs/rust-api.md) |
| Vite 8 and React | `npm install @ferriki/core @ferriki/vite` | [Vite macros guide](node/vite/README.md) |
## See your first result in Node.js
Ferriki requires Node.js 22.13.0 or newer and uses ESM. npm installs the
matching optional native package for Linux x64/arm64 (glibc or musl), macOS
Apple Silicon, or Windows x64/arm64; keep optional dependencies enabled.
Install the package in your project:
```sh
npm install @ferriki/core
```
Language and theme payloads download from the release-pinned CDN on first use,
are verified with SHA-256, and are cached locally. For offline builds, populate
the cache ahead of time or use a mirror. See [asset loading](docs/asset-loading.md).
Save this complete ESM file as `highlight.mjs`, then run `node highlight.mjs`:
```js
import { writeFile } from "node:fs/promises";
import { codeToHtml } from "@ferriki/core";
const html = await codeToHtml("const answer = 42;", {
lang: "javascript",
theme: "github-dark",
});
await writeFile("highlighted.html", html);
console.log("Saved highlighted.html. Open it in a browser to preview your code.");
```
## Reuse one highlighter for repeat work
For a documentation build or CMS worker, create a highlighter with the
languages and themes you need, then keep it around for the blocks you render.
Calls with loaded languages and themes are synchronous. Create one highlighter
per worker, and dispose it when that worker shuts down.
```js
import { createHighlighter } from "@ferriki/core";
const highlighter = await createHighlighter({
langs: ["typescript", "rust", "css"],
themes: ["github-light", "github-dark"],
});
try {
const html = highlighter.codeToHtml("const answer: number = 42;", {
lang: "typescript",
theme: "github-dark",
});
console.log(html);
} finally {
highlighter.dispose();
}
```
The retained Shiki comparisons below used Ferriki 1.1.1 and Ferroni 2.2.2,
before prepared regex packages. On that 14-file Blacksmith corpus, a reused
highlighter produced the same HTML as Shiki/WASM and ran **3.3× faster on Linux x86-64** and **4.1×
faster on macOS ARM64**. See the [benchmark report](https://ferriki.dev/evidence/benchmarks)
for hosts, conditions, first-use timings, and raw results.
A separate capture with six fresh processes per engine and workload on each
host measured **27–31% lower whole-process RSS than Shiki/WASM** after 600
documents in a shared 12-file cohort. See the
[memory details](https://ferriki.dev/evidence/benchmarks#process-memory).
## More ways to use Ferriki
| Shiki-shaped HTML | `codeToHtml`, highlighters, singleton helpers, and transformer callbacks for Node.js |
| Stylesheet-driven themes | Nested TextMate scope classes, generated CSS, and theme maps that switch without highlighting again |
| A grammar of your own | Ferriki's curated catalog plus custom TextMate grammars, aliases, and injections; see the [grammar guide](docs/grammars.md) |
| Code in Vite components | `code()` and React `<Code />` macros that prepare highlighted output at build time on Vite 8 |
| Native Rust highlighting | The [`ferriki` crate](https://docs.rs/ferriki): tokens, line HTML, and class-based HTML |
Import `@ferriki/core/macro` or `@ferriki/core/react/macro` in the modules whose
examples you want prepared. The build delivers highlighted output, and React
`<Code />` uses a small framework-free presentation module in the browser.
Grammar payloads stay on the build side; see the [Vite guide](node/vite/README.md)
for the quickstart, SSR behavior, and limits.
## Start with Rust
Enable the remote asset catalog with `cargo add ferriki --features remote`.
This small program highlights a Rust function and prints HTML:
```rust
use ferriki::{
Highlighter, RemoteAssets, RenderOptions, StandardAssetCatalogs, render_html,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut highlighter = Highlighter::builder()
.with_assets(StandardAssetCatalogs::remote(RemoteAssets::default())?)
.load_languages(["rust"])
.load_themes(["github-dark"])
.build()?;
let tokens = highlighter.highlight("fn main() {}", "rust", "github-dark")?;
println!("{}", render_html(&tokens, &RenderOptions::default()));
Ok(())
}
```
## Compatibility
Ferriki follows semantic versioning: breaking changes to its public API
require a major version; see the [changelog](node/ferriki/CHANGELOG.md). It
pins Shiki v4.4.3 and vscode-textmate v9.3.2 as behavioral references.
Shiki's tests run unchanged from a pinned mirror, each classified as supported,
deferred, or out of scope; the tokenizer is checked against the full
vscode-textmate oracle. Node's public output is HTML, while transformer
callbacks can inspect token and HAST data. The Rust crate exposes tokens and
HTML rendering. See the [compatibility policy](docs/compatibility.md) and
[Shiki migration guide](docs/migrations/shiki-to-ferriki.md).
## Documentation
- [ferriki.dev](https://ferriki.dev): guides and [benchmarks](https://ferriki.dev/evidence/benchmarks)
- [API reference](docs/ferriki-api.md), [class-based highlighting](docs/class-highlighting.md), and [asset loading](docs/asset-loading.md)
- [Inline code macros](docs/inline-code-macros.md) and [code example authoring](docs/code-example-authoring.md)
- [Rust API and Ferromark](docs/rust-api.md), plus [troubleshooting](docs/troubleshooting.md)
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for the build, test lanes, and repository
layout, and [`adr/`](adr/README.md) for the decisions behind the project.
## License
Licensed under either of [MIT](./LICENSE-MIT) or [Apache-2.0](./LICENSE-APACHE)
at your option.
### <a href="https://ferramenta.dev"><img src="https://raw.githubusercontent.com/sebastian-software/ferramenta/main/app/assets/brand/logo-light.svg" width="24" height="24" alt="" /> More from Ferramenta</a>
[Ferramenta](https://ferramenta.dev) — A family of Rust tools.
**Engines**
| [ferroni](https://ferroni.dev) | Oniguruma-compatible regex engine |
| [ferromark](https://ferromark.dev) | Markdown to HTML, sanitized by default |
| [ferrolex](https://github.com/sebastian-software/ferrolex) | Spell checking for text and code |
| [ferrocat](https://ferrocat.dev) | Translation catalog engine |
| [ferralk](https://github.com/sebastian-software/ferralk) | Glob matching and parallel filesystem walking |
| [ferrugo](https://github.com/sebastian-software/ferrugo) | PDF previews for untrusted files |
**Applications**
| [palamedes](https://palamedes.dev) | Internationalization for TypeScript applications |
| [dalo](https://dalo.sh) | Your team's agent setup, versioned like code |
| [ardo](https://ardo-docs.dev) | Documentation sites built with React |
---
<p align="center">
<a href="https://oss.sebastian-software.com"><img src="https://raw.githubusercontent.com/sebastian-software/oss.sebastian-software.com/main/app/assets/logo-software.svg" alt="Sebastian Software" width="160" /></a><br />
TypeScript, React & Rust consulting<br />
Experts in Agentic Software Development<br />
<a href="https://sebastian-software.de">Work with us</a> · <a href="https://oss.sebastian-software.com">More open source</a>
</p>
<p align="center">Copyright © 2026 Sebastian Software GmbH</p>