This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
YTgify Chrome Extension - A Chrome extension that creates GIFs from YouTube videos with an integrated visual interface in the YouTube player. The extension uses Manifest V3 and injects UI elements directly into YouTube's video player for seamless GIF creation.
ast-grep is a structural search tool that understands TypeScript/JavaScript AST. It's more powerful than text-based search for finding code patterns.
# Installation (if not already installed)
npm install -g @ast-grep/cli
# Find all React components
ast-grep --pattern 'const $COMP = () => { $$$ }' --lang tsx
# Find all useEffect hooks
ast-grep --pattern 'useEffect(() => { $$$ }, [$$$])' --lang tsx
# Find Chrome API message handlers
ast-grep --pattern 'chrome.runtime.onMessage.addListener($$$)' --lang ts
# Find all interfaces extending a specific type
ast-grep --pattern 'interface $NAME extends $TYPE { $$$ }' --lang ts
# Find React useState declarations
ast-grep --pattern 'const [$STATE, $SETTER] = useState($$$)' --lang tsx
# Find all imports from a specific module
ast-grep --pattern 'import { $$$ } from "@/types"' --lang ts
# Replace pattern example: Update all console.log to use a logger
ast-grep --pattern 'console.log($ARG)' --rewrite 'logger.debug($ARG)' --lang ts
# Find all event handlers in React components
ast-grep --pattern 'on$EVENT={$HANDLER}' --lang tsx
# Find all Chrome storage API calls
ast-grep --pattern 'chrome.storage.$METHOD.$ACTION($$$)' --lang tsFor more complex patterns and rules, see ast-grep documentation.
npm run dev # Start webpack in watch mode for development
npm run build # Build production-ready extension in dist/
npm run clean # Remove dist directorynpm run lint # Run ESLint on src/**/*.{ts,tsx}
npm run typecheck # Run TypeScript type checking (tsc --noEmit)npm test # Run all tests
npm test:watch # Run tests in watch mode
npm test -- path/to/test # Run a specific test file
npm run validate:pre-push # Run full validation pipeline (same as Git hooks)Important Context: This project uses mandatory Git hooks instead of GitHub Actions for E2E testing because:
- Chrome extensions interacting with YouTube videos cannot be reliably tested in CI environments
- YouTube blocks/rate-limits GitHub Actions IPs
- Video playback requires real browser environments with proper codecs
- Extension loading in headless Chrome has limitations
All commits and pushes automatically run the full validation suite locally where tests can properly interact with YouTube.
- Build the extension:
npm run build - Open Chrome and go to
chrome://extensions/ - Enable "Developer mode"
- Click "Load unpacked" and select the
distfolder
The extension follows Chrome's Manifest V3 architecture with three main entry points:
-
Background Service Worker (
src/background/index.ts)- Handles persistent extension logic
- Manages message passing between components
- Processes frame extraction and GIF encoding requests
- Runs as ES module service worker
-
Content Script (
src/content/index.ts)- Injects into YouTube pages matching
https://*.youtube.com/* - Inserts GIF button into YouTube player controls
- Manages timeline overlay for segment selection
- Communicates with background worker for processing
- Injects into YouTube pages matching
-
Popup Interface (
src/popup/index.tsx)- React-based UI shown when extension icon clicked
- Provides access to GIF library and settings
- Tab-based interface (Create/Library views)
YouTube Page → Content Script → Background Worker → Processing
↓ ↓
Timeline Overlay GIF Encoding
↓ ↓
Editor Panel Storage/Export
All GIF-related types are defined in src/types/index.ts:
GifData: Complete GIF with blob data and metadataGifSettings: User-configurable encoding parametersTimelineSelection: Video segment selection dataTextOverlay: Text overlay configuration
The project uses Webpack with multiple entry points configured in webpack.config.js:
- Separate bundles for background, content, and popup
- CSS extraction with PostCSS/Tailwind processing
- Automatic manifest and icon copying
- Path aliases (
@/components,@/lib, etc.) for clean imports
- IndexedDB: For GIF library storage (blob data + metadata)
- Chrome Storage API: For user preferences and settings
- Temporary Canvas: For frame manipulation during processing
The content script uses MutationObserver to detect YouTube's dynamic player loading and injects the GIF button into .ytp-right-controls. The button must be styled to match YouTube's native controls.
All communication between content script and background worker uses Chrome's message passing API with typed message objects. Frame extraction and GIF encoding are handled asynchronously in the background worker.
The project uses TypeScript path aliases that must match between tsconfig.json and webpack.config.js. The tsconfig must NOT have noEmit: true for webpack builds to work.
The extension uses Radix UI components (via shadcn/ui pattern) with Tailwind CSS. Components should follow the shadcn pattern of composition with class variance authority for styling variants.
The extension implements a GIF creation workflow integrated directly into YouTube's player:
- User clicks GIF button in player controls
- Timeline overlay appears for segment selection
- Editor panel opens with live preview
- User adjusts settings (frame rate, resolution, text overlays)
- GIF is encoded and saved to library or downloaded
The GIF library provides persistent local storage with search, filtering, and re-editing capabilities.