Pretext NPM: How to Install and Use the Pretext JavaScript & TypeScript Library

Apr 2, 2026

If you have been searching for "pretext npm," "pretext javascript," or "pretext typescript," you are in the right place. Pretext is a pure JavaScript text layout engine available on npm that computes line breaks, text height, and layout dimensions — all without touching the DOM. It is written in TypeScript with full type definitions included.

This guide covers everything you need to get started: installing the Pretext npm package, understanding the API, using it with TypeScript, integrating it with popular frameworks, and applying it to real-world use cases.

Installing Pretext from NPM

Getting started with the Pretext npm package takes one command:

npm install pretext

Or with other package managers:

# yarn
yarn add pretext

# pnpm
pnpm add pretext

# bun
bun add pretext

The Pretext npm package is approximately 15KB gzipped, has zero dependencies, and includes TypeScript type definitions out of the box. There is nothing else to install and nothing to configure.

Quick Start — Your First Pretext Layout

Here is the simplest possible Pretext JavaScript example:

import { prepare } from 'pretext';

// 1. Create a measurement context for your font
const ctx = prepare({
  fontFamily: 'Inter',
  fontSize: 16,
  lineHeight: 1.5,
});

// 2. Compute layout at a given width
const result = ctx.layout('Hello, world! This is Pretext.', {
  width: 200,
});

console.log(result.height);  // total height in pixels
console.log(result.lines);   // number of lines

That is it. Two function calls — prepare() and layout() — and you have exact text dimensions without any DOM access.

Pretext TypeScript Support

The Pretext npm package is written in TypeScript and ships with complete type definitions. You get full autocomplete, type checking, and documentation in any TypeScript-aware editor.

import { prepare } from 'pretext';
import type { PrepareOptions, LayoutResult } from 'pretext';

const options: PrepareOptions = {
  fontFamily: 'Inter',
  fontSize: 16,
  lineHeight: 1.5,
};

const ctx = prepare(options);

const result: LayoutResult = ctx.layout(
  'Pretext TypeScript support is first-class.',
  { width: 320 }
);

// TypeScript knows the shape of LayoutResult
console.log(result.height);  // number
console.log(result.lines);   // number

No need for @types/pretext or any additional type packages — everything is included in the Pretext npm package itself.

The Pretext JavaScript API

The Pretext API is small, focused, and designed around a two-phase architecture: prepare once, layout many times.

prepare(options)

Creates a reusable measurement context for a specific font configuration.

const ctx = prepare({
  fontFamily: 'Inter',       // CSS font-family string
  fontSize: 16,              // font size in pixels
  lineHeight: 1.5,           // line height multiplier
});

This is the only function that does any "expensive" work — it analyzes font metrics and builds internal lookup tables. It runs once per font configuration and takes roughly 0.1–1ms. The returned context is reusable for unlimited layout calls.

ctx.layout(text, options)

Computes line breaks and total height for the given text at the given width.

const result = ctx.layout('Your text here', {
  width: 300,    // container width in pixels
});

// result.height  — total height in pixels
// result.lines   — number of lines

Each layout() call takes approximately 0.0002ms — that is 600x faster than DOM measurement. You can call it thousands of times per frame.

ctx.layoutWithLines(text, options)

Like layout(), but also returns the text content and width of each line.

const result = ctx.layoutWithLines('Your text here', {
  width: 300,
});

result.lineData.forEach((line) => {
  console.log(line.text, line.width);
});

Useful when you need to know exactly where each line breaks — for rendering custom text layouts, underlining specific lines, or building text editors.

ctx.layoutNextLine(text, options)

Computes one line at a time with variable width per line. This is the most powerful function in the Pretext JavaScript API — it enables text reflow around irregular shapes.

let cursor = 0;
const lineWidths = [400, 380, 350, 320, 300]; // narrowing container

lineWidths.forEach((width) => {
  const line = ctx.layoutNextLine(text, { width, cursor });
  console.log(line.text, line.width);
  cursor = line.cursor;
});

This is how the community showcases achieve text wrapping around 3D objects, umbrellas, and other irregular shapes — each line gets a different available width.

ctx.walkLineRanges(text, options, callback)

Iterates over line boundaries without building strings. The most memory-efficient way to process line breaks in the Pretext JavaScript library.

ctx.walkLineRanges('Your text here', { width: 300 }, (start, end) => {
  console.log(`Line from index ${start} to ${end}`);
});

clearCache()

Clears internal glyph-width caches. Useful in long-running applications where font configurations change frequently.

import { clearCache } from 'pretext';
clearCache();

Using Pretext in JavaScript Projects

With React

Pretext works naturally with React. Create the measurement context once and use it across renders:

import { useMemo } from 'react';
import { prepare } from 'pretext';

function TextBlock({ text, width }) {
  const ctx = useMemo(() => prepare({
    fontFamily: 'Inter',
    fontSize: 16,
    lineHeight: 1.5,
  }), []);

  const { height } = ctx.layout(text, { width });

  return (
    <div style={{ width, height }}>
      {text}
    </div>
  );
}

This pattern is especially powerful for virtual scrolling — predict the height of every item without mounting it to the DOM.

With Vue

import { ref, computed } from 'vue';
import { prepare } from 'pretext';

const ctx = prepare({
  fontFamily: 'Inter',
  fontSize: 16,
  lineHeight: 1.5,
});

const text = ref('Your dynamic text here');
const width = ref(300);

const height = computed(() => {
  return ctx.layout(text.value, { width: width.value }).height;
});

With Svelte

<script>
  import { prepare } from 'pretext';

  const ctx = prepare({
    fontFamily: 'Inter',
    fontSize: 16,
    lineHeight: 1.5,
  });

  let text = 'Your dynamic text here';
  let width = 300;

  $: result = ctx.layout(text, { width });
</script>

<div style="width: {width}px; height: {result.height}px">
  {text}
</div>

With Node.js / Server-Side

Because Pretext has zero DOM access, it runs natively in server environments:

// Works in Node.js, Deno, Bun
import { prepare } from 'pretext';

const ctx = prepare({
  fontFamily: 'Inter',
  fontSize: 16,
  lineHeight: 1.5,
});

// Pre-calculate layout on the server
const result = ctx.layout(articleContent, { width: 680 });
console.log(`Article height: ${result.height}px, ${result.lines} lines`);

This enables server-side layout pre-calculation — send the client exact dimensions so there is zero layout shift on page load.

In Web Workers

Offload text measurement to a background thread:

// worker.js
import { prepare } from 'pretext';

const ctx = prepare({
  fontFamily: 'Inter',
  fontSize: 16,
  lineHeight: 1.5,
});

self.onmessage = (e) => {
  const { text, width } = e.data;
  const result = ctx.layout(text, { width });
  self.postMessage(result);
};

The main thread stays completely free while Pretext computes layouts in the background.

Real-World Use Cases

Virtual Scrolling

The most common use case for the Pretext npm package. Predict row heights for thousands of items without mounting any DOM elements:

const ctx = prepare({ fontFamily: 'Inter', fontSize: 14, lineHeight: 1.5 });

const items = messages.map((msg) => ({
  ...msg,
  estimatedHeight: ctx.layout(msg.text, { width: containerWidth }).height + padding,
}));

// Pass to React Virtuoso, TanStack Virtual, or any virtualizer

Chat Interfaces

Size message bubbles precisely. No more oversized bubbles with wasted whitespace:

// Find the minimum width that keeps the same line count
const fullResult = ctx.layout(message, { width: maxBubbleWidth });
let optimalWidth = maxBubbleWidth;

// Binary search for tightest fit
let lo = 100, hi = maxBubbleWidth;
while (lo < hi) {
  const mid = (lo + hi) >> 1;
  const test = ctx.layout(message, { width: mid });
  if (test.lines === fullResult.lines) hi = mid;
  else lo = mid + 1;
}
optimalWidth = lo;

Responsive Layout Pre-Calculation

Compute text dimensions at multiple breakpoints from a single prepare() call:

const ctx = prepare({ fontFamily: 'Inter', fontSize: 16, lineHeight: 1.5 });

const mobile  = ctx.layout(text, { width: 320 });
const tablet  = ctx.layout(text, { width: 768 });
const desktop = ctx.layout(text, { width: 1024 });

// Three layouts, zero DOM operations

Pretext JavaScript vs Other Approaches

ApproachSpeedDOM RequiredSSRTypeScriptBundle Size
Pretext npm~0.0002msNoYesBuilt-in~15KB
DOM measurement~0.06msYesNoN/AN/A
Canvas measureText~0.01msPartialNoN/AN/A
Hidden span hack~0.1msYesNoN/AN/A

Pretext is the only JavaScript text measurement solution that works everywhere — browser, server, worker — with zero DOM access and full TypeScript support.

Community Showcases

Developers are using the Pretext npm package to build things that were previously impossible in the browser:

tldraw — Instant Canvas Text

tldraw integrating Pretext for instant canvas text measurement

The tldraw collaborative whiteboard uses Pretext for instant text measurement — smooth text reflow without any DOM access.

Watch the demo →

3D Object Text Wrap

Text wrapping around a 3D gaussian splat object

Text wrapping around a 3D gaussian splat in real time, powered by Pretext's layoutNextLine() variable-width API.

Watch the demo →

Sand Writing Effect

Sand writing effect built with Pretext and Rive

Characters appear as if drawn in sand — precise text positioning from Pretext meets artistic Rive animation.

Watch the demo →

60FPS Playground Stress Test

Performance stress test pushing Pretext to its limits

Andrea Giammarchi pushed the Pretext playground from 60fps to its absolute limits — demonstrating real-time text layout at scale.

Watch the demo →

Browse all 25+ demos →

Frequently Asked Questions

Is the Pretext npm package free?

Yes. Pretext is MIT-licensed and completely free for any use — personal, commercial, or open source.

Does Pretext JavaScript work with my framework?

Yes. Pretext is framework-agnostic with zero dependencies. It works with React, Vue, Svelte, Angular, Solid, vanilla JavaScript, and any other framework.

Does the Pretext npm package include TypeScript types?

Yes. Pretext is written in TypeScript and ships complete type definitions. No @types package needed.

Can I use Pretext in Node.js / server-side?

Yes. Pretext has zero DOM access, so it runs natively in Node.js, Deno, Bun, and edge runtimes like Cloudflare Workers.

How accurate is Pretext compared to the browser?

Pretext uses the browser's own font engine (via Canvas measureText()) as ground truth during the prepare() phase. The layout() results match browser rendering with sub-pixel accuracy.

Does Pretext handle CJK, Arabic, and other scripts?

Yes. Pretext uses Intl.Segmenter for Unicode-aware word boundary detection. It handles CJK characters, Arabic, Hebrew, Thai, Korean, emoji, and mixed-script text with the same API.

Get Started

Install the Pretext npm package and start measuring text in JavaScript or TypeScript today:

npm install pretext
Pretext.js Team

Pretext.js Team

Pretext NPM: How to Install and Use the Pretext JavaScript & TypeScript Library | Blog