+ {t(
+ 'socialProof.pendingSummary',
+ 'Public activity metrics appear here after we collect enough completed jobs and verified ratings.'
+ )}
+
+ )}
- {t('socialProof.basedOnRatings', { count: stats.rating_count })}
+ {hasReliableRating
+ ? t('socialProof.basedOnRatings', { count: stats.rating_count })
+ : t('socialProof.pendingRatings', 'Ratings summary will unlock after enough verified feedback.')}
{t('socialProof.viewDevelopers')}
diff --git a/frontend/src/pages/DevelopersPage.tsx b/frontend/src/pages/DevelopersPage.tsx
index 6f9be8e..f6ed8c8 100644
--- a/frontend/src/pages/DevelopersPage.tsx
+++ b/frontend/src/pages/DevelopersPage.tsx
@@ -22,15 +22,14 @@ const ENDPOINT_GROUPS = [
},
];
-const CURL_UPLOAD = `curl -X POST https://your-domain.example/api/v1/convert/pdf-to-word \\
- -H "X-API-Key: spdf_your_api_key" \\
- -F "file=@./sample.pdf"`;
-
-const CURL_POLL = `curl https://your-domain.example/api/v1/tasks/
/status \\
- -H "X-API-Key: spdf_your_api_key"`;
-
export default function DevelopersPage() {
const { t } = useTranslation();
+ const origin = typeof window !== 'undefined' ? window.location.origin : 'https://dociva.io';
+ const curlUpload = `curl -X POST ${origin}/api/v1/convert/pdf-to-word \\
+ -H "X-API-Key: spdf_your_api_key" \\
+ -F "file=@./sample.pdf"`;
+ const curlPoll = `curl ${origin}/api/tasks//status \\
+ -H "X-API-Key: spdf_your_api_key"`;
return (
<>
@@ -91,12 +90,12 @@ export default function DevelopersPage() {
{t('pages.developers.authExampleTitle')}
{t('pages.developers.authExampleSubtitle')}
- {CURL_UPLOAD}
+ {curlUpload}
{t('pages.developers.pollExampleTitle')}
{t('pages.developers.pollExampleSubtitle')}
- {CURL_POLL}
+ {curlPoll}
diff --git a/frontend/src/utils/seo.ts b/frontend/src/utils/seo.ts
index b6b4044..f9d28d6 100644
--- a/frontend/src/utils/seo.ts
+++ b/frontend/src/utils/seo.ts
@@ -17,6 +17,8 @@ export interface LanguageAlternate {
ogLocale: string;
}
+const DEFAULT_SOCIAL_IMAGE_PATH = '/social-preview.svg';
+
const LANGUAGE_CONFIG: Record<'en' | 'ar' | 'fr', { hrefLang: string; ogLocale: string }> = {
en: { hrefLang: 'en', ogLocale: 'en_US' },
ar: { hrefLang: 'ar', ogLocale: 'ar_SA' },
@@ -42,6 +44,10 @@ export function buildLanguageAlternates(origin: string, path: string): LanguageA
}));
}
+export function buildSocialImageUrl(origin: string): string {
+ return `${origin}${DEFAULT_SOCIAL_IMAGE_PATH}`;
+}
+
/**
* Generate WebApplication JSON-LD structured data for a tool page.
*/
diff --git a/scripts/generate_sitemap.py b/scripts/generate_sitemap.py
index 4f6c2ba..bbcbdde 100644
--- a/scripts/generate_sitemap.py
+++ b/scripts/generate_sitemap.py
@@ -11,7 +11,9 @@ Usage:
import argparse
import os
+import re
from datetime import datetime
+from pathlib import Path
# ─── Route definitions with priority and changefreq ──────────────────────────
@@ -95,9 +97,21 @@ TOOL_GROUPS = [
]
+def get_blog_slugs() -> list[str]:
+ repo_root = Path(__file__).resolve().parents[1]
+ blog_articles_path = repo_root / 'frontend' / 'src' / 'content' / 'blogArticles.ts'
+
+ if not blog_articles_path.exists():
+ return []
+
+ content = blog_articles_path.read_text(encoding='utf-8')
+ return list(dict.fromkeys(re.findall(r"slug:\s*'([^']+)'", content)))
+
+
def generate_sitemap(domain: str) -> str:
today = datetime.now().strftime('%Y-%m-%d')
urls = []
+ blog_slugs = get_blog_slugs()
# Static pages
for page in PAGES:
@@ -108,6 +122,16 @@ def generate_sitemap(domain: str) -> str:
{page["priority"]}
''')
+ if blog_slugs:
+ urls.append('\n ')
+ for slug in blog_slugs:
+ urls.append(f'''
+ {domain}/blog/{slug}
+ {today}
+ monthly
+ 0.6
+ ''')
+
# Tool pages by category
for label, routes in TOOL_GROUPS:
urls.append(f'\n ')
@@ -143,7 +167,7 @@ def main():
with open(args.output, 'w', encoding='utf-8') as f:
f.write(sitemap)
- total = len(PAGES) + sum(len(routes) for _, routes in TOOL_GROUPS)
+ total = len(PAGES) + len(get_blog_slugs()) + sum(len(routes) for _, routes in TOOL_GROUPS)
print(f"Sitemap generated: {args.output}")
print(f"Total URLs: {total}")