לא סומכים, מודדים: לוח מודעות שנבנה ביום אחד ונבדק במדידות
קודי ה-QR הראשונים בלוח המודעות שלי נראו מושלמים, אבל אי אפשר היה לסרוק אותם. כך מדדתי כל חלק מסוכן ב-TaazTV במקום לסמוך על העין.

בערב של 17 בספטמבר 2026 לוח המודעות שלי נראה גמור. הכרטיסים עלו בטורים שלהם, פס המבזקים גלל, ועל כל מודעה היה קוד QR מסודר עם סמל תע“ץ באמצע. ואז כיוונתי טלפון לאחד הקודים, ושום דבר לא קרה.
הקודים היו יפים וחסרי תועלת, והם גם עברו את הבדיקה שלי. את העורך ואת הגלילה מדדתי מוקדם יותר באותו יום, כך שהכלל כבר היה קיים: שום דבר לא נחשב עובד עד שמדדתי אותו. הרגע הזה הוסיף לו את החצי השני: הבודק חייב להיות עצמאי.
הבעיה
TaazTV הוא לוח חדשות ומודעות דיגיטלי למסכים ברחבי מרכז תע“ץ. מסך 16:9 אחד מרכז את שם היחידה, שעון עם התאריך העברי והלועזי, תפריט, הלו”ז של היום, טלפוני חירום ושלוחות פנימיות, פס מבזקים ולוח נע של כרטיסי מודעות. אנשי הצוות מנהלים אותו מפאנל ניהול בעברית, בדפדפן.
שלושה דברים הפכו את זה לקשה יותר ממה שזה נשמע:
- הרשת סגורה. אין אינטרנט, ולכן כל גופן, אייקון וקוד QR צריכים להיווצר בתוך הפרויקט.
- מי שמעדכנים את הלוח הם לא מתכנתים. העורך חייב להיות מובן מאליו.
- על מסך אי אפשר ללחוץ. אם למודעה יש המשך, הדרך היחידה להגיע אליו היא קוד QR שטלפון קורא ממרחק של כמה מטרים.
איך עבדתי: קודם מבנה המסך, אחר כך הכלים
העיצוב התחיל אצלי. ב-15 בספטמבר בניתי אב-טיפוס ראשון, “לוח המודעות”: עמוד אחד עם שלושה טורים של כרטיסים נגללים, פס הודעות דחופות ושעון. אחר כך תכננתי חלוקה לארבעה אזורים: סרגל עליון, הלוח הראשי, פאנל צד ופס מבזקים בתחתית. רק אז העברתי את אב-הטיפוס, חלוקת המסך וסמל תע“ץ ל-Claude Design, שהפיק את מסך התצוגה, את פאנל הניהול ואת עיצובי הכרטיסים.
ב-17 בספטמבר, בין 11:40 ל-21:30, הפכתי את העיצובים האלה למוצר עובד עם Claude Code. ב-14 מתוך 15 הקומיטים מופיעה שורת השותפות שלו, והודעות הקומיט מתעדות מה התבקש, מה השתנה ואיך זה נבדק. אני עברתי על כל שינוי וקבעתי את הדרישות: הכרטיס שמשמש גם כעורך של עצמו, רשימה אחת לכרטיסים ולשקופיות, חלונות זמן שבועיים, ועבודה מלאה בלי אינטרנט.
כלי AI מאפשרים להגיע מהר למשהו שנראה גמור, אבל הם לא הופכים אותו לנכון. לכן כל חלק מסוכן קיבל מדידה משלו.
מה ניסיתי קודם: קודי ה-QR
המקודד הראשון נכתב מאפס בתוך הפרויקט. בקודים שהוא יצר היו הריבועים הנכונים בפינות הנכונות, מודולים מעוגלים והסמל באמצע. הם נראו תקינים, ומפענח שנכתב לצד המקודד פענח אותם נכון, אבל טלפונים לא הצליחו לקרוא אותם.
יכולתי להתחיל לחפש את הבאג במקודד: במיסוך, בבלוקים של תיקון השגיאות, בסדר הביטים. במקום זה שאלתי שאלה פשוטה יותר: למה אני כותב מקודד QR בכלל? קידוד הוא בעיה פתורה. החלק שבאמת שלי הוא המראה.
מה עבד
קודי QR: מקודד מוכח, ומפענח שקובע אם הם עובדים
החלפתי את המקודד ב-qrcode-generator, ספריית קוד פתוח מוכחת ברישיון MIT, שנשמרת בתוך הפרויקט כדי שתעבוד בלי
אינטרנט. מעליה יושבת שכבת הרינדור שלי: היא מעגלת כל מודול לפי השכנים שלו, מציירת את שלושת סימני הפינה כצורות שלמות,
ומפנה מקום לסמל.
הסמל הוא החלק המסוכן, כי הוא מסתיר מודולים שהטלפון צריך. קוד QR יכול לאבד חלק מהמודולים שלו ועדיין להיקרא, בזכות תיקון השגיאות, אבל רק עד גבול מסוים. לכן הכללים נוקשים:
if the emblem is on:
encode with error-correction level Q
if the web address is too long for level Q:
encode with level M and drop the emblem # a long web address must still scan
hidden = modules under the emblem / all modules
while hidden > 15%:
shrink the emblem and count again
בנוסף, בורר הסגנונות מאפיר צירופים של מסגרת וצורת מרכז שסורקים מתקשים בהם, כך שאי אפשר לבחור קוד יפה שלא עובד.
ואז הגיעה המדידה. יצרתי 254 קודי בדיקה, בכל צורות המודולים, המסגרות, המרכזים וגדלי הסמל, עם כתובות בעברית וכתובות
ארוכות, ונתתי למפענח עצמאי, ספריית הקוד הפתוח jsQR, לקרוא כל אחד מהם ולהשוות את התוצאה למה שקודד. כל ה-254 נקראו
נכון. הגודל הבינוני מתוכנן כך שאפשר לסרוק אותו בנוחות ממרחק של כשני מטרים ממסך גדול.
העורך: אותו קוד רינדור, ובדיקה של הסגנונות המחושבים
אנשי הצוות עורכים כרטיס על ידי הקלדה ישירות עליו: לוחצים על הכותרת ומקלידים, לוחצים על התמונה כדי להחליף אותה, לוחצים על קוד ה-QR כדי להגדיר אותו. כדי שזה יעבוד באמת, הכרטיס בעורך חייב להיות בדיוק הכרטיס שעל המסך, ולא טופס שדומה לו בערך.
לכן מסך התצוגה והפאנל מציירים את הכרטיסים באותו סקריפט ובאותו גיליון סגנונות. אבל גם “אותו קוד” עדיין לא מוכיח כלום, כי הסביבה יכולה לשנות גדלים וגופנים. השוויתי את הסגנונות המחושבים של אותו כרטיס בשני העמודים, מאפיין אחרי מאפיין, ותיקנתי את ההבדלים עד שלא נשאר אף אחד.
הגלילה: 1,681 פריימים
טורי הכרטיסים עולים לאט, בלולאה בלי סוף. כל טור מעביר כרטיס שיצא מלמעלה אל התחתית, כך שהלולאה אף פעם לא קופצת. קל לבנות גלילה אינסופית שכמעט עובדת: גמגום כל כמה שניות, או קפיצה קטנה לאחור כשכרטיס עובר, הם דברים שבקושי שמים לב אליהם במבט חטוף, אבל הם בולטים מאוד במסך שפועל כל היום.
מדדתי את הגלילה לאורך 1,681 פריימים, שנדגמו בדפדפן עם requestAnimationFrame. המהירות החציונית הייתה בדיוק ביעד,
ולא הייתה אף קפיצה לאחור.
עיצוב לאנשים שאינם מתכנתים
המדידות שומרות על הנכונות, והעיצוב הוא מה שהופך את הלוח לשימושי. כמה החלטות שאני גאה בהן:
- פריט חדש מתחיל מתמונות. הוספת פריט פותחת רשת שרטוטים של שמונת סגנונות הכרטיס, ולא רשימת שמות. בוחרים איך הוא אמור להיראות.
- מבנה המסך מתקן את עצמו. אזור כבוי או ריק נעלם, והמסך מסתדר מחדש בלי חורים. טורים שכל התוכן שלהם נכנס במסך עומדים במקום, וטורים ארוכים יותר ממשיכים לגלול.
- חלונות זמן. אפשר להגביל כל פריט לימים מסוימים בשבוע, בין שתי שעות, למשל תדריך יציאה הביתה שעולה מעצמו בימי חמישי ב-15:00 ויורד ב-19:00.
- בטוח לתפעול. גרירה בכל רשימה, ביטול וביצוע מחדש של עד 40 צעדים, וגיבוי בקובץ אחד שכולל גם את התמונות. גיבוי פגום נדחה עם הסבר.
מה הייתי עושה אחרת
הייתי מתחיל מהספרייה המוכחת. כתיבת המקודד בעצמי לא חסכה כלום, ועלתה לי בשעות האחרונות של הערב. העבודה המעניינת הייתה תמיד שכבת הרינדור.
הייתי גם בוחר בודק עצמאי כבר מההתחלה. המפענח הראשון שלי נכתב לפי אותה הבנה של תקן ה-QR כמו המקודד, ולכן חלק איתו
את אותה טעות: ביטי הפורמט, הדבר הראשון שסורק קורא, היו בסדר הפוך אצל שניהם, והשניים הסכימו זה עם זה. מפענח מבוסס,
jsQR, דחה את כל הקודים האלה כבר בפעם הראשונה שראה אותם. היום, כשאני מתחיל לבנות יכולת חזותית חדשה, אני שואל
קודם כול: איזה מספר יגיד לי שזה עובד?
איפה זה רץ
TaazTV עבר מאב-טיפוס ראשון למוצר מוגמר בשלושה ימים, והמוצר העובד נבנה ביום אחד, בכ-4,600 שורות JavaScript, בלי פריימוורק ובלי שלב בנייה. סיפור הפרויקט של TaazTV מציג את סכמת העיצוב של הלוח ואת המסך המוגמר, עם שני סרטונים קצרים: הלוח בזמן ריצה, ועריכה חיה.
הפרויקט
למה פיצלתי את הפלטפורמה למאגרי קוד נפרדים, ואיחדתי אותה בחזרה ביום אחד