Methodology v1.0
July 18, 2026 • By AICompatible Team • 8 min read

كيفية إنشاء ملف llms.txt ديناميكيًا في Next.js وWordPress وShopify: دليل عملي للمطورين

لماذا يُعد الإنشاء الديناميكي لملفات llms.txt ضروريًا للمنصات المتنامية

الخلاصة الأساسية (BLUF): تصبح ملفات llms.txt الثابتة قديمة في غضون ساعات على منصات المحتوى عالية السرعة، مما يخلق فجوة حرجة بين ما تكتشفه وكلاء الذكاء الاصطناعي وما هو موجود فعليًا. يضمن الإنشاء الديناميكي الدقة في الوقت الفعلي، ويلغي عبء الصيانة اليدوية، ويضمن أن نماذج اللغة الكبيرة تتلقى دائمًا بنية الموقع الحالية، والتسلسلات الهرمية للمحتوى، ومواقع الموارد—مما يجعله لا غنى عنه لتثبيتات WordPress المؤسسية، وتطبيقات Next.js، ومتاجر Shopify التي تنشر عشرات الصفحات يوميًا.

فهم مواصفات llms.txt والمتطلبات الديناميكية

يعمل ملف llms.txt كملف بيان قابل للقراءة آليًا يوجه برامج الزحف بالذكاء الاصطناعي، ونماذج اللغة، والوكلاء المستقلين عبر بنية المعلومات في موقعك. على عكس robots.txt، الذي يركز على أذونات الزحف، يوفر llms.txt البنية الدلالية، وتصنيف المحتوى، وإشارات الأولوية المُحسَّنة خصيصًا لاستهلاك نماذج اللغة الكبيرة.

يصبح الإنشاء الديناميكي حاسمًا عندما:

  • تتجاوز سرعة المحتوى قدرة التحديث اليدوي: كتالوجات التجارة الإلكترونية التي تضيف أكثر من 50 منتجًا يوميًا، أو مواقع الأخبار التي تنشر كل ساعة، أو وثائق SaaS التي تُحدَّث مع كل دورة إصدار
  • تتطور التصنيفات برمجيًا: صفحات الفئات المُنشأة تلقائيًا، أو أنظمة التصفية الديناميكية، أو التسلسلات الهرمية للمحتوى الذي ينشئه المستخدمون
  • توجد طبقات تخصيص: المتغيرات الجغرافية، أو المسارات الخاصة باللغة، أو الموارد المحمية بالمصادقة التي تتطلب عرضًا مشروطًا
  • تجميع المحتوى متعدد المصادر: بنيات نظام إدارة المحتوى بدون رأس، أو الخدمات الدقيقة التي تغذي واجهات برمجة تطبيقات المحتوى، أو مصادر البيانات الموحدة

تنفيذ llms.txt الديناميكي في WordPress

يشغل WordPress 43% من الويب، مما يجعل أنماط تنفيذ llms.txt فيه بالغة الأهمية. يستخدم النهج التالي إجراء template_redirect لاعتراض الطلبات قبل عرض القالب، مما يضمن أقصى أداء وتوافق مع طبقات التخزين المؤقت.

التنفيذ الكامل لـ PHP في WordPress

<?php
/**
 * مُنشئ llms.txt الديناميكي لـ WordPress
 * أضف إلى functions.php للقالب أو أنشئه كإضافة
 */

add_action('template_redirect', 'serve_dynamic_llms_txt');

function serve_dynamic_llms_txt() {
    // الاستجابة فقط لطلبات /llms.txt
    if ($_SERVER['REQUEST_URI'] !== '/llms.txt') {
        return;
    }

    // تعيين الرؤوس المناسبة
    header('Content-Type: text/plain; charset=utf-8');
    header('X-Robots-Tag: noindex');
    
    // منع التخزين المؤقت للمحتوى الديناميكي حقًا
    header('Cache-Control: no-cache, must-revalidate');
    
    // بدء الإخراج
    echo "# llms.txt - تم إنشاؤه ديناميكيًا\n";
    echo "# تاريخ الإنشاء: " . current_time('c') . "\n\n";
    
    // بيانات الموقع الوصفية
    echo "# الموقع: " . get_bloginfo('name') . "\n";
    echo "# الوصف: " . get_bloginfo('description') . "\n";
    echo "# الرابط: " . home_url() . "\n\n";
    
    // الصفحات الرئيسية
    echo "## التنقل الأساسي\n\n";
    $pages = get_pages(array('sort_column' => 'menu_order', 'hierarchical' => 0));
    foreach ($pages as $page) {
        echo "- [{$page->post_title}](" . get_permalink($page->ID) . ")\n";
    }
    echo "\n";
    
    // مقالات المدونة حسب الفئة
    echo "## محتوى المدونة\n\n";
    $categories = get_categories(array('hide_empty' => true, 'orderby' => 'count', 'order' => 'DESC'));
    
    foreach ($categories as $category) {
        echo "### {$category->name} ({$category->count} مقالة)\n\n";
        
        $posts = get_posts(array(
            'category' => $category->term_id,
            'numberposts' => 10,
            'orderby' => 'date',
            'order' => 'DESC'
        ));
        
        foreach ($posts as $post) {
            $date = get_the_date('Y-m-d', $post->ID);
            echo "- [{$post->post_title}](" . get_permalink($post->ID) . ") - {$date}\n";
        }
        echo "\n";
    }
    
    // تكامل المنتجات لـ WooCommerce
    if (class_exists('WooCommerce')) {
        echo "## كتالوج المنتجات\n\n";
        
        $product_categories = get_terms(array(
            'taxonomy' => 'product_cat',
            'hide_empty' => true,
            'orderby' => 'count',
            'order' => 'DESC',
            'number' => 10
        ));
        
        foreach ($product_categories as $cat) {
            echo "- [{$cat->name}](" . get_term_link($cat) . ") - {$cat->count} منتج\n";
        }
        echo "\n";
    }
    
    // الوثائق أو أنواع المنشورات المخصصة
    $custom_post_types = get_post_types(array('public' => true, '_builtin' => false), 'objects');
    
    foreach ($custom_post_types as $cpt) {
        echo "## {$cpt->labels->name}\n\n";
        
        $cpt_posts = get_posts(array(
            'post_type' => $cpt->name,
            'numberposts' => 20,
            'orderby' => 'date',
            'order' => 'DESC'
        ));
        
        foreach ($cpt_posts as $post) {
            echo "- [{$post->post_title}](" . get_permalink($post->ID) . ")\n";
        }
        echo "\n";
    }
    
    exit; // منع WordPress من متابعة التنفيذ
}

استراتيجيات تحسين الأداء في WordPress

لتثبيتات WordPress عالية الحركة، نفذ أنماط التخزين المؤقت التالية:

  • التخزين المؤقت عبر Transient API: احفظ الإخراج المُنشأ في set_transient('llms_txt_cache', $output, 3600) مع إبطال تلقائي عند خطافات نشر المقالات
  • تكامل التخزين المؤقت للكائنات: استفد من Redis أو Memcached للبيئات الموزعة
  • التخزين المؤقت على حافة CDN: عيّن رؤوس Cache-Control المناسبة (مثل max-age=1800) لعقد Cloudflare أو Fastly
  • إعادة الإنشاء الانتقائية: اربط بإجراءات save_post وcreated_term وdeleted_term لإبطال التخزين المؤقت فقط عند تغيير المحتوى

تنفيذ معالج المسار في Next.js (App Router)

يوفر Next.js 13+ App Router قدرات بث أصلية مثالية لملفات llms.txt الكبيرة. يستخدم التنفيذ التالي معالجات المسار مع TypeScript لضمان أمان النوع والتوافق مع وقت تشغيل الحافة.

تنفيذ TypeScript في Next.js

// app/llms.txt/route.ts

import { NextRequest, NextResponse } from 'next/server';

// اختياري: تمكين وقت تشغيل الحافة للتوزيع العالمي
// export const runtime = 'edge';

export async function GET(request: NextRequest) {
  const encoder = new TextEncoder();
  
  const stream = new ReadableStream({
    async start(controller) {
      // دالة مساعدة لكتابة الأجزاء
      const write = (text: string) => {
        controller.enqueue(encoder.encode(text));
      };
      
      // قسم الرأس
      write('# llms.txt - خريطة الموقع الديناميكية\n');
      write(`# تاريخ الإنشاء: ${new Date().toISOString()}\n`);
      write(`# الرابط الأساسي: ${process.env.NEXT_PUBLIC_SITE_URL}\n\n`);
      
      // جلب البيانات من نظام إدارة المحتوى/قاعدة البيانات
      try {
        // مثال: الجلب من نظام إدارة محتوى بدون رأس
        const pages = await fetch(`${process.env.CMS_API_URL}/pages`, {
          headers: { 'Authorization': `Bearer ${process.env.CMS_API_KEY}` },
          next: { revalidate: 3600 } // التخزين المؤقت بنمط ISR
        }).then(res => res.json());
        
        write('## الصفحات الرئيسية\n\n');
        pages.forEach((page: any) => {
          write(`- [${page.title}](${process.env.NEXT_PUBLIC_SITE_URL}${page.slug})\n`);
        });
        write('\n');
        
        // مقالات المدونة مع معالجة الترقيم
        write('## مقالات المدونة\n\n');
        let page = 1;
        let hasMore = true;
        
        while (hasMore && page <= 10) { // حد لمنع الحلقات اللانهائية
          const posts = await fetch(
            `${process.env.CMS_API_URL}/posts?page=${page}&per_page=50`,
            { next: { revalidate: 1800 } }
          ).then(res => res.json());
          
          if (posts.length === 0) {
            hasMore = false;
            break;
          }
          
          posts.forEach((post: any) => {
            const date = new Date(post.publishedAt).toISOString().split('T')[0];
            write(`- [${post.title}](${process.env.NEXT_PUBLIC_SITE_URL}/blog/${post.slug}) - ${date}\n`);
          });
          
          page++;
        }
        write('\n');
        
        // كتالوج المنتجات (إن وُجد)
        const products = await fetch(`${process.env.CMS_API_URL}/products?limit=100`)
          .then(res => res.json())
          .catch(() => []);
        
        if (products.length > 0) {
          write('## المنتجات\n\n');
          
          // التجميع حسب الفئة
          const categorized = products.reduce((acc: any, product: any) => {
            const cat = product.category || 'غير مصنف';
            if (!acc[cat]) acc[cat] = [];
            acc[cat].push(product);
            return acc;
          }, {});
          
          Object.entries(categorized).forEach(([category, items]: [string, any]) => {
            write(`### ${category}\n\n`);
            items.forEach((product: any) => {
              write(`- [${product.name}](${process.env.NEXT_PUBLIC_SITE_URL}/products/${product.slug})\n`);
            });
            write('\n');
          });
        }
        
        // مسارات وثائق واجهة برمجة التطبيقات
        write('## وثائق واجهة برمجة التطبيقات\n\n');
        write(`- [مرجع واجهة برمجة التطبيقات](${process.env.NEXT_PUBLIC_SITE_URL}/docs/api)\n`);
        write(`- [دليل المصادقة](${process.env.NEXT_PUBLIC_SITE_URL}/docs/auth)\n`);
        write(`- [حدود المعدل](${process.env.NEXT_PUBLIC_SITE_URL}/docs/limits)\n\n`);
        
      } catch (error) {
        write(`# خطأ في إنشاء المحتوى الديناميكي: ${error}\n`);
      }
      
      controller.close();
    }
  });
  
  return new NextResponse(stream, {
    headers: {
      'Content-Type': 'text/plain; charset=utf-8',
      'Cache-Control': 'public, s-maxage=1800, stale-while-revalidate=3600',
      'X-Robots-Tag': 'noindex',
    },
  });
}

الأنماط المتقدمة في Next.js

تكامل إعادة الإنشاء الثابت التدريجي (ISR): ادمج معالجات المسار مع ISR من خلال تعيين قيم revalidate في استدعاءات fetch، مما يسمح بالتخزين المؤقت على الحافة مع الحفاظ على ضمانات النضارة.

جلب البيانات المتوازي: استخدم Promise.all() لجلب مصادر محتوى متعددة في وقت واحد، مما يقلل إجمالي وقت الإنشاء:

const [pages, posts, products] = await Promise.all([
  fetchPages(),
  fetchPosts(),
  fetchProducts()
]);

الأقسام المشروطة: نفذ علامات الميزات أو الشروط المستندة إلى البيئة لعرض بنى محتوى مختلفة لبيئات التطوير مقابل الإنتاج.

تنفيذ llms.txt الديناميكي في Shopify

تتطلب بنية Shopify نُهجًا مختلفة حسب إعداد متجرك. يقدم محرك قوالب Liquid وبنية القالب في المنصة تحديات وفرصًا فريدة.

الطريقة الأولى: قالب Liquid مخصص

أنشئ قالب صفحة جديد في قالبك:

{% comment %}
  الملف: templates/page.llms.liquid
  أنشئ صفحة في لوحة تحكم Shopify مع لاحقة القالب "llms"
  الوصول عبر: yourstore.com/pages/llms-txt
{% endcomment %}

{% layout none %}
{% content_for "content_type" %}text/plain{% endcontent_for %}

# llms.txt - {{ shop.name }}
# تاريخ الإنشاء: {{ "now" | date: "%Y-%m-%d %H:%M:%S %Z" }}
# رابط المتجر: {{ shop.url }}

## المجموعات

{% for collection in collections %}
{% if collection.products_count > 0 %}
### {{ collection.title }} ({{ collection.products_count }} منتج)

{% for product in collection.products limit: 20 %}
- [{{ product.title }}]({{ shop.url }}{{ product.url }}) - {{ product.price | money }}
{% endfor %}

{% endif %}
{% endfor %}

## مقالات المدونة

{% for article in blogs.news.articles %}
- [{{ article.title }}]({{ shop.url }}{{ article.url }}) - {{ article.published_at | date: "%Y-%m-%d" }}
{% endfor %}

## الصفحات

{% for page in pages %}
- [{{ page.title }}]({{ shop.url }}{{ page.url }})
{% endfor %}

الطريقة الثانية: وكيل تطبيق Shopify

لمتاجر Shopify Plus المؤسسية، نفذ وكيل تطبيق يُنشئ llms.txt من جانب الخادم:

  1. تكوين وكيل التطبيق: في إعدادات تطبيق Shopify، عيّن مسار الوكيل إلى /apps/llms يشير إلى نقطة نهاية الخادم
  2. تنفيذ الخادم: أنشئ نقطة نهاية Node.js/Python/Ruby تستخدم Shopify Admin API لجلب المخزون الحالي والمجموعات والمحتوى
  3. إعادة كتابة الرابط: استخدم Shopify Scripts أو تعديلات القالب لإعادة توجيه /llms.txt إلى /apps/llms/generate
// معالج وكيل التطبيق في Express.js
app.get('/generate', async (req, res) => {
  const shopifyClient = new Shopify.Clients.Rest(
    req.query.shop,
    process.env.SHOPIFY_ACCESS_TOKEN
  );
  
  res.setHeader('Content-Type', 'text/plain');
  
  // جلب المجموعات
  const collections = await shopifyClient.get({
    path: 'custom_collections',
  });
  
  let output = '# llms.txt\n\n## المجموعات\n\n';
  
  for (const collection of collections.body.custom_collections) {
    const products = await shopifyClient.get({
      path: `collections/${collection.id}/products`,
      query: { limit: 50 }
    });
    
    output += `### ${collection.title}\n\n`;
    products.body.products.forEach(product => {
      output += `- [${product.title}](https://${req.query.shop}/products/${product.handle})\n`;
    });
    output += '\n';
  }
  
  res.send(output);
});

الطريقة الثالثة: Shopify Hydrogen (بدون رأس)

لواجهات Hydrogen، نفذ مسار خادم مشابه لـ Next.js:

// app/routes/llms[.]txt.tsx
import { LoaderFunction } from '@shopify/remix-oxygen';

export const loader: LoaderFunction = async ({ context }) => {
  const { storefront } = context;
  
  const { collections } = await storefront.query(`
    query LLMSData {
      collections(first: 50) {
        nodes {
          title
          handle
          products(first: 20) {
            nodes {
              title
              handle
            }
          }
        }
      }
    }
  `);
  
  let output = '# llms.txt\n\n';
  
  collections.nodes.forEach(collection => {
    output += `## ${collection.title}\n\n`;
    collection.products.nodes.forEach(product => {
      output += `- [${product.title}](/products/${product.handle})\n`;
    });
    output += '\n';
  });
  
  return new Response(output, {
    headers: {
      'Content-Type': 'text/plain',
      'Cache-Control': 'public, max-age=3600'
    }
  });
};

منهجيات التحقق والاختبار

يتطلب ضمان أن ملف llms.txt المُنشأ ديناميكيًا يلبي متطلبات المواصفات ويعمل بشكل مثالي التحقق المنهجي.

قائمة التحقق من صحة التنسيق

  • الامتثال لـ Markdown: تحقق من التسلسل الهرمي الصحيح للعناوين (H1 للعنوان، H2 للأقسام، H3 للأقسام الفرعية)
  • سلامة الروابط: يجب أن تكون جميع عناوين URL مطلقة ومشفرة بشكل صحيح وتُرجع رموز حالة 200
  • ترميز الأحرف: ترميز UTF-8 مع معالجة صحيحة للأحرف الخاصة والرموز التعبيرية والنص الدولي
  • اعتبارات حجم الملف: احتفظ بحجم أقل من 10 ميجابايت لمعالجة مثالية لنماذج اللغة الكبيرة؛ نفذ الترقيم أو التلخيص للمواقع الأكبر
  • مؤشرات تكرار التحديث: قم بتضمين طوابع زمنية للإنشاء وتلميحات تكرار التغيير

سكريبت الاختبار الآلي

import requests
import re
from urllib.parse import urlparse

def validate_llms_txt(url):
    """التحقق من صحة تنسيق ومحتوى llms.txt"""
    
    response = requests.get(url)
    
    # التحقق من رؤوس الاستجابة
    assert response.status_code == 200, "الملف غير قابل للوصول"
    assert 'text/plain' in response.headers.get('Content-Type', ''), "نوع محتوى خاطئ"
    
    content = response.text
    lines = content.split('\n')
    
    # التحقق من البنية
    assert lines[0].startswith('#'), "يجب أن يبدأ بالعنوان"
    
    # استخراج والتحقق من جميع عناوين URL
    url_pattern = r'\[([^\]]+)\]\(([^\)]+)\)'
    urls = re.findall(url_pattern, content)
    
    print(f"تم العثور على {len(urls)} رابط")
    
    # التحقق من العينة (فحص أول 10 روابط)
    for title, link in urls[:10]:
        parsed = urlparse(link)
        assert parsed.scheme in ['http', 'https'], f"مخطط غير صالح: {link}"
        assert parsed.netloc, f"نطاق مفقود: {link}"
        
        # اختياري: التحقق من إمكانية الوصول إلى الرابط
        try:
            link_response = requests.head(link, timeout=5, allow_redirects=True)
            assert link_response.status_code < 400, f"رابط معطل: {link}"
        except requests.RequestException as e:
            print(f"تحذير: تعذر التحقق من {link}: {e}")
    
    # التحقق من الأقسام المطلوبة
    assert '##' in content, "رؤوس الأقسام مفقودة"
    
    # التحقق من حجم الملف
    size_mb = len(content.encode('utf-8')) / (1024 * 1024)
    assert size_mb < 10, f"الملف كبير جدًا: {size_mb:.2f}MB"
    
    print("✓ نجح التحقق")
    return True

# الاستخدام
validate_llms_txt('https://yoursite.com/llms.txt')

مراقبة الأداء

نفذ استراتيجيات المراقبة التالية لضمان عدم تأثير الإنشاء الديناميكي على أداء الموقع:

  • تتبع وقت الاستجابة: عيّن تنبيهات لأوقات الإنشاء التي تتجاوز ثانيتين
  • مراقبة معدل نجاح التخزين المؤقت: تتبع نسبة الاستجابات المخزنة مؤقتًا مقابل المُعاد إنشاؤها
  • تسجيل معدل الأخطاء: راقب استعلامات قاعدة البيانات الفاشلة أو استدعاءات واجهة برمجة التطبيقات أثناء الإنشاء
  • استخدام الموارد: قس استخدام المعالج والذاكرة أثناء فترات الإنشاء القصوى

تقنيات التحسين المتقدمة

العرض المشروط للمحتوى

نفذ التصفية الذكية بناءً على وكيل المستخدم أو الموقع الجغرافي أو حالة المصادقة:

// مثال Next.js مع أقسام مشروطة
export async function GET(request: NextRequest) {
  const userAgent = request.headers.get('user-agent') || '';
  const isGoogleBot = userAgent.includes('Googlebot');
  const isLLMCrawler = userAgent.includes('GPTBot') || userAgent.includes('Claude');
  
  // عرض أعماق محتوى مختلفة بناءً على نوع الزاحف
  const maxItems = isLLMCrawler ? 1000 : isGoogleBot ? 500 : 100;
  
  // إنشاء المحتوى مع الحدود المناسبة
}

تحديد الأولويات الهرمي

بنية المحتوى لعرض الصفحات عالية القيمة أولاً، باستخدام مؤشرات الأولوية:

## محتوى عالي الأولوية

- [إطلاق المنتج 2024](/launch) - الأولوية: عالية، التحديث: 2024-01-15
- [الصفحة الرئيسية للوثائق](/docs) - الأولوية: عالية، التحديث: 2024-01-10

## محتوى قياسي

- [أرشيف المدونة](/blog) - الأولوية: متوسطة

دعم متعدد اللغات

للمواقع الدولية، أنشئ متغيرات llms.txt خاصة باللغة:

// مثال WordPress متعدد اللغات
function serve_dynamic_llms_txt() {
    $lang = isset($_GET['lang']) ? sanitize_text_field($_GET['lang']) : 'en';
    
    if ($lang !== 'en') {
        // إنشاء نسخة محلية
        $posts = get_posts(array(
            'lang' => $lang,
            'numberposts' => 50
        ));
    }
    
    echo "# llms.txt ({$lang})\n\n";
    // ... بقية الإنشاء
}

اعتبارات الأمان

يُدخل الإنشاء الديناميكي ناقلات أمان محتملة يجب معالجتها:

  • تحديد المعدل: نفذ تقييد الطلبات لمنع هجمات استنزاف الموارد (مثل 60 طلبًا لكل عنوان IP في الساعة)
  • تنقية المدخلات: تحقق من صحة جميع المحتوى الديناميكي وقم بتجاوزه لمنع هجمات الحقن
  • منع تجاوز المصادقة: لا تعرض أبدًا عناوين URL للمحتوى الخاص في llms.txt، حتى لو كانت الصفحات نفسها محمية
  • الكشف عن المعلومات: تجنب الكشف عن مسارات النظام الداخلية أو نقاط نهاية واجهة برمجة التطبيقات أو البيانات الوصفية الحساسة
  • تخفيف هجمات DDoS: استخدم الحماية على مستوى CDN ونفذ قواطع الدوائر لفشل الخدمات الأولية

أفضل ممارسات الصيانة والمراقبة

أنشئ إجراءات تشغيلية لضمان الموثوقية طويلة الأجل:

  1. الاختبار الآلي في CI/CD: قم بتضمين التحقق من llms.txt في خطوط أنابيب النشر
  2. التحكم في إصدارات القوالب: تتبع التغييرات على منطق الإنشاء برسائل التزام مفصلة
  3. عتبات التنبيه: أعد إشعارات لفشل الإنشاء أو تدهور الأداء أو انتهاكات التنسيق
  4. المراجعات المنتظمة: مراجعات شهرية للمحتوى المضمن والروابط المعطلة والدقة الهيكلية
  5. التوثيق: احتفظ بأدلة استكشاف الأخطاء وإصلاحها للمشكلات الشائعة وتحديث منطق الإنشاء

الخلاصة

يحول الإنشاء الديناميكي لـ llms.txt ملفًا ثابتًا إلى وثيقة حية تمثل بدقة الحالة الحالية لموقعك. من خلال تنفيذ حلول خاصة بالمنصة لـ WordPress وNext.js وShopify، تضمن أن وكلاء الذكاء الاصطناعي يتلقون دائمًا معلومات موثوقة ومحدثة حول بنية المحتوى الخاصة بك. يؤتي الاستثمار في الإنشاء الديناميكي ثماره من خلال تحسين قابلية الاكتشاف بواسطة الذكاء الاصطناعي، وتقليل عبء الصيانة، وتعزيز الفهم الدلالي لممتلكاتك الرقمية. مع تزايد انتشار أدوات البحث والاكتشاف المدعومة بنماذج اللغة الكبيرة، ستنتقل ملفات llms.txt الديناميكية من ميزة تنافسية إلى متطلب أساسي للمواقع الإلكترونية الجادة.