7is היא חברת ייעוץ תפעולי ישראלית שנוסדה ב-2010, ומלווה הנהלות בכירות בבנקאות, ביטוח, קמעונאות, רכב, תקשורת ובריאות. הלקוחות שלה הם ארגונים שעובדים בשתי שפות. האתר שלה עבד באחת.
האתר היה בעברית בלבד, על תבנית בשם sevenis שצברה עוד ספרייה כל שנה-שנתיים מאז שנבנתה: Foundation 6, gulp ו-SCSS, jQuery, Font Awesome, animate.css, motion-ui ו-wow.js. הטקסט של כל עמוד ישב בגוש אחד בעורך של וורדפרס, בלי שום חלוקה פנימית.
בניתי אותו מחדש. תבנית חדשה על Tailwind v4, מתיחת פנים ולא עיצוב מחדש מהיסוד, שפה שנייה, ותוכן העמודים שעבר לשדות עם תוויות. הקומיט הראשון ב-23 ביולי, האחרון ב-30 ביולי, עם Claude Code לאורך כל הדרך. האתר באוויר היום ב-7-is.com, בעברית ובאנגלית.


מה השתנה עבור המשרד
האתר מדבר אנגלית, וזו כל הסיבה שהפרויקט קרה. כל השאר נגזר מזה. אי אפשר להרכיב שפה שנייה על stylesheet שיודע לסדר תוכן רק מימין לשמאל, ולכן דרישת השפה חייבה בנייה מחדש של התבנית, והבנייה מחדש פינתה מקום למתיחת פנים שהייתה מתבקשת כבר מזמן.
האתר גם נראה שוב כמו משרד שמייעץ לבנקים. העיצוב הישן הפך עם השנים לאוסף עמודים שכל אחד מהם פתר את בעיית ה-layout שלו בדרך משלו, ומה שהחליף אותו הוא מערכת אחת שכל העמודים שואבים ממנה.
העמודים קלים בהרבה. יש בהמשך מדידות אמיתיות, לא רק הצהרה שלי.
צוות השיווק יכול לערוך אותו עכשיו. עמודי אודות וקריירה היו גוש HTML אחד, שהתבנית חתכה לרצועות לפי ניחוש היכן נופלות הכותרות.
כל מקטע הוא היום שדה נפרד עם תווית, וזו בדיוק חוויית העריכה ש-page builders מבטיחים, בלי המשקל שהם גוררים איתם.
לפני ואחרי, במספרים
״לפני״ היא הגרסה ש-7-is.com הגיש עד העלייה לאוויר, ונמדדה בסוף יולי. ״אחרי״ היא הגרסה שבאוויר היום. שורת ה-JavaScript היא זו שכמעט לא זזה: ה-bundle הישן עדיין נטען.
שפות
עברית בלבד
עברית + אנגלית
Polylang Pro, 23 זוגות
CSS של התבנית
rtl.css 1,121.5 KB + main.css 1,121.2 KB
tailwind.css 68.1 KB
קובץ אחד, בלי build ל-RTL
JS של התבנית
main.js 1,902.7 KB, לא ממוזער
720.6 KB על הדיסק, 89.1 KB ברשת
ה-bundle הישן עדיין נטען
LCP, מובייל מואט
לא נמדד
805 מ״ש
CLS 0.00, Slow 4G עם האטה פי 4
קבצים בתבנית
409
294
250 קבצים שהשתנו
קבצי גופן ב-repo
156
8
2 קבצי woff2 מסוג variable
בניית התבנית מחדש
התבנית הישנה התבססה על starter בשם podium. שום דבר בה לא היה חריג לתקופתה, וזו בדיוק הייתה הבעיה: שמונה שנים של ברירות מחדל, כל אחת סבירה בפני עצמה, שהצטברו לקוד שאף אחד לא רצה לגעת בו.
ההסרה נעשתה בשלבים ממוספרים ומפורשים, כל שלב בקומיט משלו, כך שאפשר לבטל כל אחד מהם בלי לפרום את השאר.
- שלב 1 הסיר קוד מת.
- שלב 2 הוריד את Font Awesome, animate.css, motion-ui ו-wow.js.
- שלב 3 הניח את תשתית Tailwind v4.
- שלב 4 הסיר את Foundation לגמרי.
האייקונים הפכו ל-SVG inline בתוך inc/icons.php, מה שחסך webfont ובקשה חוסמת רינדור. הקרוסלה בעמוד הבית עברה מ-slick ל-Splide, והיא נטענת היום רק בעמוד הבית ולא בכל עמוד.
התבנית ירדה מ-409 קבצים ל-294. בסך הכל בפרויקט: 250 קבצים שהשתנו, 17,577 שורות שנוספו ו-59,651 שנמחקו.
המחיקות עולות על התוספות ביחס של כשלוש לאחת, וכך באמת נראית עבודה מהסוג הזה: רובה הסרה.
מערכת עיצוב ב-53 custom properties
ה-stylesheet הישן ביטא את החלטות העיצוב שלו כמשתני SCSS שנעלמו בזמן ה-build, בתוספת לא מעט ערכים שהוקלדו ישירות לתוך הכללים. אי אפשר היה לבחון צבע בדפדפן ולגלות מה שמו.
הגרסה החדשה מנסחת את המערכת כ-53 custom properties בקובץ src/tailwind.css: צבע, סקאלת טיפוגרפיה, מרווחים וקונטיינרים. סקאלת הטיפוגרפיה מסבירה את עצמה בתוך הקוד.
--text-base: 1.125rem; /* 18 - body copy */
--text-lg: 1.25rem; /* 20 - lead paragraphs, card text */
--text-3xl: 2.5rem; /* 40 - section display */
--text-5xl: 3.75rem; /* 60 - homepage hero (was 55) */
--color-brand: #f5771c; /* the accent - CTAs, borders, active nav */
--color-brand-dark: #d55f09; /* button hover (was SCSS darken 10%) */
אותה הערה, was SCSS darken 10%, היא כל הפואנטה של התרגיל. צבע ה-hover הישן היה קיים רק כקריאה לפונקציה; היום הוא ערך עם שם, ומי שיבוא אחריי לא צריך להריץ build כדי לגלות מה הערך שלו.
שלושת המגה-בייט שאף אחד לא שם לב אליהם
ממצא אחד מהאודיט ראוי לתיעוד, כי התיקון שלו לא עלה דבר והוא היה באוויר במשך שנים.
הקובץ inc/enqueue-scripts.php של התבנית כלל את דומיין הפרודקשן 7-is.com בתוך מערך $dev_domains. לכן הקבוע WP_ENV קיבל את הערך development בפרודקשן, והאתר שבאוויר הגיש לגולשים אמיתיים קבצי פיתוח לא ממוזערים: שני stylesheets במשקל 1,121.5 KB ו-1,121.2 KB, ו-bundle של JavaScript במשקל 1,902.7 KB.
מעל 3 MB של קבצי תבנית, לא ממוזערים, בכל טעינת עמוד שלא מגיעה מה-cache. לא שרת איטי ולא תמונות כבדות. דומיין אחד במערך אחד.
שני ה-stylesheets הם היום קובץ tailwind.css אחד במשקל 68.1 KB, בלי build נפרד ל-RTL. איך זה קרה, בחלק הבא.
המראה החדש
רוב חלקי האתר נראים היום אחרת. החלקים ששווה לתאר הם אלה שבהם החלטה שהתקבלה שוב ושוב, אחרת בכל פעם, הפכה סוף סוף לרכיב אחד.
כל עמוד פנימי נפתח היום בבאנר משותף, sevenis_page_hero(). קודם לכן עמוד נפתח ברצועת תמונה חשופה, ורק נמוך יותר, מנותקת ממנה ויזואלית, הופיעה הכותרת. הבאנר מחבר בין השניים ונותן לכל חלק באתר את אותה פתיחה.
המוטיב החוזר של האתר הוא ״section head״: קו כתום וסמל של טבעות קונצנטריות, שחוזר באותה צורה בכל המקטעים, כך שהעין לומדת את מבנה האתר. שני סגנונות כפתור, ״Wipe״ ו-״Hairline״, נלקחו ממחקר עיצוב ומיושמים בכל האתר, במקום להמציא כפתור חדש בכל עמוד.
ה-header נבנה מחדש בגרסה כהה, עם סרגל מובייל נמוך יותר. ה-footer הפך לקריאה לפעולה שסוגרת את העמוד, עמודות קישורים ובלוק יצירת קשר, ולא עוד פינה שאליה זורקים כל מה שנשאר.

לפניאחריהטיפוגרפיה קיבלה סקאלה אחת, כל הכותרות הוגדרו ל-line-height של 1.3, והגופן הוא variable woff2 עם fallback מקומי תואם מטריקות, שהוגדר כ-local("Arial") וגופנים דומים לו, כך שהמעבר לגופן הרשת לא מזיז את ה-layout. ה-repo ירד מ-156 קבצי גופן ל-8.
אנימציית ה-scroll reveal שרדה, עדינה בהרבה מגרסת wow.js שהיא החליפה.
עברית ואנגלית
לאתר לא הייתה גרסה אנגלית כלל. הוספתה הייתה נתח העבודה הגדול ביותר, וממנה נגזר רוב מה שנעשה מסביב.
הצנרת הדו-לשונית
Polylang Pro, עם עברית (he_IL, RTL) כשפת ברירת המחדל ואנגלית (en_US, LTR) כשפה שנייה. תפריטים, טפסי Contact Form 7, ערכי שדות ACF ומחליף השפות ב-header, כולם מתחלפים לפי השפה הפעילה.
השארתי את ה-slugs העבריים גם על הכתובות באנגלית, כך שעמוד אנגלי יושב בנתיב כמו /en/אודות/. זה נראה מוזר בכתב, אבל זה גם מה ששומר על שתי השפות מצומדות, בלי לתחזק סכימת slugs שנייה שעלולה לצאת מסנכרון בשקט.
מחרוזות שמגיעות מהתבנית עצמה נכתבות בשתי השפות באותה שורה, דרך helper קטן, sevenis_txt($he, $en), שבוחר לפי pll_current_language() ונופל חזרה לעברית. יש 44 קריאות אליו.
החלופה, קטלוגי .po, נדחתה מכיוון שהקוד הקיים כבר עשה את אותה עבודה עם ternaries שפוזרו על פני קבצי התבנית. ה-helper מנסח את התנאי פעם אחת.


Logical properties במקום build נפרד ל-RTL
זה הדבר שהכי שווה לקחת מהפרויקט הזה הלאה.
הגרסה הישנה הגישה קובץ rtl.css נפרד, שיקוף מלא של ה-stylesheet הראשי במשקל 1,121.5 KB, מכיוון שה-stylesheet הראשי נכתב במונחים של ימין ושמאל, ושיקוף היה הדרך היחידה להפוך אותו. לגרסה החדשה אין stylesheet של RTL, ואין בה אף תנאי is_rtl().
הכיוון מגיע מהמאפיין dir על <html> ומ-CSS logical properties: padding-inline-start במקום padding-left, margin-block-end במקום margin-bottom. הדפדפן פותר אותם לפי הכיוון. רק דברים שהם באמת פיזיים מקבלים כלל [dir="rtl"], ויש כאלה מעטים: חיתוך של background-position, ו-dock במיקום קבוע.
לא מכירים? כתבתי בנפרד מדריך ל-CSS logical properties, עם הרשימה המלאה ועם המקבילה של כל תכונה פיזית.
אתר דו-לשוני הוא stylesheet אחד, לא שניים. ה-stylesheet השני מעולם לא נבע מהדו-לשוניות. הוא היה סימפטום של CSS שנכתב בכיוונים פיזיים.
תרגום התוכן
צנרת אינה תרגום. את התוכן עצמו היה צריך לכתוב.
| סוג תוכן | עברית | אנגלית |
|---|---|---|
| עמודים | 7 | 7 |
| מאמרי שירות ותובנות | 17 | 16 |
| פוסטים בבלוג | 3 | 0 |
ל-23 מתוך 27 הפריטים בעברית יש מקבילה באנגלית, מקושרת אליה כזוג תרגום ב-Polylang. ארבעת הפערים האלה מכוונים. שלושת פוסטי הבלוג הם הודעות נקודתיות לשוק הישראלי בלי קהל באנגלית, ומאמר שירות אחד עוכב על ידי הלקוח.
Contact Form 7 רץ כשני טפסים נפרדים, אחד לכל שפה, במקום טופס אחד שמחזיק תנאי נפרד לכל מחרוזת.
שני הטפסים מוגנים ב-Cloudflare Turnstile, שהחליף תג reCAPTCHA שישב בצורה צורמת ב-footer החדש ואסף מידע שלמשרד לא הייתה סיבה לאסוף. על ההגדרה הזאת כתבתי בנפרד, במדריך להגדרת Cloudflare Turnstile עם Contact Form 7.

ביצועים, נמדדים
בבריף המקורי לתיעוד הזה הייתה הסתייגות שלפיה לא בוצעו מדידות ביצועים. עכשיו, כשהאתר באוויר, הן בוצעו.
האתר רץ עם WP Rocket על אחסון LiteSpeed. WP Rocket אחראי על ה-page caching, ממזער CSS ו-JavaScript, ומגדיר defer לחמישה סקריפטים בעמוד הבית. את סקירת ההגדרות המלאה שלי כתבתי במדריך WP Rocket.
מה שגולש בעמוד הבית באמת מוריד היום, כפי שנמדד בהעברה ברשת עם דחיסה פעילה:
| קובץ | על הדיסק | ממוזער | ברשת |
|---|---|---|---|
tailwind.css |
68.1 KB | 68.7 KB | 13.6 KB |
main.js (ה-bundle הישן) |
720.6 KB | 409.6 KB | 89.1 KB |
splide.min.js |
29.1 KB | 29.1 KB | 12.6 KB |
בערך 115 KB של CSS ו-JavaScript של התבנית עוברים ברשת, מול גרסה שהגישה מעל 3 MB לא דחוסים.
בפרופיל מובייל מואט, Slow 4G עם האטת מעבד פי 4, עמוד הבית רושם LCP של 805 מילישניות ו-CLS 0.00.
נתון תזוזת ה-layout הוא זה שאני הכי מרוצה ממנו. הוא תוצאה ישירה של גופן ה-fallback תואם המטריקות: גופן הרשת נטען ושום דבר לא זז.
אלה מספרי מעבדה מתוך trace מואט, לא נתוני שדה. האתר לא באוויר מספיק זמן כדי להופיע בדוח Chrome UX, ולכן אין עדיין מדידה של גולשים אמיתיים.
תוכן העמודים יוצא מהגושים ונכנס לשדות
עמודי אודות וקריירה החזיקו את כל הטקסט שלהם בשדה post_content אחד. התבנית חתכה אותו לרצועות ויזואליות לפי פיצול על כותרות <h2>, מה שעבד, אבל גם הפך את מבנה העמוד לבלתי נראה למי שערך אותו. מחקו כותרת, ושתי רצועות התאחדו בשקט. גריד הצוות הופיע רק מכיוון ש-shortcode בשם [sevenis_team] במקרה ישב בפסקה הנכונה.
כל רצועה היא היום לשונית ACF עם תווית, וגריד הצוות הוא תיבת סימון.
ה-helper נופל חזרה לפיצול <h2> הישן כשהשדות ריקים, כך שעמוד שלא מולא, תרגום חדש או שכפול, עדיין נטען כמו שצריך במקום להישאר עם באנר ושום דבר מתחתיו.
מלכודת אחת ששווה להעביר הלאה: ההגדרה hide_on_screen של ACF אינה מסתירה את עורך התוכן תחת עורך הבלוקים. היא משפיעה רק על העורך הקלאסי. את העורך היה צריך להסיר עם remove_post_type_support(), ורק בעמוד הספציפי שנערך.

לפניאחריהעלאה לאוויר
workflow של GitHub Actions בונה את התבנית ומסנכרן אותה ב-rsync ל-Cloudways בכל push. שני פרטים בתוכו קיימים בגלל סכנות ספציפיות.
ה-rsync מסרב להעלות לכל יעד מלבד האפליקציה של 7is. כמה פרויקטים חולקים שרת Cloudways אחד מאחורי שמות תיקיות אטומים כמו erhxryjtbb ו-zaqhvpuxze, שקל מאוד לבלבל ביניהם והבלבול הרסני. מפתח ה-SSH של שרת הסטייג'ינג מוגדר מראש (pinned) ולא נסרק בזמן ההרצה.
ניקוי ה-cache רץ מבפנים החוצה. Breeze מחזיק HTML מרונדר על הדיסק, ולכן ניקוי של Varnish קודם רק ממלא אותו מחדש מהעותק הישן של Breeze. נדרשו שלושה קומיטים רצופים כדי למצוא ולתקן את זה.
לסטייג'ינג יש הגנות משלו מפני מנועי חיפוש, והן מבוססות על ה-host של הבקשה ולא על option של וורדפרס. הסיבה היא שהסטייג'ינג מרוענן בייבוא מסד הנתונים של הפרודקשן, וייבוא כזה דורס כל הגדרה שמבוססת option, כולל תיבת הסימון ״מנע ממנועי חיפוש לאנדקס אתר זה״ של וורדפרס עצמה.
איך עבדתי
שבוע הוא זמן קצר לבנייה מחדש בסדר גודל כזה, ואני רוצה לדייק למה, מכיוון שהתשובה אינה שאני מקליד מהר.
ניהלתי את הפרויקט עם Claude Code. הגרסה הכנה של הטענה הזאת צנועה מגרסת השיווק: ה-AI לא עיצב את האתר, והוא לא הכריע בשום דבר שבאמת חשוב.
מה שהוא כן שינה הוא העלות של עבודה בצעדים קטנים, שכל אחד מהם מאומת בנפרד. בנייה מחדש שנוגעת ב-250 קבצים יכולה לרוץ כמאה שינויים נפרדים, כל אחד מהם מושווה מול baseline תקין, ברגע שהעלות המכנית של בדיקת שינוי כמו שצריך יורדת קרוב לאפס.
משם הגיעה המהירות. על אף אחד מההרגלים שלמטה לא היה כדאי לוותר גם בפרויקט בלי שום AI, וזו בדיוק הנקודה.
1. התבנית הישנה נכנסה לקומיט הראשון, כמו שהיא
הקומיט הראשון הוא תצלום מצב של התבנית בדיוק כפי שרצה ב-7-is.com. לא מנוקה, לא מפורמט מחדש. כל מה שבא אחריו ניתן להשוואה מול מה שהפרודקשן הגיש בפועל, וזה מה שהפך את שאר העבודה לניתנת לבדיקה, ולא רק זהירה.
2. עבודה לא טריוויאלית קיבלה מפרט כתוב מראש
שני מפרטים יושבים ב-repo, אחד למקטע הצוות בעמוד הבית ואחד למעבר התוכן ל-ACF. כל אחד מהם מגדיר את הבעיה, את מבנה השדות, את התנהגות ה-fallback, את הדרך לאמת את התוצאה, ורשימה מפורשת של מה שהוצא מההיקף במכוון.
המפרט הוא מה שהופך שינוי בסיוע AI למשהו שאפשר לסקור. סוכן AI יבנה בשמחה כל דבר שתתארו לו.
ולכן המפרט הוא המקום שבו אתם מגלים שמה שתיארתם אינו מה שרציתם, בזמן שהגילוי עוד זול. סעיף ״מה לא נעשה״ הצדיק את מקומו יותר מפעם אחת.
3. קומיט לכל שינוי, עם הסיבה בהודעה
106 קומיטים, עם הודעות שמסבירות למה, לא מה. ההודעה הבאה מתעדת באג שמעולם לא קרה. היא מסבירה שהרצועה מזוהה לפי התוכן שלה ולא לפי המיקום שלה בעמוד, כך ששינוי סדר המקטעים לא יגרום לסמל הטבעות להופיע מאחורי תמונות הצוות:
Keyed to the band's CONTENT rather than to its index, so reordering the sections cannot strand the rings behind the portraits.
מי שישנה את סדר המקטעים ב-CMS בעוד שנה לא ידע כמה קרוב זה היה, וזו בדיוק הסיבה שההודעה אומרת את זה.
הערות בקוד עושות את אותה עבודה בשביל חלופות שנדחו: למה לא השתמשתי ב-border במקום ב-text-decoration, ולמה בדיקת host עדיפה על option של וורדפרס.
4. רפקטור לא נחשב ניטרלי עד שהוכח שהוא כזה
כל דבר שנועד להיות ניטרלי ויזואלית היה חייב להיות מוכח ככזה. שמרתי את ה-HTML המרונדר של כל כתובת מושפעת לפני השינוי, סיננתי רעש שמשתנה בין בקשה לבקשה כמו nonces של Contact Form 7 ו-cachebusters של קבצים, ואז השוויתי מול ה-HTML שאחרי. מעבר התוכן ל-ACF התקבל רק אחרי ששלושה מתוך ארבעת העמודים חזרו זהים ברמת הבייט, והרביעי נבדל אך ורק בשינוי טיפוגרפי מכוון.
״זה נראה אותו דבר״ מעולם לא היה הסטנדרט.
5. כל שינוי נבדק בשתי השפות
באתר דו-לשוני, ״זה עובד״ הוא משפט לא שלם עד שאומרים באיזו שפה. כמה קומיטים קיימים אך ורק מכיוון שתיקון בעברית שבר את האנגלית, או מכיוון שסריקה דו-לשונית מצאה מחרוזת לא מתורגמת.
תיקוני טיפוגרפיה ומרווחים אומתו בקריאת computed styles ב-390px וב-1440px ב-Chrome headless, ולא בהצצה לצילום מסך.
כך באג אחד שדווח התברר כשלושה. דווח על כותרת גדולה מדי במקטע אחד, וסריקה של כל הכותרות בעמוד מצאה את אותו פגם בדיוק בשני מקטעים נוספים.
מה יצא מכל זה
אתר ייעוץ שהיה בעברית בלבד הוא היום דו-לשוני, על תבנית שנבנתה מחדש ולא טולאה, עם מערכת עיצוב שלא הייתה לו קודם, ועם תוכן העמודים בשדות עם תוויות במקום בגוש אחד בעורך.
המספרים שחשובים: 23 זוגות תרגום בשתי שפות, 409 קבצי תבנית שירדו ל-294, בערך 115 KB של CSS ו-JavaScript שעוברים ברשת, ועמוד בית שמצייר את האלמנט הגדול ביותר שלו ב-805 מילישניות על טלפון מואט, בלי להזיז את ה-layout.
שבוע עבודה, רובו בשלושה ימים, והחלקים שלא הושלמו כתובים למעלה במקום להישאר למישהו לגלות אותם בעצמו.