Write TSDoc comments for Expo SDK APIs following official conventions. MUST USE when introducing new user-facing TypeScript APIs in expo-* packages - document APIs correctly from the start, not as an afterthought. Also use when improving existing documentation. Covers @platform, @example, @deprecated, @default annotations, third-person declarative style, blockquote notes, and type export patterns for docs generation.
npx skills add https://github.com/expo/expo --skill expo-api-docs
Guidelines for writing TSDoc comments in Expo SDK packages. The docs generation system (GenerateDocsAPIData.ts + TypeDoc) extracts these comments to produce API reference documentation.
Document APIs as you write them, not as an afterthought. When implementing new features, write TSDoc comments alongside the code.
packages/expo-*width propertyUse third-person declarative ("Gets...", "Returns...", "Checks..."), not imperative ("Get...", "Return...").
/**
* Gets the uptime since the last reboot of the device, in milliseconds.
* Android devices do not count time spent in deep sleep.
*
* @return A promise fulfilled with the milliseconds since last reboot.
*
* @example
* ```ts
* const uptime = await Device.getUptimeAsync();
* // 4371054
* ```
*
* @platform android
* @platform ios
*/
export async function getUptimeAsync(): Promise<number> {
Key points:
/**
* Sets the sensor update interval.
*
* @param intervalMs Desired interval in milliseconds between sensor updates.
* > Starting from Android 12 (API level 31), the system has a 200Hz limit for each sensor updates.
* >
* > If you need an update interval less than 5ms, add `android.permission.HIGH_SAMPLING_RATE_SENSORS`
* > to [**app.json** `permissions` field](/versions/latest/config/app/#permissions).
*/
setUpdateInterval(intervalMs: number): void {
Format: @param paramName Description starting with capital letter
Parameters can include:
Document each property individually:
export type GetImageOptions = {
/**
* The format of the clipboard image to be converted to.
*/
format: 'png' | 'jpeg';
/**
* Specify the quality of the returned image, between `0` and `1`.
* Applicable only when `format` is set to `jpeg`, ignored otherwise.
* @default 1
*/
jpegQuality?: number;
};
Teach something useful. Bad: "The width". Good: "The width of the captured photo, measured in pixels".
| Tag | Purpose | Example |
|-----|---------|---------|
| @param | Parameter description | @param options Configuration for the request |
| @return / @returns | Return value description | @return A promise fulfilled with the result |
| @default | Default value (no markdown, rendered as inline code) | @default 1 |
| @platform | Platform availability (android, ios, web, expo) | @platform ios 11+ |
| @example | Code example (placed at bottom of description) | See examples below |
| @deprecated | Deprecation notice (auto-formatted as warning) | @deprecated Use newMethod() instead |
| @experimental | Experimental API label | @experimental |
| @hidden / @internal / @private | Hide from generated docs | @hidden |
| @header | Group methods under custom headers | @header Scheduling |
| @needsAudit | Mark for security/API audit (comment, not tag) | // @needsAudit |
| @hideType | Hide generated Type callout for constants | @hideType |
Platform tag notes:
@platform when all platforms are supported — only add when limiting availability@platform tags for multiple platforms (one per line)@platform ios 11+android, ios, web, expo (Expo Go)Always wrap in triple backticks with language tag:
/**
* Checks device root/jailbreak status.
*
* @example
* ```ts
* const isRooted = await Device.isRootedExperimentalAsync();
* if (isRooted) {
* console.warn('Device may be compromised');
* }
* ```
*/
Use > blockquotes for important callouts:
/**
* > **Note:** This method requires the `CAMERA` permission.
*
* > **warning** This method is experimental and not completely reliable.
*/
Formats:
> Note: — informational> warning — caution (lowercase "warning")> on each line with blank > between paragraphs/**
* `true` if the app is running on a real device and `false` if running
* in a simulator or emulator. On web, this is always set to `true`.
*/
export const isDevice: boolean = ExpoDevice.isDevice;
Document the enum and individual values:
/**
* Type used to define what type of data is stored in the clipboard.
*/
export enum ContentType {
PLAIN_TEXT = 'plain-text',
HTML = 'html',
IMAGE = 'image',
/**
* @platform iOS
*/
URL = 'url',
}
Use "resolves to" in @returns tags, following MDN's convention:
@returns A promise that resolves to a CameraPhoto object.@returns A promise fulfilled with a CameraPhoto object.In inline prose, "resolves with" is acceptable (e.g. "The promise resolves with the parsed result").
Critical: Types must be exported from the entry point file for docs generation to pick them up.
Direct re-export from types file:
// index.ts or MainModule.ts
export {
type FileCreateOptions,
type DirectoryCreateOptions,
type FileHandle,
} from './Module.types';
Re-export after import:
// Haptics.ts
import { NotificationFeedbackType, ImpactFeedbackStyle } from './Haptics.types';
// ... function implementations ...
export { NotificationFeedbackType, ImpactFeedbackStyle };
The GenerateDocsAPIData script processes the entry point specified in its package mapping and extracts all publicly exported symbols.
When writing examples in documentation pages:
import * as FileSystem from 'expo-file-system';
const content = await FileSystem.readAsStringAsync(uri);
Always include:
ts, tsx, js, json, swift, kotlin)<SnackInline label="Basic file read" dependencies={['expo-file-system']}>
import * as FileSystem from 'expo-file-system';
export default function App() {
// ...
}
</SnackInline>
<Collapsible summary="Advanced usage with error handling">
try {
const result = await someAsyncOperation();
} catch (error) {
console.error('Operation failed:', error);
}
</Collapsible>
End documentation pages with:
<APISection packageName="expo-file-system" apiName="FileSystem" />
This auto-generates the API reference from TSDoc comments.
Do:
@platform tags for platform-specific APIs@example blocksDon't:
@link tag (not supported — use standard markdown links)@platform tags when all platforms are supportedGuide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
Next.js best practices - file conventions, RSC boundaries, data patterns, async APIs, metadata, error handling, route handlers, image/font optimization, bundling
Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification
Take expo/expo-api-docs from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.