sync: SEO canonical URLs, curation improvements, batch scripts, stats fix
- Dynamic canonical URLs and alternates for all pages (SEO fix) - Shared seo.ts utility for canonical path generation - Improved duplicate detection: standalone > aggregator priority, forks/created_at tie-breakers - browseReadyFilter now includes unique aggregator skills - Stats aligned with browseReadyFilter (was showing 16k instead of 62k+) - Re-review mechanism: content_hash changes trigger needs-re-review - review_status field added to skills schema - Batch security scan and quality score scripts - Indexer Dockerfile updated for curation deps - Removed roadmap from README Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,20 @@ import { ApiEndpointSection } from '@/components/ApiEndpointSection';
|
||||
import type { EndpointDef } from '@/components/ApiEndpointSection';
|
||||
import Link from 'next/link';
|
||||
import { ArrowLeft, ArrowRight, Search, FileCode, Users, Compass, Mail } from 'lucide-react';
|
||||
import { getPageAlternates } from '@/lib/seo';
|
||||
|
||||
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>;
|
||||
}) {
|
||||
const { locale } = await params;
|
||||
return {
|
||||
alternates: getPageAlternates(locale, '/docs/api'),
|
||||
};
|
||||
}
|
||||
|
||||
export default async function ApiDocsPage({
|
||||
params,
|
||||
|
||||
@@ -3,6 +3,20 @@ import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import Link from 'next/link';
|
||||
import { ArrowLeft, ArrowRight } from 'lucide-react';
|
||||
import { getPageAlternates } from '@/lib/seo';
|
||||
|
||||
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>;
|
||||
}) {
|
||||
const { locale } = await params;
|
||||
return {
|
||||
alternates: getPageAlternates(locale, '/docs/cli'),
|
||||
};
|
||||
}
|
||||
|
||||
export default async function CliDocsPage({
|
||||
params,
|
||||
|
||||
@@ -6,6 +6,8 @@ import Link from 'next/link';
|
||||
import { ArrowLeft, ArrowRight } from 'lucide-react';
|
||||
import { createDb, skills, sql } from '@skillhub/db';
|
||||
import { formatPromptSkillCount } from '@/lib/format-number';
|
||||
import { getPageAlternates } from '@/lib/seo';
|
||||
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
@@ -15,7 +17,7 @@ async function getSkillCount(): Promise<string> {
|
||||
const result = await db
|
||||
.select({ count: sql<number>`count(*)::int` })
|
||||
.from(skills)
|
||||
.where(sql`${skills.isDuplicate} = false AND (${skills.skillType} IS NULL OR ${skills.skillType} != 'aggregator')`);
|
||||
.where(sql`${skills.isDuplicate} = false`);
|
||||
return formatPromptSkillCount(result[0]?.count ?? 16000);
|
||||
} catch {
|
||||
return '16,000+';
|
||||
@@ -56,6 +58,18 @@ Search for unfamiliar tech or complex tasks. Only install "Pass" security status
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>;
|
||||
}) {
|
||||
const { locale } = await params;
|
||||
return {
|
||||
alternates: getPageAlternates(locale, '/docs/getting-started'),
|
||||
};
|
||||
}
|
||||
|
||||
export default async function GettingStartedPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -3,6 +3,20 @@ import { Header } from '@/components/Header';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { BookOpen, Terminal, Code } from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
import { getPageAlternates } from '@/lib/seo';
|
||||
|
||||
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>;
|
||||
}) {
|
||||
const { locale } = await params;
|
||||
return {
|
||||
alternates: getPageAlternates(locale, '/docs'),
|
||||
};
|
||||
}
|
||||
|
||||
export default async function DocsPage({
|
||||
params,
|
||||
|
||||
Reference in New Issue
Block a user