لو موقعك بيظهر في نتائج Google كويس، لكن لما حد يسأل Perplexity أو ChatGPT سؤال موضوعك بيتخصص فيه، الإجابة بتجيب من مصادر تانية — فـ المشكلة غالبًا مش في محتواك، المشكلة إن نماذج الـ LLM مبتعرفش ازاي تنتقّي منه.
الخلاصة قبل ما نبدأ: ملف llms.txt بيحل المشكلة دي في أقل من 30 سطر كود Python + ملف GitHub Actions واحد. السكربت في الآخر شغّال فعليًا، وأرقام الـ referrer من مشروع جرّبته بنفسي.
ليه llms.txt مهم في 2026 بالظبط؟
ChatGPT Search و Perplexity و Claude مع أداة الويب، كلها لما بتجاوب على سؤال، بتعمل خطوتين: (1) بتحدد صفحات ممكن تحتوي الإجابة، (2) بتفتحها وتقرأ منها. الخطوة الأولى بتعتمد على sitemap.xml والـ search، لكن الخطوة الثانية مُكلفة — كل صفحة HTML فيها navigation وإعلانات وتعليقات، فـ النموذج بيحتاج يقرا 50 ألف كلمة عشان يستخرج 200 كلمة مفيدة.
ملف llms.txt بيقول للنموذج: "متخدش ده طريق طويل، هنا فهرس منظّم لأهم صفحاتي، كل صفحة معاها سطر وصف قصير". النتيجة: النموذج بيختار صفحاتك أسرع، وبيقتبس منها أكتر.
مثال بسيط جدًا للمبتدئين
تخيّل إنك بتدخل مكتبة جديدة. فيه طريقتين:
- الطريقة الأولى: تفضل تمشي بين الرفوف وتقرا كل غلاف كتاب. هتلاقي اللي بتدوّر عليه بعد 3 ساعات.
- الطريقة الثانية: في المدخل فيه ورقة A4 مكتوب فيها: "قسم الرياضيات – رف 3 – كتب 12 إلى 34". هتوصل في دقيقة.
ملف llms.txt هو الورقة A4 دي. الـ LLM هو اللي داخل المكتبة. من غيره، بيقرا موقعك كله عشان يطلع بجملة.
الشكل الرسمي للملف
المواصفة اللي طلعها Jeremy Howard في 2024 واعتمدها Anthropic ثم Perplexity في 2025، بتطلب ملف Markdown بسيط في جذر الدومين (https://example.com/llms.txt) بالشكل ده:
# اسم الموقع
> سطر أو اتنين يشرحوا الموقع بيتكلم عن إيه بالظبط.
## Docs
- [عنوان الصفحة](https://example.com/page): وصف قصير لمحتواها.
- [صفحة تانية](https://example.com/page2): وصف آخر.
## Blog
- [مقال](https://example.com/post-1): النتيجة اللي هيكسبها القارئ.
ملحوظة مهمة: فيه نسخة موسّعة اسمها llms-full.txt بيتحط فيها نص كل صفحة كامل بصيغة Markdown. Anthropic بتستخدم llms-full.txt في docs.anthropic.com، ومقاساتها نحو 800 KB. نبني الاتنين.
السكربت الكامل — ينفع انسخه زي ما هو
السكربت بيقرا sitemap.xml بتاع موقعك، يفتح كل URL، يستخرج العنوان والـ meta description، ويبني الملف. شغّال على أي موقع عنده sitemap صالح.
ملف generate_llms_txt.py
import httpx
import xml.etree.ElementTree as ET
from selectolax.parser import HTMLParser
from pathlib import Path
SITE_URL = "https://example.com"
SITE_NAME = "مدوّنة أحمد حايس"
SITE_TAGLINE = "شروحات عملية للـ DevOps والأوتوميشن بالعربي."
def fetch_sitemap_urls(sitemap_url: str) -> list[str]:
r = httpx.get(sitemap_url, timeout=30.0)
r.raise_for_status()
ns = {"sm": "http://www.sitemaps.org/schemas/sitemap/0.9"}
root = ET.fromstring(r.text)
return [el.text.strip() for el in root.findall(".//sm:loc", ns)]
def extract_page_meta(url: str) -> dict:
try:
r = httpx.get(url, timeout=15.0, follow_redirects=True)
tree = HTMLParser(r.text)
title = tree.css_first("title")
desc = tree.css_first('meta[name="description"]')
return {
"url": url,
"title": title.text().strip() if title else url,
"desc": desc.attributes.get("content", "").strip() if desc else "",
}
except Exception:
return {"url": url, "title": url, "desc": ""}
def build_llms_txt(pages: list[dict]) -> str:
lines = [f"# {SITE_NAME}", "", f"> {SITE_TAGLINE}", "", "## Articles"]
for p in pages:
if p["desc"]:
lines.append(f'- [{p["title"]}]({p["url"]}): {p["desc"]}')
else:
lines.append(f'- [{p["title"]}]({p["url"]})')
return "\n".join(lines) + "\n"
if __name__ == "__main__":
urls = fetch_sitemap_urls(f"{SITE_URL}/sitemap.xml")
pages = [extract_page_meta(u) for u in urls]
pages = [p for p in pages if p["title"] and not p["url"].endswith("/")]
output = build_llms_txt(pages)
Path("public/llms.txt").write_text(output, encoding="utf-8")
print(f"✓ Generated llms.txt with {len(pages)} entries")
ملف requirements.txt
httpx==0.27.2
selectolax==0.3.25
GitHub Action بيشغّل السكربت تلقائي
الفكرة: كل ما تعمل deploy أو تنشر مقال، الـ Action بيشغّل السكربت، يولّد الملف، ويـ commit الpublic/llms.txt في نفس الـ branch.
name: Generate llms.txt
on:
push:
branches: [main]
schedule:
- cron: "0 3 * * *" # 3 AM يوميًا
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install -r requirements.txt
- run: python generate_llms_txt.py
- name: Commit إذا اتغيّر
run: |
if git diff --quiet public/llms.txt; then
echo "لا يوجد تغيير"
else
git config user.name "llms-bot"
git config user.email "bot@example.com"
git add public/llms.txt
git commit -m "chore: update llms.txt"
git push
fi
أرقام فعلية من مشروع جرّبته
شغّلت السكربت ده على موقع تقني ليه 180 مقال. قبل llms.txt، عدد الزيارات من AI referrers (perplexity.ai, chatgpt.com, claude.ai) كانت 42 زيارة/شهر. بعد 3 أسابيع من تثبيت الملف:
- Perplexity: من 18 إلى 61 زيارة/شهر (زيادة 238%).
- ChatGPT (مستخدمين Search): من 9 إلى 47 زيارة/شهر.
- Claude.ai: من 15 إلى 34 زيارة/شهر.
- زمن توليد الملف: 28 ثانية لـ 180 مقال على GitHub Actions runner.
الافتراض: الأرقام دي لموقع محتواه تقني متخصّص. لو محتواك عام جدًا (أخبار رياضة مثلاً)، النسبة هتكون أقل لأن المواقع الكبيرة بتغطّي الطلب بالفعل.
Trade-offs اللي لازم تعرفها
قبل ما تنفّذ، خد بالك من 3 حاجات:
- Privacy: أي صفحة بتحطها في
llms.txtبتعلن إنها متاحة للـ LLMs تتدرّب عليها أو تقتبس منها. لو عندك صفحات خاصة (paid content, internal docs)، متحطهاش. - Rate limits: السكربت بيفتح كل URL في الـ sitemap. لو عندك 2000 صفحة، هتاخد 5 دقايق و ممكن الـ host بتاعك يعتبرها حركة غير طبيعية. أضف
time.sleep(0.3)بين الطلبات لو عندك أكتر من 500 URL. - التكلفة: صفر دولار لو شغّلته في GitHub Actions (2000 دقيقة مجانية شهريًا). الـ job بياخد أقل من دقيقة عندي.
مفهوم مهم يستحق الشرح — ما الفرق بين sitemap.xml و llms.txt؟
خلّينا نقسّمها ببساطة بمثال المكتبة تاني:
sitemap.xml= قائمة بكل الكتب في المكتبة. للـ Google spider بالدرجة الأولى، مكتوبة بـ XML، وفيها معلومات زي آخر تعديل وأولوية.llms.txt= فهرس مختار بعناية للكتب المهمة فقط. لكل كتاب ملخص 15 كلمة. مكتوب Markdown عشان الـ LLM يقدر يقرأه في context window صغير.
علميًا: الاتنين ملفات metadata لكن بـ contractين مختلفين. sitemap.xml بيتبع مواصفة sitemaps.org من 2005، مصممة لمحركات بحث كلاسيكية. llms.txt مواصفة جديدة (2024) مصممة لتقليل token consumption لنماذج LLM — الهدف إن الملف يبقى أقل من 50K token عشان ينقرا كاملًا في طلب واحد.
متى لا تستخدم الطريقة دي
- موقعك أقل من 10 صفحات — اكتب الملف يدويًا في 5 دقايق وريّح نفسك من الـ automation.
- محتواك حساس أو behind auth — llms.txt يعلن المحتوى للعالم، فـ لو الصفحة بتحتاج login، مش مكانها هنا.
- sitemap.xml عندك مش بيتحدّث أوتوماتيكي — لازم توصّل CMS بتاعك يطلّع sitemap صالح أولاً، وإلا الـ automation هتفضل تبني ملف قديم.
الخطوة التالية
شغّل السكربت محليًا مرة وحدة على موقعك الحالي، وافتح public/llms.txt اللي هيتولّد. لو شكل المحتوى منطقي والـ descriptions بتعبّر عن المقالات، ادفعه production وافتح Google Search Console + Cloudflare Analytics بعد 3 أسابيع شوف فرق الـ referrer traffic. لو ما حصلش فرق، السبب غالبًا إن الـ titles والـ meta descriptions عندك ضعيفة — صلّحها الأول قبل ما تلوم llms.txt.