Developer Docs
capstring is a small, serious, zero-dependency library for turning text into any case, code convention, encoding, or ridiculous fun style. Unicode and emoji safe. It ships a CLI, TypeScript types, and a free HTTP API, all documented on this page.
| Library | Node 22+, any modern browser, Deno, Bun | Install |
|---|---|---|
| CLI | npx capstring kebab "hello world" | Command line |
| HTTP API | https://capstring.netlify.app/api | HTTP API ยท API Reference |
| Playground | Type, click to copy | Open |
- Smart tokenizer:
XMLHttpRequest,hello_world,hello-world, andhelloWorldall split correctly. - Real slug: diacritics folded, punctuation dropped, ASCII only.
- Unicode and emoji safe: flags, ZWJ sequences, keycaps, and combining accents survive every style.
- Zero dependencies, 7 files, under 40 kB on npm, and a test fails if that ever grows.
- 100% test coverage, every behavior change recorded in the changelog.
Install
Requires Node 22.13 or newer. ES modules only: use import, not require. No runtime dependencies are installed.
In a browser with no bundler, import the library file straight from a CDN. It is dependency-free and browser-safe.
Transform a string
capstring(str, style = 'same', options = {}) returns the transformed string. The default export and the named export are the same function.
| Parameter | Type | Default | Description |
|---|---|---|---|
str | string | Text to transform | |
style | Style | 'same' | A style name, see Styles |
options.strict | boolean | false | Throw instead of returning false or the input |
Passing a non-string returns false. An empty string returns ''. An unknown style returns the input unchanged. These are deliberate so the function is safe to call with untrusted values.
Strict mode
Turn on strict to throw instead: a TypeError when str is not a string, a RangeError when style is not a known style. The CLI and the HTTP API always validate strictly.
Every style at once
capstringAll(str, options) runs every style and returns an object keyed by style name in canonical order. Same options and same non-string behavior as capstring. The playground is built on this one call.
Discover styles
| Export | What it is |
|---|---|
STYLES | Frozen array of every style name in canonical order. New styles are appended, so indexes are stable. |
CATEGORIES | Frozen object grouping every style exactly once: case, code, fun, encoding, art. |
getStyles() | A fresh, mutable copy of STYLES. |
isValidStyle(value) | true for a style name. In TypeScript it narrows value to Style. |
Styles
Every style, what it does, and how it handles the edges. Outputs on this page are computed live by the library, so they are exactly what you get. The first example is always hello world.
Command line
The package ships a capstring executable. Two ways to get it:
# no install, runs the latest version each time
npx capstring kebab "hello world"
# or install once and use it anywhere
npm install -g capstring
capstring kebab "hello world"
capstring <style> [text...] Transform text (reads stdin when no text is given)
capstring --all [text...] Print every style
capstring --count [text...] Count words, characters, and spaces
capstring --list List style names
-a, --all Print every style
-c, --count Count words, characters, and spaces
-l, --list List style names, one per line
--json JSON output
-h, --help Show this help
-v, --version Show version
-- End of options
Multiple text arguments are joined with one space. Flags may appear anywhere. With no text argument the CLI reads all of stdin and strips one trailing newline, so it slots into pipelines. Multiline stdin is treated as one string; in the --all table, line breaks inside a result are shown escaped so every style stays on one row.
| Exit code | Meaning |
|---|---|
0 | Success |
2 | Usage error: unknown style, unknown option, or no text given on a terminal |
TypeScript
Types ship in the package. Every style name is a string literal in the Style union, so editors autocomplete them and typos fail to compile. capstring and capstringAll are overloaded so the return type matches the input: a string in gives a string back, unknown in gives string | false. The style parameter accepts Style | (string & {}), which keeps autocomplete while still allowing arbitrary strings.
A test in the repository fails if the union ever drifts from the runtime STYLES array.
HTTP API
The same transformations over HTTP, for any language or no code at all. Base URL https://capstring.netlify.app/api, no key, CORS enabled, cacheable. The interactive API Reference lets you try every endpoint in the browser.
| Endpoint | Returns |
|---|---|
GET /api/:style/:text | { input, style, output } |
GET /api/all/:text | every style at once |
POST /api/batch | { "style": "kebab", "texts": ["a", "b"] }, up to 1,000 |
GET /api/spell/:text | spell-corrected text and corrections, optional ?style= |
GET /api/count/:text | words, characters, characters without spaces |
GET /api/lorem/:count | lorem ipsum, 1 to 1000 words, optional ?style= |
GET /api/badge/:style/:text | SVG badge, ?label= to override |
GET /api/styles | style names and categories |
Output formats
JSON by default. Choose another with a file extension on the path, a format query parameter, or an Accept header. The extension wins when more than one is given. Errors come back in the same format with a matching status.
| Format | Extension | Accept |
|---|---|---|
| JSON | .json | application/json |
| Plain text | .txt | text/plain |
| HTML | .html | text/html |
| XML | .xml | application/xml |
| YAML | .yaml or .yml | text/yaml |
| CSV | .csv | text/csv |
| JSONP | .jsonp with ?callback= | application/javascript |
| SVG image | .svg | image/svg+xml |
| PNG image | .png | image/png |
Use ?text= instead of the path when the text contains slashes or ends in an extension. Add ?pretty=1 for indented JSON. Image formats draw a single line and cut output beyond 200 characters with an ellipsis.
Limits and caching
| What | Limit |
|---|---|
| Text | 10,000 characters (GET URLs are capped at about 8 KB by the host; use POST /api/batch for longer text) |
| Spell check | 500 characters, 50 corrections per request |
| Batch | 1,000 texts, 100,000 characters in total |
| Lorem | 1,000 words |
| Badge label | 100 characters |
Deterministic responses carry Cache-Control: public, max-age=86400. Anything involving the random style or a POST body is no-store.
What ships on npm
| File | Purpose |
|---|---|
index.js | The whole library, browser-safe |
index.d.ts | TypeScript declarations |
cli.js | CLI logic as a testable main(argv, io) |
bin/capstring.js | The npx capstring executable |
Plus package.json, README.md, and LICENSE. Zero dependencies, sideEffects: false so bundlers can tree-shake it. Release notes live in the changelog.