# How to Add New Track Types to Clypra's Timeline Store

> Learn how to add new track types video audio text sticker and filter to Clypra's timeline store by extending the TrackType union and registering UI heights in the Zustand store.

- Repository: [Abdulkabir Musa/Clypra](https://github.com/AIEraDev/Clypra)
- Tags: how-to-guide
- Published: 2026-07-16

---

**Adding a new track type to Clypra's timeline store requires extending the `TrackType` union in the types definition and registering a corresponding UI height in the Zustand store's `trackHeights` lookup table.**

Clypra stores every timeline element—including tracks, clips, gaps, transitions, and markers—in a single **Zustand** store located at [`src/store/timelineStore.ts`](https://github.com/AIEraDev/Clypra/blob/main/src/store/timelineStore.ts). To successfully add new track types such as video, audio, text, sticker, or filter variants to Clypra's timeline store, you must declare the type string in the TypeScript union and configure its visual representation, while the generic store mutations handle the rest automatically.

## Understanding the Timeline Architecture

The timeline store operates on a generic `Track` array without inspecting specific `type` values for core operations. The `TrackType` union, defined in [`src/types/index.ts`](https://github.com/AIEraDev/Clypra/blob/main/src/types/index.ts), controls which strings are valid when creating tracks. When a track is instantiated via `addTrack` or `insertTrackAt`, the store references a `trackHeights` object (lines 17‑23 in [`src/store/timelineStore.ts`](https://github.com/AIEraDev/Clypra/blob/main/src/store/timelineStore.ts)) to assign the default pixel height. This architecture means you can introduce entirely new track categories—such as subtitles or custom effects—without modifying gap detection, ripple editing, or epoch handling logic.

## Step-by-Step Guide to Adding New Track Types

### Step 1: Extend the TrackType Union

First, declare the new track type in the central types file. Open [`src/types/index.ts`](https://github.com/AIEraDev/Clypra/blob/main/src/types/index.ts) and add your new type string to the `TrackType` union:

```typescript
// src/types/index.ts
export type TrackType =
  | "video"
  | "audio"
  | "text"
  | "sticker"
  | "filter"
  | "video-effect"
  | "body-effect"
  | "animated-overlay"
  // Add your new type here
  | "subtitle";

```

This TypeScript definition ensures type safety throughout the application when the new track type is referenced.

### Step 2: Register UI Height in trackHeights

Next, configure the visual height for the new track type in the store. In [`src/store/timelineStore.ts`](https://github.com/AIEraDev/Clypra/blob/main/src/store/timelineStore.ts), locate the `trackHeights` object (lines 17‑23) and add a mapping for your new type:

```typescript
// src/store/timelineStore.ts
const trackHeights: Record<string, number> = {
  video: 68,
  audio: 52,
  text: 30,
  sticker: 30,
  filter: 30,
  "video-effect": 30,
  "body-effect": 30,
  "animated-overlay": 30,
  // Height for the new track type
  subtitle: 30,
};

```

The store uses this value to set the `height` property when creating tracks, ensuring consistent UI rendering.

### Step 3: (Optional) Customize Insertion Logic

By default, new tracks append to the timeline based on generic rules. If your track type requires specific placement—such as always appearing below the main video track—modify the insertion helpers. Update `getInsertIndexForNewTrack` (lines 29‑38) or `getInsertIndexForNewTrackGrouped` (lines 41‑71) in [`src/store/timelineStore.ts`](https://github.com/AIEraDev/Clypra/blob/main/src/store/timelineStore.ts):

```typescript
// src/store/timelineStore.ts
export function getInsertIndexForNewTrack(
  tracks: Track[],
  trackType: TrackType
): number {
  if (trackType === "subtitle") {
    // Place subtitles immediately after the main video track
    const mainIdx = tracks.findIndex((t) => t.type === "video");
    return mainIdx >= 0 ? mainIdx + 1 : tracks.length;
  }
  // Existing logic for other types...
  return tracks.length;
}

```

This optional step ensures logical grouping when users add multiple track types.

### Step 4: Create Tracks Using the New Type

With the configuration complete, create tracks using the standard store methods. The `addTrack` method accepts any valid `TrackType` string:

```typescript
import { useTimelineStore } from "@/store/timelineStore";

function onAddSubtitleTrack() {
  useTimelineStore.getState().addTrack("subtitle");
}

```

The store automatically applies the configured height and executes all standard lifecycle operations.

## How Generic Store Operations Handle New Types

The timeline store's mutation methods—including `addTrack`, `insertTrackAt`, and `removeTrack`—are designed to accept any `TrackType` value. Because gap detection, ripple editing, and clip management operate on the generic `Track[]` array without inspecting the specific `type` field, these features work immediately with your new track type. UI components in [`src/components/editor/timeline/index.ts`](https://github.com/AIEraDev/Clypra/blob/main/src/components/editor/timeline/index.ts) render tracks by reading the `type` and `height` properties directly from the store, so new types appear automatically without component modifications.

## Summary

- **Extend `TrackType`** in [`src/types/index.ts`](https://github.com/AIEraDev/Clypra/blob/main/src/types/index.ts) to declare valid type strings
- **Configure `trackHeights`** in [`src/store/timelineStore.ts`](https://github.com/AIEraDev/Clypra/blob/main/src/store/timelineStore.ts) (lines 17‑23) to set pixel heights
- **Optionally customize** `getInsertIndexForNewTrack` (lines 29‑38) or `getInsertIndexForNewTrackGrouped` (lines 41‑71) for specific insertion rules
- **Use `addTrack()`** with the new type string to create instances
- **Leverage automatic handling** for gaps, ripple editing, and UI rendering without additional code changes

## Frequently Asked Questions

### Do I need to modify the track removal logic when adding a new type?

No. The `removeTrack` method in [`src/store/timelineStore.ts`](https://github.com/AIEraDev/Clypra/blob/main/src/store/timelineStore.ts) operates on track IDs rather than types, so it handles new track types automatically without modification.

### Will ripple editing and gap detection work with custom track types?

Yes. These features rely on the generic `Track` array structure and timestamp calculations rather than specific `type` values, so they function immediately for any track added to the store.

### How do I set different heights for sub-types of tracks?

Add distinct entries to the `trackHeights` object in [`src/store/timelineStore.ts`](https://github.com/AIEraDev/Clypra/blob/main/src/store/timelineStore.ts) for each variation. For example, `"subtitle": 25` and `"caption": 35` can coexist with separate height values.

### Where should I place custom insertion logic if I want tracks grouped by type?

Implement the grouping logic in the `getInsertIndexForNewTrackGrouped` function (lines 41‑71) in [`src/store/timelineStore.ts`](https://github.com/AIEraDev/Clypra/blob/main/src/store/timelineStore.ts), which is designed specifically for type-aware positioning algorithms.