feat(curation): auto-curation after crawl + quality messaging
Automate curation: - Add runPostCrawlCuration() to DB queries — runs after every full and incremental crawl (classify, dedup, category counts) - No more need for manual curate.mjs runs after each crawl Quality messaging: - Homepage stats label: "Skills" → "Curated Skills" (en/fa) - Add curation note: "deduplicated and quality-filtered from X+ repos" - Update fallback counts from 172K to 16K across all touchpoints (BetaBanner, getting-started prompts, email templates) - getting-started skill count query now uses browse-ready filter Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,10 +14,11 @@ async function getSkillCount(): Promise<string> {
|
||||
const db = createDb();
|
||||
const result = await db
|
||||
.select({ count: sql<number>`count(*)::int` })
|
||||
.from(skills);
|
||||
return formatPromptSkillCount(result[0]?.count ?? 170000);
|
||||
.from(skills)
|
||||
.where(sql`${skills.isDuplicate} = false AND (${skills.skillType} IS NULL OR ${skills.skillType} != 'aggregator')`);
|
||||
return formatPromptSkillCount(result[0]?.count ?? 16000);
|
||||
} catch {
|
||||
return '170,000+';
|
||||
return '16,000+';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,11 +44,19 @@ async function getStats() {
|
||||
.where(browseReady);
|
||||
const totalContributors = contributorsResult[0]?.count ?? 0;
|
||||
|
||||
// Get total indexed skills (all, before curation) for curation note
|
||||
const totalIndexedResult = await db
|
||||
.select({ count: sql<number>`count(*)::int` })
|
||||
.from(skills)
|
||||
.where(sql`${skills.isBlocked} = false`);
|
||||
const totalIndexed = totalIndexedResult[0]?.count ?? 0;
|
||||
|
||||
return {
|
||||
totalSkills,
|
||||
totalDownloads,
|
||||
totalCategories,
|
||||
totalContributors,
|
||||
totalIndexed,
|
||||
platforms: 5,
|
||||
};
|
||||
} catch (error) {
|
||||
@@ -186,6 +194,9 @@ export default async function HomePage({
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-center text-text-muted text-sm mt-6">
|
||||
{t('stats.curationNote', { totalIndexed: formatCompactNumber(statsData?.totalIndexed ?? 0, locale) })}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ export function BetaBanner() {
|
||||
|
||||
if (!isVisible) return null;
|
||||
|
||||
const count = skillCount || (locale === 'fa' ? '۱۷۲k' : '172k');
|
||||
const count = skillCount || (locale === 'fa' ? '۱۶k' : '16k');
|
||||
|
||||
return (
|
||||
<div className="relative bg-gradient-to-r from-primary-600 to-primary-500 text-white">
|
||||
|
||||
@@ -220,12 +220,12 @@ export function buildWelcomeEmail(locale: Locale, username: string, email?: stri
|
||||
const dir = getDir(locale);
|
||||
const align = getAlign(locale);
|
||||
|
||||
// Format skill count: dynamic if provided, fallback to "172,000+"
|
||||
// Format skill count: dynamic if provided, fallback to "16,000+"
|
||||
const skillCountStr = totalSkillCount
|
||||
? (locale === 'fa'
|
||||
? totalSkillCount.toLocaleString('fa-IR')
|
||||
: totalSkillCount.toLocaleString('en-US'))
|
||||
: (locale === 'fa' ? '۱۷۲,۰۰۰' : '172,000');
|
||||
: (locale === 'fa' ? '۱۶,۰۰۰' : '16,000');
|
||||
|
||||
const body = `
|
||||
<h1 style="margin: 0 0 16px 0; color: ${COLORS.text}; font-size: 24px; text-align: ${align};">
|
||||
|
||||
@@ -47,10 +47,11 @@
|
||||
"ctaSecondary": "Getting Started"
|
||||
},
|
||||
"stats": {
|
||||
"skills": "Skills",
|
||||
"skills": "Curated Skills",
|
||||
"downloads": "Downloads",
|
||||
"contributors": "Contributors",
|
||||
"categories": "Categories"
|
||||
"categories": "Categories",
|
||||
"curationNote": "Every skill is deduplicated and quality-filtered from {totalIndexed}+ indexed repositories"
|
||||
},
|
||||
"featured": {
|
||||
"title": "Featured Skills",
|
||||
|
||||
@@ -47,10 +47,11 @@
|
||||
"ctaSecondary": "راهنمای شروع"
|
||||
},
|
||||
"stats": {
|
||||
"skills": "مهارت",
|
||||
"skills": "مهارت برگزیده",
|
||||
"downloads": "دانلود",
|
||||
"contributors": "مشارکتکننده",
|
||||
"categories": "دستهبندی"
|
||||
"categories": "دستهبندی",
|
||||
"curationNote": "هر مهارت از میان {totalIndexed}+ مخزن ایندکسشده، حذف تکراری و فیلتر کیفیت شده است"
|
||||
},
|
||||
"featured": {
|
||||
"title": "مهارتهای ویژه",
|
||||
|
||||
Reference in New Issue
Block a user