דלגו לתוכן

post.md

23 באוק׳ 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. התיעוד מדגיש שאי אפשר ליצור favicon באופן דינמי, ולכן icon.tsx עושה את העבודה. כל אלה חולקים סט קטן של אבני בניין, כך ששינוי סמל המותג משנה את האייקון ואת כל כרטיסי השיתוף בבת אחת.

מכשור

שני קבצים מטפלים בתצפיתיות. instrumentation.ts רץ בשרת ומדווח על שגיאות בקשות. instrumentation-client.ts רץ לפני ההידרציה ועוקב אחר שגיאות לקוח, מדדי ווב ושינויי נתיב. שניהם מעבירים אירועים למדווח שמפזר אותם ליעדים:

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