---
id: "packages/active-format/getting-started"
title: "Getting started"
description: "Receive active-format in your repository, declare it, and make the first call."
url: "/packages/active-format/getting-started"
locale: "en"
revision: "fe687508602ec8d5"
---

# Getting started

These steps were carried out in a new, empty repository with a React app on Vite, through the
managed transfer, without any path to Foundation or to the source repository.

## Prepare your repository

A pnpm workspace with `packages/*`, Node.js 26, and byte-exact checkouts for transferred packages:

```yaml
# pnpm-workspace.yaml
packages:
  - packages/*
  - apps/*
```

```text
# .gitattributes
packages/** -text
```

## Receive the package

`active-format` can be requested on its own: it depends on no other workspace package. Ask the
source repository for a bundle of `active-format` (on the `development` channel while it is
unreleased), then follow [Receiving packages](/receiving-packages):

```bash
node tools/rps/rps-apply.mjs plan --bundle <bundle-folder> --development
node tools/rps/rps-apply.mjs apply --bundle <bundle-folder> --expect-plan <digest> --development
```

The package now sits in `packages/active-format`. Do not edit it there.

## Declare, install and verify

In the `package.json` of the app that uses it:

```json
{
  "dependencies": {
    "@workspace/active-format": "workspace:*"
  }
}
```

```bash
pnpm install
```

Then prove that your app resolves the managed copy:

```bash
node tools/rps/rps-apply.mjs verify-install --from <app-folder>
```

The output must list `@workspace/active-format` as `current`. If it lists no package, nothing was
checked: the declaration or the installation is missing.

The package ships TypeScript source. Vite compiles it as it is. In a Next.js app, add it to
`transpilePackages` in `next.config`:

```js
const nextConfig = {
  transpilePackages: ['@workspace/active-format'],
};
```

## The first call

```ts
import {
  classifyNumberInput,
  composePresentationContext,
  formatCurrency,
  formatDateOnly,
  toIanaTimeZone,
} from '@workspace/active-format';

formatDateOnly('2026-12-31', 'nl'); // '31 dec. 2026'
formatCurrency({amount: 1234.5, currency: 'EUR'}, 'nl'); // '€ 1.234,50'

const presentation = composePresentationContext(
  'en',
  {dateFormat: 'DMY_NUMERIC'},
  toIanaTimeZone('Europe/Amsterdam'),
);
classifyNumberInput('1234.56', presentation).number; // 1234.56
// A grouping separator is refused while typing and accepted when pasted:
classifyNumberInput('1,234.56', presentation).status; // 'invalid'
classifyNumberInput('1,234.56', presentation, {mode: 'paste'}).number; // 1234.56
```

The same calls, running in your browser:

**Example: A first call**

Client: Runs entirely in your browser. Source: `examples/format/first-format.tsx`.

```tsx
// apps/docs/examples/format/first-format.tsx
'use client';

import {formatCurrency, formatDateOnly} from '@workspace/active-format';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@workspace/active-ui/components/primitives/table';

const LANGUAGES = ['en', 'nl', 'de'] as const;

/** The first call: the same values, the presentation passed explicitly. */
export default function FirstFormat() {
  return (
    <Table>
      <TableHeader>
        <TableRow>
          <TableHead>Language</TableHead>
          <TableHead>Calendar day</TableHead>
          <TableHead>Amount</TableHead>
        </TableRow>
      </TableHeader>
      <TableBody>
        {LANGUAGES.map((language) => (
          <TableRow key={language}>
            <TableCell className="font-mono">{language}</TableCell>
            <TableCell suppressHydrationWarning>
              {formatDateOnly('2026-12-31', language)}
            </TableCell>
            <TableCell suppressHydrationWarning>
              {formatCurrency({amount: 1234.5, currency: 'EUR'}, language)}
            </TableCell>
          </TableRow>
        ))}
      </TableBody>
    </Table>
  );
}
```

## Check the runtime

If you call `formatCurrency` with exact decimal strings or `formatElapsedDuration`, check that your
runtime supports them; see [Errors and runtime](/packages/active-format/errors-and-runtime#runtime-requirements).

## Next

Read [Presentation](/packages/active-format/presentation) before you pass a presentation through
your own components.
