AI-powered headline generator for WordPress using OpenAI GPT-4o-mini. Generate catchy, SEO-friendly headlines directly from the Gutenberg block editor.
- ✅
package.json- NPM dependencies and build scripts - ✅
.gitignore- Git ignore rules - ✅
phpunit.xml- PHPUnit test configuration - ✅
jest.config.js- Jest test configuration
- ✅
headlinehero-ai.php- Main plugin file with WordPress plugin header - ✅
includes/class-headlinehero-ai.php- Main plugin class (singleton pattern) - ✅
includes/class-settings.php- Settings page and Options API - ✅
includes/class-rest-api.php- REST API endpoints - ✅
includes/class-openai-client.php- OpenAI API integration - ✅
includes/class-assets.php- Asset enqueuing - ✅
includes/class-cache.php- Headline caching (5-minute TTL) - ✅
includes/class-history.php- Headline history tracking
- ✅
admin/views/settings-page.php- Settings page template - ✅
admin/css/admin-style.css- Admin page styling
- ✅
src/index.js- Entry point, registers plugin - ✅
src/sidebar.js- Main PluginSidebar component
- ⏳
src/hooks/usePostContent.js- Extract post title & first 500 words - ⏳
src/hooks/useHeadlineGenerator.js- API calls & state management - ⏳
src/hooks/useHistory.js- Load headline history - ⏳
src/hooks/useFavorites.js- Manage favorites in localStorage
- ⏳
src/components/HeadlineGenerator.js- Main generator component - ⏳
src/components/HeadlineList.js- Display all headlines - ⏳
src/components/HeadlineItem.js- Single headline with "Use This" button - ⏳
src/components/GenerateButton.js- Generate button with loading state - ⏳
src/components/ErrorNotice.js- Error display - ⏳
src/components/HistoryPanel.js- Historical headlines (optional advanced feature) - ⏳
src/components/FavoritesPanel.js- Favorites panel (optional advanced feature) - ⏳
src/components/CharacterCounter.js- Character limit display (optional)
- ⏳
src/utils/api.js- API helper functions - ⏳
src/utils/validation.js- Input validation - ⏳
src/utils/textExtraction.js- Text extraction from blocks
- ⏳
src/styles/sidebar.scss- Sidebar component styles
- ⏳
readme.txt- WordPress.org standard readme - ⏳ PHPDoc and JSDoc comments in all files
- ⏳
tests/php/test-rest-api.php- REST API tests - ⏳
tests/php/test-openai-client.php- OpenAI client tests - ⏳
tests/php/test-cache.php- Cache tests - ⏳
tests/js/HeadlineGenerator.test.js- Component tests - ⏳
tests/js/useHeadlineGenerator.test.js- Hook tests - ⏳
tests/js/validation.test.js- Validation tests
npm installThis will install all WordPress packages defined in package.json.
Start the development server with hot reloading:
npm startCreate optimized production build:
npm run buildThis compiles React code to /build directory.
- Copy the entire
headlinehero-ai-wp-pluginfolder towp-content/plugins/ - Go to WordPress Admin > Plugins
- Activate "HeadlineHero AI"
- Go to Settings > HeadlineHero AI
- Enter your OpenAI API key
- Select your default tone preference
- Create or edit a post in the block editor
- Look for the "HeadlineHero AI" sidebar panel (lightbulb icon)
- Write at least 10 words in your post
- Click "Generate Headlines"
- Select one of the 5 generated headlines by clicking "Use This"
Singleton Pattern: The main plugin class uses a singleton pattern to ensure only one instance exists.
REST API Endpoints:
POST /wp-json/headlinehero/v1/generate- Generate headlinesGET /wp-json/headlinehero/v1/history/{post_id}- Get historyDELETE /wp-json/headlinehero/v1/history/{post_id}- Clear history
Security:
- REST API authentication (automatic with WordPress)
- Capability check:
current_user_can('edit_posts') - Input sanitization:
sanitize_text_field(),wp_kses_post() - Output escaping:
esc_html(),esc_attr(),esc_url() - API key stored in wp_options (not exposed to frontend)
Caching:
- Headlines cached in post meta for 5 minutes
- Cache invalidated on post save
- Reduces API costs and improves performance
History:
- Last 10 generation sessions stored per post
- Includes tone, timestamp, and headlines
- Retrievable via REST API
Component Structure:
index.js (entry point)
↓
sidebar.js (PluginSidebar)
↓
HeadlineGenerator (main component)
├─ GenerateButton
├─ HeadlineList
│ └─ HeadlineItem (× 5)
├─ ErrorNotice
├─ HistoryPanel (optional)
├─ FavoritesPanel (optional)
└─ CharacterCounter (optional)
Custom Hooks:
usePostContent- Extracts title and first 500 words from editoruseHeadlineGenerator- Manages API calls and stateuseHistory- Loads headline historyuseFavorites- Manages favorites in localStorage
State Management:
- Uses WordPress
@wordpress/datafor editor state - Local component state for UI
- localStorage for favorites
✅ Generate 5 AI-powered headlines from post content ✅ Three tone options: Professional, Clickbaity, Minimalist ✅ Smart caching (5-minute TTL) ✅ Headline history tracking (last 10 sessions) ✅ Secure API key storage ✅ REST API with proper authentication
⏳ One-click headline application ⏳ Tone selector in sidebar ⏳ Loading spinner during generation ⏳ Error handling with user-friendly messages ⏳ Favorites system (localStorage) ⏳ Character limit warnings ⏳ History panel (collapsible)
- Go to Settings > HeadlineHero AI
- Enter your OpenAI API key
- Save settings
define('HEADLINEHERO_API_KEY', 'sk-your-api-key-here');npm run lint:js # Lint JavaScript
npm run lint:css # Lint CSSnpm run format # Format code with Prettiernpm run test:unit # Run Jest tests
phpunit # Run PHPUnit testsEach tone generates different styles of headlines:
Professional:
- Authoritative and credible
- Clear and informative
- SEO-optimized
- Example: "How to Improve WordPress Security: A Complete Guide"
Clickbaity:
- Curiosity-inducing
- Emotional triggers
- Urgency and mystery
- Example: "You Won't Believe These 5 WordPress Security Tricks"
Minimalist:
- Concise and elegant
- Maximum meaning, minimum words
- Direct and impactful
- Example: "WordPress Security Essentials"
-
Create
src/hooks/usePostContent.js:- Use
@wordpress/datato get current post - Extract title:
select('core/editor').getEditedPostAttribute('title') - Extract content:
select('core/editor').getEditedPostAttribute('content') - Get first 500 words of plain text
- Return:
{ title, content, postId, wordCount }
- Use
-
Create
src/hooks/useHeadlineGenerator.js:- State:
headlines,loading,error generateHeadlines(title, content, tone)function- Use
apiFetchto call REST API - Handle loading/error states
- Return:
{ headlines, loading, error, generateHeadlines }
- State:
-
Create
src/utils/api.js:generateHeadlines(title, content, tone, postId)- API wrapper- Error parsing and formatting
-
Create
src/utils/validation.js:validatePostContent(title, content)- Check minimum requirements- Return:
{ valid: boolean, error: string }
-
Create
src/utils/textExtraction.js:extractPlainText(content)- Strip HTML/blocksgetFirstNWords(text, n)- Get first N words
-
Create
src/components/HeadlineGenerator.js:- Use
usePostContentanduseHeadlineGeneratorhooks - Render tone selector (SelectControl)
- Render generate button
- Display loading spinner
- Show error notices
- Render HeadlineList when headlines available
- Use
-
Create
src/components/HeadlineList.js:- Map
headlinesarray toHeadlineItemcomponents - Pass callbacks for "Use This" action
- Map
-
Create
src/components/HeadlineItem.js:- Display single headline
- "Use This" button
- Use
dispatch('core/editor').editPost({ title: headline })to update title
-
Create
src/components/GenerateButton.js:- Button with loading state (show Spinner when loading)
- Disabled if no API key or insufficient content
-
Create
src/components/ErrorNotice.js:- Use
@wordpress/componentsNotice component - Display error messages
- Optional "Go to Settings" button for API key errors
- Use
-
Install dependencies:
npm install
-
Build assets:
npm run build
-
Test in WordPress:
- Activate plugin
- Configure API key
- Create a post
- Test headline generation
-
Favorites System:
- Create
src/hooks/useFavorites.js - Create
src/components/FavoritesPanel.js - Store in localStorage
- Create
-
History Panel:
- Create
src/hooks/useHistory.js - Create
src/components/HistoryPanel.js - Fetch from REST API
- Create
-
Character Counter:
- Create
src/components/CharacterCounter.js - Color-coded warnings
- Create
-
Styling:
- Create
src/styles/sidebar.scss - Custom styles for components
- Create
-
Write Tests:
- PHPUnit tests for backend
- Jest tests for React components
-
Create readme.txt:
- WordPress.org standard format
- Installation instructions
- FAQ section
- Changelog
-
Add Documentation:
- PHPDoc for all PHP functions
- JSDoc for React components
- Inline comments for complex logic
- PHP classes:
class-name-here.php - React components:
ComponentName.js(PascalCase) - React hooks:
useHookName.js(camelCase with 'use' prefix) - Utilities:
utilityName.js(camelCase) - Styles:
name-here.scss(kebab-case)
If you see "Build files not found" error in WordPress:
npm install
npm run build- Verify key starts with
sk- - Check it's entered correctly in settings
- Test connection from OpenAI platform
- Check browser console for errors
- Verify API key is configured
- Check WordPress REST API is accessible
- Ensure post has at least 10 words
- Verify you're using Gutenberg (block editor)
- Check plugin is activated
- Look for lightbulb icon in top right
- Issues: https://github.com/rehanadil/headlinehero-ai/issues
- Documentation: See
/Users/rehanadil/.claude/plans/parsed-frolicking-cupcake.md - License: GPL v2 or later
Built with:
- WordPress Gutenberg
- OpenAI GPT-4o-mini
- @wordpress/scripts
- React
Version: 1.0.0 Author: Rehan Adil License: GPL v2 or later