-
Notifications
You must be signed in to change notification settings - Fork 2
Troubleshooting Guide
Solutions to common issues and problems with power-seo.
Symptom:
Error: Cannot find module '@power-seo/core'
Solution:
-
Verify installation:
npm list @power-seo/core
-
Clear cache and reinstall:
rm -rf node_modules npm install
-
Check Node.js version:
node --version # Must be 18.0.0+
Symptom:
Type error: Property 'focusKeyphrase' is missing
Solution:
-
Update TypeScript:
npm install --save-dev typescript@latest
-
Regenerate types:
npm run typecheck
-
Check tsconfig.json:
{ "compilerOptions": { "strict": true, "skipLibCheck": false } }
Symptom: Page source doesn't show meta tags when viewing browser source
Solution:
For Next.js:
// ❌ Wrong - generateMetadata not called
export default function Page() {
return <h1>Page</h1>;
}
// ✅ Correct - generateMetadata is required
export function generateMetadata() {
return createMetadata({
title: 'Page Title',
description: 'Description'
});
}
export default function Page() {
return <h1>Page</h1>;
}For Remix:
// ✅ Must use meta export
export const meta: MetaFunction = () =>
createMetaDescriptors({
title: 'Page Title',
description: 'Description'
});For React SPA:
// ✅ Must wrap with DefaultSEO
<DefaultSEO
title="My Site"
description="Description"
>
<Routes>
{/* routes */}
</Routes>
</DefaultSEO>Symptom:
Schema validation failed: issues=[...]
Solution: Check for common errors:
import { article, validateSchema } from '@power-seo/schema';
const schema = article({
headline: 'Title',
// ❌ Missing required: datePublished
});
const { valid, issues } = validateSchema(schema);
if (!valid) {
issues.forEach(issue => {
console.error(`${issue.path}: ${issue.message}`);
// Output: "root.datePublished: Property is missing"
});
}
// ✅ Fixed - add required fields
const schema = article({
headline: 'Title',
datePublished: '2026-01-15' // ✅ Add this
});Common validation errors:
- Missing
datePublishedin article - Invalid date format (must be ISO 8601:
YYYY-MM-DDTHH:MM:SSZ) - Image width/height not specified
- Malformed URLs
Symptom: Facebook/Twitter show old content even after editing
Solution:
-
Check Open Graph tags:
openGraph={{ type: 'article', images: [{ url: 'https://example.com/og.jpg', // ✅ Must be absolute URL width: 1200, height: 630 }] }}
-
Validate image URL is accessible:
- Open URL in browser - must load
- Use HTTPS (not HTTP)
- Image must be 1200x630px minimum
-
Clear social cache:
- Facebook: https://developers.facebook.com/tools/debug/
- Twitter: https://cards-dev.twitter.com/validator
- LinkedIn: https://www.linkedin.com/feed/
-
Wait for cache expiration (1-48 hours)
Symptom:
Score: 25/55 (45%)
Solution: Check individual factors:
import { analyzeContent } from '@power-seo/content-analysis';
const result = analyzeContent({
title: 'My Article',
content: '<h1>My Article</h1><p>Content here</p>',
focusKeyphrase: 'my keyword',
images: [{ src: '/image.jpg', alt: 'Image alt' }],
internalLinks: ['/page1'],
externalLinks: ['https://external.com']
});
// Check individual results
result.results.forEach(r => {
console.log(`${r.name}: ${r.status}`);
console.log(` Message: ${r.message}`);
});Common issues:
- ❌ Keyphrase not in title → Add to title
- ❌ Keyphrase density too low → Use keyword more (2-3% optimal)
- ❌ Description too short → Expand to 120-160 chars
- ❌ No internal links → Add 2-3 internal links
- ❌ Content too short → Write 300+ words
- ❌ Images missing alt text → Add descriptive alt text
Symptom:
Flesch-Kincaid Grade: 16.5
(requires 16+ years of education)
Solution: Simplify content:
import { analyzeReadability } from '@power-seo/readability';
const result = analyzeReadability({
content: '<h1>Title</h1><p>Your content</p>'
});
console.log(result.recommendations);
// Example: ['Shorten sentences', 'Use simpler words', 'Break up paragraphs']Strategies to improve:
-
Shorter sentences (15-20 words average)
❌ Complex content with advanced terminology ✅ Keep it simple. Use basic words. Short sentences. -
Shorter words
❌ utilize, approximately, subsequently ✅ use, about, later -
More paragraphs (max 3-4 sentences per paragraph)
-
More subheadings (one per 300 words)
Symptom:
Error: Out of memory
Solution: Use streaming instead:
// ❌ Wrong - loads all URLs in memory
const xml = generateSitemap({
hostname: 'https://example.com',
urls: allMillion Urls // Too much memory!
});
// ✅ Correct - streams URLs
import { streamSitemap } from '@power-seo/sitemap';
export async function GET() {
const urls = await fetchAllUrls(); // from database
const chunks = [...streamSitemap('https://example.com', urls)];
return new Response(chunks.join(''), {
headers: { 'Content-Type': 'application/xml' }
});
}Solution: Use sitemap splitting:
import { splitSitemap } from '@power-seo/sitemap';
const { index, sitemaps } = splitSitemap({
hostname: 'https://example.com',
urls: allUrls // Can be 1M+ URLs
});
// index.xml contains references to sitemaps
// sitemaps[0], sitemaps[1], etc. contain actual URLs (max 50k each)Symptom:
User visits /old-page → Still sees /old-page
Solution:
For Next.js (next.config.js):
// ❌ Wrong - redirects defined but not used
export async function redirects() {
return [
{ source: '/old', destination: '/new', permanent: true }
];
}
// ✅ Correct - must be in next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
async redirects() {
return [
{ source: '/old', destination: '/new', permanent: true }
];
}
};
module.exports = nextConfig;For Remix:
// ✅ Use redirect() in loaders
import { redirect } from '@remix-run/node';
export const loader: LoaderFunction = async ({ params }) => {
if (params.oldSlug) {
throw redirect(`/new-url/${params.oldSlug}`, 301);
}
return null;
};Symptom:
Bundle size: 250 KB (expected < 100 KB)
Solution:
-
Only install needed packages:
# ❌ Wrong - installs everything npm install @power-seo/core @power-seo/react @power-seo/schema \ @power-seo/audit @power-seo/search-console ... # ✅ Right - install only what you need npm install @power-seo/meta @power-seo/schema
-
Check what you import:
// ❌ Wrong - imports entire package import * as powerseo from '@power-seo/schema'; // ✅ Right - imports only used function import { article } from '@power-seo/schema';
-
Verify tree-shaking works:
npm install -g bundlesize bundlesize --max-size 100KB
-
Use production build:
npm run build # Minifies and optimizes
Symptom:
Property 'datePublished' is missing
Solution: All required fields must be provided:
import { article } from '@power-seo/schema';
// ❌ Type error - missing datePublished
const schema = article({
headline: 'Title'
});
// ✅ Correct - all required fields
const schema = article({
headline: 'Title',
datePublished: '2026-01-15T10:00:00Z'
});Symptom:
analyzeContent() takes 500ms+
Solution:
-
Debounce analysis in React:
const [debounceTimer, setDebounceTimer] = useState(null); const handleChange = (content) => { clearTimeout(debounceTimer); setDebounceTimer(setTimeout(() => { // Run analysis only after user stops typing analyzeContent(content); }, 300)); };
-
Memoize results:
const analysis = useMemo( () => analyzeContent(content), [content] // Only recompute if content changes );
-
Run in Web Worker:
// worker.ts import { analyzeContent } from '@power-seo/content-analysis'; self.onmessage = (e) => { const result = analyzeContent(e.data); self.postMessage(result); }; // component.tsx const worker = new Worker('worker.ts'); worker.postMessage(content); worker.onmessage = (e) => setAnalysis(e.data);
Solution:
// ✅ generateMetadata receives params
export function generateMetadata({ params, searchParams }) {
return createMetadata({
title: `Product: ${params.id}`,
description: `Showing product ${params.id}`
});
}
// ✅ Revalidate cache if needed
export const revalidate = 3600; // Revalidate every hourSolution:
// ✅ Must be in route file, not component
export const meta: MetaFunction = () =>
createMetaDescriptors({...});
// ✅ meta export must be at route level
export default function Route() {
return <h1>Page</h1>;
}Solution:
// ✅ Update meta tags on each route change
import { useEffect } from 'react';
import { SEO } from '@power-seo/react';
function Page() {
useEffect(() => {
// Ensure document title is set
document.title = 'Page Title';
}, []);
return (
<>
<SEO title="Page Title" description="Description" />
<h1>Page Content</h1>
</>
);
}If you can't find a solution:
- Check GitHub Issues: https://github.com/CyberCraftBD/power-seo/issues
- Start Discussion: https://github.com/CyberCraftBD/power-seo/discussions
- Email: info@ccbd.dev
-
Debug Tips:
// Enable verbose logging const result = analyzeContent(input); console.log(JSON.stringify(result, null, 2));