home / skills / yonatangross / orchestkit / callout-positioning

callout-positioning skill

/plugins/ork/skills/callout-positioning

This skill helps you place callouts, arrows, and annotations precisely in Remotion video compositions across formats and resolutions.

npx playbooks add skill yonatangross/orchestkit --skill callout-positioning

Review the files below or copy the command above to add this skill to your agents.

Files (4)
SKILL.md
10.3 KB
---
name: callout-positioning
description: Debug grids and coordinate systems for accurate arrow/annotation placement in video compositions
tags: [video, remotion, callout, annotation, debug, coordinates, arrows]
user-invocable: false
version: 1.0.0
context: fork
author: OrchestKit
---

# Callout Positioning

Debug grids and coordinate systems for accurate arrow/annotation placement in Remotion video compositions. Essential for precise callout placement across different resolutions and aspect ratios.

## Overview

- Positioning callouts, arrows, and annotations in video compositions
- Debugging coordinate misalignment in Remotion renders
- Calibrating element positions using screenshot-based workflow
- Creating responsive annotations for multi-resolution exports
- Building reusable callout components with precise positioning

## Quick Start

```tsx
// 1. Enable debug grid during development
import { DebugGrid } from './components/DebugGrid';

<AbsoluteFill>
  <YourScene />
  <DebugGrid enabled={process.env.NODE_ENV === 'development'} />
</AbsoluteFill>

// 2. Position callouts using grid coordinates
<Callout
  x={960}   // Center horizontal (1920/2)
  y={540}   // Center vertical (1080/2)
  type="pointer"
  label="Click here"
/>
```

## Coordinate Systems

### 1920x1080 (Horizontal/Landscape)

Standard YouTube/Twitter format. Origin at top-left.

| Region | X Range | Y Range | Description |
|--------|---------|---------|-------------|
| Top-Left | 0-640 | 0-360 | Logo/watermark |
| Top-Center | 640-1280 | 0-360 | Titles |
| Top-Right | 1280-1920 | 0-360 | Controls/badges |
| Center | 640-1280 | 360-720 | Main content |
| Bottom | 0-1920 | 720-1080 | CTAs/captions |

### 1080x1920 (Vertical/Portrait)

TikTok/Reels/Shorts format. Origin at top-left.

| Region | X Range | Y Range | Description |
|--------|---------|---------|-------------|
| Safe-Top | 0-1080 | 200-400 | Below platform UI |
| Center | 0-1080 | 640-1280 | Main content |
| Safe-Bottom | 0-1080 | 1520-1720 | Above controls |

### 1080x1080 (Square)

Instagram/LinkedIn format.

| Region | X Range | Y Range | Description |
|--------|---------|---------|-------------|
| Center | 270-810 | 270-810 | Safe content zone |
| Margins | 0-270 | 0-1080 | Decorative only |

## Debug Grid Component

Enable during development to visualize coordinates.

```tsx
import { DebugGrid } from './components/DebugGrid';

// In your composition
<AbsoluteFill>
  <YourSceneContent />

  {/* Toggle with prop or env var */}
  <DebugGrid
    enabled={showDebug}
    gridSize={100}        // Grid cell size in pixels
    showCoordinates       // Show X,Y at cursor position
    showRulers            // Show pixel rulers on edges
    highlightCenter       // Crosshair at center
    opacity={0.5}
  />
</AbsoluteFill>
```

**See: `references/debug-grid-component.md`** for full component implementation.

## Callout Types

### 1. Pointer Callout

Arrow pointing to a specific location with label.

```tsx
<PointerCallout
  targetX={400}
  targetY={300}
  labelX={600}
  labelY={200}
  label="Important feature"
  arrowColor="#8b5cf6"
  animate              // Fade in with arrow draw
/>
```

### 2. Bracket Callout

Brackets around a region to highlight an area.

```tsx
<BracketCallout
  x={300}
  y={200}
  width={400}
  height={150}
  label="This section"
  position="right"      // Label position: top, right, bottom, left
  bracketColor="#22c55e"
/>
```

### 3. Highlight Callout

Colored overlay to emphasize a region.

```tsx
<HighlightCallout
  x={500}
  y={400}
  width={200}
  height={100}
  color="rgba(139, 92, 246, 0.3)"
  pulse                // Pulsing animation
/>
```

### 4. Number Badge

Numbered circle for step-by-step annotations.

```tsx
<NumberBadge
  number={1}
  x={300}
  y={250}
  size={40}
  color="#f59e0b"
/>
```

## Calibration Workflow

### Step 1: Enable Debug Grid

```tsx
// In your composition root
const showDebug = true; // Toggle manually or via env

<DebugGrid enabled={showDebug} showCoordinates showRulers />
```

### Step 2: Take Screenshot

```bash
# Render single frame with debug grid
npx remotion still MyComposition --frame=30 --output=debug-frame.png
```

### Step 3: Measure Coordinates

Open screenshot in image editor. Note pixel coordinates of target elements.

### Step 4: Apply Coordinates

```tsx
// Use measured coordinates
<PointerCallout
  targetX={847}    // Measured from screenshot
  targetY={312}    // Measured from screenshot
  labelX={1000}
  labelY={200}
  label="Feature name"
/>
```

### Step 5: Verify and Iterate

Re-render and compare. Adjust as needed.

**See: `references/calibration-workflow.md`** for detailed step-by-step guide.

## Responsive Positioning

### Scale-Based Positioning

```tsx
function ResponsiveCallout({ baseWidth = 1920, baseHeight = 1080, x, y, ...props }) {
  const { width, height } = useVideoConfig();

  // Scale coordinates proportionally
  const scaledX = (x / baseWidth) * width;
  const scaledY = (y / baseHeight) * height;

  return <Callout x={scaledX} y={scaledY} {...props} />;
}
```

### Anchor-Based Positioning

```tsx
// Position relative to anchors
type Anchor = 'top-left' | 'top-center' | 'top-right'
            | 'center-left' | 'center' | 'center-right'
            | 'bottom-left' | 'bottom-center' | 'bottom-right';

function AnchoredCallout({ anchor, offsetX = 0, offsetY = 0, ...props }) {
  const { width, height } = useVideoConfig();

  const anchors = {
    'top-left': { x: 0, y: 0 },
    'center': { x: width / 2, y: height / 2 },
    'bottom-right': { x: width, y: height },
    // ... other anchors
  };

  const base = anchors[anchor];
  return <Callout x={base.x + offsetX} y={base.y + offsetY} {...props} />;
}
```

### Format-Specific Presets

```tsx
// Presets for common positions per format
const CALLOUT_PRESETS = {
  '1920x1080': {
    title: { x: 960, y: 100 },
    centerContent: { x: 960, y: 540 },
    bottomCTA: { x: 960, y: 950 },
    topRightBadge: { x: 1800, y: 100 },
  },
  '1080x1920': {
    title: { x: 540, y: 300 },
    centerContent: { x: 540, y: 960 },
    bottomCTA: { x: 540, y: 1700 },
  },
  '1080x1080': {
    title: { x: 540, y: 150 },
    centerContent: { x: 540, y: 540 },
    bottomCTA: { x: 540, y: 930 },
  },
};

function useCalloutPreset(position: string) {
  const { width, height } = useVideoConfig();
  const format = `${width}x${height}`;
  return CALLOUT_PRESETS[format]?.[position] ?? { x: width/2, y: height/2 };
}
```

## Arrow Styling

### Arrow Variants

```tsx
// Solid arrow
<Arrow
  fromX={100} fromY={100}
  toX={300} toY={200}
  strokeColor="#8b5cf6"
  strokeWidth={3}
  headSize={12}
/>

// Curved arrow
<CurvedArrow
  fromX={100} fromY={100}
  toX={300} toY={200}
  curve={0.3}          // Curve amount (0 = straight, 1 = max curve)
  strokeColor="#22c55e"
/>

// Dashed arrow
<Arrow
  fromX={100} fromY={100}
  toX={300} toY={200}
  strokeDasharray="5,5"
  strokeColor="#f59e0b"
/>
```

### Animated Arrows

```tsx
<AnimatedArrow
  fromX={100} fromY={100}
  toX={300} toY={200}
  startFrame={30}
  drawDuration={15}     // Frames to draw arrow
  strokeColor="#8b5cf6"
/>
```

## Best Practices

### 1. Use Debug Grid During Development

Always enable debug grid when positioning callouts. Disable for final renders.

```tsx
const DEBUG = process.env.DEBUG_GRID === 'true';
<DebugGrid enabled={DEBUG} />
```

### 2. Document Coordinates

Comment coordinates with context.

```tsx
<Callout
  x={847}   // Terminal window top-left corner
  y={312}   // First line of output
  label="Result"
/>
```

### 3. Test All Formats

Verify callout positions in all target formats before finalizing.

```bash
# Render test frames for each format
npx remotion still MyComposition-Horizontal --frame=60 --output=test-h.png
npx remotion still MyComposition-Vertical --frame=60 --output=test-v.png
npx remotion still MyComposition-Square --frame=60 --output=test-s.png
```

### 4. Use Relative Positioning When Possible

Prefer anchor-based or percentage positioning over hardcoded pixels for reusability.

### 5. Layer Callouts Properly

Ensure callouts appear above content but below UI overlays.

```
Layer order (top to bottom):
1. UI Overlays (watermark, progress)
2. Callouts/Annotations
3. Main Content
4. Background
```

## Common Pitfalls

| Pitfall | Problem | Solution |
|---------|---------|----------|
| Hardcoded coordinates | Breaks on format change | Use responsive positioning |
| No debug grid | Guessing coordinates | Enable DebugGrid during dev |
| Wrong layer order | Callouts hidden | Check z-index/layer stack |
| Missing safe zones | Content cut off on mobile | Use safe zone margins |
| No calibration | Misaligned annotations | Follow calibration workflow |

## References

- `references/debug-grid-component.md` - Full React/Remotion debug grid component
- `references/coordinate-systems.md` - Grid systems for different resolutions
- `references/calibration-workflow.md` - Step-by-step positioning workflow

## Related Skills

- `remotion-composer` - Core Remotion composition patterns
- `video-storyboarding` - Scene planning and structure
- `video-pacing` - Timing and rhythm for animations

## Key Decisions

| Decision | Choice | Rationale |
|----------|--------|-----------|
| Coordinate origin | Top-left (0,0) | Standard screen coordinate convention |
| Debug grid default | Disabled | Performance in production |
| Position units | Pixels | Direct mapping to render resolution |
| Responsive method | Scale-based | Works across all formats consistently |

---

**Skill Version**: 1.0.0
**Last Updated**: 2026-01-25

## Capability Details

### debug-grid
**Keywords:** debug, grid, overlay, coordinates, ruler, measurement
**Solves:**
- How do I see coordinates in my Remotion composition?
- Debug grid for video positioning
- Visualize pixel coordinates during development

### callout-placement
**Keywords:** callout, annotation, arrow, pointer, label, highlight
**Solves:**
- How do I add callouts to my video?
- Position arrows and labels in Remotion
- Annotate video content with pointers

### coordinate-calibration
**Keywords:** calibrate, measure, screenshot, position, align
**Solves:**
- How do I find exact coordinates for elements?
- Screenshot-based coordinate calibration
- Measure pixel positions in video frames

### responsive-positioning
**Keywords:** responsive, scale, anchor, format, resolution
**Solves:**
- How do I make callouts work across formats?
- Responsive positioning for 1080p and 4K
- Anchor-based positioning in Remotion

Overview

This skill provides tools and patterns to debug grids and coordinate systems for precise callout, arrow, and annotation placement in Remotion video compositions. It helps calibrate positions across resolutions and aspect ratios so annotations stay accurate in multi-format exports. Included components and presets speed up development and verification workflows.

How this skill works

The skill adds a visual DebugGrid overlay that displays rulers, grid cells, coordinates, and center crosshairs during development. It offers callout components (pointer, bracket, highlight, number badge) with pixel and responsive positioning helpers (scale-based, anchor-based, and format presets). A simple screenshot-based calibration workflow ties measured pixels to callout props, and animated arrow variants support timed draws.

When to use it

  • Position arrows and labels precisely in Remotion compositions during development
  • Calibrate annotation positions after rendering a reference frame or screenshot
  • Make annotations responsive across landscape, portrait, and square video formats
  • Debug misaligned callouts or verify safe-area placement before final render
  • Create reusable, production-ready callout components for a design system

Best practices

  • Enable DebugGrid only in development and disable for final renders to avoid performance impact
  • Document measured coordinates with inline comments to preserve context
  • Prefer anchor-based or scaled positioning instead of hardcoded pixels when sharing across formats
  • Test callouts in each target format (1920x1080, 1080x1920, 1080x1080) and render verification frames
  • Layer callouts above content but below persistent UI overlays; follow a clear z-order convention

Example use cases

  • Annotate a product demo with animated pointer arrows that draw on at specific timestamps
  • Highlight a UI region across landscape and vertical cuts using scaled coordinates and presets
  • Create numbered step badges for onboarding videos with consistent placement across resolutions
  • Bracket an area to call out features during narrated walkthroughs and pulse a highlight for emphasis
  • Run a calibration pass: enable grid, render a still, measure in an image editor, apply coordinates, re-render to verify

FAQ

How do I measure coordinates for a target element?

Render a single debug frame with DebugGrid enabled, open the screenshot in an image editor, and read pixel X,Y. Use those values in the callout props or convert them with scale-based helpers.

Will callouts break on different aspect ratios?

Hardcoded pixels can break; use the provided scale-based or anchor-based helpers and format presets to maintain placement across aspect ratios.