How to Implement Text Overlays with Custom Fonts, Styles, and Animations in Clypra

You implement text overlays in Clypra by creating a TextClip with custom styling options and attaching a TextEffectDefinition for animations, then placing it on an overlay track where the compositor handles blending and depth ordering.

Clypra treats every visual element on the timeline as a clip, which means text overlays are specialized Clip objects with an "overlay" role and a "text" asset type. This guide walks you through how to implement text overlays with custom fonts, styles, and animations in Clypra using the architecture found in the AIEraDev/Clypra repository.

Understanding the Clypra Text Overlay Architecture

In Clypra, a text overlay is formally a Clip whose role is "overlay" and whose underlying asset type is "text". The system separates concerns across type definitions, clip utilities, and rendering pipelines to ensure overlays render correctly on top of primary video tracks.

The Clip-Based Model

According to src/types/index.ts (lines 94-213), the system defines TrackType, ClipKind, and the ClipOverlay interface. These types declare overlay-specific properties such as blendMode, opacity, and zIndex. When you place a text asset on a non-primary track, the placement policy in src/lib/timeline/placementPolicy.ts automatically assigns the "overlay" role via the resolveTargetTrackType function.

Core Components

The implementation spans several key source files:

Implement Text Overlays with Custom Fonts and Styles in Clypra

The createTextClip function in src/lib/text/textClip.ts serves as the primary entry point for building text overlays. It accepts a CreateTextClipOptions object that defines typography, colors, effects, and positioning.

TextClip Options and Customization

The CreateTextClipOptions interface supports extensive styling:

  • Typography: fontFamily, fontSize, fontWeight, bold, italic, letterSpacing, lineHeight
  • Appearance: color, stroke, shadow, background
  • Layout: position, canvasWidth, canvasHeight
  • References: styleId (for saved text styles), effectDefinition (for animations)
// src/lib/text/textClip.ts usage
import { createTextClip } from '@clypra/lib/text/textClip';

const clip = createTextClip({
  trackId: 't2',
  startTime: 12.0,
  duration: 5,
  text: 'Welcome to Clypra!',
  canvasWidth: 1920,
  canvasHeight: 1080,
  fontSize: 72,
  fontFamily: 'Inter',
  fontWeight: 700,
  color: '#FFF',
  bold: true,
  italic: false,
  letterSpacing: 2,
  lineHeight: 1.2,
  position: 'bottom',
  // Custom stroke and shadow for visual depth
  stroke: { color: '#000', width: 3 },
  shadow: { color: '#000', blur: 6, offsetX: 2, offsetY: 2 },
});

Handling Effects and Animations

To animate a text overlay, you attach a TextEffectDefinition to the clip. This definition drives keyframe interpolation and declares how the system should calculate the bounding box during animation.

Attaching TextEffectDefinition

The effect definition controls how text appears over time. You define keyframes for properties like opacity, reveal, and transform values. The render engine hooks read the current timeline position and feed the interpolated values to the canvas.

Computing Effect Bleed Areas

The effectBleed function (lines 123-190 in src/lib/text/textClip.ts) calculates safe padding by inspecting the style's strokes, shadows, glows, and bevels. Alternatively, provide an explicit boundingBox in your TextEffectDefinition for exact padding control.

// Example TextEffectDefinition with keyframes
export const typeWriterEffect: TextEffectDefinition = {
  name: 'Type Writer',
  keyframes: [
    { time: 0, opacity: 0, reveal: 0 },
    { time: 1.5, opacity: 1, reveal: 0.5 },
    { time: 5, opacity: 1, reveal: 1 },
  ],
  // Optional explicit boundingBox instead of using effectBleed
  boundingBox: { mode: 'clip', paddingX: 12, paddingY: 8 },
};

// Attach when creating the clip
const animatedClip = createTextClip({
  ...baseOptions,
  effectDefinition: typeWriterEffect,
});

Timeline Placement and Rendering

Once created, the clip must be placed on the timeline and rendered through Clypra's compositor, which ensures proper depth ordering and blending.

Track Types and Role Assignment

Place text clips on tracks with trackType set to "text" or "overlay". According to src/lib/timeline/placementPolicy.ts, the resolveTargetTrackType logic automatically assigns the "overlay" role, ensuring the clip renders after the primary video track but before final output.

Compositor Evaluation and Blending

During evaluation in src/core/evaluation/evaluator.ts (lines 306-389), the system sorts visual layers by role (primary → overlay → text → effect), then applies the blendMode and opacity properties from the ClipOverlay interface. The zIndex controls stacking among multiple overlays.

// Rendering with viewport hooks
import { useViewportController } from '@/core/interactions/ViewportController';
import { useTimelineStore } from '@/store/timelineStore';

function OverlayRenderer({ clip }) {
  const { time } = useTimelineStore(); // Current scrub time
  const { transform } = useViewportController(clip, time);

  return (
    <canvas
      style={{
        transform,
        mixBlendMode: clip.blendMode ?? 'normal',
        opacity: clip.opacity ?? 1,
      }}
    />
  );
}

Summary

  • Text overlays are specialized Clip objects with role: "overlay" and asset type "text".
  • Use createTextClip from src/lib/text/textClip.ts with CreateTextClipOptions to define custom fonts, colors, strokes, and shadows.
  • Attach a TextEffectDefinition for animations, using either an explicit boundingBox or the fallback effectBleed function to calculate padding from style effects.
  • Place clips on "text" or "overlay" tracks; the placement policy in src/lib/timeline/placementPolicy.ts handles role assignment automatically.
  • The compositor in src/core/evaluation/evaluator.ts sorts layers by role and applies blend modes and opacity.
  • ViewportController and render engine hooks provide live transform data for scrubbing and final output.

Frequently Asked Questions

How does Clypra determine the bounding box for animated text overlays?

Clypra computes bounding boxes through the effectBleed function in src/lib/text/textClip.ts (lines 123-190), which inspects stroke width, shadow blur, glows, and bevels to calculate safe padding. Alternatively, you can specify an explicit boundingBox property in your TextEffectDefinition with exact paddingX and paddingY values to override the automatic calculation.

What track type should I use for text overlays in Clypra?

Place text overlays on tracks with trackType set to "text" or "overlay". According to src/lib/timeline/placementPolicy.ts, the resolveTargetTrackType function automatically assigns the "overlay" role to text assets placed on non-primary tracks, ensuring they render after the primary video but maintain proper depth ordering relative to other overlays.

Can I use custom web fonts with Clypra text overlays?

Yes. Pass your custom font family name to the fontFamily property in CreateTextClipOptions when calling createTextClip. The renderer loads web fonts automatically during the rendering phase, allowing you to reference any font available to the browser or bundled with your application.

How do I animate opacity and transforms in a text overlay?

Define keyframes in your TextEffectDefinition object, specifying values like opacity and reveal at different timestamps. The render engine hooks in src/lib/renderEngine/hooks.ts read the current timeline position and feed transform data to the ViewportController, which updates the canvas during scrubbing or final playback.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →