# TypeWords Practice Step Types and Actions: Complete Developer Guide

> Explore TypeWords practice step types followWrite spell listen dictation and identify. Learn their actions like wordAdvance shuffleOnEnter and onEnd for effective practice flows.

- Repository: [Zyronon/TypeWords](https://github.com/zyronon/TypeWords)
- Tags: deep-dive
- Published: 2026-09-03

---

**TypeWords defines five practice step types—`followWrite`, `spell`, `listen`, `dictation`, and `identify`—each mapping to a `WordPracticeType` and configurable via `wordAdvance`, `shuffleOnEnter`, and `onEnd` actions in the practice flow system.**

The TypeWords codebase implements a flexible, template-driven practice workflow where each learning activity is composed of reusable step configurations. These step types determine how users interact with vocabulary words—whether following along, spelling from memory, or testing recognition—while core actions control word progression, randomization, and end-of-step behavior.

## Five Practice Step Types in TypeWords

TypeWords organizes all practice activities around five step templates defined in `STEP_TEMPLATE_META` within [`app/core/composables/practice-words/practice-flow-config.ts`](https://github.com/zyronon/TypeWords/blob/main/app/core/composables/practice-words/practice-flow-config.ts). Each template specifies a `WordPracticeType` that drives the UI and validation logic.

| Step ID | Practice Type | Chinese Label | Core Interaction |
|---------|---------------|---------------|----------------|
| `followWrite` | `FollowWrite` | 跟写 | User follows the word spelling as it appears on screen |
| `spell` | `Spell` | 拼写 | User types the word from memory with no visual hint |
| `listen` | `Listen` | 听写 | User hears pronunciation, then types the word |
| `dictation` | `Dictation` | 默写 | User sees the meaning, then types the word without audio |
| `identify` | `Identify` | 自测 | User views the word and decides if they know it |

These templates provide the foundation for both **system flows** (built-in learning algorithms) and **custom flows** (user-defined practice sequences).

## Core Actions: How Steps Behave at Runtime

Beyond the visual template, each step instance configures three critical actions that control runtime behavior. These actions are defined per-step in flow configurations and processed by the runtime engine in [`practice-flow-runtime.ts`](https://github.com/zyronon/TypeWords/blob/main/practice-flow-runtime.ts).

### Word Advance Modes

The **`wordAdvance`** action determines how the word list progresses through a step. Two modes exist:

- **`increment`** — Advances one word at a time. Used for simple, linear practice.
- **`wordLoop`** — Operates on a group of words (`groupSize`) and optionally runs sub-steps. Enables grouped learning with follow-up validation.

In the **system flow**, the `followWrite` step uses a `wordLoop` with trailing `spell` sub-step:

```typescript
// From practice-flow-config.ts lines 68-71
{
  templateId: 'followWrite',
  wordAdvance: WORD_LOOP_WITH_SPELL,  // group loop + spell sub-step
  onEnd: DEFAULT_ON_END,
  shuffleOnEnter: false,
}

```

This configuration processes words in batches, then immediately tests spelling retention for that batch.

### Shuffle on Entry

The **`shuffleOnEnter`** boolean randomizes word order when a step begins. This prevents pattern learning in phases where sequence memory would undermine the exercise.

Both `listen` and `dictation` steps enable shuffling in the system flow:

```typescript
// listen step (lines 75-78)
{
  templateId: 'listen',
  shuffleOnEnter: true,
  onEnd: DEFAULT_ON_END,
},
// dictation step (lines 80-83)
{
  templateId: 'dictation',
  shuffleOnEnter: true,
  onEnd: DEFAULT_ON_END,
}

```

### End-of-Step Actions

The **`onEnd`** action accepts an array of `PracticeEndAction` objects executed after step completion. The repository provides `DEFAULT_ON_END`, which implements a "wrong-word-clear" workflow:

```typescript
// DEFAULT_ON_END definition (lines 49-51)
export const DEFAULT_ON_END: PracticeEndAction[] = [
  { type: 'clearWrongWords' },
  { type: 'jumpTo', target: 'followWrite', wordAdvance: WORD_LOOP_WITH_SPELL }
]

```

This pattern—used across all built-in steps—resets error tracking and guides struggling users back to guided follow-write practice with loop-based reinforcement.

## Accessing Step Configuration Programmatically

The `STEP_TEMPLATE_META` object provides metadata lookup for any step type. Use this to build dynamic UIs or validate flow configurations:

```typescript
import { STEP_TEMPLATE_META } from '@/core/composables/practice-words/practice-flow-config.ts'

function getStepInfo(stepId: keyof typeof STEP_TEMPLATE_META) {
  const step = STEP_TEMPLATE_META[stepId]
  console.log(`Step "${step.label}" uses practice type ${step.practiceType}`)
}

getStepInfo('listen')  // "Step "听写" uses practice type WordPracticeType.Listen"

```

## Creating Custom Flows with Step Types

New practice flows combine step templates with custom action configurations. The `PracticeFlowConfig` interface in [`practice-flow-types.ts`](https://github.com/zyronon/TypeWords/blob/main/practice-flow-types.ts) enables runtime flow construction:

```typescript
import type { PracticeFlowConfig } from '@/core/composables/practice-words/practice-flow-types.ts'

function createMinimalSpellFlow(): PracticeFlowConfig {
  return {
    id: 'spellOnly',
    version: 1,
    mode: WordPracticeMode.Free,
    label: 'spelling_drill',
    nodes: [
      {
        id: 'mainNode',
        label: 'Spelling Practice',
        source: 'current',
        steps: [
          {
            templateId: 'spell',
            wordAdvance: { type: 'increment' },  // Simple linear progression
            onEnd: [],                           // No special handling
            shuffleOnEnter: false,
          },
        ],
      },
    ],
  }
}

```

Custom flows inherit all template behaviors while overriding actions to match specific learning objectives.

## Key Implementation Files

Understanding the complete practice system requires familiarity with these modules:

| File | Responsibility |
|------|----------------|
| [`app/core/composables/practice-words/practice-flow-config.ts`](https://github.com/zyronon/TypeWords/blob/main/app/core/composables/practice-words/practice-flow-config.ts) | `STEP_TEMPLATE_META` definition, built-in flows (`BUILTIN_FLOWS`), default actions |
| [`app/core/composables/practice-words/practice-flow-types.ts`](https://github.com/zyronon/TypeWords/blob/main/app/core/composables/practice-words/practice-flow-types.ts) | TypeScript interfaces: `PracticeFlowConfig`, `PracticeStep`, `PracticeEndAction` |
| [`app/core/composables/practice-words/practice-flow-runtime.ts`](https://github.com/zyronon/TypeWords/blob/main/app/core/composables/practice-words/practice-flow-runtime.ts) | Step execution, advancement logic, sub-step handling |
| [`app/core/composables/practice-words/practice-word-session.ts`](https://github.com/zyronon/TypeWords/blob/main/app/core/composables/practice-words/practice-word-session.ts) | Session state: current words, wrong-word tracking, progress snapshots |
| [`app/core/stores/practice.ts`](https://github.com/zyronon/TypeWords/blob/main/app/core/stores/practice.ts) | Pinia store exposing reactive practice state to UI components |

## Summary

- **Five step types**—`followWrite`, `spell`, `listen`, `dictation`, `identify`—provide the interaction models for all TypeWords practice activities.
- **`wordAdvance`** controls progression: `increment` for linear flow or `wordLoop` for grouped practice with optional sub-steps.
- **`shuffleOnEnter`** randomizes word order; typically enabled for `listen` and `dictation` to prevent sequence memorization.
- **`onEnd`** actions handle step transitions, with `DEFAULT_ON_END` providing wrong-word recovery and guided remediation.
- All configurations are type-safe, extensible, and defined in [`practice-flow-config.ts`](https://github.com/zyronon/TypeWords/blob/main/practice-flow-config.ts) for both built-in and custom flow authoring.

## Frequently Asked Questions

### What is the difference between `listen` and `dictation` step types?

Both require typing from memory, but `listen` plays audio pronunciation first while `dictation` shows only the word's meaning without audio. Both typically use `shuffleOnEnter: true` to ensure users process words individually rather than learning sequence patterns.

### How does `wordLoop` with a sub-step work in practice?

The `wordLoop` advance mode batches words (default `GROUP_SIZE`) and, upon completing a batch, automatically injects a sub-step—commonly a `spell` validation. This creates an "expose then test" rhythm where users first see words in context, then immediately prove retention.

### Where are wrong words tracked during a practice session?

Wrong-word state lives in [`practice-word-session.ts`](https://github.com/zyronon/TypeWords/blob/main/practice-word-session.ts), updated during step execution and cleared by `PracticeEndAction` of type `'clearWrongWords'`. The `DEFAULT_ON_END` configuration uses this to reset state when transitioning users back to `followWrite` for remediation.

### Can I create entirely new step types beyond the five built-in templates?

The template system is extensible: add entries to `STEP_TEMPLATE_META` with a new `WordPracticeType`, then implement corresponding UI components. However, the action system (`wordAdvance`, `shuffleOnEnter`, `onEnd`) requires no changes—new templates automatically inherit configurable action support.