تخطَّ إلى المحتوى

post.md

23‏/10‏/2026 · قراءة 3 دقيقة
فن ASCII متحرك لقارب كاتاماران Nacra 17 يبحر عبر المحيط عند الغروب

كيف بُني هذا الموقع

جولة قصيرة في بنية cmkrw.com، من تخطيط الطرفية إلى Markdown والرسوم البيانية وتقارير الأخطاء.

  • nextjs
  • design
المحتويات

هذا الموقع صغير عن قصد: صفحة واحدة، ومدونة واحدة، وأقل قدر ممكن من JavaScript. إليك كيف تتكامل أجزاؤه، إن أردت بناء شيء مشابه.

الطرفية هي التخطيط

صُمّم الموقع كتطبيق طرفية. يمتد شريط علامات تبويب في الأعلى، ويقع سطر الحالة في الأسفل، وكل ما بينهما لوحات: صناديق بإطار يستقر عنوانها في حافتها العلوية. مكوّن صغير واحد هو Pane يرسمها جميعًا.

تخطيط المدونة: قائمة المقالات على جانب والمقال المفتوح على الجانب الآخرالمدونة بنمط القائمة والتفاصيل: تبقى القائمة ثابتة بينما يتغير المقال.

ويتبع التنقل الفكرة نفسها. في المدونة تبقى قائمة المقالات على جانب بينما يُفتح المقال على الجانب الآخر، فلا يحتاج التنقل بين المقالات إلى رابط رجوع. وتعمل الاختصارات كما في الطرفية، ويمكنك فرز هذا الجدول بالنقر على رأس أي عمود:

اختصارات لوحة المفاتيح
1فتح الرئيسيةعام
2فتح المدونةعام
jالتمرير لأسفلعام
kالتمرير لأعلىعام
g gالانتقال إلى البدايةعام
Gالانتقال إلى النهايةعام
nمقال أقدمالمدونة
pمقال أحدثالمدونة
dتبديل المظهرعام
?عرض الاختصاراتعام

الحركة في معظمها CSS. يُكتب الأمر في رأس الصفحة بتحريك steps()، وتظهر اللوحات تدريجيًا عند التمرير إليها، ويتبع الخط تحت شريط التبويب ونسبة التمرير في سطر الحالة موضع التمرير. وكل ذلك يتوقف عند تفعيل prefers-reduced-motion.

كتابة المقالات

المقالات ملفات Markdown عادية في content/blog/<slug>/<locale>.md تُعرض بواسطة TanStack Markdown. إذا غابت ترجمة يُستخدم الملف الإنجليزي، ويُبقي draft: true المقال خارج نسخة الإنتاج.

وتتولى ثلاث أدوات من TanStack بقية العمل:

  • Markdown يحلل المقال ويعرضه كعناصر React دون سلسلة HTML وسيطة.
  • Highlight يلوّن كتل الشيفرة. تُضمَّن فقط اللغات التي أسجلها، وتأتي الألوان من متغيرات CSS نفسها التي يستخدمها بقية المظهر.
  • Charts وTable يُدرجان بتعليق من سطر واحد يسمّي ملف JSON بجوار المقال.

يمكن أن تحمل كتل الشيفرة عنوان ملف:

src/features/blog/embeds/index.tsx
export function createEmbeds(slug: string, locale: string) {
  return {
    chart: ({ data = "", kind = "bar", x = "x", y = "y", title = "Chart" }) => (
      <TuiChart
        rows={getPostDataset(slug, data, locale)}
        kind={kind}
        x={x}
        y={y}
        label={title}
      />
    ),
  }
}

وتعمل جداول Markdown العادية أيضًا وتحصل على التنسيق نفسه:

الطبقةالمجلدالمسؤولية
المساراتapp/الصفحات والبيانات الوصفية والأيقونات والصور
الواجهةcomponents/tui/اللوحات وشريط التنقل وسطر الحالة وربط المفاتيح
الميزاتfeatures/أقسام الصفحة الرئيسية والمدونة
الأدواتlib/, hooks/البيانات الوصفية والمراقبة وإدخال المفاتيح

وهذا عدد ملفات المصدر في كل مجلد وقت الكتابة:

ملفات المصدر لكل مجلد
عرض البيانات
folderfiles
app17
components16
lib16
features15
i18n4
hooks3
types1

أيقونات وبطاقات مشاركة مولَّدة

يبني Next.js 16 صور البيانات الوصفية من ملفات في مجلد app/:

  • يرسم icon.tsx وapple-icon.tsx أيقونة الموقع وأيقونة iOS من ملف SVG واحد هو assets/logo-icon.svg.
  • يرسم opengraph-image.tsx بطاقة المشاركة للصفحة الرئيسية، ويرسم ملف آخر بطاقة لكل مقال.

لا يوجد favicon.tsx. تنص الوثائق صراحةً على أن الأيقونة المفضلة لا يمكن توليدها، لذا يتولى icon.tsx هذه المهمة. وتشترك كلها في مجموعة صغيرة من العناصر الأساسية، فتغيير شعار العلامة يغيّر الأيقونة وجميع بطاقات المشاركة دفعة واحدة.

القياس والمراقبة

يتولى ملفان المراقبة. يعمل instrumentation.ts على الخادم ويبلّغ عن أخطاء الطلبات. ويعمل instrumentation-client.ts قبل الاستعادة (hydration) ويتتبع أخطاء العميل ومقاييس الويب وتغيّر المسارات. ويمرّر كلاهما الأحداث إلى مُبلِّغ يوزعها على عدة وجهات:

src/lib/observability/server.ts
export const serverReporter = createReporter([
  consoleSink,
  ...(endpoint ? [endpointSink(endpoint)] : []),
])

تُرسل أحداث العميل إلى /api/observability الذي يسجلها. وعند ربط المُبلِّغ بجامع حقيقي لاحقًا يكفي إضافة وجهة واحدة دون لمس أي من ملفَّي الدخول.

الترجمات

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

NORMAL~/blog/how-this-site-is-built
0%

اختصارات لوحة المفاتيح

12
التنقل الرئيسي
jk
التمرير لأسفل / لأعلى
g gG
الانتقال إلى البداية / النهاية
np
مقال أحدث / أقدم
d
تبديل المظهر
:
فتح لوحة الأوامر
?
إظهار هذه المساعدة أو إخفاؤها
esc