Catch prompt typos
before they reach the model.
tprompt is a 2KB TypeScript primitive that turns {{usrName}} into a tsc error — not a silent runtime string the model receives.
$ pnpm add @nkwib/tpromptOne primitive
prompt('...{{name}}...'). That's it. Variables are
inferred at the type level from the literal string — no decorators, no
codegen, no runtime schema.
Typo-proof
{{usrName}} in the template + userName at the
call site = compile error. Your prompt cannot ship with an unbound placeholder.
2KB. Zero deps.
sideEffects: false, ESM source, dual-published. Validation
is structural — bring Zod, Valibot, ArkType, or your own.
Pluggable delimiter
Default is {{var}} (LangChain / BAML / OpenAI prompts).
Single-brace via tprompt/single-brace. Custom via makePromptTag.
Multi-turn ready
.partial({role}) binds a subset; the rest is supplied
later. Partials don't compose — by design — so the type stays honest.
Optional runtime check
.validate(schema) throws; .validateSafe(schema) returns a Result. Two modes, no overlap. Pick one per call site.
Drop-in for the prompt ecosystem
Default {{var}} matches LangChain, BAML, the OpenAI
prompt cookbook, and Anthropic's prompt library. Coming from f-string
territory? One subpath import switches to {var}.
// Default: {{var}}
import { prompt } from '@nkwib/tprompt';
prompt('Hi {{name}}');
// Single-brace: {var}
import { prompt } from '@nkwib/tprompt/single-brace';
prompt('Hi {name}');
// Bring your own:
import { makePromptTag } from '@nkwib/tprompt';
const angle = makePromptTag({ open: '<<', close: '>>' });
The whole library is one idea.
Variables only. No template logic. No DSL. No surprises.