Shared Inner Pages
דמו אחד, כמה דפי בית, סט פנימיים אחד.
#sip-idea
הרעיון
ורטיקל שווה בדרך כלל יותר מדף בית אחד להראות ללקוח: כהה, בהיר, מגזין. העמודים הפנימיים זהים בכולם. לשכפל את הדמו פירושו שלושה עותקים של כל עמוד פנימי, ובפעם השנייה שהתוכן משתנה שניים מהם כבר שקריים.
במקום זה: כל דף בית מקבל כתובת משלו, והעמודים הפנימיים נבנים פעם אחת. הדפדפן זוכר מאיזה דף בית הגולש הגיע, והעמוד הפנימי מתלבש עליו: התפריט, הלוגו, הצבעים והפונט.
#sip-curse
למה: הקללה של העותקים
עד 5.11 כל דף בית קיבל עותק משלו של כל העמודים הפנימיים תחת /v/<home>/…. ה-build ספר 868 עמודי דמו כשהתוכן האמיתי הוא 370: ה-SaaS בנה את אותם 8 עמודים 9 פעמים, עורכי הדין 29 עמודים 6 פעמים. כל עותק הוא עוד עמוד לבנות, לבדוק ולתחזק. עכשיו כל 12 הדמואים עם כמה דפי בית הם סט פנימיים אחד.
#sip-how
איך זה עובד
app/demos/_shared/shared-home/ the mechanism, every demo uses it
home-script.ts which home: ?home= → /v/<home>/ in the path → localStorage
HomeScript.tsx sets the home's attributes on the frame BEFORE the first paint
use-home.tsx useHome() for the chrome · RememberHome on each home · HomeAttrs
HomeOnly.tsx homes that are different businesses: every home's body, one shown
/demos/lawyer_18_09/v/labor/about → rewritten to /demos/lawyer_18_09/about
(next.config.mjs, SHARED_HOME_DEMOS)- שני מקרים. דפי בית של אותו עסק (עורכי הדין, ה-SaaS): העמוד הפנימי אחד, ורק העטיפה מתחלפת. דפי בית שהם עסקים שונים (מרפאות, מסעדות, כנסים, בלוגים): עמוד הרשימה נושא את הגוף של כל עסק בתוך
HomeOnly, ורק של העסק הנוכחי מוצג. עמוד פריט נבנה פעם אחת, מהעסק שיש לו את ה-slug. - בלי הבהוב. הסקריפט רץ בתוך ה-HTML לפני הציור, כמו מתג מצב כהה. אחרי לחיצה בתוך האתר הוא לא רץ, ו-HomeAttrs עושה את אותו דבר.
- לינקים. לינק פנימי של דף בית יכול להיות
/v/<home>/about: ה-rewrite מגיש את העמוד המשותף, והכתובת עדיין אומרת מאיזה דף בית באת.
#sip-cms
לא להגזים בעמודי CMS
בדמו, רשימה צריכה 1 עד 3 עמודי פריט לדוגמה. השאר מקשרים אליהם: לחצת על תמי והגעת לדף הצוות של יוסי, ואף אחד לא שם לב. בדמו נדל״ן אין טעם לרנדר 12 נכסים, ובבלוג מספיקות 3 כתבות. כמה פריטים מוצגים ברשימה זה עניין של עיצוב. כמה עמודים נבנים זה עניין של משקל.
מה שאחיד ממילא הוא וריאנט. אם שכפלת כתבות בקוד והן זהות חוץ מהכותרת, זה לא תוכן, זה עמוד אחד שמתחלף. המלל בעמוד הפריט כללי, ואז אין סיבה לבנות אותו פעם לכל פריט. הפתרון תלוי בעיצוב: עיצוב עם 6 כתבות ב-4 קטגוריות לא צריך 24 כתבות, אפשר להשתמש באותן תמונות ולערבב את הסדר. חרטות בסגנון הזה, זה דמו.
שני דפים לדף אחד. שני דפי בית חלשים, כשבכל אחד חלק יפה, הופכים לאחד: ההדר מהאחד והגוף מהשני. ה-SaaS עבר כך מ-9 מוצרים למוצר אחד (6.11): הדף של Linkflow מתחת להדר של Payora. המלל עצמו כללי, אף אחד לא שם לב.
app/demos/_shared/example-pages.ts
const posts = examplePages(site.posts.map((p) => p.slug), 4);
posts.slugs // what the route builds (generateStaticParams, dynamicParams = false)
posts.page(slug) // what a card opens: itself, or an example in turn
live: realty 60 listings -> 3 · blog 54 posts -> 12 · dentist 24 services -> 6
photographer albums, barber services: one per homeצורה אחת לכל הדמואים
לכל הדמואים עם כמה דפי בית יש אותו עץ ואותם שמות ב-variants.ts. אותה טכניקה משמשת גם לדף נחיתה שנראה כמו אתר שלם.
app/demos/<brand>/
layout.tsx fonts + data-demo only
_homes/Home<Name>.tsx one file per homepage
_shared/variants.ts the table, in the names below
_shared/variant-registry.ts only when each home is a different business (its own pictures)
_shared/pages/<Brand><Page>.tsx the inner page bodies, each takes root
_shared/<x>-homes.ts the homes on the mechanism: a skin per home (SharedHomes)
(home)/ the base home, at the bare demo URL
(base)/ the ONE set of inner pages (conference's is (ai)/)
v/[variant]/ every other homepage, the home only
BASE the base home's URL
HomeSlug HOME_SLUGS HOMES homeRoot() isHomeSlug() every homepage, the base included
VariantSlug VARIANT_SLUGS VARIANTS variantRoot() isVariantSlug() only the homes under v/[variant]
HOME_LIST homeSlugOf(root) the switcher chip · the home of a root
HOME_TABLE getHome(slug) variant-registry.ts, brand demos only: every home with its assets
HOME_BY_VARIANT v/[variant]/page.tsx: which home component each slug renders#sip-control
איפה יושב הניהול
בכל מימוש יש טבלה אחת שהיא כל הניהול. הוספת דף בית היא שורה בטבלה ועוד קומפוננטה אחת, בלי קבצי ניתוב חדשים. חיווט הניתוב עצמו יושב בתוך תיקיית הדמו, והפירוט העדכני שלו בפרק 10 של סקיל הדמו.
אלמוג ושות׳
כמה דפי בית, סט פנימיים אחד, ומחליף גרסאות בפינת המסך.
app/demos/lawyer_18_09/_shared/variants.tsשורה אחת לכל דף בית: slug, שם לתצוגה, ערכת צבע, ו-root שכל לינק פנימי נבנה ממנו.
לדמוCatania
מסעדות, מסושי ועד פאב, על אותו בסיס: תפריט, גלריה ויצירת קשר משותפים, מותג שונה לכל אחת.
app/demos/catania_24_06/_shared/variants.tsשורה לכל מסעדה, והמותג שלה ב-_shared/brands/.
לדמומרפאות
מרפאות (שיניים, ילדים, פלסטיקה, רפואה סינית, פסיכולוגיה, אורתופדיה) על סט פנימיים אחד.
app/demos/dentist_27_05/_shared/variants.tsשורה לכל מרפאה, אותו מבנה כמו אצל עורכי הדין.
לדמו#sip-check
לבדוק שאין דליפה
דליפה היא לינק בעמוד של גרסה אחת שמוביל לגרסה אחרת. מספיק /demos/x/about קבוע אחד בעמוד משותף, וגולש שנכנס דרך הדף הבהיר חוזר לכהה. בעין אי אפשר לתפוס את זה: בגרסת הבסיס הלינק השבור מוביל בדיוק למקום הנכון. לכן יש בדיקה.
npm run dev # one terminal
npm run check:variants # another
npm run check:variants -- --only lawyer # one demo
npm run check:variants -- --url http://localhost:3100מוצא את הדמואים
כל דמו עם _shared/variants.ts, ואת הבסיס שלו מ-export const BASE. דמו חדש בתבנית הזו נכנס לבדיקה לבד.
מוצא את הגרסאות
מהלינקים של מחליף הגרסאות בדף הבית של הבסיס. המחליף נבנה מ-variants.ts, אז זו אותה רשימה בדיוק.
סורק כל גרסה
מתחיל בדף הבית שלה, עובר על כל עמוד פנימי שהיא מקשרת אליו, ובודק כל <a href>. לינק שמוביל לגרסה אחרת הוא דליפה.
כך נראית דליפה בפלט:
✗ lawyer_18_09 6 variants · 78 pages · 15s
LEAK banking/demos/lawyer_18_09/v/banking
→ /demos/lawyer_18_09/about (should start with /demos/lawyer_18_09/v/banking)אותה הרצה מדווחת גם על לינק פנימי שמחזיר שגיאה (BROKEN). אם יש משהו, הפקודה נכשלת (exit 1), אז אפשר להריץ אותה לפני merge.
דמו חדש עם כמה דפי בית, שני תנאים כדי שהבדיקה תראה אותו
_shared/variants.tsעםexport const BASE = '/demos/…'- כל <Link> במחליף הגרסאות מקבל
data-variant-switch="". מזה הבדיקה יודעת מה הגרסאות, וזה גם החריג היחיד שמותר לו להוביל לגרסה אחרת.
בלי המחליף המסומן, הבדיקה רואה גרסה אחת בלבד ומזהירה על זה.
#sip-works
הגרסאות בעמוד הדמו (/works)
שני דברים שונים, ובכוונה: האתר של הדמו הוא אתר אחד עם כמה דפי בית, והעמודים הפנימיים משותפים (כל מה שלמעלה). עמוד הדמו ב־/works הוא עמוד אחד לכל דף בית, בשביל החיפוש: אותו עמוד, לפי פרמטר.
/works/lawyer the demo's first home (criminal)
/works/lawyer?home=corporate another home: its slug, what it IS
/works/lawyer?home=almog-corporate the preview id the URLs carried until 26.10: still works,
its canonical is the slug's- בשרת (searchParams): ה־<title> והכותרת, "אתר לאורתופד" (
siteFor, אוsiteTitleכשזה לא נקרא טוב, "אתר לעורך דין מקרקעין"), canonical משלו עם הפרמטר, המסגרת החיה והתמונה של הגרסה. - השורה מתחת לכותרת נשארת של הדמו: התיאור של גרסה בכרטיס של עמוד התחום מתאר את העסק, לא את האתר.
- "עוד דמואים": כל השאר מאותו תחום, בלי הגרסה שעל המסך; בדף של גרסה דף הבית הראשון של הדמו נכנס לרשימה.
- מפת האתר: כל גרסה שורה משלה (
app/sitemap.ts). - מעבר בין שתי גרסאות של אותו דמו בתוך האתר משנה רק את הפרמטר: למסגרת יש key לפי הגרסה, אחרת היא שמרה את הקודמת.
המקור: worksHomes(demo) ב־data/industries-data.ts, מהדוגמאות של עמודי התחום (לכל אחת home, ה־slug מ־_shared/variants.ts של הדמו) ומהגרסאות שכרטיס מונה בעצמו (ה־SaaS, homes ב־demos-data). כל קישור עם ?home= נבנה ב־homeKey(e), אף פעם לא ביד.
גרסה חדשה של דמו, ב־/works ובחיפוש
- שורה ב־
_shared/variants.tsשל הדמו (היא כבר דף בית אמיתי, §10). - שורת דוגמה בעמוד התחום, דרך ה־builder של הדמו (
clinicExampleוכו׳), שממלא אתhome. - זהו: עמוד הדמו, הכותרת, ה־canonical, מפת האתר והרשימות מתעדכנים לבד. צילום:
npm run shotלתמונה המקדימה של הגרסה.
