8 שלב בניית מיומנויות

מבנה פרויקט ו-Routing — איפה שמים מה

AI יכול לבנות לך אתר שלם תוך דקות — אבל אם אתה לא מבין את מבנה הקבצים שהוא יצר, אתה לא יכול לתחזק, לשנות, או להסביר לו איפה לשים דברים חדשים. בפרק הזה נפרק את המבנה של פרויקט Next.js, נבין מה כל תיקייה וקובץ עושים, ונלמד את שפת ה-routing שהופכת תיקיות לדפים באתר.

מה יהיה לך בסוף הפרק הזה
מה תדעו לעשות אחרי הפרק הזה
לפני שמתחילים

פרקים קודמים: פרק 1 (הווב ב-2026), פרק 2 (React), פרק 3 (Frameworks — במיוחד Next.js).

מה צריך: דפדפן עם גישה ל-AI (V0, Bolt, Lovable, Claude, או Cursor). לא צריך להתקין שום דבר — הפרק הזה קונספטואלי עם תרגולים מול AI.

זמן משוער: 50-65 דקות קריאה + תרגולים.

הפרויקט שלך

מאיפה באנו: בפרק 07 למדתם לבחור אייקונים (Lucide), פונטים (Heebo) ותמונות (Unsplash). עכשיו נלמד איפה כל אחד מהם יושב בתוך מבנה הפרויקט — הגדרות הפונט ב-layout.tsx, התמונות ב-public/, וספריית האייקונים כ-import מ-node_modules.

מה נעשה היום: נפרק פרויקט Next.js שלם — תיקייה אחרי תיקייה, קובץ אחרי קובץ. נבין מה routing, מה dynamic routes, ואיך להגיד ל-AI בדיוק איפה לשים כל דבר חדש.

לאן ממשיכים: בפרק 09 נלמד לפרוס את הפרויקט הזה לאוויר — Vercel, Netlify או Cloudflare Pages. מבנה הפרויקט שנלמד כאן קובע איך הפריסה עובדת.

מונחים חדשים בפרק הזה
מונח (English)תרגוםהסבר בשורה אחת
app directoryתיקיית appהתיקייה הראשית ב-Next.js שמגדירה את כל ה-routes של האתר
page.tsxקובץ דףקובץ שהופך תיקייה ל-route נגיש — בלעדיו התיקייה לא תהיה דף באתר
layout.tsxקובץ פריסהשכבת UI משותפת שעוטפת כל דף — header, footer, הגדרות גלובליות
loading.tsxמסך טעינהמסך טעינה שמופיע אוטומטית בזמן שהדף נטען
error.tsxמסך שגיאהמסך שגיאה שמופיע אוטומטית כשמשהו נשבר בדף
file-based routingניתוב מבוסס קבציםשיטה שבה מבנה התיקיות קובע את ה-URLs — כל תיקייה עם page.tsx הופכת לנתיב
dynamic routesנתיבים דינמייםנתיבים עם פרמטרים משתנים — כמו דף מוצר שמשתנה לפי ID
route groupsקבוצות ניתובתיקיות בסוגריים () שמארגנות קוד בלי להשפיע על ה-URL
package.jsonמניפסט הפרויקטתעודת הזהות של הפרויקט — רשימת תלויות, סקריפטים והגדרות
dependenciesתלויותחבילות שהפרויקט צריך כדי לרוץ — React, Next.js וכו׳
devDependenciesתלויות פיתוחחבילות שצריך רק בפיתוח — TypeScript, ESLint וכו׳
node_modulesתיקיית חבילותתיקייה ענקית שמכילה את כל החבילות המותקנות — לא נוגעים, לא מעלים ל-Git
tsconfig.jsonהגדרות TypeScriptקובץ הגדרות TypeScript — כולל path aliases כמו @/ שמקצרים imports
middleware.tsשכבת בינייםקוד שרץ לפני כל בקשה — בדיקת הרשאות, הפניות, או שינוי headers
scriptsסקריפטיםפקודות מוכנות ב-package.json — dev להפעלה, build לבנייה, start לייצור
מתחיל 7 דקות מושג חינם

מה AI מייצר כשאומרים "צור פרויקט Next.js"

כשאתם אומרים ל-V0, Bolt, Lovable, או כל AI אחר "צור לי פרויקט Next.js" — הוא לא יוצר קובץ אחד. הוא יוצר מבנה שלם של תיקיות וקבצים. בפרויקט טיפוסי יש 20-40 קבצים מהרגע הראשון, ואם ביקשתם גם shadcn/ui ו-Tailwind — אפילו יותר.

הנה מה שבדרך כלל נוצר:

my-project/
├── app/                    # כל הדפים והניתוב
│   ├── layout.tsx          # שלד האתר (header, footer, fonts)
│   ├── page.tsx            # עמוד הבית (/)
│   ├── globals.css         # סגנונות גלובליים
│   └── favicon.ico         # האייקון בטאב של הדפדפן
├── components/             # קומפוננטות משותפות
│   └── ui/                 # קומפוננטות shadcn/ui
├── lib/                    # פונקציות עזר
│   └── utils.ts            # utility functions
├── hooks/                  # custom hooks
├── public/                 # קבצים סטטיים (תמונות, לוגו)
├── package.json            # תעודת זהות + תלויות
├── tsconfig.json           # הגדרות TypeScript
├── next.config.ts          # הגדרות Next.js
├── tailwind.config.ts      # הגדרות Tailwind
├── postcss.config.js       # הגדרות PostCSS
├── .gitignore              # קבצים שלא עולים ל-Git
└── node_modules/           # כל החבילות (ענק!)

נראה מרשים? בואו נפרק את זה חלק אחרי חלק. אל תנסו לשנן — תבינו את הלוגיקה, ואז תדעו תמיד איפה לחפש.

הלוגיקה פשוטה: כל תיקייה יש לה תפקיד אחד ברור. app/ מנהלת את הדפים. components/ מחזיקה חלקים שחוזרים על עצמם. lib/ מחזיקה לוגיקה. public/ מחזיקה קבצים שהדפדפן צריך ישירות. וקבצי ההגדרות (package.json, tsconfig.json) אומרים לפרויקט איך להתנהג.

עשו עכשיו 3 דקות

פתחו V0, Bolt או Lovable, בקשו "Create a Next.js landing page", והסתכלו על רשימת הקבצים שנוצרו. אל תקראו את הקוד — רק ספרו כמה תיקיות יש, וראו אם אתם מזהים את השמות מהרשימה למעלה.

חשוב להבין: AI שונים מייצרים מבנים קצת שונים. V0 נוטה ליצור מבנה נקי עם shadcn/ui מובנה. Bolt מוסיף לפעמים תיקיות נוספות. Lovable בונה מבנה משלו. אבל העקרונות זהים — אם אתם מבינים את המבנה הסטנדרטי, תבינו כל וריאציה.

הנה השוואה מהירה של מה כל כלי AI מייצר:

כלי AIFrameworkספריית UIמבנה ברירת מחדל
V0 (by Vercel)Next.js 15shadcn/ui + Tailwindנקי ומסודר, app/ עם layout ו-page
BoltNext.js / Viteshadcn/ui + Tailwindדומה ל-V0, לפעמים מוסיף תיקיות נוספות
LovableVite + Reactshadcn/ui + Tailwindמבנה קצת שונה — src/ במקום app/
Claude Codeלפי בקשהלפי בקשהיוצר בדיוק מה שמבקשים
Cursorלפי בקשהלפי בקשהעובד על פרויקט קיים — לא יוצר מאפס

שימו לב ל-Lovable: הוא משתמש ב-Vite + React במקום Next.js, ולכן המבנה שלו קצת שונה — יש תיקיית src/ במקום app/, והניתוב נעשה עם ספרייה בשם react-router במקום file-based routing. כל מה שנלמד בפרק הזה רלוונטי בעיקר ל-Next.js — שהוא ברירת המחדל של V0, Bolt, ורוב כלי ה-AI.

הנקודה המרכזית: אתם לא צריכים לזכור כל קובץ. אתם צריכים לדעת 5 תיקיות ו-4 קבצים מיוחדים. זה הכל. את השאר תמיד אפשר לשאול את ה-AI.

עשו עכשיו 2 דקות

חשבו על פרויקט שאתם רוצים לבנות (אתר פורטפוליו? חנות? בלוג?). כתבו רשימה של 3 דפים שהאתר צריך. בסוף הפרק תדעו בדיוק איפה כל דף יושב במבנה התיקיות.

מתחיל 8 דקות מושג חינם

תיקיית app/ — הלב של הפרויקט

תיקיית app/ היא המקום שבו כל הדפים של האתר שלכם חיים. זו ההמצאה המרכזית של App Router שלמדנו בפרק 03 — כל תיקייה בתוך app/ יכולה להפוך לדף באתר.

אבל לא כל קובץ בתוך app/ הוא דף. יש 4 קבצים מיוחדים ש-Next.js מזהה אוטומטית. כל אחד עושה משהו אחר:

קובץמה הוא עושהחובה?דוגמה
page.tsx הופך תיקייה לדף נגיש. זה התוכן שהמבקר רואה. כן (לכל route) app/about/page.tsx/about
layout.tsx עוטף את כל הדפים בשכבה משותפת — header, footer, font loading. לא נטען מחדש בניווט. כן (ב-root) Root layout: app/layout.tsx
loading.tsx מסך טעינה שמופיע אוטומטית בזמן שהדף נטען. משתמש ב-React Suspense מאחורי הקלעים. לא ספינר או שלד בזמן טעינה
error.tsx מסך שגיאה שמופיע כשמשהו נשבר. תופס שגיאות ומציג הודעה ידידותית במקום מסך לבן. לא "משהו השתבש, נסו שוב"

נסביר את הלוגיקה עם משל: דמיינו בניין משרדים. layout.tsx הוא הלובי, המעלית, והמסדרונות — התשתית שכולם חולקים. page.tsx הוא החדר הספציפי שנכנסים אליו — התוכן המשתנה. loading.tsx הוא שלט "רגע, מכינים את החדר". error.tsx הוא שלט "החדר הזה סגור לתיקונים".

יש עוד שני קבצים מיוחדים שכדאי להכיר:

הנה דוגמה למבנה app/ של אתר עם כמה דפים:

app/
├── layout.tsx          # Root layout — עוטף הכל (html, body, fonts)
├── page.tsx            # עמוד הבית (/)
├── loading.tsx         # טעינה גלובלית
├── not-found.tsx       # דף 404
├── globals.css         # סגנונות גלובליים
├── about/
│   └── page.tsx        # דף אודות (/about)
├── blog/
│   ├── page.tsx        # רשימת פוסטים (/blog)
│   └── [slug]/
│       └── page.tsx    # פוסט בודד (/blog/my-first-post)
└── contact/
    └── page.tsx        # דף יצירת קשר (/contact)
טעות נפוצה: מחיקת layout.tsx

layout.tsx בתיקיית app/ הוא חובה. הוא מכיל את תגית <html> ו-<body> — בלעדיו אין HTML תקין. אם מחקתם אותו בטעות, האתר כולו יישבר. אם ה-AI שלכם מציע לערוך את layout.tsx — קראו מה הוא משנה לפני שאתם מאשרים. ואם משהו נשבר — בדקו שלא מחקתם layout.tsx.

מה Root Layout חייב לכלול:

// app/layout.tsx — המבנה הבסיסי
export default function RootLayout({ children }) {
  return (
    <html lang="he" dir="rtl">
      <body>
        {children}   {/* כאן נכנס התוכן של כל דף */}
      </body>
    </html>
  )
}

שימו לב ל-lang="he" dir="rtl" — זה מה שגורם לאתר להיות בעברית ומימין לשמאל. טיפ חשוב לשוק הישראלי: אם ה-AI לא הוסיף את זה, בקשו ממנו: "הגדר את ה-layout עם lang='he' dir='rtl' — האתר בעברית."

layout בפרויקט אמיתי כולל הרבה יותר:

// app/layout.tsx — גרסה מציאותית
import { Heebo } from 'next/font/google'
import './globals.css'
import { Header } from '@/components/layout/header'
import { Footer } from '@/components/layout/footer'

const heebo = Heebo({ subsets: ['hebrew'] })

export const metadata = {
  title: 'האתר שלי',
  description: 'אתר שנבנה עם Next.js',
}

export default function RootLayout({ children }) {
  return (
    <html lang="he" dir="rtl">
      <body className={heebo.className}>
        <Header />
        {children}
        <Footer />
      </body>
    </html>
  )
}

שימו לב — ה-Header וה-Footer מיובאים מ-components/layout/. הפונט Heebo (שלמדנו בפרק 07) נטען עם next/font/google. ה-globals.css מכיל את ה-Tailwind directives. כל זה קורה פעם אחת ב-layout — וכל דף באתר מקבל את זה אוטומטית.

מה עוד שמים ב-Root Layout?

כל מה שצריך לרוץ בכל דף — הולך ל-Root Layout. כל מה שספציפי לדף אחד — הולך ל-page.tsx של אותו דף. זו הפרדת אחריות בסיסית — layout עוטף, page מציג תוכן.

שגיאה שה-AI עושה לפעמים: שם Google Analytics או שירותים חיצוניים בתוך page.tsx במקום ב-layout.tsx. התוצאה — הסקריפט נטען רק בעמוד הבית ולא בשאר הדפים. אם שירות צריך לרוץ בכל מקום — הוא חייב להיות ב-layout.tsx.

Layout מקונן (Nested Layout): אפשר ליצור layout נפרד לכל חלק באתר. לדוגמה, דפי הבלוג יכולים לקבל sidebar שלא מופיע בשאר האתר:

app/
├── layout.tsx              # Root layout — Header + Footer לכולם
├── page.tsx                # עמוד הבית
├── blog/
│   ├── layout.tsx          # Blog layout — מוסיף Sidebar רק לבלוג
│   ├── page.tsx            # רשימת פוסטים
│   └── [slug]/page.tsx     # פוסט בודד
└── about/page.tsx          # דף אודות (ללא sidebar)

כשמבקר נכנס ל-/blog, Next.js טוען שניהם: Root Layout (header+footer) ובתוכו Blog Layout (sidebar). כשנכנס ל-/about — רק Root Layout. זו עוצמה של layouts מקוננים — ה-AI יכול ליצור חוויות שונות לחלקים שונים באתר.

דוגמאות לשימוש ב-nested layouts בשוק הישראלי:

עשו עכשיו 2 דקות

בקשו מ-AI: "הראה לי את layout.tsx של פרויקט Next.js בעברית." בדקו — האם יש lang="he" ו-dir="rtl"? האם יש טעינת פונטים? אלה שני הדברים הכי חשובים ב-layout.

מתחיל 2 דקות מושג חינם

SVG Diagram: מפת תיקיות של פרויקט Next.js

לפני שנצלול לכל תיקייה בנפרד, הנה מבט-על שמסכם את כל מבנה הפרויקט. שמרו את הדיאגרמה הזו — היא שווה זהב כשצריכים להיזכר איפה מה:

מפת מבנה פרויקט Next.js — מה כל תיקייה עושה my-project/ שורש הפרויקט app/ דפים וניתוב page.tsx, layout.tsx, loading.tsx components/ קומפוננטות משותפות ui/, forms/, layout/ lib/ לוגיקה ופונקציות עזר utils.ts, api clients public/ קבצים סטטיים images/, favicon, robots.txt hooks/ custom hooks לשימוש חוזר קבצי הגדרות (בשורש) package.json תלויות וסקריפטים tsconfig.json הגדרות TypeScript next.config.ts הגדרות Next.js tailwind.config.ts הגדרות Tailwind node_modules/ לא נוגעים! לא מעלים ל-Git!
מתחיל 7 דקות מושג חינם

File-Based Routing — הנתיב בתיקייה = הנתיב ב-URL

זה אחד מהרעיונות הכי אלגנטיים ב-Next.js: מבנה התיקיות שלכם הוא ה-URL של האתר. לא צריך להגדיר routing בנפרד, לא צריך קובץ config, לא צריך לכתוב קוד ניתוב. התיקייה היא הנתיב.

הכלל פשוט:

תיקייה + קובץURL באתרהסבר
app/page.tsx/עמוד הבית
app/about/page.tsx/aboutדף אודות
app/blog/page.tsx/blogרשימת הבלוג
app/blog/first-post/page.tsx/blog/first-postפוסט ספציפי
app/products/shoes/page.tsx/products/shoesקטגוריית נעליים

שימו לב לנקודה קריטית: רק תיקייה שיש בה page.tsx הופכת ל-route. אם יש תיקייה בלי page.tsx — היא לא דף באתר. זה אומר שאפשר ליצור תיקיות לארגון בלי שהן יהפכו לדפים.

מה קורה כשמבקר גולש לדף?

  1. Next.js מקבל את ה-URL (למשל /about)
  2. מחפש תיקייה מתאימה ב-app/ (למצא app/about/)
  3. בודק שיש page.tsx בתיקייה
  4. טוען את layout.tsx של ההורה (Root Layout)
  5. מרנדר את ה-layout עם ה-page בתוכו
  6. אם יש loading.tsx — מציג אותו בזמן הטעינה
  7. אם יש שגיאה ו-error.tsx קיים — מציג את מסך השגיאה

כל הזרימה הזו קורית אוטומטית. אתם לא צריכים לכתוב קוד routing — רק ליצור תיקיות ולשים בהן את הקבצים הנכונים. זה file-based routing.

למה זה חשוב ל-Vibe Coders? כי עכשיו כשאתם רוצים להוסיף דף חדש, אתם יודעים בדיוק מה לבקש מ-AI:

Prompt מומלץ להוספת דף
צור דף "שירותים" באתר Next.js שלי.
הקובץ צריך להיות ב-app/services/page.tsx.
השתמש ב-layout.tsx הקיים.
הדף צריך להיות Server Component.

בלי להבין file-based routing, הייתם אומרים "תוסיף דף שירותים" — וה-AI היה מחליט לבד איפה לשים אותו, ואולי בוחר מקום שלא מתאים למבנה הקיים.

דוגמה מהשוק הישראלי: סטארט-אפ ישראלי שבונה אתר SaaS עם AI צריך בדרך כלל את הדפים האלה:

app/
├── page.tsx                    # Landing page (/)
├── pricing/page.tsx            # דף תמחור (/pricing)
├── features/page.tsx           # יכולות המוצר (/features)
├── blog/
│   ├── page.tsx                # רשימת מאמרים (/blog)
│   └── [slug]/page.tsx         # מאמר בודד (/blog/ai-trends-2026)
├── login/page.tsx              # כניסה (/login)
├── signup/page.tsx             # הרשמה (/signup)
├── dashboard/
│   ├── page.tsx                # דשבורד (/dashboard)
│   ├── settings/page.tsx       # הגדרות (/dashboard/settings)
│   └── projects/
│       ├── page.tsx            # רשימת פרויקטים (/dashboard/projects)
│       └── [id]/page.tsx       # פרויקט בודד (/dashboard/projects/42)
└── api/
    ├── auth/route.ts           # API לאימות
    └── contact/route.ts        # API ליצירת קשר

שימו לב איך המבנה הפיזי של התיקיות משקף את המבנה הלוגי של האתר. אין קסמים, אין config files מסובכים — רק תיקיות וקבצים. כל מתכנת (או AI) שפותח את הפרויקט מבין מיד מה יש באתר.

טיפ מעשי: כשמתחילים פרויקט חדש, בקשו מה-AI ליצור את מבנה התיקיות לפני שמתחילים לכתוב קוד. קל יותר לתכנן מבנה ריק מאשר לסדר מבנה שכבר מלא. כתבו: "צור את מבנה התיקיות לפרויקט [תאור הפרויקט] — אל תכתוב קוד עדיין, רק את התיקיות והקבצים הריקים."

טעות נפוצה: ערבוב pages/ ו-app/

Next.js תומך בשתי שיטות routing: pages/ (הישנה) ו-app/ (החדשה). ערבוב בין השתיים גורם לבאגים מבלבלים ששניהם עובדים "בערך" אבל קונפליקטים ביניהם. בכל פרויקט חדש, ציינו ל-AI: "השתמש רק ב-App Router עם תיקיית app/ — אל תיצור תיקיית pages/."

עשו עכשיו 3 דקות

בקשו מ-AI: "צור דף about בפרויקט Next.js." בדקו — האם הוא שם את הקובץ ב-app/about/page.tsx? אם כן — הוא עשה את זה נכון. אם הוא שם אותו ב-pages/about.tsx — הוא השתמש בגישה הישנה.

בינוני 7 דקות מושג חינם

Dynamic Routes — דפים שמשתנים לפי פרמטר

יש לכם חנות עם 500 מוצרים. אתם לא הולכים ליצור 500 תיקיות. במקום זה, Next.js נותן לכם dynamic routes — תיקיות עם סוגריים מרובעים שאומרות "כאן יהיה פרמטר שמשתנה".

הנה שלושה סוגי סוגריים ומה כל אחד עושה:

תחבירדוגמהURL שתואםמתי להשתמש
[id] app/products/[id]/page.tsx /products/123, /products/abc פרמטר אחד — מוצר, פוסט, משתמש
[...slug] app/docs/[...slug]/page.tsx /docs/a, /docs/a/b/c נתיב עם עומק משתנה — דוקומנטציה
[[...slug]] app/shop/[[...slug]]/page.tsx /shop, /shop/men/shoes כמו catch-all אבל גם בלי פרמטר

הכי נפוץ: [id] — פרמטר אחד. 90% מהמקרים זה מה שצריכים. דף מוצר, פוסט בבלוג, פרופיל משתמש — כולם [id].

Route Groups — ארגון בלי השפעה על URL

לפעמים רוצים לארגן קבצים בתיקיות בלי שהתיקייה תופיע ב-URL. לזה יש סוגריים עגולים:

app/
├── (marketing)/          # לא מופיע ב-URL!
│   ├── about/page.tsx    # /about (לא /marketing/about)
│   └── pricing/page.tsx  # /pricing
├── (dashboard)/          # לא מופיע ב-URL!
│   ├── settings/page.tsx # /settings
│   └── profile/page.tsx  # /profile
└── page.tsx              # /

Route groups מאפשרים לכם לארגן את הקוד לפי לוגיקה עסקית (שיווק, דשבורד, ניהול) בלי שזה משפיע על מה שהמבקר רואה ב-URL. טיפ: כל route group יכול גם לקבל layout.tsx משלו — כך שלדפי השיווק יש עיצוב אחד ולדשבורד עיצוב אחר.

איך dynamic route עובד בפועל? כשיוצרים app/products/[id]/page.tsx, הקובץ מקבל את הפרמטר כ-prop:

// app/products/[id]/page.tsx
export default function ProductPage({ params }) {
  // אם המבקר גולש ל-/products/42
  // אז params.id = "42"
  return <h1>מוצר מספר {params.id}</h1>
}

לא צריך לכתוב את זה — ה-AI כותב. אבל כדאי להבין שה-[id] בשם התיקייה הופך ל-params.id בקוד. אם שניתם את השם ל-[slug] — הפרמטר יהיה params.slug. השם בסוגריים המרובעים קובע את שם המשתנה.

דוגמה מתקדמת — Nested Dynamic Routes:

app/shop/[category]/[productId]/page.tsx
# URL: /shop/electronics/iphone-15
# params.category = "electronics"
# params.productId = "iphone-15"

זו דרך נפוצה לבנות ניווט בחנות — קטגוריה ואז מוצר. כל שכבה של סוגריים מרובעים מוסיפה פרמטר.

מתי לבחור Catch-All? דמיינו אתר תיעוד (documentation) — כמו docs.mysite.com. הנתיבים שם עמוקים: /docs/getting-started, /docs/api/auth/tokens, /docs/guides/deployment/vercel. כל הנתיבים האלה צריכים את אותו layout ואותו עיצוב, אבל העומק משתנה. Catch-all route ([...slug]) פותר את זה — קובץ אחד שתופס כל עומק URL.

Catch-All vs Optional Catch-All:

עשו עכשיו 3 דקות

חשבו על אתר חנות. כתבו 3 נתיבים שצריכים להיות דינמיים (לדוגמה: דף מוצר, דף קטגוריה, דף סינון). עכשיו כתבו את מבנה התיקיות — איך כל אחד ייראה ב-app/?

Decision Framework: מתי לבקש מ-AI route דינמי
מצבסוג Routeמה לכתוב ל-AI
אותו layout, מידע שונה (מוצר, פוסט)[id]"צור דף מוצר דינמי ב-app/products/[id]/page.tsx"
עומק URL משתנה (docs, wiki)[...slug]"צור routing עם catch-all ב-app/docs/[...slug]/page.tsx"
אותו דבר + גם עמוד ראשי[[...slug]]"צור optional catch-all — גם /shop וגם /shop/category"
ארגון פנימי בלי השפעה על URL(group)"צור route group בשם (marketing) לדפים השיווקיים"
מתחיל 2 דקות מושג חינם

SVG Diagram: File-Based Routing — מתיקייה ל-URL

הנה מיפוי ויזואלי שמראה בדיוק איך תיקיות הופכות ל-URLs:

File-Based Routing — מתיקייה ל-URL מבנה תיקיות URL בדפדפן app/page.tsx mysite.com/ app/about/page.tsx mysite.com/about app/blog/page.tsx mysite.com/blog app/blog/[slug]/page.tsx mysite.com/blog/my-post app/products/[id]/page.tsx mysite.com/products/42 app/(marketing)/pricing/page.tsx mysite.com/pricing static route — נתיב קבוע dynamic route — פרמטר משתנה route group — ארגון בלבד
מתחיל 5 דקות מושג חינם

תיקיית components/ — הקומפוננטות המשותפות

בפרק 02 למדנו ש-React עובד עם קומפוננטות — חלקים קטנים ושימושיים חוזר שמרכיבים את הדף. כל הקומפוננטות ה"גלובליות" — כאלה שמשמשות יותר מדף אחד — חיות בתיקיית components/.

המבנה הנפוץ:

components/
├── ui/                 # קומפוננטות shadcn/ui (Button, Card, Dialog...)
│   ├── button.tsx
│   ├── card.tsx
│   ├── dialog.tsx
│   └── input.tsx
├── layout/             # חלקים מבניים (Header, Footer, Sidebar)
│   ├── header.tsx
│   ├── footer.tsx
│   └── sidebar.tsx
├── forms/              # טפסים (ContactForm, SearchBar)
│   ├── contact-form.tsx
│   └── search-bar.tsx
└── shared/             # קומפוננטות משותפות אחרות
    ├── logo.tsx
    └── theme-toggle.tsx

למה חשוב לדעת את זה? כשאתם אומרים ל-AI "צור כפתור" בלי לציין איפה לשים אותו — הוא עלול לכתוב את הכפתור ישירות בתוך הדף. זה עובד, אבל אם תרצו לשנות את הכפתור בכל הדפים — תצטרכו לשנות בכל מקום בנפרד. זו הבעיה של קוד כפול (code duplication).

הפתרון: קומפוננטה נפרדת בתיקיית components/. ככה, כפתור אחד מוגדר פעם אחת — וכל דף משתמש בו. שינוי בקובץ אחד = שינוי בכל האתר. זו בדיוק הסיבה שבפרק 02 למדנו לחשוב בקומפוננטות.

הבדל חשוב — components/ui/ vs components/layout/:

הדרך הנכונה לבקש מ-AI קומפוננטה חדשה:

Prompt נכון לקומפוננטה חדשה
צור קומפוננטת testimonial card.
שים אותה ב-components/ui/testimonial-card.tsx.
השתמש ב-shadcn Card כבסיס.
תייבא אותה מ-app/page.tsx.
טעות נפוצה: הכל בקובץ אחד

AI נוטה ליצור קבצים ארוכים מאוד — 500 שורות ויותר עם כל הקומפוננטות בקובץ אחד. זה עובד אבל בלתי אפשרי לתחזוקה. אחרי שה-AI יוצר קובץ גדול, בקשו ממנו: "פצל את הקובץ הזה לקומפוננטות נפרדות בתיקיית components/". הוא יעשה את זה בכיף — פשוט צריך לבקש.

עשו עכשיו 2 דקות

בקשו מ-AI: "הראה לי איזה קומפוננטות יש בתיקיית components/ של פרויקט Next.js טיפוסי עם shadcn/ui." השוו לרשימה למעלה — מה חופף? מה שונה?

מתחיל 6 דקות מושג חינם

תיקיות lib/, hooks/ ו-public/ — כל אחת עם תפקיד

שלוש תיקיות נוספות שתראו בכל פרויקט, וכל אחת עם תפקיד ברור:

lib/ — הלוגיקה מאחורי הקלעים

תיקיית lib/ (קיצור של library) מכילה פונקציות עזר שלא קשורות ל-UI. אם components/ היא "מה שרואים", אז lib/ היא "מה שעובד מאחורי הקלעים".

lib/
├── utils.ts            # פונקציות עזר (cn() ל-className merge)
├── api.ts              # פונקציות גישה ל-API
├── constants.ts        # קבועים (צבעים, URLs, הגדרות)
├── validations.ts      # בדיקות תקינות לטפסים
└── supabase.ts         # חיבור ל-Supabase (אם משתמשים)

הקובץ הכי נפוץ כאן הוא utils.ts. כש-shadcn/ui מותקנת, הוא מכיל פונקציה בשם cn() שמאפשרת לשלב classes של Tailwind בצורה נוחה — שלמדנו בפרק 04. אל תמחקו את הקובץ הזה — הרבה קומפוננטות shadcn תלויות בו ובלעדיו הן יישברו.

מה עוד נמצא ב-lib/?

כלל אצבע: אם זה קוד שלא קשור ישירות ל-UI (לא מרנדר שום דבר למסך) — הוא הולך ל-lib/. אם זה קוד שכן מרנדר UI (מחזיר JSX) — הוא הולך ל-components/. ואם זה קוד שמשתמש ב-React hooks — הוא הולך ל-hooks/.

hooks/ — לוגיקה שמתחברת ל-React

תיקיית hooks/ מכילה custom hooks — פונקציות מיוחדות שמשתמשות ביכולות של React (כמו useState ו-useEffect שלמדנו בפרק 02). הן מאפשרות שימוש חוזר בלוגיקה.

hooks/
├── use-mobile.ts       # זיהוי אם המבקר בנייד
├── use-scroll.ts       # מעקב אחרי גלילה
├── use-theme.ts        # ניהול dark/light mode
└── use-debounce.ts     # השהיית קריאות API בחיפוש

כלל אצבע: אם שם הקובץ מתחיל ב-use- — זה hook. אם ה-AI יצר hook, הוא צריך להיות בתיקיית hooks/. אם הוא שם אותו במקום אחר — בקשו ממנו להעביר.

מה ההבדל בין hook ל-utility function? פונקציות ב-lib/ הן "טהורות" — הן מקבלות מידע ומחזירות תוצאה, בלי קשר ל-React. hooks ב-hooks/ משתמשות ביכולות ספציפיות של React (כמו useState, useEffect, useRef שלמדנו בפרק 02). אם אתם מזהים use בתחילת השם — זה hook, ומקומו ב-hooks/.

דוגמאות מעשיות:

public/ — קבצים שהדפדפן רואה ישירות

תיקיית public/ מכילה קבצים סטטיים שהדפדפן ניגש אליהם ישירות — בלי שום עיבוד. כל קובץ ב-public/ זמין דרך ה-URL של האתר.

public/
├── images/             # תמונות (מ-Unsplash, לוגואים)
│   ├── hero.webp
│   └── logo.svg
├── favicon.ico         # האייקון בטאב הדפדפן
├── robots.txt          # הוראות ל-Google (SEO)
├── sitemap.xml         # מפת האתר (SEO)
└── og-image.png        # תמונה לשיתוף ברשתות חברתיות

הכלל: public/images/hero.webp → ניגש דרך mysite.com/images/hero.webp. פשוט. התיקייה public/ "נעלמת" מה-URL — רק מה שבתוכה נשאר.

זוכרים את פרק 07? התמונות מ-Unsplash שלמדתם לבחור — הן הולכות ל-public/images/. הלוגו שלכם — public/logo.svg. ה-favicon — public/favicon.ico. עכשיו אתם יודעים בדיוק איפה הם חיים.

מה ההבדל בין תמונה ב-public/ לבין תמונה שמיובאת בקוד?

שיטהאיך משתמשיםמתי לבחור
public/ <img src="/images/hero.webp" /> תמונות גדולות שלא משתנות, favicon, og-image
import בקוד import logo from './logo.svg' תמונות קטנות שמשתנות לפי theme, אייקונים מיוחדים
next/image <Image src="/images/hero.webp" /> תמונות שצריכות אופטימיזציה אוטומטית (שלמדנו בפרק 07)

כלל אצבע: אם אתם בונים עם Next.js — השתמשו ב-next/image כמעט תמיד. שימו את התמונה ב-public/images/ ותייחסו אליה עם src="/images/hero.webp". Next.js ידאג לאופטימיזציה אוטומטית.

Decision Framework: איפה לשים כל סוג קובץ
סוג הקובץתיקייהדוגמהPrompt ל-AI
דף באתרapp/[route]/דף אודות"צור דף ב-app/about/page.tsx"
קומפוננטת UIcomponents/ui/כפתור, כרטיס"צור קומפוננטה ב-components/ui/card.tsx"
חלק מבני (header)components/layout/Header, Footer"צור header ב-components/layout/header.tsx"
פונקציית עזרlib/חיבור API"הוסף API client ב-lib/api.ts"
Custom hookhooks/זיהוי נייד"צור hook ב-hooks/use-mobile.ts"
תמונה / לוגוpublic/images/hero image"שים את התמונה ב-public/images/hero.webp"
API endpointapp/api/form submit"צור API route ב-app/api/contact/route.ts"
עשו עכשיו 3 דקות

פתחו כל אתר, לחצו F12, וב-Network tab (סננו ל-Img) חפשו קבצי תמונות. שימו לב לנתיבים — אלה קבצים סטטיים שחיים בתיקיית public/ (או equivalent).

בינוני 8 דקות מושג חינם

package.json — תעודת הזהות של הפרויקט

כל פרויקט Node.js (כולל Next.js) מתחיל עם קובץ אחד: package.json. הוא "תעודת הזהות" של הפרויקט — מי הפרויקט, מה הוא צריך כדי לעבוד, ואיך מפעילים אותו.

הנה package.json טיפוסי של פרויקט Next.js עם shadcn/ui:

{
  "name": "my-portfolio",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "next": "^15.1.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "lucide-react": "^0.460.0",
    "@radix-ui/react-dialog": "^1.1.0",
    "class-variance-authority": "^0.7.0",
    "clsx": "^2.1.0",
    "tailwind-merge": "^2.6.0"
  },
  "devDependencies": {
    "typescript": "^5.7.0",
    "@types/react": "^19.0.0",
    "@types/node": "^22.0.0",
    "tailwindcss": "^4.0.0",
    "eslint": "^9.0.0",
    "eslint-config-next": "^15.1.0"
  }
}

בואו נפרק את זה חלק אחרי חלק:

scripts — הפקודות שמפעילות את הפרויקט

פקודהמה היא עושהמתי משתמשים
npm run devמפעילה שרת פיתוח מקומי (localhost:3000)בזמן שעובדים — רואים שינויים בזמן אמת
npm run buildבונה גרסת production מותאמת וקטנהלפני העלאה לאוויר
npm run startמפעילה את גרסת ה-productionבשרת הייצור
npm run lintבודקת שגיאות וסטנדרטים בקודלפני commit / deploy

הפקודה שתשתמשו בה הכי הרבה: npm run dev. היא מפעילה את האתר על המחשב שלכם ב-localhost:3000 (כתובת מקומית שרק אתם רואים). כל שינוי בקוד מתעדכן אוטומטית — זה נקרא Hot Module Replacement (HMR), ובגרסה החדשה של Next.js הוא משתמש ב-Turbopack שהוא מהיר במיוחד.

מה ה-^ (caret) אומר ליד גרסה? כש-package.json מציין "next": "^15.1.0", ה-^ אומר "גרסה 15.1.0 או גבוהה יותר, אבל בתוך 15.x.x בלבד". זה מאפשר עדכוני באגים אוטומטיים בלי לשבור דברים. לא צריך לזכור את זה — אבל כשתראו ^ לא תיבהלו.

dependencies — חבילות שהאתר צריך כדי לעבוד

אלה החבילות שנכנסות ל-production — כלומר, המשתמש הסופי צריך אותן. כמה דוגמאות מהרשימה למעלה:

חבילהמה היא עושהלמדנו בפרק
nextה-framework עצמו — כל ה-routing, SSR, ובנייהפרק 03
reactספריית ה-UI — קומפוננטות, state, hooksפרק 02
lucide-reactספריית אייקונים (Lucide)פרק 07
@radix-ui/react-dialogקומפוננטת Dialog מ-Radix (ה-primitives של shadcn)פרק 05
class-variance-authorityניהול וריאציות של קומפוננטות (primary/secondary button)-
tailwind-mergeמיזוג classes של Tailwind בלי קונפליקטיםפרק 04

devDependencies — חבילות שצריך רק בפיתוח

אלה חבילות שעוזרות לכם בזמן העבודה, אבל לא נכנסות לאתר הסופי. למשל TypeScript — המהדר (compiler) רץ בזמן הפיתוח, אבל הדפדפן מקבל JavaScript רגיל.

ההבדל שחשוב ל-Vibe Coders: אתם לא צריכים לנהל את ה-dependencies ידנית. כש-AI מוסיף חבילה — הוא מריץ npm install package-name והיא מתווספת אוטומטית ל-package.json. אבל כדאי לדעת לקרוא את הרשימה כדי להבין מה בפרויקט.

מה קורה כשמריצים npm install?

  1. npm קורא את package.json
  2. מוריד את כל ה-dependencies ו-devDependencies
  3. שם את הכל ב-node_modules/
  4. יוצר או מעדכן את package-lock.json (שנועל גרסאות)

למה לפעמים npm install נכשל? שלוש סיבות נפוצות:

שגיאהמה קרהמה לעשות
ERESOLVEקונפליקט בין גרסאות חבילותבקשו מ-AI: "תקן את קונפליקט הגרסאות ב-package.json"
EACCESאין הרשאות כתיבהאל תריצו sudo! בקשו מ-AI לפתור הרשאות npm
ENOENTחסר package.jsonוודאו שאתם בתיקייה הנכונה

טיפ מנוסה: אם npm install נתקע או נכשל — הפתרון הכי נפוץ הוא למחוק ולהתקין מחדש:

rm -rf node_modules package-lock.json
npm install

זה פותר 80% מבעיות ההתקנה. שמרו את הפקודה הזו — תצטרכו אותה.

עשו עכשיו 3 דקות

בקשו מ-AI: "הראה לי את ה-package.json של פרויקט Next.js עם shadcn/ui ו-Lucide icons." ספרו — כמה dependencies יש? כמה devDependencies? נסו לזהות 3 חבילות שלמדתם עליהן בפרקים קודמים.

מתחיל 3 דקות מושג חינם

node_modules — הענק השקט

בפרק 01 הזכרנו ש-npm install לוקח זמן. עכשיו נבין למה: הפקודה הזו מורידה את כל החבילות שרשומות ב-package.json (ואת כל החבילות שהן צריכות, ואת כל החבילות שאלה צריכות...) ושמה אותן בתיקייה אחת ענקית: node_modules/.

מספרים שצריך לדעת:

שלושה כללים בלבד לגבי node_modules:

  1. לא נכנסים. אף פעם אל תערכו קבצים בתוך node_modules.
  2. לא מעלים. לעולם לא ל-Git, לעולם לא לשום מקום.
  3. אפשר למחוק. אם משהו מתנהג מוזר — מחקו את node_modules והריצו npm install מחדש. זה פותר 80% מהבעיות.

מה זה package-lock.json? קובץ שנוצר אוטומטית ונועל את הגרסאות המדויקות של כל חבילה. בניגוד ל-node_modules — את הקובץ הזה כן מעלים ל-Git. הוא מבטיח שכשמישהו אחר (או שרת build) ירוץ npm install — הוא יקבל בדיוק את אותן גרסאות.

סיכום: מה עולה ל-Git ומה לא?

קובץ/תיקייהעולה ל-Git?למה?
package.jsonכן ✅מגדיר את התלויות
package-lock.jsonכן ✅נועל גרסאות מדויקות
node_modules/לאענק, אפשר לשחזר עם npm install
.env.localלאמכיל secrets (API keys)
.next/לאתיקיית build — נוצרת מחדש
כל השארכן ✅קוד, הגדרות, תמונות

כל אלה כבר מוגדרים ב-.gitignore שה-AI יוצר אוטומטית. אבל כדאי להבין למה כל שורה שם — כדי שלא תמחקו שורות חשובות בטעות כשעורכים את הקובץ. טיפ: אם ביצעתם push ל-GitHub ואחרי זה הבנתם ש-secrets נכנסו — לא מספיק למחוק אותם. הם נשארים בהיסטוריית Git. תצטרכו לבטל את ה-key ולייצר חדש. מניעה עדיפה על ריפוי.

טעות נפוצה: עושים commit ל-node_modules — ה-repo מתנפח ל-500MB

קורה בעיקר ל-Vibe Coders שעובדים בלי template מוכן או שמחקו את .gitignore בטעות ("זה סתם קובץ ריק לא?"). אתם מריצים git add .git commit -m "first commit"git push, ופתאום ה-push תקוע לדקות ארוכות או נכשל עם השגיאה "file too large" (GitHub חוסם קבצים מעל 100MB). הבעיה: 200-500MB של node_modules עם עשרות אלפי קבצים נכנסו ל-Git. התוצאות: (1) הכל איטי — כל git clone מוריד חצי ג'יגה, (2) GitHub חוסם או מאט, (3) אם יש secrets בחבילות (נדיר אבל קורה) — הם חשופים לעד, (4) היסטוריית Git מזוהמת גם אם תמחקו את node_modules בcommit הבא, הקבצים נשארים ב-history לנצח (או עד git filter-branch).

הפתרון: לפני ה-commit הראשון, וודאו שיש .gitignore ושיש בו לפחות: node_modules/, .next/, .env*.local, dist/, build/. כלי AI כמו V0, Lovable ו-create-next-app יוצרים .gitignore נכון אוטומטית — אל תמחקו אותו. אם כבר עשיתם commit בטעות: הרצו git rm -r --cached node_modules, הוסיפו node_modules/ ל-.gitignore, וcommit מחדש. לנקות את ה-history לגמרי — git filter-repo או BFG Repo-Cleaner (אבל עדיף פשוט לפתוח repo חדש אם הפרויקט צעיר).

טעות נפוצה: מערבבים app/ ו-pages/ router ב-Next.js

הסיטואציה: יש לכם פרויקט ישן שנוצר לפני שנתיים (Next.js 12/13) עם pages/ router. עכשיו אתם מבקשים מ-AI "add a /dashboard page" — ו-AI מייצר לכם app/dashboard/page.tsx, כי זה ברירת המחדל ב-Next.js 14+. Next.js לא זורק שגיאה — הוא תומך בשני ה-routers במקביל, וזה בדיוק הבעיה. מה קורה: (1) app/ מנצח על pages/ אם יש התנגשות נתיבים, אבל לא תמיד באופן עקבי. (2) קונבנציות ההביאת נתונים שונות לגמרי — ב-pages/ זה getServerSideProps/getStaticProps, ב-app/ זה async components. AI מערבב ביניהם ומייצר קוד שבור. (3) Middleware מתנהג אחרת בכל אחד. (4) Global CSS ו-layouts סותרים — יש _app.tsx מ-pages וגם layout.tsx מ-app, ולא ברור איזה מכתיב. (5) bundle size תופח — Next.js טוען runtime של שניהם.

הפתרון: בחרו אחד והתחייבו. לפרויקט חדש — תמיד app/ (זו ברירת המחדל של Next.js 14+ ו-V0). לפרויקט ישן שעובד — אל תתחילו להוסיף app/ עד שתהיו מוכנים להגר הכל. לפני כל פרומפט ציינו: "This project uses App Router only (app/ directory). Do not create any files in pages/. Use async Server Components for data fetching." אם הורשתם פרויקט עם שניהם — תוכנית מיגרציה: מגרים דף-דף מ-pages/ ל-app/, מוחקים את pages/ רק כשכולו עבר ונבדק.

עשו עכשיו 2 דקות

בקשו מ-AI: "הראה לי קובץ .gitignore טיפוסי של פרויקט Next.js." ראו אילו קבצים ותיקיות הוא מתעלם מהם — וודאו ש-node_modules ו-.env.local שם.

בינוני 5 דקות מושג חינם

tsconfig.json ו-next.config — הגדרות שאפשר לשנות

שני קבצי הגדרות שתראו בשורש כל פרויקט. לא צריך להבין כל שורה — צריך לדעת מה אפשר לבקש מ-AI לשנות בהם.

tsconfig.json — הגדרות TypeScript

TypeScript היא שפת תכנות שמרחיבה את JavaScript עם "סוגי נתונים" (types). בעולם של AI, כמעט כל פרויקט נוצר עם TypeScript — ולכן אתם רואים קבצים עם סיומת .tsx במקום .jsx.

הדבר הכי שימושי ב-tsconfig.json ל-Vibe Coders הוא path aliases:

// tsconfig.json (חלק רלוונטי)
{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"]    // או "./*" — תלוי בפרויקט
    }
  }
}

מה זה נותן? במקום לכתוב imports ארוכים ומבלבלים:

// בלי path alias — ארוך ומבלבל
import { Button } from '../../../components/ui/button'

// עם path alias — קצר וברור
import { Button } from '@/components/ui/button'

ה-@/ מחליף את כל הנתיב היחסי. כשאתם רואים @/ ב-import — זה אומר "מתחילים מ-root של הפרויקט". כש-AI כותב imports — הוא בדרך כלל משתמש ב-@/. עכשיו אתם מבינים מאיפה זה בא.

למה path aliases חשובים? בפרויקט גדול, imports יחסיים הופכים לסיוט:

// בלי alias — כשהקובץ עמוק
import { Button } from '../../../../components/ui/button'
import { formatDate } from '../../../../lib/utils'
import { useScroll } from '../../../../hooks/use-scroll'

// עם @/ alias — תמיד אותו דבר, לא משנה כמה עמוק
import { Button } from '@/components/ui/button'
import { formatDate } from '@/lib/utils'
import { useScroll } from '@/hooks/use-scroll'

אם ה-AI שלכם כותב imports עם ../../../ ארוכים — בקשו ממנו: "השתמש ב-@/ path alias לכל ה-imports."

next.config.ts — הגדרות Next.js

קובץ שמאפשר לשנות את ההתנהגות של Next.js. הדברים הכי נפוצים שמבקשים מ-AI לשנות כאן:

הגדרהמה היא עושהPrompt ל-AI
images.remotePatternsמאפשרת טעינת תמונות מדומיינים חיצוניים"הוסף ל-next.config תמיכה בתמונות מ-unsplash.com"
redirectsהפניות מ-URL ישן לחדש"הוסף redirect מ-/old-page ל-/new-page"
envמשתני סביבה שזמינים בקוד"הגדר את API_URL כ-environment variable"

על Environment Variables: משתני סביבה (Environment Variables) הם ערכים שמשתנים בין סביבות — למשל, API key שונה ל-development ו-production. הם חיים בקבצי .env:

# .env.local — קובץ שנשאר רק במחשב שלכם
DATABASE_URL="postgresql://localhost:5432/mydb"
NEXT_PUBLIC_API_URL="https://api.mysite.com"
SECRET_API_KEY="sk-1234567890"

הכלל: משתנים שמתחילים ב-NEXT_PUBLIC_ זמינים גם בדפדפן (בקוד הצד-לקוח). משתנים בלי הקידומת הזו זמינים רק בשרת — מה שהופך אותם בטוחים לסודות כמו API keys.

אל תשימו secrets בקוד! תמיד ב-.env.local שלא עולה ל-Git. ה-AI לפעמים שם API keys ישירות בקוד — זו טעות אבטחה חמורה. אם הפרויקט עולה ל-GitHub — כל העולם יראה את ה-key שלכם. בקשו מה-AI: "העבר את ה-API key ל-environment variable ב-.env.local. אל תשים secrets ישירות בקוד."

דוגמה לקובצי .env מרובים:

.env                # ברירת מחדל (עולה ל-Git — רק ערכים לא סודיים)
.env.local          # מקומי (לא עולה ל-Git — secrets פה)
.env.development    # סביבת פיתוח
.env.production     # סביבת ייצור

.env.local תמיד דורס (overrides) את .env. לכן secrets הולכים ל-.env.local והגדרות כלליות (כמו שם האתר) הולכות ל-.env.

עשו עכשיו 2 דקות

בקשו מ-AI: "מה @/ אומר ב-import statements ב-Next.js?" — התשובה קשורה ל-tsconfig.json שדיברנו עליו. אם התשובה מזכירה "path alias" — אתם בכיוון.

בינוני 4 דקות מושג חינם

Middleware — הסינון לפני שהדף נטען

דמיינו מאבטח בכניסה לבניין. הוא בודק כל אחד לפני שהם נכנסים — יש לך כרטיס? מותר לך להיכנס לקומה הזו? Middleware ב-Next.js עושה בדיוק את זה — הוא קוד שרץ לפני כל בקשה לאתר שלכם.

איפה הוא חי: בניגוד לכל הקבצים האחרים, middleware.ts חי בשורש הפרויקט, לא בתוך app/:

my-project/
├── middleware.ts        # <-- כאן! בשורש, לא בתוך app/
├── app/
├── components/
└── ...

מה אפשר לעשות עם middleware?

תרחישמה middleware עושהדוגמה
אימות (Authentication)בודק אם המשתמש מחוברמפנה לדף login אם לא מחובר
הפניות (Redirects)מנתב מ-URL ישן לחדש/blog/articles
שפה (i18n)מזהה שפת המבקר ומפנהמבקר ישראלי → /he/...
A/B Testingמפנה מבקרים לגרסאות שונות50% רואים גרסה A, 50% גרסה B
Geo-blockingחוסם או מפנה לפי מדינהמדינות מסוימות רואות דף מיוחד

מתי להשתמש: רוב הפרויקטים של Vibe Coders לא צריכים middleware בהתחלה. זה כלי מתקדם שרלוונטי בעיקר כשיש אימות משתמשים או צורך בהפניות מתוחכמות. אבל כדאי לדעת שהוא קיים כדי שכשה-AI ייצור אותו — תבינו מה הוא עושה ולמה.

טיפ לשוק הישראלי: אם אתם בונים אתר דו-לשוני (עברית + אנגלית), middleware הוא הדרך הנכונה לנתב מבקרים לשפה הנכונה. בקשו מ-AI: "הוסף middleware שמזהה את שפת הדפדפן ומפנה ל-/he או /en בהתאם."

איך middleware נראה? הנה דוגמה פשוטה:

// middleware.ts — בשורש הפרויקט
import { NextResponse } from 'next/server'

export function middleware(request) {
  // אם מנסים לגשת ל-/dashboard בלי token
  const token = request.cookies.get('session-token')
  if (!token) {
    // מפנים לדף ההתחברות
    return NextResponse.redirect(new URL('/login', request.url))
  }
  // אחרת — ממשיכים כרגיל
  return NextResponse.next()
}

// על אילו נתיבים הוא רץ
export const config = {
  matcher: '/dashboard/:path*'
}

שוב — לא צריך לכתוב את זה. אבל כשה-AI מציע middleware, עכשיו אתם מבינים מה הוא עושה: בודק תנאי, ואם התנאי לא מתקיים — מפנה. ה-config.matcher אומר "הרץ את הבדיקה הזו רק על נתיבים שמתחילים ב-/dashboard".

עשו עכשיו 2 דקות

חשבו על אתר שאתם רוצים לבנות. יש בו אזור מוגן שדורש התחברות? אם כן — middleware הוא הכלי. כתבו שורה אחת שמתארת מה ה-middleware שלכם צריך לבדוק.

מתחיל 2 דקות מושג חינם

SVG Diagram: המפה המלאה — מהקובץ לדפדפן

הנה סיכום ויזואלי של כל מה שלמדנו — איך בקשה מהדפדפן עוברת דרך כל שכבות הפרויקט:

הזרימה המלאה — מהדפדפן לדף דפדפן mysite.com/blog middleware.ts בדיקה + סינון App Router מתאים תיקייה → URL layout.tsx שכבה משותפת page.tsx התוכן שהמבקר רואה components/ UI, forms, layout parts lib/ utils, API, constants hooks/ custom React hooks public/ images, favicon, static קבצי הגדרות: package.json | tsconfig.json | next.config.ts | tailwind.config.ts node_modules/ חבילות — לא נוגעים, לא מעלים

המפה הזו היא הדבר הכי חשוב בפרק. אם אתם מבינים את הזרימה — דפדפן → middleware → router → layout → page (עם components, lib, hooks ו-public בצד) — אתם מבינים איך פרויקט Next.js עובד.

איך להשתמש במפה הזו בפרקטיקה:

כשמשהו לא עובד, 90% מהבעיות הן בעיות מיקום — קובץ לא במקום הנכון, import שגוי, או תיקייה חסרה. הבנת המפה הזו חוסכת שעות של דיבוג.

עשו עכשיו 2 דקות

הסתכלו על הדיאגרמה למעלה ותענו: אם אתם רוצים להוסיף Google Analytics לאתר — באיזה קובץ תשימו את הקוד? (רמז: זה צריך לרוץ בכל דף)

מתחיל 6 דקות תרגול חינם

איך לנהל שיחה עם AI על מבנה — 10 תרחישים

כל מה שלמדנו בפרק הזה מתמצה ליכולת אחת: לדעת להגיד ל-AI בדיוק איפה לשים כל דבר. הנה 10 תרחישים נפוצים — מה רוצים, ומה אומרים ל-AI:

#רוצה Xתגיד ל-AI Y
1דף חדש באתר"צור דף services ב-app/services/page.tsx"
2קומפוננטת UI חדשה"צור קומפוננטת testimonial ב-components/ui/testimonial.tsx"
3Header משותף"צור header ב-components/layout/header.tsx ותייבא אותו ב-layout.tsx"
4דף מוצר דינמי"צור דף מוצר ב-app/products/[id]/page.tsx עם dynamic route"
5API endpoint"צור API route ב-app/api/contact/route.ts שמקבל POST"
6פונקציית עזר"הוסף פונקציה ב-lib/utils.ts שמפרמטת תאריכים"
7Custom hook"צור hook ב-hooks/use-scroll-position.ts"
8תמיכה בתמונות חיצוניות"הוסף ל-next.config.ts תמיכה בתמונות מ-unsplash.com"
9הפניה מ-URL ישן"הוסף redirect ב-next.config.ts מ-/old ל-/new"
10בדיקת הרשאות"הוסף middleware.ts בשורש שבודק אם יש token לפני /dashboard"

שימו לב לדפוס: כל prompt כולל שלושה דברים:

  1. מה לבנות — קומפוננטה, דף, API, hook
  2. איפה לשים — נתיב מדויק לקובץ (app/, components/, lib/)
  3. הקשר — מה הקובץ צריך לעשות ועם מה הוא מתחבר

זה נוסחת הזהב לשיחה עם AI על מבנה. כשאתם עוקבים אחרי הנוסחה הזו, ה-AI יוצר קוד שמתשלב בפרויקט במקום לצוף בחלל. זו הסיבה שהפרק הזה כל כך חשוב — הוא הופך אתכם ממשתמשי AI למנהלי פרויקט שעובדים עם AI.

בלי מבנה ברור בראש, הייתם אומרים "תוסיף כפתור" — וה-AI היה שם אותו איפה שנוח לו. עכשיו אתם אומרים "שים את הכפתור ב-components/ui/button.tsx" — וה-AI עושה בדיוק מה שאתם רוצים.

שאלות שעוזרות לתקן AI שטעה במיקום:

כשאתם מכירים את המבנה, אתם יכולים לבקר את העבודה של ה-AI בזמן אמת. זה לא שונה ממנהל שיודע מספיק על עיצוב כדי לבקר גרפיקאי — לא צריך לדעת לעצב, צריך לדעת מה נכון.

Prompt Template לתחילת כל פרויקט:

System Prompt מומלץ למבנה פרויקט
מבנה הפרויקט שלי:
- דפים: app/ directory עם App Router (לא pages/)
- קומפוננטות UI: components/ui/ (shadcn/ui)
- חלקים מבניים: components/layout/ (header, footer)
- פונקציות עזר: lib/
- Custom hooks: hooks/
- תמונות וקבצים סטטיים: public/images/
- API routes: app/api/
- הגדרות: layout.tsx בשורש app/

כשאתה יוצר קובץ חדש, ציין תמיד את הנתיב המלא.
אל תשים הכל בקובץ אחד — פצל לקומפוננטות.

שמרו את ה-prompt הזה. בכל פעם שמתחילים עבודה עם AI על פרויקט — הדביקו אותו בתחילת השיחה. ב-Cursor אפשר לשמור אותו בקובץ .cursorrules בשורש הפרויקט. ב-V0 אפשר לציין את זה בהנחיות הפרויקט. ב-Claude Code אפשר לשים ב-CLAUDE.md.

ההבדל בין prompt גנרי ל-prompt מדויק:

Prompt גנרי (חלש)Prompt מדויק (חזק)
"תוסיף טופס יצירת קשר""צור ContactForm ב-components/forms/contact-form.tsx, עם שדות name, email, message. השתמש ב-shadcn Input ו-Button. הוסף את הטופס ב-app/contact/page.tsx."
"תוסיף דף מוצרים""צור דף רשימת מוצרים ב-app/products/page.tsx, ודף מוצר בודד ב-app/products/[id]/page.tsx. השתמש ב-Card מ-shadcn להצגת כל מוצר."
"תעשה header""צור Header ב-components/layout/header.tsx עם לוגו (מ-public/logo.svg), ניווט ל-3 דפים, וכפתור CTA. תייבא אותו ב-app/layout.tsx."

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

עשו עכשיו 3 דקות

בחרו תרחיש אחד מהטבלה למעלה ונסו אותו עם ה-AI שלכם. האם הוא שם את הקובץ בדיוק במקום שביקשתם? אם כן — מעולה, אתם מנהלים את הפרויקט. אם לא — תקנו אותו.

דוגמה מייצגת: סטארט-אפ ישראלי מסדר מבנה עם AI

סטארט-אפ ישראלי בתחום ה-FinTech ביקש מ-AI "תבנה לי אתר". התוצאה: קובץ page.tsx אחד עם 800 שורות — header, hero, features, pricing, footer — הכל ביחד. זה עבד, אבל כשביקשו לשנות רק את ה-header — היה צריך לחפש בתוך 800 שורות.

מה עשו: ביקשו מה-AI לפצל לפי מבנה מסודר:

התוצאה: page.tsx ירד ל-30 שורות שרק מייבאות קומפוננטות. כל שינוי נעשה בקובץ נפרד, בלי לגעת בשאר. לקח אחד: אף פעם אל תקבלו קובץ של 500+ שורות מה-AI. תמיד בקשו לפצל.

הנוסחה: אם קובץ ארוך מ-200 שורות — כנראה שאפשר לפצל. אם ארוך מ-400 — בטוח שצריך. בקשו מה-AI: "פצל את הקומפוננטות לקבצים נפרדים ב-components/ ותייבא אותם ב-page.tsx." הוא ישמח לעשות את זה — פשוט צריך לבקש.

תרגיל 1: מיפוי מבנה פרויקט שלם

זמן: 20 דקות | רמה: מתחיל | תוצר: מפת מבנה מלאה עם הסברים

  1. בקשו מ-AI ליצור פרויקט:
    צור מבנה תיקיות לפרויקט Next.js של אתר פורטפוליו.
    האתר צריך: עמוד בית, דף אודות, גלריית עבודות (עם דף לכל פרויקט),
    דף צור קשר, ובלוג.
    השתמש ב-App Router, shadcn/ui, Tailwind, ו-Lucide icons.
  2. העתיקו את עץ התיקיות שה-AI ייצר לקובץ טקסט נפרד
  3. ליד כל תיקייה, כתבו הסבר של שורה אחת — מה התפקיד שלה? (השתמשו בטבלאות מהפרק)
  4. זהו 3 דברים שחסרים — האם יש loading.tsx? error.tsx? not-found.tsx? בקשו מה-AI להוסיף
  5. בדקו: האם הבלוג משתמש ב-dynamic route? האם הגלריה משתמשת ב-[id]?

תוצאה צפויה: מפת מבנה של 15-25 תיקיות וקבצים, עם הסבר ליד כל אחד. שלושה קבצים מיוחדים שהוספתם (loading, error, not-found). הבנה של למה הבלוג צריך [slug] דינמי.

מה לבדוק בפלט של ה-AI:

תרגיל 2: בניית מערכת routing לאתר חנות

זמן: 15 דקות | רמה: בינוני | תוצר: מבנה routing מלא עם dynamic routes

  1. הגדירו 6 דפים שחנות אונליין צריכה:
    • עמוד בית
    • רשימת מוצרים (לפי קטגוריה)
    • דף מוצר בודד
    • עגלת קניות
    • אודות / יצירת קשר
    • תנאי שימוש / מדיניות פרטיות
  2. כתבו את מבנה התיקיות ב-app/ — אילו routes הם static ואילו dynamic?
  3. החליטו: האם צריך route group? (רמז: דפים "משפטיים" כמו terms ו-privacy יכולים להיות ב-(legal))
  4. בקשו מ-AI ליצור את המבנה ובדקו אם הוא תואם למה שתכננתם
  5. בונוס: בקשו מה-AI להוסיף middleware שבודק אם עגלת הקניות לא ריקה לפני גישה ל-checkout

תוצאה צפויה: מבנה שכולל app/products/[category]/page.tsx (קטגוריה), app/products/[category]/[id]/page.tsx (מוצר בודד), app/cart/page.tsx, app/(legal)/terms/page.tsx, ו-app/(legal)/privacy/page.tsx.

תרגיל 3: קריאת package.json ושיחה עם AI על dependencies

זמן: 15 דקות | רמה: בינוני | תוצר: package.json מוסבר עם הערות

  1. בקשו מ-AI:
    הראה לי package.json מלא של פרויקט Next.js 15 עם:
    - shadcn/ui
    - Lucide icons
    - Tailwind CSS v4
    - TypeScript
    כולל scripts ו-dependencies.
  2. זהו 5 dependencies וכתבו ליד כל אחד מה הוא עושה (השתמשו בטבלה מהפרק)
  3. מצאו את ה-scripts: מה npm run dev עושה? מה npm run build?
  4. בקשו מה-AI להוסיף dependency חדש:
    הוסף את framer-motion כ-dependency (לא devDependency). למה זה dependency ולא dev?
  5. כתבו הסבר של שורה אחת — מה ההבדל בין dependencies ל-devDependencies?

תוצאה צפויה: הבנה שלמה של package.json — מה כל חלק עושה, למה framer-motion הוא dependency (כי הוא רץ בדפדפן) ולא devDependency, ויכולת לקרוא כל package.json בעתיד.

שגרת עבודה — הרגלים מהפרק הזה
תדירותמה לעשות
יומיכשנותנים prompt ל-AI — ציינו נתיב קובץ מדויק. תמיד. "שים את זה ב-components/ui/" במקום "תבנה לי כפתור".
יומיאחרי שה-AI יוצר קבצים — סרקו את עץ התיקיות. האם הכל במקום הנכון? האם יש קובץ ענק שצריך לפצל?
שבועיפתחו את ה-package.json של הפרויקט שלכם. יש dependencies שאתם לא מזהים? שאלו את ה-AI מה כל אחד עושה.
שבועיבדקו שיש loading.tsx ו-error.tsx בתיקיות העיקריות — ניהול שגיאות וטעינה הם סימן לפרויקט מקצועי.
חודשיסרקו את תיקיית components/ — יש קומפוננטות כפולות? קבצים שלא בשימוש? בקשו מ-AI לנקות.
חודשיבדקו שה-next.config עדכני — גרסאות חדשות של Next.js מוסיפות יכולות. שאלו AI מה חדש.
אם אתם עושים רק דבר אחד מהפרק הזה

שננו את 5 התיקיות: app/ (דפים), components/ (UI), lib/ (לוגיקה), hooks/ (React hooks), public/ (קבצים סטטיים). אם אתם יודעים את החמישה האלה — אתם יודעים להגיד ל-AI איפה לשים כל דבר. זה ההבדל בין "תבנה לי אתר" (ו-AI מחליט הכל) לבין "תשים את ה-header ב-components/layout/header.tsx" (ואתם מחליטים).

בדקו את עצמכם — 5 שאלות
  1. מה ההבדל בין page.tsx ל-layout.tsx, ולמה שניהם נמצאים בתיקיית app/? (רמז: אחד הוא התוכן, השני הוא העטיפה)
  2. אם יש לכם אתר עם 100 מוצרים — כמה קבצי page.tsx צריך לדפי המוצרים? (רמז: dynamic routes)
  3. מה ההבדל בין תיקייה [slug] לתיקייה (marketing)? (רמז: סוגריים מרובעים vs עגולים)
  4. למה node_modules לא עולה ל-Git, ואיך משחזרים אותו? (רמז: package-lock.json)
  5. אתם רוצים שה-AI יבנה header שמופיע בכל דף — איפה לשים אותו ואיפה לייבא? (רמז: components/ + layout.tsx)

אם עניתם נכון על 4 מתוך 5 — אתם מוכנים לפרק הבא.

סיכום הפרק

הפרק הזה נתן לכם את המפה של כל פרויקט Next.js. התובנה המרכזית: כשאתם מבינים את המבנה, אתם לא רק קוראים קוד — אתם מנהלים את הפרויקט. במקום לתת ל-AI להחליט איפה לשים כל קובץ, אתם אומרים לו בדיוק איפה כל דבר הולך.

למדנו ש-app/ מנהלת את כל הדפים ושקבצים מיוחדים (page.tsx, layout.tsx, loading.tsx, error.tsx) שולטים בהתנהגות. ש-file-based routing הופך תיקיות ל-URLs, ש-dynamic routes עם סוגריים מרובעים פותרים את בעיית "הרבה דפים זהים עם מידע שונה", וש-route groups בסוגריים עגולים מארגנים בלי להשפיע על ה-URL.

ראינו ש-components/ מחזיקה UI, lib/ מחזיקה לוגיקה, hooks/ מחזיקה custom hooks, ו-public/ מחזיקה קבצים סטטיים. למדנו לקרוא package.json ולהבין מה כל dependency עושה, ולמה node_modules היא תיקייה שלא נוגעים בה ולא מעלים ל-Git.

בפרק הבא נלמד על Deployment — פריסת האתר לאוויר. Vercel, Netlify ו-Cloudflare Pages — כל אחד יודע לקחת את מבנה הפרויקט שלמדנו כאן ולהפוך אותו לאתר חי. כל ה-routing, הדפים, ה-middleware — הכל עולה ביחד. המבנה שלמדנו כאן קובע איך הפריסה עובדת.

רשימת בדיקה — מה השלמתם?