mikehenken/writing/storybook-antigravity-skills-nextjs-getting-wins
Published
25 min read
AI AGENT SKILLS

Agent Skills for Storybook 8 and Next.js App Router

How SKILL.md files encode Storybook setup checks, next/navigation mocks, and Radix portal pitfalls for Next.js 15+ projects.

Mike Henken

AI Platform Architect

Jan 15, 202625 min read
Persistent state turns a chat model into an agent. Modular Skills turn that state into something you can version, review, and reuse across repos.

Agent Skills are structured, file-based instructions that load when context matches. They work better than dumping stack docs into every prompt because the agent pulls depth only when the task needs it.

Google AntiGravity, Claude, and Cursor all converge on SKILL.md files, but they discover and execute them differently. This article compares those paths, then walks through a Storybook 8 skill for Next.js App Router + Shadcn UI, with doc links you can verify.

From Autocomplete to Orchestration

To grasp the necessity of "Agent Skills," we must map the trajectory of AI in the development environment.

  • First Generation: Stochastic CompletionTools like initial Copilot versions used "fill-in-the-middle" (FIM). They predicted tokens but lacked "intent awareness."
  • Second Generation: Contextual Chat (RAG)Systems like Cursor and Copilot Chat allowed Q&A with the codebase context. However, the interaction remained synchronous and human-initiated.
  • Third Generation: Agent-First EnvironmentsExemplified by Google AntiGravity. The IDE becomes an orchestration layer. Agents possessPlanning, Tool Use, and State Persistence.

Capability Evolution

Comparing Standard Completion vs AntiGravity Agents

Skill Efficiency Metrics

Standard Prompt
AntiGravity Skill

The Economics of Context

Modern frontend stacks (Next.js App Router, Shadcn, Tailwind) generate massive context requirements. Feeding tens of thousands of tokens of documentation into every request is prohibitively expensive and degrades model reasoning ("Needle in a Haystack" problem).

Progressive Disclosure

This constraint necessitates Progressive Disclosure. Instead of dumping the entire knowledge base, the agent maintains a lightweight index. It loads the heavy procedural knowledge - the "Skill" - only when triggered. This mimics human experts "loading" knowledge from documentation only when needed.

Anatomy of an Agent Skill

The SKILL.md standard is not merely a prompt; it is a structured program for the agent's cognitive process. Explore the layers of a production-ready skill below.

cursorrules.md
// 1. HEADER & ROLE DEFINITION
// Establishes authority and tech stack context immediately.

Act as an expert Senior Frontend Engineer.
Stack: Next.js 14 (App Router), TypeScript, Tailwind CSS, Shadcn UI.
Tool: Storybook 8.

Goal: Create self-contained, interactive stories.
Rules:
- Prefer functional components.
- Use strict TypeScript types.
- Avoid 'any'.

Ecosystem Analysis

FeatureGoogle AntiGravityAnthropic ClaudeCursor
Primary UnitSKILL.md in .agent/skillsSKILL.md in .claude/skills.cursor/rules/*.mdc
Execution ScopeProject-wide orchestrationChat SessionEditor Window
Browser AccessNative "Antigravity Browser"Via MCP ToolLimited / Extension based
Context StrategyProgressive DisclosureProgressive DisclosureEmbeddings + Rules

The Next.js + Storybook 8 Friction Points

Storybook 8 with the @storybook/nextjs framework is the usual setup for App Router projects. It is also where teams hit the same three bugs: navigation mocks, font variables, and Radix portals.

The next/navigation Mocking Problem

App Router replaces next/router with next/navigation. Components using useRouter will crash in Storybook unless you set parameters.nextjs.navigation per theNext.js framework options. Legacy navigation-mock addons are deprecated in Storybook 8+.

The Font Loading Disconnect

Shadcn utilizes next/font for CSS variables. Storybook runs in an iframe that doesn't inherit the Root Layout. Without manual injection via decorators or preview-head.html, components look generic (Times New Roman fallback), breaking visual fidelity.

The Portal/Dialog Trap

Radix UI primitives render Portals to document.body. In Storybook, the theme class (e.g., .dark) is often on a wrapper div. Portals escape this wrapper, resulting in unstyled/white Dialogs in Dark Mode contexts. The skill must enforce decorators that wrap the Story body or apply classes globally.

The Artifact

The Master Skill

The complete construction of the standard-compliant skill, formatted for Google AntiGravity. Copy this into .agent/skills/storybook-architect/SKILL.md.

SKILL.md (v1.2.0)
.agent/skills/storybook-architect/SKILL.md
1name: storybook-architect  
2description: Expert system for creating, debugging, and maintaining Storybook 8 stories in a Next.js App Router + Shadcn UI + Tailwind project. Handles mocking of next/navigation, font injection, and Radix primitives.  
3references:
4  - Storybook 8 Next.js framework: https://storybook.js.org/docs/get-started/frameworks/nextjs
5  - nextjs.navigation parameters: https://storybook.js.org/docs/get-started/frameworks/nextjs#nextjs-options
6  - Interaction tests (@storybook/test): https://storybook.js.org/docs/writing-tests
7  - Storybook 9 migration notes (when upgrading): https://storybook.js.org/docs/releases/migration-guide
8triggers:
9  - "create story"  
10  - "add storybook"  
11  - "fix storybook"  
12  - "mock router"  
13  - "debug component visualization"
14
15---
16
17You are an expert Frontend Architect specializing in Design Systems. Your goal is to ensure that UI components are developed in isolation with fidelity that matches the App Router layout.
18
19## Context analysis (pre-flight)
20
21Before generating any code, you MUST perform the following checks:
22
231. **Detect Import Aliases:**  
24   - Read tsconfig.json. Rule: Use the detected alias consistently.  
252. **Verify Configuration:**  
26   - Read .storybook/preview.ts (Storybook 8 uses preview.ts, not preview.js).  
27   - **Check:** import '../app/globals.css' present?  
28   - **Check:** framework: '@storybook/nextjs' and nextjs: { appDirectory: true } in main.ts?  
29   - **Action:** If missing, propose fix aligned with https://storybook.js.org/docs/get-started/frameworks/nextjs  
303. **Identify Component Dependencies:**  
31   - **Navigation:** If useRouter/useSearchParams -> Apply parameters.nextjs.navigation (see framework docs).  
32   - **Portals:** If Dialog/Sheet/Popover -> Ensure decorator for Radix Portals.
33
34## Story generation standards
35
36### File naming
37* Create [Component].stories.tsx in the same directory as the component.
38
39### Import structure
40```typescript
41import type { Meta, StoryObj } from '@storybook/react';  
42import { fn } from '@storybook/test';  
43import { [Component] } from './[Component]';  
44```
45
46### Meta configuration
47```typescript
48const meta = {  
49  title: 'Feature/[Component]',  
50  component: [Component],  
51  tags: ['autodocs'],  
52  parameters: {  
53    layout: 'centered',  
54    nextjs: { appDirectory: true }, // required for App Router  
55  },  
56  args: { onSubmit: fn() },  
57} satisfies Meta<typeof [Component]>;
58export default meta;
59type Story = StoryObj<typeof meta>;
60```
61
62## Complex integrations
63
64### A. Mocking next/navigation
65```typescript
66export const WithCustomRoute: Story = {  
67  parameters: {  
68    nextjs: {  
69      navigation: {  
70        pathname: '/users/123',  
71        query: { tab: 'settings' },  
72      },  
73    },  
74  },  
75};
76```
77
78### B. Shadcn Dialogs & Portals
79If styling is broken on Dialogs (white bg in dark mode), ensure theme class is applied to body or use decorator:
80```typescript
81decorators: [(Story) => <div className="dark"><Story/></div>]
82```
83
84## Interaction testing (play function)
85For interactive components (Forms, Buttons), use @storybook/test per Storybook 8 docs:
86```typescript
87import { userEvent, within, expect } from '@storybook/test';
88
89export const Interactive: Story = {
90  play: async ({ canvasElement }) => {
91    const canvas = within(canvasElement);
92    await userEvent.type(canvas.getByLabelText(/email/i), '[email protected]');
93    await userEvent.click(canvas.getByRole('button'));
94    await expect(args.onSubmit).toHaveBeenCalled();
95  }
96};
97```
98
99## Artifact output
100Output the FULL file content. Do not use placeholders.
101

References

  1. Storybook 8: Next.js framework
  2. Storybook: Writing tests
  3. Storybook migration guide (8 to 9)
  4. Shadcn UI documentation