הצינור: ממארז נבחר עד אישור שמכבד את המתנה
הכול רץ בדפדפן מעל קובץ נתונים אחד ו-localStorage; אין מסד נתונים ואין שלב build.
הרעיון שמחזיק את החנות הוא שהמתנה היא ישות בפני עצמה, ולא עוד שדה בטופס. ברגע שמסמנים שההזמנה היא מתנה, נולד אובייקט אחד שנושא את הפתק בכתב יד, את סוג האריזה, את הבקשה לשלוח ישירות לנמענת ואת ההוראה להסתיר את המחיר — והאובייקט הזה נשמר ב-localStorage ונקרא מחדש בכל מסך בהמשך, כך שאף העדפה לא נופלת בין עמוד לעמוד. באותה רוח נבנה גם הקופון: הוא נשמר ככלל (קוד, סוג, ערך) ולא כסכום קפוא, ולכן הנחה באחוזים מחושבת מחדש מהסכום החי בכל שינוי בעגלה במקום להישאר תקועה על השקלים של רגע ההפעלה. שתי ההחלטות האלה נראות קטנות, אבל הן ההבדל בין חנות שמרגישה אמינה לבין חנות שסותרת את עצמה במסך האחרון.
ארבעת המסכים לא מחזיקים כל אחד עותק משלו של ההעדפות. יש אובייקט מתנה אחד ב-localStorage, וכל מסך קורא ממנו — זה מה שמונע את הסתירה הקלאסית שבה עמוד המוצר מבטיח פתק כתוב יד ומסך האישור לא יודע עליו.
מה זה
MALINA היא חנות אונליין למארזי מתנה ולאקססוריז לנשים, כולה בעברית RTL. יש בה 27 עמודי HTML — בית, בוטיק, עמוד מוצר, עגלה, תשלום, מועדפים, חשבון, שאלות נפוצות ועמודי נחיתה לפי אירוע — והיא רצה בלי שלב build כלל: vanilla HTML, CSS ו-JavaScript.
כל הקטלוג יושב בקובץ נתונים אחד עם 31 מוצרים ו-8 קטגוריות. הוא המקור היחיד לשמות, למחירים, לתמונות ולשיוך הקטגוריה, וכל עמוד בחנות נגזר ממנו.
הבעיה
רוב תבניות המסחר מתייחסות למתנה כאל תיבת סימון בסוף התהליך. התוצאה מוכרת: מבטיחים פתק אישי בעמוד המוצר, ובמסך התשלום כבר אין לו זכר — או גרוע מזה, החבילה מגיעה לנמענת עם תווית מחיר.
הבעיה השנייה הייתה שהחנות צריכה להיראות כמו בוטיק ולא כמו קטלוג. מארז מתנה נמכר על תחושה, על אריזה ועל טקסט — לא על טבלת מפרטים.
מה בניתי
בניתי את חבילת המתנה כשכבה מלאה ולא כתוספת: פתק בכתב יד עד 200 תווים, בחירת אריזה, משלוח ישיר לנמענת והסתרת מחיר קבועה. כל אלה נשמרים באובייקט אחד שנקרא מחדש בעגלה, במסך התשלום ובאישור, כדי שההבטחה תשרוד את כל הצינור.
לצידה בניתי מנוע קופונים שמחזיק כלל ולא סכום, מד כמות מול מלאי, מעריך תאריך מסירה, רשימת תכולה לכל מארז והעברת הזמנה לוואטסאפ של החנות בסוף התהליך. שכבת החיפוש והסינון עובדת גם על אירוע, על צבע ועל תכולה, לא רק על שם המוצר.
איך זה עובד
אין שרת ואין מסד נתונים. המצב כולו נשמר ב-localStorage בארבעה מפתחות נפרדים — עגלה, מועדפים, קופון ומתנה — וכל עמוד טוען את קובץ הנתונים ומרנדר את עצמו ממנו. מפתחות האחסון נשמרו בשמותיהם המקוריים בכוונה, כי שינוי שם היה מוחק את העגלה של כל מי שכבר גלש בחנות.
העיצוב הוא Liquid Glass בגוונים של ברי ושמפניה על רקע קרם, עם אנימציות GSAP שנטענות בהשהיה. כל התמונות מקומיות ואין תלות ב-CDN תמונות חיצוני. מעל הכול יושבת שכבת הגנה מפני שכפול — סקריפט בצד הלקוח יחד עם middleware בקצה — כך שדפדפן אוטומטי מקבל עמוד חסום במקום את החנות.
הסטאק
Vanilla HTML/CSS/JS בלי bundler, קובץ נתונים אחד לקטלוג, localStorage למצב, GSAP ו-Motion לאנימציות, ופריסה סטטית על Vercel. גרסת ה-cache-buster מתקדמת ידנית בכל שינוי של CSS או JS, כדי שגולשים חוזרים לא יקבלו קוד ישן.
התוצאה
החנות חיה ב-malina-pi.vercel.app ועוברת את המסלול המלא: בחירת מארז, סימון מתנה עם פתק, הוספה לעגלה, תשלום בשלושה שלבים ואישור שמסכם את ההזמנה ומעביר אותה לוואטסאפ. הצינור נסגר בלי שער תשלומים — זו החלטה עסקית שנשארה פתוחה, לא פער טכני.
הדמו החי פתוח לגמרי: אפשר לעבור על הקטלוג, לפתוח מוצר, להוסיף לעגלה, להפעיל קופון ולעבור את כל מסלול ההזמנה עד מסך האישור.