{post.category}{minutesLabel(post.readingMinutes)}{formatNumber(post.views ?? 0)} قراءة{accessLabel(post.access)}
{post.title}
{post.dek}
import { getViewer } from '@/lib/viewer' import Topnav from '@/components/topnav' import Footer from '@/components/footer' import Link from 'next/link' import { getPayload } from 'payload' import configPromise from '@payload-config' import { TOPICS, topicsFor, INTEREST_MAP } from '@/lib/topics' import { formatNumber, guidesLabel, minutesLabel, MEMBERSHIP_PRICE } from '@/lib/format' import { freeEarlyAccess, accessLabel, LAUNCH_POLICY } from '@/lib/launch' export const dynamic = 'force-dynamic' /* Demo seed articles remain in the library, but never in the popular section. */ const DEMO_POST_SLUGS = ['first-arabic-agent', 'agent-loop-stop-condition', 'choosing-your-model', 'systematic-model-eval', 'simple-arabic-rag', 'vector-databases-in-practice', 'safe-agent-guardrails', 'agent-output-review-gates', 'indispensable-ai-tools', 'tool-pipelines-and-permissions', 'ai-in-your-business', 'prototype-to-production', 'article-agent-guide'] type Doc = { id: number; title: string; slug: string; dek?: string | null; access: 'free' | 'vip'; category: string; level?: string | null; readingMinutes: number; views?: number | null; cover?: { url?: string | null } | number | null } export default async function HomePage() { const viewer = await getViewer() const payload = await getPayload({ config: configPromise }) const { docs: raw } = await payload.find({ collection: 'posts', where: { status: { equals: 'published' } }, depth: 1, limit: 200, sort: '-publishedAt', select: { title: true, slug: true, dek: true, access: true, category: true, level: true, readingMinutes: true, cover: true }, }) const docs = raw as unknown as Doc[] const freeCount = docs.filter(d => d.access === 'free').length // Hero personalization: matching the viewer's interest floats to the top, // level match ranks higher, ties keep the -publishedAt order. Anonymous // viewers get the plain newest-first list. const interestTopic = viewer?.interest ? INTEREST_MAP[viewer.interest] : undefined const score = (d: Doc) => { if (!interestTopic || !topicsFor(d).includes(interestTopic)) return 0 return d.level === viewer?.level ? 2 : 1 } const hero = docs .map((d, i) => ({ d, i, s: score(d) })) .sort((a, b) => b.s - a.s || a.i - b.i) .slice(0, 4) .map(({ d }) => d) const counts = Object.fromEntries(TOPICS.map(t => [t.key, docs.filter(d => topicsFor(d).includes(t.key)).length])) // Query the complete published collection, not just the 200 newest posts. // Read-count ties prefer the newest publication, then a stable slug order. const { docs: popular } = await payload.find({ collection: 'posts', where: { and: [{ status: { equals: 'published' } }, { slug: { not_in: DEMO_POST_SLUGS } }] }, depth: 1, limit: 6, sort: ['-views', '-publishedAt', 'slug'], select: { title: true, slug: true, dek: true, access: true, category: true, readingMinutes: true, cover: true, views: true }, }) const startHere = popular as unknown as Doc[] return (
مكتبة عربية للذكاء الاصطناعي العملي
محتوى عربي عملي عن الوكلاء والنماذج والأتمتة، يكتبه مهندسو بنية تحتية لمن يريد أن يشغّل شيئاً حقيقياً.
ينتمي كل عنصر محتوى إلى مسار، ويظهر محتوى المبتدئين أيضاً في الأساسيات.
{post.category}{minutesLabel(post.readingMinutes)}{formatNumber(post.views ?? 0)} قراءة{accessLabel(post.access)}
{post.dek}
{LAUNCH_POLICY.summary}
وصول مبكر مجاني
يمكنك قراءة المحتوى المنشور خلال الوصول المبكر دون بطاقة دفع.
> ) : ({MEMBERSHIP_PRICE} شهرياً، وتلغي متى شئت
)}