Skip to main content
The skills system is a modular architecture that enhances code generation quality by injecting specialized knowledge based on the user’s prompt. It consists of two types of skills: guidance skills (best practices and patterns) and example skills (complete working code).

Architecture overview

The skills system is implemented in src/skills/index.ts and operates in two phases:
  1. Skill detection: An LLM classifier analyzes the prompt and returns matching skill names
  2. Content injection: Relevant skill content is appended to the system prompt before generation

Skill types

Guidance skills

Markdown files containing best practices, common patterns, and rules for specific animation categories. Examples: charts, typography, 3D, transitions.

Example skills

Complete, working animation code from the examples library. Used when the prompt closely matches a known use case.

Skill detection

Skill detection uses a specialized prompt to classify user requests:
export const SKILL_DETECTION_PROMPT = `Classify this motion graphics prompt into ALL applicable categories.
A prompt can match multiple categories. Only include categories that are clearly relevant.

Guidance categories (patterns and rules):
- charts: data visualizations, graphs, histograms, bar charts, pie charts, progress bars, statistics, metrics
- typography: kinetic text, typewriter effects, text animations, word carousels, animated titles, text-heavy content
- social-media: Instagram stories, TikTok content, YouTube shorts, social media posts, reels, vertical video
- messaging: chat interfaces, WhatsApp conversations, iMessage, chat bubbles, text messages, DMs, messenger
- 3d: 3D objects, ThreeJS, spatial animations, rotating cubes, 3D scenes
- transitions: scene changes, fades between clips, slide transitions, wipes, multiple scenes
- sequencing: multiple elements appearing at different times, staggered animations, choreographed entrances
- spring-physics: bouncy animations, organic motion, elastic effects, overshoot animations

Code examples (complete working references):
- example-histogram: animated bar chart with spring animations and @remotion/shapes
- example-progress-bar: loading bar animation from 0 to 100%
- example-text-rotation: rotating words with fade/blur transitions
- example-falling-spheres: 3D bouncing spheres with ThreeJS and physics simulation
- example-animated-shapes: bouncing/rotating SVG shapes (circle, triangle, rect, star)
- example-lottie: loading and displaying Lottie animations from URL
- example-gold-price-chart: bar chart with Y-axis labels, monthly data, staggered animations
- example-typewriter-highlight: typewriter effect with cursor blink, pause, and word highlight
- example-word-carousel: rotating words with crossfade and blur transitions

Return an array of matching category names. Return an empty array if none apply.`;
From src/skills/index.ts:97-121

Detection implementation

// Detect which skills apply to this prompt
let detectedSkills: SkillName[] = [];
try {
  const skillResult = await generateObject({
    model: openai("gpt-5.2"),
    system: SKILL_DETECTION_PROMPT,
    prompt: `User prompt: "${prompt}"`,
    schema: z.object({
      skills: z.array(z.enum(SKILL_NAMES)),
    }),
  });
  detectedSkills = skillResult.object.skills;
  console.log("Detected skills:", detectedSkills);
} catch (skillError) {
  console.error("Skill detection error:", skillError);
}
From src/app/api/generate/route.ts:357-371
Skill detection is non-blocking. If the API call fails, code generation continues without specialized guidance rather than failing the entire request.

Guidance skills

Guidance skills are markdown files containing best practices, common pitfalls, and code patterns. They’re imported at build time and injected into the system prompt.

Available guidance skills

const GUIDANCE_SKILLS = [
  "charts",
  "typography",
  "social-media",
  "messaging",
  "3d",
  "transitions",
  "sequencing",
  "spring-physics",
] as const;
From src/skills/index.ts:14-23

Example: Charts skill

The charts skill (src/skills/charts.md) provides specific guidance on data visualizations:
## Bar Chart Animations

Stagger bar entrances with 3-5 frame delays and use spring() for organic motion.

**Incorrect (all bars animate together):**

```tsx
const bars = data.map((item, i) => {
  const height = spring({ frame, fps, config: { damping: 18 } });
  return <div style={{ height: height * item.value }} />;
});
Correct (staggered entrances):
const STAGGER_DELAY = 5;

const bars = data.map((item, i) => {
  const delay = i * STAGGER_DELAY;
  const height = spring({
    frame: frame - delay,
    fps,
    config: { damping: 18, stiffness: 80 },
  });
  return <div style={{ height: height * item.value }} />;
});

From `src/skills/charts.md:8-35`

### Markdown file structure

Each guidance skill markdown file includes:

- **Frontmatter**: Title, impact rating, and tags
- **Sections**: Organized by specific patterns or problems
- **Code comparisons**: "Incorrect" vs "Correct" examples
- **Explanations**: Why one approach is preferred

## Example skills

Example skills reference complete, working animations from the examples library. They're useful when the prompt closely matches a known pattern.

### Available example skills

```typescript
const EXAMPLE_SKILLS = [
  "example-histogram",
  "example-progress-bar",
  "example-text-rotation",
  "example-falling-spheres",
  "example-animated-shapes",
  "example-lottie",
  "example-gold-price-chart",
  "example-typewriter-highlight",
  "example-word-carousel",
] as const;
From src/skills/index.ts:26-36

Example skill resolution

export function getSkillContent(skillName: SkillName): string {
  // Handle example skills - return the code directly
  if (skillName.startsWith("example-")) {
    const exampleId =
      exampleIdMap[skillName as (typeof EXAMPLE_SKILLS)[number]];
    const example = examples.find((e) => e.id === exampleId);
    if (example) {
      return `## Example: ${example.name}\n${example.description}\n\n\`\`\`tsx\n${example.code}\`\`\``;
    }
    return "";
  }

  // Handle guidance skills - return imported markdown content
  return (
    guidanceSkillContent[skillName as (typeof GUIDANCE_SKILLS)[number]] || ""
  );
}
From src/skills/index.ts:67-83

Content injection

Detected skill content is combined and appended to the base system prompt:
// Load skill-specific content only for NEW skills
const skillContent = getCombinedSkillContent(newSkills as SkillName[]);
const enhancedSystemPrompt = skillContent
  ? `${SYSTEM_PROMPT}\n\n## SKILL-SPECIFIC GUIDANCE\n${skillContent}`
  : SYSTEM_PROMPT;
From src/app/api/generate/route.ts:388-392 The getCombinedSkillContent function concatenates all skill content with separators:
export function getCombinedSkillContent(skills: SkillName[]): string {
  if (skills.length === 0) {
    return "";
  }

  const contents = skills
    .map((skill) => getSkillContent(skill))
    .filter((content) => content.length > 0);

  return contents.join("\n\n---\n\n");
}
From src/skills/index.ts:85-95

Skill caching

To avoid sending redundant content in follow-up messages, the system tracks previously used skills:
// Filter out skills that were already used in the conversation to avoid redundant context
const newSkills = detectedSkills.filter(
  (skill) => !previouslyUsedSkills.includes(skill),
);
if (
  previouslyUsedSkills.length > 0 &&
  newSkills.length < detectedSkills.length
) {
  console.log(
    `Skipping ${detectedSkills.length - newSkills.length} previously used skills:`,
    detectedSkills.filter((s) => previouslyUsedSkills.includes(s)),
  );
}
From src/app/api/generate/route.ts:374-386 Previously used skills remain in the conversation context, so they don’t need to be re-injected.

Adding new skills

To add a new guidance skill:
  1. Create a new markdown file in src/skills/ (e.g., particles.md)
  2. Add the skill name to GUIDANCE_SKILLS array
  3. Import the file at the top of src/skills/index.ts
  4. Add it to the guidanceSkillContent mapping
  5. Update SKILL_DETECTION_PROMPT with classification criteria
To add a new example skill:
  1. Add the example to src/examples/code.ts
  2. Add the skill name to EXAMPLE_SKILLS array (prefix with example-)
  3. Add the mapping in exampleIdMap
  4. Update SKILL_DETECTION_PROMPT with classification criteria
Guidance skills work best when they show incorrect vs correct code patterns. This helps the LLM avoid common mistakes.

Build docs developers (and LLMs) love