> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vowen.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Text Expander

> Type short triggers that expand into longer text snippets.

<div style={{ marginTop: "-2.5rem" }}>
  <Info>Free plan includes built-in expansions plus 1 custom expansion. <a href="https://vowen.ai" className="font-semibold underline-offset-2" style={{ color: "#8b5cf6", backgroundColor: "rgba(139, 92, 246, 0.12)", border: "1px solid rgba(139, 92, 246, 0.35)", padding: "2px 8px", borderRadius: "6px", fontSize: "0.85em", textDecoration: "none", whiteSpace: "nowrap" }}>Pro</a> unlocks unlimited custom expansions.</Info>
</div>

## What is Text Expander?

Type a short trigger like `:date` anywhere on your computer and Vowen expands it into longer text. It works globally, in any app and any text field.

<div className="my-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 p-2">
  <div style={{ position: "relative", background: "#000", borderRadius: "0.5rem", overflow: "hidden" }}>
    <video
      muted
      playsInline
      preload="metadata"
      poster="/videos/text-expander-demo-poster.jpg"
      style={{ width: "100%", display: "block", cursor: "pointer" }}
      onLoadedMetadata={(e) => { try { e.currentTarget.currentTime = 2; } catch (err) {} }}
      onClick={(e) => {
    const v = e.currentTarget;
    if (v.paused) { v.muted = false; v.play(); } else { v.pause(); }
  }}
      onPlay={(e) => {
    const parent = e.currentTarget.parentElement;
    const playBtn = parent.querySelector('[data-play-btn]');
    if (playBtn) { playBtn.style.opacity = '0'; playBtn.style.pointerEvents = 'none'; }
    const muteBtn = parent.querySelector('[data-mute-btn]');
    if (muteBtn) {
      muteBtn.querySelector('[data-icon-muted]').style.display = 'none';
      muteBtn.querySelector('[data-icon-unmuted]').style.display = 'block';
    }
  }}
      onPause={(e) => {
    const playBtn = e.currentTarget.parentElement.querySelector('[data-play-btn]');
    if (playBtn) { playBtn.style.opacity = '1'; playBtn.style.pointerEvents = 'auto'; }
  }}
    >
      <source src="https://mintcdn.com/vowen/2NLLQOm5sszam2ni/videos/text-expander-demo.mp4?fit=max&auto=format&n=2NLLQOm5sszam2ni&q=85&s=1849cdd282ffbfbd71dbbd0596932398" type="video/mp4" data-path="videos/text-expander-demo.mp4" />
    </video>

    <button
      data-play-btn
      aria-label="Play video"
      onClick={(e) => {
    const v = e.currentTarget.parentElement.querySelector('video');
    v.muted = false; v.play();
  }}
      style={{ position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)", width: "72px", height: "72px", borderRadius: "9999px", background: "rgba(0,0,0,0.55)", border: "2px solid rgba(255,255,255,0.9)", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", transition: "opacity 0.2s ease", padding: 0 }}
    >
      <svg width="28" height="28" viewBox="0 0 24 24" fill="white" style={{ marginLeft: "4px" }}>
        <path d="M8 5v14l11-7z" />
      </svg>
    </button>

    <button
      data-mute-btn
      aria-label="Toggle mute"
      onClick={(e) => {
    e.stopPropagation();
    const v = e.currentTarget.parentElement.querySelector('video');
    v.muted = !v.muted;
    e.currentTarget.querySelector('[data-icon-muted]').style.display = v.muted ? 'block' : 'none';
    e.currentTarget.querySelector('[data-icon-unmuted]').style.display = v.muted ? 'none' : 'block';
  }}
      style={{ position: "absolute", top: "0.75rem", right: "0.75rem", background: "rgba(0,0,0,0.55)", border: "none", borderRadius: "9999px", width: "36px", height: "36px", cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center", padding: 0 }}
    >
      <svg data-icon-muted width="16" height="16" viewBox="0 0 24 24" fill="white" style={{ display: "block" }}>
        <path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.17v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z" />
      </svg>

      <svg data-icon-unmuted width="16" height="16" viewBox="0 0 24 24" fill="white" style={{ display: "none" }}>
        <path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z" />
      </svg>
    </button>
  </div>
</div>

## Built-in Expansions

There are exactly two, and neither can be deleted.

| Trigger | Expands To | Example Output |
| - | - | - |
| `:date` | Current date | 2026-05-10 |
| `:time` | Current time | 14:30 |

## Creating Custom Expansions

1. Open the Vowen app and click **Dictionary** in the left sidebar
2. Switch to the **Expansions** tab
3. Click **+ Add Expansion**
4. Enter your trigger (e.g., `:addr`) and replacement text (e.g., "123 Main Street, Suite 400, New York, NY 10001")
5. Click Save

New custom expansions open in the **Rich** editor by default, so you can keep bold, links, lists, and other formatting in the expanded text. Use the **Plain/Rich** toggle in the editor if you'd rather store the expansion as plain text. (The built-in `:date` and `:time` are always plain.)

<Frame caption="Expansions are the third tab beside Dictionary and Threads. Built-in ones are marked; the rest are yours to edit.">
  <img src="https://mintcdn.com/vowen/94qaixcfbwWHsixE/images/app/expansions-list.png?fit=max&auto=format&n=94qaixcfbwWHsixE&q=85&s=43622b8e6462729bef6c2ac8c935168e" alt="The Expansions tab listing shortcuts such as colon date, colon sig and colon intro, with Built-in, Rich and Fill-ins badges" width="2400" height="1600" data-path="images/app/expansions-list.png" />
</Frame>

## How It Works

1. You type the trigger characters (e.g., `:email`)
2. Vowen detects the completed trigger
3. It simulates backspaces to delete the trigger
4. It pastes the replacement text

<Frame caption="An expansion is a shortcut beginning with a colon and the text it expands into. Fill-ins are declared at the bottom.">
  <img src="https://mintcdn.com/vowen/neO8QYHih6ewC77b/images/app/expansions-add.png?fit=max&auto=format&n=neO8QYHih6ewC77b&q=85&s=ce1065690c69d62c1cef21c1ac0aaec2" alt="The Add expansion dialog showing a Shortcut field, a rich text Expands to editor, and a Fill-ins section" width="1080" height="1103" data-path="images/app/expansions-add.png" />
</Frame>

This happens in real-time as you type, no shortcut needed.

## Use Cases

* **Contact info:** `:email` → your email address
* **Signatures:** `:sig` → your full email signature
* **Boilerplate:** `:thanks` → "Thank you for your message. I'll get back to you shortly."
* **Links:** `:gh` → your GitHub profile URL
* **Date/Time:** `:date` → today's date (built-in)

## Fill-in Variables

An expansion does not have to be a fixed block of text. Put a `{{name}}` token anywhere in the
replacement and Vowen opens a small focused form when the trigger fires, collects the values, and
injects the finished text.

```
Hi {{first_name}},

Thanks for coming in on {{visit_date}}. Your follow-up is {{followup}}.
```

Typing `:letter` opens a form with three fields. Fill them, press **Insert**, and the completed
letter is pasted into whatever you were typing in.

### How the fill-in form behaves

* It opens over the app you were typing in and takes keyboard focus, but never brings the rest of
  Vowen forward. Your typed `:shortcut` stays visible until you submit.
* Fields appear in the order the tokens appear in the text.
* **Tab** moves between fields, **Enter** advances (and submits from the last single-line field),
  **Cmd/Ctrl + Enter** submits from anywhere, **Esc** cancels.
* A live **Preview** underneath shows the finished text as you type.
* Cancelling is a clean no-op. Nothing has been deleted from the target app yet.

### Variable types

Configure each token as one of five types.

| Type | Control in the form | Extra settings |
| - | - | - |
| `text` | Single-line input | Default value |
| `multiline` | Multi-line textarea | Default value |
| `choice` | Pick exactly one option | Option list, and which option is preselected |
| `multiselect` | Pick any number of options | Option list, plus the separator used to join the picks (defaults to `, `) |
| `date` | Date picker | Date format, chosen from the same presets as `{{DATE}}` below |

Every type also has:

* **Label:** the text shown above the field in the form. Falls back to the token name.
* **Required:** a toggle. The Insert button stays disabled until every required field is filled.

A token with no configuration at all still works. It falls back to a plain text field, so you can
write `{{anything}}` and get a prompt for it without touching any settings.

### The variable library

Variables you want in more than one expansion live in a reusable library, so you define
`{{client_name}}` once and every expansion containing that token picks it up.

The library lives in the **Expansions settings modal** (see below), on the **Variables** tab. It
lists each variable with its type, its details, and how many expansions currently use it.

Vowen resolves each token with this precedence:

<Steps>
  <Step title="Per-expansion configuration">
    Anything you customized on that specific expansion wins. The editor shows a **Customize for this expansion** action, and a **Reset to library** action to undo it.
  </Step>

  <Step title="The global variable library">
    A library entry with a matching name. Expansions using it show a **Library** pill, and editing the library entry changes every expansion at once.
  </Step>

  <Step title="A plain text field">
    The fallback when neither of the above matches the token name.
  </Step>
</Steps>

<Note>`DATE` and `TIME` are reserved and cannot be used as variable names. Renaming a library variable is allowed, but expansions still referencing the old token silently fall back to a plain text field.</Note>

## Date and Time Tokens

Use `{{DATE}}` and `{{TIME}}` inside any expansion, not just the built-ins. They resolve
automatically without prompting. Add `:key` to pick a format. The expansion editor has an
**Insert date / time** menu that writes these tokens for you.

### Date presets

| Token | Format | Example |
| - | - | - |
| `{{DATE}}` or `{{DATE:iso}}` | ISO (YYYY-MM-DD) | 2026-05-10 |
| `{{DATE:us-short}}` | US (MM/DD/YYYY) | 05/10/2026 |
| `{{DATE:us-long}}` | US long (Month D, YYYY) | May 10, 2026 |
| `{{DATE:eu-short}}` | European (DD/MM/YYYY) | 10/05/2026 |
| `{{DATE:eu-long}}` | European long (D Month YYYY) | 10 May 2026 |
| `{{DATE:verbose}}` | Verbose (Weekday, Month D, YYYY) | Sunday, May 10, 2026 |
| `{{DATE:compact}}` | Compact (YYYYMMDD) | 20260510 |
| `{{DATE:year}}` | Year only | 2026 |
| `{{DATE:month-year}}` | Month and year | May 2026 |
| `{{DATE:weekday}}` | Weekday name | Sunday |

### Time presets

| Token | Format | Example |
| - | - | - |
| `{{TIME}}` or `{{TIME:24h}}` | 24-hour (HH:MM) | 14:30 |
| `{{TIME:24h-seconds}}` | 24-hour with seconds | 14:30:05 |
| `{{TIME:12h}}` | 12-hour (H:MM AM/PM) | 2:30 PM |
| `{{TIME:12h-seconds}}` | 12-hour with seconds | 2:30:05 PM |
| `{{TIME:iso-datetime}}` | ISO datetime | 2026-05-10T14:30:05 |
| `{{TIME:unix}}` | Unix timestamp (seconds) | 1778423405 |

An unrecognised key falls back to the default for that token (`iso` for dates, `24h` for times).

## Expansions Settings Modal

Click the gear icon in the window toolbar while the **Expansions** tab is open. The modal has two
tabs:

* **General:** the **Show suggestions dropdown** toggle.
* **Variables:** the global variable library described above, with create, edit and delete.

## Managing Expansions

* **Enable/Disable:** toggle individual expansions without deleting them
* **Edit:** change the trigger or replacement text
* **Delete:** remove custom expansions (built-ins cannot be deleted)
* **Built-in label:** shows which expansions are system-provided
* **Search:** filter the list by shortcut or text with the search bar at the top
* **Tags:** label expansions with colored tags, then use the tag filter bar (with any/all match modes) and sort options to organize a large library

## Suggestions Dropdown

Turn on **Show suggestions dropdown** on the **General** tab of the Expansions settings modal (the gear icon in the window toolbar) and Vowen shows a live picker as you type a `:` trigger. Matching expansions appear in a small list near your cursor. Click one to insert it without stealing focus from the app you're typing in, which helps when you can't remember the exact shortcut. It's off by default.

Expansions with fill-in variables show their tokens as `[Label]` slots in the picker preview, so you can tell at a glance that choosing one opens a form rather than pasting immediately.

## Bulk Import

Building dozens of expansions one-by-one in the app is slow. Prepare a JSON file with all of them (plain text or rich HTML) and import it in one click. See [Import & Export Data](/features/import-data) for the file format and an LLM-ready prompt that converts any source list (spreadsheet, Word doc, wiki) into a ready-to-import file.

## Behavior Notes

* Expansions are **paused during voice recording** (won't interfere with transcription)
* A **mouse click resets** the trigger buffer (starts fresh)
* Triggers are **case-sensitive**
* The trigger prefix `:` is not configurable currently


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.