כדי להפוך את האבטיפוס שיצרתם עם ה-AI לאפליקציה אמיתית שמשתמשים יכולים לבטוח בה, אתם חייבים את "
- טופס/endpoint מוגן ב-Turnstile עם validation בצד Worker — אפס challenges למשתמשים אמיתיים
- אתר/Worker מגודר ב-Zero Trust Access עם email-OTP login (עד 50 seats) — בלי ספריית auth ובלי DB משתמשים
- named tunnel חי לדומיין מותאם + Worker שמעבד email נכנס וכותב events ל-Analytics Engine
- להוסיף Turnstile (CAPTCHA בלתי נראה, חינם ללא מגבלת נפח) לטופס/endpoint עם server-side token validation ב-Worker
- לגדר Worker או אתר מאחורי Zero Trust Access (Google/GitHub/email-OTP, 50 seats חינם) בלי לכתוב קוד auth
- להקים named tunnel יציב עם wrangler tunnel create/run לדומיין מותאם (כולל תמיכת SSE)
- לעבד email נכנס ב-Worker עם Email Routing ולכתוב events ל-Analytics Engine (100k/day) כתחליף ל-Google Analytics
- פרק 1 — ה-Free Stack — מה אתה באמת מקבל ב-$0, ופריסה תוך 10 דקות
- פרק 2 — Workers ו-Storage — קיר ה-10ms, ובחירת KV / D1 / R2 / Durable Objects
- כלים/חשבונות: Wrangler CLI (wrangler dev, wrangler deploy, wrangler secret put, wrangler tail, wrangler tunnel) — primary toolchain, Miniflare — local Worker simulation runtime (embedded in wrangler dev since v3), Wrangler Local Explorer (open beta 2026) — browser UI for local KV/D1/R2/DO inspection, cloudflared binary — now auto-managed by Wrangler tunnel commands, Hono framework — lightweight router for Workers (zero dependency, <12kb, typed RPC), Cloudflare Vite plugin — first-class Vite integration for Workers + static assets
הפרק הקודם: בפרק הקודם בנינו את הבלוג המהיר המבוסס על Static Assets עם טבלאות אחסון של D1 ושימוש קל ב-KV להגדרות דינמיות.
הפרק הזה: הלומד יחבר את שכבת ה-glue שהופכת Worker לאפליקציה אמיתית, מאובטחת ונצפית — Turnstile, Zero Trust Access, Cloudflare Tunnel, Email Routing ו-Analytics Engine — כולם ב-$0, עם הבנה מתי כל אחד נשבר מהמגבלה החינמית
הפרק הבא: בפרק הבא נבצע אינטגרציה מלאה של כלל הרכיבים שבנינו לכדי מוצר full-stack מושלם על ה-Free Tier, תוך ניתוח מלא של מגבלות העלות.
| מונח | הסבר |
|---|---|
| Turnstile | אלטרנטיבה חכמה ובלתי נראית ל-reCAPTCHA של Google, הפועלת ללא יצירת הפרעות למשתמשים אמיתיים ואינה דורשת פתרון אתגרים חזותיים. |
| Zero Trust Access | פתרון אבטחה ברמת הרשת המאפשר להגן על אפליקציות וכתובות URL מפני גישה לא מורשית בהתבסס על אימות זהות, ללא צורך בכתיבת קוד auth. |
| Named Tunnel | מנהרה מאובטחת המנוהלת על ידי קובץ קונפיגורציה או דרך Wrangler, המקשרת בין פורט מקומי במחשב האישי לדומיין מותאם רשום ב-Cloudflare. |
| Email Routing | שירות חינמי המאפשר לנתב הודעות אימייל נכנסות ישירות לכתובות אחרות או לקוד Worker לצורך עיבוד מתקדם. |
| Analytics Engine | בסיס נתונים מסוג time-series המיועד לאיסוף וכתיבה מהירה של אירועים ונתוני שימוש ישירות מתוך סביבת הריצה של Workers. |
| Secrets Store | חנות סודות מרכזית ומשותפת המאפשרת לנהל משתנים חסויים ברמת החשבון במקום להגדיר אותם בנפרד לכל Worker. |
מבוא ל-Glue Layer והתקנת יסודות האפליקציה המודרנית
כשבונים אפליקציות מבוססות בינה מלאכותית (AI) כיום, קל מאוד להסתחרר מהיכולות המדהימות של מודלי שפה גדולים (LLMs - Large Language Models) ולשכוח כיצד נראית מערכת שלמה באמת. אפליקציה שמציגה רק חלונית צ'אט שמדברת עם API חיצוני אינה מוצר אמיתי. כדי להפוך רעיון למוצר בר-קיימא, אנחנו זקוקים למה שמכונה ה-**Glue Layer** (שכבת הדבק). שכבה זו היא רקמת החיבור הלוגית שמחברת בין חזית האפליקציה (Frontend) לבין מנועי ה-AI, בסיסי הנתונים, מערכות הדיוור, מנגנוני הזיהוי והאימות (Authentication) ומערכות המעקב והאנליטיקה (Analytics). ללא שכבת הדבק, האפליקציה שלכם תהיה כמו אוסף של איים מבודדים שאינם מסוגלים לתקשר זה עם זה בבטחה ובמהירות. כדי לנהל את שכבת הדבק הזו בצורה אלגנטית, אנו מאמצים את הגישה של **Integration Architecture** (ארכיטקטורת אינטגרציה) מודרנית. במקום להקים שרתים כבדים, לנהל מערכות הפעלה ולהתמודד עם זמני הפעלה קרים (Cold Starts - העיכוב שנוצר כאשר שרת Serverless עולה מאפס כדי לטפל בבקשה ראשונה), אנו מתבססים על Cloudflare Workers. זהו מנוע הרצה מבוסס V8 Isolates (סביבות ריצה קלילות ומבודדות של דפדפן כרום, הרצות בקצה הרשת קרוב למשתמש). ארכיטקטורה זו מאפשרת לנו להריץ את קוד ה-API שלנו ביותר מ-300 ערים בעולם בו-זמנית, עם זמן עליה אפסי ועלויות מזעריות. היתרון הגדול עבור "Vibe Coders" הוא שאין צורך לנהל מכולות (Containers) או להגדיר שרתי Kubernetes מסובכים; הקוד פשוט רץ בדיוק היכן שהמשתמש נמצא. במקביל, בנייה מודרנית מחייבת אותנו ליישם את ה-**Zero-Trust Paradigm** (פרדיגמת אפס אמון). בעבר, מפתחים נהגו להגן על האפליקציה שלהם באמצעות "חומת אש" היקפית, מתוך הנחה שכל מה שנמצא בתוך הרשת הפנימית הוא בטוח. כיום, בעידן שבו סוכני AI עצמאיים, בוטים ומערכות מבוזרות מתקשרים ביניהם ללא הרף, הגישה השתנתה לחלוטין: אנחנו לא סומכים על אף בקשה, אף מכשיר ואף משתמש כברירת מחדל, ומאמתים כל פעולה מחדש (Never Trust, Always Verify). שכבת הדבק של Cloudflare מאפשרת לנו לעטוף את ה-API ואת ממשקי הניהול שלנו בפתרונות אבטחה מובנים, לחשוף את סביבת הפיתוח המקומית החוצה בבטחה דרך מנהרות מאובטחות (Tunnels), ולמנוע זליגת מפתחות API וסודות באמצעות שימוש במנהל סודות מרכזי ישירות בקצה. הלב הפועם של ניהול הפיתוח והפריסה של פרויקט כזה הוא ה-**Wrangler Configuration** (קונפיגורציית Wrangler). קובץ הגדרות זה, הקרויwrangler.toml, מגדיר למעשה את המבנה והמשאבים של האפליקציה שלנו. בשנת 2026, Cloudflare הפכה את תשתית Workers Static Assets (אירוח קבצים סטטיים מובנה ב-Workers) לתקן המוביל והמומלץ ביותר לפיתוח אפליקציות full-stack, כשהיא מחליפה באופן מלא את פלטפורמת Pages הישנה שנכנסה למצב תחזוקה. באמצעות קונפיגורציה פשוטה בקובץ זה, אנו יכולים להגדיר שרת API מבוסס **Hono** (מסגרת עבודה קלילה ומהירה במיוחד לניתוב בקשות ב-TypeScript השוקלת פחות מ-12KB) אשר יגיש קבצים סטטיים במהירות האור ישירות מרשת ה-CDN של Cloudflare, ובמקביל יטפל בבקשות דינמיות ובקריאות AI בצד השרת.
בצעד זה נקים את השלד המלא של האפליקציה שלנו באמצעות Wrangler ו-Hono. הצעדים כוללים את יצירת הקבצים הנדרשים והרצתם מקומית ובייצור.
-
ודאו התקנת Node.js: פתחו את הטרמינל (Terminal) והריצו את הפקודה הבאה כדי לוודא שמותקנת אצלכם גרסה עדכנית של Node.js:
node -vהפלט הצפוי הוא מספר גרסה (למשל,
v18.20.0ומעלה). -
התחברו לחשבון Cloudflare: אם אין לכם חשבון, פתחו אחד בחינם בכתובת dash.cloudflare.com. לאחר מכן, בצעו הזדהות דרך שורת הפקודה על ידי הרצת הפקודה הבאה בדפדפן שיפתח לכם:
npx wrangler loginהפלט הצפוי לאחר אישור בדפדפן:
Successfully logged in to Cloudflare!. -
צרו תיקיית פרויקט חדשה והתקינו תלויות: הריצו את הפקודות הבאות כדי ליצור תיקייה, לאתחל קובץ
package.jsonולהתקין את Wrangler ואת Hono:mkdir vibe-glue-app cd vibe-glue-app npm init -y npm install hono npm install -D wrangler -
צרו את קובץ הגדרות ה-Wrangler: צרו קובץ בשם
wrangler.tomlבשורש התיקייה והדביקו בתוכו את התוכן הבא:name = "vibe-glue-app" main = "src/index.ts" compatibility_date = "2026-03-01" [assets] directory = "./public" binding = "ASSETS" -
צרו את קוד השרת (API): צרו תיקייה בשם
srcובתוכה קובץ בשםindex.tsעם קוד השרת הבא המשתמש ב-Hono:import { Hono } from 'hono' const app = new Hono() // נתיב API שישמש את שכבת הדבק שלנו app.get('/api/health', (c) => { return c.json({ status: 'ok', timestamp: new Date().toISOString(), message: 'The Glue Layer is operational!' }) }) export default app -
צרו את קבצי ה-Frontend הסטטיים: צרו תיקייה בשם
publicובתוכה קובץ בשםindex.html. קובץ זה ייטען ישירות מה-Edge CDN של Cloudflare ויבצע פנייה ל-API הדינמי שלנו:<!DOCTYPE html> <html lang="he" dir="rtl"> <head> <meta charset="UTF-8"> <title>Vibe Glue App</title> <style> body { font-family: sans-serif; background: #0f172a; color: #f8fafc; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; } .card { background: #1e293b; padding: 2rem; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.3); text-align: center; max-width: 400px; } button { background: #2563eb; color: white; border: none; padding: 0.75rem 1.5rem; border-radius: 4px; cursor: pointer; font-size: 1rem; margin-top: 1rem; } button:hover { background: #1d4ed8; } pre { background: #020617; padding: 1rem; border-radius: 4px; text-align: left; direction: ltr; margin-top: 1rem; font-size: 0.85rem; } </style> </head> <body> <div class="card"> <h1>חיבור ה-Glue Layer הצליח! 🎉</h1> <p>הדף הזה מוגש כנכס סטטי ישירות מה-CDN.</p> <button id="fetch-btn">בדוק חיבור ל-API</button> <pre id="output">לחץ על הכפתור לקבלת נתונים...</pre> </div> <script> document.getElementById('fetch-btn').addEventListener('click', async () => { const res = await fetch('/api/health'); const data = await res.json(); document.getElementById('output').textContent = JSON.stringify(data, null, 2); }); </script> </body> </html> -
הרצה וסימולציה מקומית: הריצו את הפקודה הבאה כדי להפעיל את השרת המקומי (מבוסס Miniflare המובנה ב-Wrangler):
npx wrangler devהטרמינל יציג פלט המראה כי השרת המקומי פעיל בכתובת
http://localhost:8787. -
פריסה לענן (Production): הריצו את פקודת הפריסה כדי להעלות את הפרויקט לאוויר:
npx wrangler deployהפלט יכיל כתובת אינטרנט ציבורית וייחודית (לדוגמה:
https://vibe-glue-app.[your-subdomain].workers.dev) שבה האפליקציה שלכם זמינה כעת לכל העולם בחינם.
פלט נראה לעין שתסיים איתו: דפדפן פתוח בכתובת http://localhost:8787 המציג כרטיסייה כהה עם כפתור כחול. לחיצה על הכפתור "בדוק חיבור ל-API" מעדכנת את בלוק הטקסט התחתון בפלט ה-JSON שחזר משרת ה-Worker שלכם, המעיד על תקשורת תקינה בין ה-Frontend ל-Backend הדינמי.
הגנת בוטים ב-$0: הכירו את Turnstile, ה-CAPTCHA הבלתי נראה
</p> <!-- אלמנט הווידג'ט של Turnstile --> <div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY" data-theme="light"></div> <button type="submit" style="margin-top: 15px; padding: 10px 20px; background: #0070f3; color: white; border: none; border-radius: 4px; cursor: pointer;">שלח</button> </form> </body> </html>npm create cloudflare@latest vibe-auth-worker
(בחרו בפריימוורק Hono ובשפת TypeScript).
התקינו את התלויות והחליפו את קוד הקובץ src/index.ts בקוד הבא, המבצע את אימות האסימון מול השרתים של Cloudflare:
אינטגרציה מלאה: Turnstile Client-Side ואימות Token ב-Worker
כשבונים אפליקציות מודרניות מבוססות בינה מלאכותית, פיתוח הפיצ'רים הוא החלק המהיר והמהנה ביותר. אך ברגע שהאפליקציה עולה לאוויר, היא הופכת למטרה מיידית עבור בוטים וסקריפטים זדוניים שמנסים לנצל את משאבי ה-API שלכם (במיוחד כשכל קריאה למודל שפה עולה לכם כסף אמיתי). כאן נכנס לתמונה Cloudflare Turnstile – חלופה מודרנית, חכמה וידידותית למשתמש המאפשרת להבחין בין אדם אמיתי למכונה ללא הצורך בפתרון חידות מעצבנות של זיהוי רמזורים או אופנועים.
האינטגרציה של Turnstile מורכבת משני חלקים קריטיים שעובדים בסינרגיה מושלמת. החלק הראשון הוא תסריט לקוח של טרנסטייל (turnstile client script) – ספריית JavaScript קלה הנטענת בדפדפן של המשתמש, מבצעת אתגרי אבטחה ברקע ומייצרת אסימון (token) ייחודי וחד-פעמי. החלק השני, והחשוב ביותר מבחינת אבטחה, הוא אימות אסימון בצד השרת (server-side token validation). ללא שלב זה, כל תוקף מתוחכם יוכל פשוט לעקוף את ממשק המשתמש ולשלוח בקשות ישירות ל-API שלכם באמצעות כלי פקודה כמו cURL. בפרק זה נלמד כיצד לבנות ארכיטקטורה מאובטחת המשלבת בין השניים בעזרת Cloudflare Workers.
הלב האבטחתי: מדוע אימות בצד השרת אינו אופציונלי
חשבו על הלקוח (Client) כעל דלת כניסה מעוצבת. ה-turnstile client script מציב שומר בכניסה שנותן לכל מבקר אמיתי כרטיס כניסה חד-פעמי. אולם, אם ה-API שלכם (העובד על גבי ה-Worker) לא בודק את הכרטיס הזה מול נקודת קצה לאימות (verification endpoint) של Cloudflare, הדלת האחורית נשארת פתוחה לרווחה. הבוט יכול פשוט להתעלם לחלוטין מדף ה-HTML שלכם ולשלוח בקשות POST ישירות לכתובת ה-Worker.
בכל פעם שמשתמש עובר את האתגר של Turnstile בדפדפן, נוצר אסימון זמני התקף למספר דקות בודדות וניתן לשימוש פעם אחת בלבד. ה-Worker שלכם חייב לתפוס את האסימון הזה, לשלוח אותו באופן מאובטח מאחורי הקלעים לשרתי Cloudstile באמצעות ה-verification endpoint הרשמי, ורק אם התשובה חוזרת כחיובית (
"success": true) – לאפשר את המשך הרצת קוד האפליקציה היקר שלכם.התמודדות עם חומת ה-CORS ב-Serverless
כאשר אתם מפרידים את האפליקציה שלכם כך שחלק הלקוח (הסטטי) מאוחסן בנפרד (למשל על גבי Workers Static Assets) וה-API רץ כ-Worker עצמאי, הדפדפן יפעיל מנגנון הגנה מובנה הנקרא CORS. כדי לאפשר לדפדפן לבצע את הבקשות האלה בבטחה, ה-Worker שלנו חייב להחזיר כותרות שיתוף משאבים בין מקורות (CORS headers) מתאימות. בלעדיהן, הדפדפן יחסום את שליחת הטופס עוד לפני שהיא תגיע לשרת האימות, ויציג שגיאה אדומה ומאיימת בקונסול.
| רכיב האבטחה | תפקיד במערכת | איפה הוא מיושם? |
|---|---|---|
| Turnstile Client Script | טעינת רכיב האבטחה בדפדפן, הרצת האתגר הבלתי נראה והפקת ה-Token. | דף ה-HTML (צד הלקוח) |
| CORS Headers | מתן אישור לדפדפן לשלוח את ה-Token ליעד השונה מכתובת האתר הסטטי. | תגובת ה-Worker (צד השרת) |
| Verification Endpoint | פנייה לכתובת הרשמית של Cloudflare לאימות סופי של אמינות ה-Token שנוצר. | קריאת Fetch מתוך ה-Worker |
לפני שנוכל לכתוב שורת קוד אחת, עלינו להצטייד במפתחות מתאימים. היכנסו ללוח הבקרה של Cloudflare, נווטו לתפריט Turnstile בצד, ולחצו על Add Widget. תנו שם לווידג'ט שלכם (למשל Vibe-Guard), הזינו את הכתובת localhost לבדיקות מקומיות, ובחרו באפשרות Managed (המומלצת ביותר המשלבת אתגר בלתי נראה עם תיבת סימון במידת הצורך). בסיום, העתיקו את ה-Site Key (המפתח הציבורי שיופיע בקוד הלקוח) ואת ה-Secret Key (המפתח הסודי שיופיע אך ורק ב-Worker שלכם).
ארכיטקטורת הזרימה של המידע
כאשר טופס נשלח, ה-Client מקודד את המידע לפורמט JSON המכיל את הפרטים הרלוונטיים יחד עם ה-Token שנוצר על ידי ה-Turnstile. ה-Worker שמקבל את הבקשה מבצע תחילה בדיקה מקדימה (Preflight Request) על מנת לוודא שהדפדפן מורשה לשלוח את המידע (באמצעות טיפול בבקשות מסוג OPTIONS). מיד לאחר מכן, ה-Worker מחלץ את ה-Token מהגוף של בקשת ה-POST, ומבצע בקשת פנייה פנימית מאובטחת אל ה-verification endpoint של Cloudflare. רק כאשר מתקבל אישור רשמי, ה-Worker ממשיך לעבד את הבקשה ומחזיר תגובה חיובית עם ה-CORS headers הנדרשים.
בתרגיל זה נבנה מאפס מערכת אימות מלאה ומאובטחת. נקים ממשק לקוח סטטי פשוט המכיל טופס הרשמה, נטמיע את ה-client script, ונפתח Worker שמבצע אימות קשוח בצד השרת וחוסם פניות ישירות שאינן מגיעות ממשתמשים אנושיים שעברו את האתגר.
-
בדיקת סביבת עבודה והתחברות: ודאו שמותקנת אצלכם גרסת Node.js עדכנית על ידי הרצת הפקודה הבאה במסוף (Terminal). אם הגרסה נמוכה מ-18, יש לעדכן את Node.js מהאתר הרשמי.
הפלט הצפוי הוא מספר הגרסה המותקנת, לדוגמה:node -vv20.11.0. כעת, התחברו לחשבון ה-Cloudflare שלכם דרך ממשק השורה הרשמי (CLI) באמצעות הרצת הפקודה הבאה:
לאחר הרצת הפקודה, ייפתח דפדפן שיבקש מכם לאשר את החיבור לחשבון השרת שלכם. עם השלמת האישור, יופיע במסוף פלט המאשר את ההתחברות המוצלחת.npx wrangler login -
יצירת פרויקט ה-Worker: צרו תיקייה חדשה לפרויקט והקימו בתוכה פרויקט Worker בסיסי ללא שימוש בתבנית מורכבת:
הפלט הצפוי הוא יצירה מהירה של קובצי הניהול של npm והורדת חבילת ה-Wrangler מקומית אל תיקיית הפרויקט.mkdir turnstile-guard && cd turnstile-guard npm init -y npm install wrangler --save-dev -
הגדרת קובץ wrangler.toml: צרו קובץ הגדרות בשם
wrangler.tomlבשורש התיקייה, והעתיקו לתוכו את התוכן הבא. קובץ זה מגדיר את שם ה-Worker ומחזיק את משתנה הסביבה הסודי שלכם:
הערה חשובה: המפתח המופיע כאן הוא מפתח בדיקות רשמי של Cloudflare שתמיד מחזיר תשובה חיובית, המאפשר לנו לפתח ולבדוק את הקוד מקומית ללא צורך במפתח אמיתי בשלב הבדיקות.name = "turnstile-validator-api" main = "src/index.js" compatibility_date = "2026-03-19" [vars] TURNSTILE_SECRET_KEY = "1x0000000000000000000000000000000AA" # מפתח בדיקות גנרי של Cloudflare -
בניית ממשק הלקוח הסטטי: צרו תיקייה בשם
publicובתוכה קובץ בשםindex.html. קובץ זה מציג את טופס ההרשמה ומטעין את תסריט הלקוח של Turnstile:<!DOCTYPE html> <html lang="he" dir="rtl"> <head> <meta charset="UTF-8"> <title>הרשמה מאובטחת</title> <!-- טעינת תסריט הלקוח של Turnstile --> <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script> <style> body { font-family: system-ui, sans-serif; background: #f3f4f6; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; } .card { background: white; padding: 2rem; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); width: 100%; max-width: 400px; } h3 { margin-top: 0; color: #1f2937; } input[type="email"] { width: 100%; padding: 0.75rem; margin: 1rem 0; border: 1px solid #d1d5db; border-radius: 4px; box-sizing: border-box; } button { background: #2563eb; color: white; border: none; width: 100%; padding: 0.75rem; border-radius: 4px; font-weight: bold; cursor: pointer; } button:hover { background: #1d4ed8; } #message { margin-top: 1rem; padding: 0.75rem; border-radius: 4px; display: none; } </style> </head> <body> <div class="card"> <h3>הרשמה לניוזלטר</h3> <form id="signup-form"> <input type="email" id="email" placeholder="הזינו את האימייל שלכם" required> <!-- אלמנט הווידג'ט של Turnstile --> <div class="cf-turnstile" data-sitekey="1x00000000000000000000AA" data-callback="onTurnstileSuccess"></div> <input type="hidden" id="turnstile-token" name="turnstile-token"> <button type="submit" style="margin-top: 1rem;">הרשמה</button> </form> <div id="message"></div> </div> <script> let isVerified = false; // פונקציית צד-לקוח המופעלת אוטומטית ברגע שהאתגר עבר בהצלחה function onTurnstileSuccess(token) { document.getElementById('turnstile-token').value = token; isVerified = true; } document.getElementById('signup-form').addEventListener('submit', async (e) => { e.preventDefault(); const messageDiv = document.getElementById('message'); const token = document.getElementById('turnstile-token').value; if (!isVerified || !token) { messageDiv.style.display = 'block'; messageDiv.style.backgroundColor = '#fecaca'; messageDiv.style.color = '#dc2626'; messageDiv.innerText = 'שגיאה: אנא השלימו את אתגר ה-Turnstile.'; return; } try { // שליחת הבקשה ל-Worker המקומי שלנו const response = await fetch('http://localhost:8787', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: document.getElementById('email').value, token: token }) }); const data = await response.json(); messageDiv.style.display = 'block'; if (response.ok) { messageDiv.style.backgroundColor = '#d1fae5'; messageDiv.style.color = '#065f46'; messageDiv.innerText = 'ההרשמה בוצעה בהצלחה! ברוכים הבאים.'; } else { messageDiv.style.backgroundColor = '#fecaca'; messageDiv.style.color = '#dc2626'; messageDiv.innerText = `שגיאה מהשרת: ${data.error}`; } } catch (err) { messageDiv.style.display = 'block'; messageDiv.style.backgroundColor = '#fecaca'; messageDiv.style.color = '#dc2626'; messageDiv.innerText = 'שגיאת תקשורת עם השרת.'; } }); </script> </body> </html> -
פיתוח ה-Worker עם אימות השרת ו-CORS: הקימו תיקייה בשם
srcובתוכה צרו קובץ בשםindex.js. קוד זה יקלוט את הבקשה, יבצע את ה-preflight לבקשותOPTIONS, יפנה ל-verification endpoint של Cloudflare, ויחזיר את כותרות ה-CORS הנכונות:export default { async fetch(request, env) { // הגדרת כותרות ה-CORS לשימוש חוזר בתגובות const corsHeaders = { "Access-Control-Allow-Origin": "*", // בסביבת פרודקשן מומלץ להחליף בדומיין הספציפי שלכם "Access-Control-Allow-Methods": "POST, OPTIONS", "Access-Control-Allow-Headers": "Content-Type", }; // טיפול בבקשות Preflight של הדפדפן (OPTIONS) if (request.method === "OPTIONS") { return new Response(null, { status: 204, headers: corsHeaders, }); } // אבטחת סוג הבקשה - אנו מקבלים רק בקשות POST לכתובת זו if (request.method !== "POST") { return new Response(JSON.stringify({ error: "Method not allowed" }), { status: 405, headers: { "Content-Type": "application/json", ...corsHeaders }, }); } try { const body = await request.json(); const token = body.token; const email = body.email; // בדיקה בסיסית שהמידע אכן התקבל בצד השרת if (!token || !email) { return new Response(JSON.stringify({ error: "Missing email or turnstile token" }), { status: 400, headers: { "Content-Type": "application/json", ...corsHeaders }, }); } // קבלת כתובת ה-IP של הלקוח לצורך אבטחה מוגברת באימות const clientIp = request.headers.get("CF-Connecting-IP"); // בניית בקשת האימות הרשמית עבור ה-Verification Endpoint const verificationFormData = new FormData(); verificationFormData.append("secret", env.TURNSTILE_SECRET_KEY); verificationFormData.append("response", token); if (clientIp) { verificationFormData.append("remoteip", clientIp); } // שליחת אימות בצד השרת אל Cloudflare const cloudflareResponse = await fetch( "https://challenges.cloudflare.com/turnstile/v0/siteverify", { body: verificationFormData, method: "POST", } ); const verificationResult = await cloudflareResponse.json(); // בדיקה האם האימות מול שרתי Cloudflare נכשל if (!verificationResult.success) { return new Response( JSON.stringify({ error: "Turnstile validation failed", details: verificationResult["error-codes"] }), { status: 403, headers: { "Content-Type": "application/json", ...corsHeaders }, } ); } // ה-Token תקין! כאן מריצים את הלוגיקה העסקית האמיתית (למשל שמירה למסד נתונים D1) return new Response( JSON.stringify({ message: "Registration successful!", user: email }), { status: 200, headers: { "Content-Type": "application/json", ...corsHeaders }, } ); } catch (err) { return new Response(JSON.stringify({ error: "Server Internal Error", details: err.message }), { status: 500, headers: { "Content-Type": "application/json", ...corsHeaders }, }); } }, }; -
הרצה מקומית ובדיקת עקיפת אבטחה: הפעילו את השרת המקומי באמצעות Wrangler:
הפלט הצפוי יראה שה-Worker שלכם רץ מקומית בכתובתnpx wrangler devhttp://localhost:8787. פתחו את הקובץpublic/index.htmlישירות בדפדפן שלכם, הזינו אימייל ולחצו על כפתור ההרשמה. תוכלו לראות את הווידג'ט הופך לירוק ומאשר את הבקשה.
כעת, נסו להריץ פקודת סקריפט מתוך ה-Terminal שמדמה תוקף זדוני המנסה לעקוף את ממשק המשתמש (ללא שליחת אסימון):
הפלט הצפוי מהמסוף יהיה חסימה מוחלטת עם שגיאהcurl -X POST http://localhost:8787 -H "Content-Type: application/json" -d '{"email":"malicious-bot@spam.com"}'400או403:{"error":"Missing email or turnstile token"}
פלט נראה לעין שתסיים איתו: דף אינטרנט פעיל לחלוטין
אבטחה בלי קוד: Zero Trust Access ואימות זהות מבוסס OTP
כאשר אנחנו בונים אפליקציות מבוססות בינה מלאכותית (AI) כ-Vibe Coders, המטרה העיקרית שלנו היא להביא ערך למשתמשים במהירות שיא ולשמור על מומנטום פיתוח מהיר. הדבר האחרון שאנחנו רוצים לבזבז עליו ימים של עבודה הוא בניית מערכת הרשמה מאפס, ניהול טבלאות משתמשים במסד הנתונים, אימות סיסמאות, ושילוב של ספקי צד שלישי. זהו "סיוט האבטחה" הקלאסי שמסרבל פרויקטים פשוטים והופך אותם למפלצות תחזוקה מורכבות שמפחיד להעלות לאינטרנט. כאן נכנס לתמונה הקונספט של Zero Trust Access (גישת "אפס אמון" — מודל אבטחה שבו כל בקשת גישה לאתר או לאפליקציה נבדקת ומאומתת בנפרד, ללא קשר לשאלה אם המשתמש נמצא ברשת הפנימית או החיצונית). הקסם האמיתי עבורנו הוא יצירת Identity-gated URL (כתובת אתר מוגנת זהות — כתובת אינטרנט ששרתי קצה חוסמים את הגישה אליהמלכודת ה-50 Seats: ניהול מגבלות ב-Access ומתי לא להשתמש בו
כשבונים אפליקציות וכלים מבוססי בינה מלאכותית בקצב מהיר, אבטחה וניהול משתמשים (Authentication) הם לרוב "כאב הראש" שכולנו מנסים לדחות לשלבים מאוחרים יותר. כאן נכנס לתמונה השירות Cloudflare Access, המהווה חלק מחבילת ה-Zero Trust של החברה. השירות מאפשר לנעול כל כתובת דומיין, Worker, או חיבור מקומי מאובטח (Tunnel) מאחורי מסך התחברות מאובטח תוך פחות מחמש דקות, ובלי לכתוב אפילו שורת קוד אחת של אימות במערכת שלכם. המערכת תומכת בשיטות התחברות פופולריות כמו Google OAuth, GitHub, או קבלת קוד חד-פעמי למייל (One-Time Pin או OTP). עבור מפתחי Vibe Coder, זה נראה כמו הפתרון המושלם: במקום להסתבך עם ספריות קוד, מסדי נתונים וניהול סרטיפיקטים, פשוט מדליקים מתג בלוח הבקרה והאתר מוגן. אך כאן מסתתר המכשול הגדול ביותר של השירות, המכונה בתעשייה "מלכודת ה-50 Seats" (חמישים המושבים). הגרסה החינמית של Cloudflare Zero Trust מציעה עד 50 "מושבים" (Seats) פעילים בחודש ללא עלות. מושב מוגדר ככתובת אימייל ייחודית שעברה אימות מוצלח מול אחד היישומים שלכם במהלך החודש הקלנדרי. המלכודת מתרחשת כאשר עוברים את רף ה-50 הזה. בניגוד לשירותים אחרים שמציעים שדרוג הדרגתי או מתריעים מראש, מודל התמחור של Teams pricing model הוא קשיח לחלוטין (Hard-limit): ברגע שהמשתמש ה-51 מנסה להתחבר, הוא פשוט ייחסם, או שהחשבון שלכם יידרש לעבור למסלול בתשלום שעלותו היא כ-$7 למשתמש לחודש (בחיוב שנתי). החלק הכואב ביותר הוא שהתשלום אינו חל רק על המשתמש ה-51 ומעלה, אלא על *כל* 51 המשתמשים שלכם רטרואקטיבית — מה שיוצר חיוב מיידי של למעלה מ-$350 בחודש על פרויקט צדדי קטן. כדי לא ליפול למלכודת הזו, חיוני להבין את ההבדל המבני בין גישה ארגונית פנימית (Corporate Access) לבין אימות משתמשים ציבורי (Public Auth). שירות Cloudflare Access תוכנן במקור עבור חברות שרוצות לאבטח את הכלים הפנימיים של העובדים שלהן מפני גישה חיצונית. הוא אינו מיועד לשמש כמערכת הרישום וההתחברות של האפליקציה הציבורית שלכם. אם אתם בונים כלי AI קהילתי, אפליקציית SaaS להמונים או מוצר שחלקים ממנו דורשים הרשמה פתוחה — חשיפת הכתובת הזו מאחורי Access תחסל את מכסת ה-50 Seats שלכם תוך שעות בודדות של תנועה אורגנית. עבור מקרים כאלה, עליכם להשתמש בפתרונות אימות ייעודיים ברמת הקוד. בנוסף, ישנם מקרים שבהם תרצו להגן על רוב האתר שלכם, אך לאפשר לחלקים מסוימים להיות נגישים לחלוטין ללא הזדהות — למשל, עבור כתובות ה-API שלכם שצריכות לקבל התראות אוטומטיות (Webhooks) משירותים חיצוניים כמו Stripe או Telegram. לשם כך משתמשים ב-Access Bypass Rules (כללי עקיפת גישה). כללים אלו מאפשרים להגדיר נתיבים ספציפיים (כמוexample.com/api/webhook) שידלגו על שלב ה-SSO ויאפשרו גישה ישירה לשרת, בעוד שאר חלקי המערכת וממשקי הניהול נשארים נעולים הרמטית מאחורי חומת האבטחה הארגונית.
היכנסו עכשיו ללוח הבקרה של Cloudflare Dashboard, נווטו ללשונית Zero Trust בתפריט הצד, ובחרו ב-Users. בדקו כמה משתמשים (Seats) רשומים כרגע כפעילים בחשבון שלכם כדי לוודא שאינכם מתקרבים לקו האדום של ה-50, ובררו האם ישנם משתמשי קצה זרים שאישרתם בטעות.
למה זה מפתה: הכי קל להגדיר שער אימות (Auth Gate) של Cloudflare תוך דקה, לפרסם את קישור האפליקציה החדשה שלכם ברשתות החברתיות, ולהניח שכל המשתמשים יוכלו להיכנס בחינם ובבטחה בעזרת קוד שיקבלו למייל שלהם.
למה זה טעות: ה-Free Tier של Zero Trust Access מוגבל קשיחה ל-50 seats (כתובות אימייל פעילות). ברגע שהמשתמש ה-51 ינסה להיכנס, הוא ייחסם לחלוטין, או שתאלצו לשדרג למסלול Teams בעלות של $7 לכל משתמש לחודש עבור כל המשתמשים שלכם יחד ($357+ בחודש).
מה לעשות במקום: עבור כלים ציבוריים מרובי משתמשים, בנה מערכת משתמשים רגילה המאובטחת בעזרת Turnstile בלבד. שמרו את Cloudflare Access אך ורק לגישה פנימית של צוות הפיתוח או הבודקים שלכם.
שאלה 1: האם האפליקציה מיועדת אך ורק לצוות פנימי, בודקים ספציפיים, או עד 50 משתמשים מוגדרים מראש?
- החלטה: השתמשו ב-Zero Trust Access. תקבלו אבטחה מקסימלית ב-$0 עלות וללא צורך לכתוב שורת קוד אחת של אימות.
שאלה 2: האם מדובר באפליקציה ציבורית, מוצר SaaS פתוח להרשמה, או כלי ויראלי לקהל הרחב?
- החלטה: השתמשו בפתרון אימות עצמאי (custom auth) על בסיס D1/KV בשילוב Turnstile כדי להגן מפני בוטים ולנהל משתמשים ללא הגבלת כמות.
יישום מעשי של שערי גישה
בתרגיל זה נבנה, נפיץ ונאבטח Worker פשוט מאחורי שער הגישה של Cloudflare Access מבלי לכתוב קוד אימות כלל.
-
הכנת סביבת העבודה והתחברות:
בדקו שגרסת ה-Node שלכם מעודכנת על ידי הרצת הפקודה הבאה במסוף (Terminal):
node -v
הפלט הצפוי: גרסה 18.0.0 ומעלה (למשל:v20.11.0). אם הפקודה אינה מזוהה, התקינו את Node.js מהאתר הרשמי.
כעת, התקינו את כלי הפיתוח Wrangler והתחברו לחשבון ה-Cloudflare שלכם:npm install -g wrangler && wrangler login
הפלט הצפוי: דפדפן ייפתח ויבקש מכם לאשר את החיבור לחשבון. לאחר האישור, תופיע במסוף הודעה:Successfully logged in!. -
יצירת ה-Worker ופריסתו:
צרו תיקייה חדשה בשם
secure-app, היכנסו אליה וצרו קובץ בשםsrc/index.jsעם הקוד הבא המייצג את המערכת הפנימית שלכם:export default { async fetch(request, env, ctx) {חשיפת localhost מנוהלת: Named Tunnels דרך פקודות Wrangler החדשות (מרץ 2026)
כשאתם בונים אפליקציות מבוססות בינה מלאכותית (AI) על המחשב המקומי שלכם (localhost), אחד האתגרים הגדולים ביותר הוא לחשוף את שרת הפיתוח שלכם לעולם החיצון. בין אם אתם צריכים לבדוק קבלת תגובות חוזרות (Webhooks) משירותים כמו Stripe, לאפשר לסוכני AI חיצוניים לגשת ל-API המקומי שלכם, או פשוט לשתף את העבודה שלכם עם לקוחות ובודקים — אתם חייבים דרך בטוחה ויציבה לחבר את המחשב שלכם לאינטרנט הציבורי. פתרון קלאסי כמו פתיחת פורטים (Ports) בנתב הביתי הוא סיוט אבטחתי מורכב, וכלים פופולריים כמו Ngrok הפכו עם השנים למגבילים ויקרים בגרסאות החינמיות שלהם.
כאן נכנס לתמונה השירות Cloudflare Tunnel (מנהרת קלאודפלייר) — כלי המאפשר לכם ליצור חיבור יוצא בלבד (Outbound-only connection) מהמחשב המקומי שלכם ישירות אל קצוות הרשת (Edge) הגלובלית של Cloudflare. המשמעות היא שאתם מקבלים כתובת אינטרנט ציבורית ובטוחה שמפנה ל-localhost שלכם, מבלי לחשוף את כתובת ה-IP האמיתית שלכם ומבלי לפתוח אף פורט נכנס בנתב הביתי או בחומת האש (Firewall) שלכם.
עד לא מזמן, הגדרת מנהרה קבועה דרך Cloudflare דרשה הורדה ידנית של קובץ ה-binary (קובץ הפעלה) של תוכנת הלקוח cloudflared, הגדרה של קובצי קונפיגורציה בפורמט YAML מורכב, וניהול ידני של מפתחות אבטחה. פיתוח אפליקציות הפך למסורבל עבור מפתחים שאינם מהנדסי מערכות או אנשי DevOps. אולם, בעדכון הדרמטי של מרץ 2026, Cloudflare שינתה את חוקי המשחק לחלוטין: היא שילבה את פקודות ניהול המנהרות ישירות לתוך כלי ה-CLI הרשמי שלה, Wrangler (כלי הפיתוח המרכזי של Cloudflare). פקודות אלו (Wrangler-managed tunnel commands) מאפשרות לכם להקים, לנהל ולהפעיל מנהרות בעלות שם (Named Tunnels) ישירות מהטרמינל, מבלי להוריד או להגדיר את תוכנת
cloudflaredבאופן עצמאי ומבלי לכתוב שורת קונפיגורציה אחת.Tunnel Mode Selection Matrixשאלה 1: האם האפליקציה שלכם דורשת כתובת קבועה ויציבה (Custom Domain), שמירה על הגדרות בין הפעלות מחדש, או ניהול מרחוק דרך דשבורד?
- כן: בצעו הגדרה של Named Tunnel. מנהרה בעלת שם משויכת לחשבון ה-Cloudflare שלכם ומאפשרת לקשור את ה-localhost ישירות לדומיין הרשום שלכם (למשל,
api.mycoolproject.com). הכתובת תישאר קבועה תמיד. - לא: המשיכו לשאלה הבאה.
שאלה 2: האם האפליקציה משתמשת בהזרמת מידע בזמן אמת (Streaming) כמו Server-Sent Events (SSE) לצורך הצגת תשובות צ'אט של AI מילה אחר מילה?
- כן: בחרו אך ורק ב-Named Tunnel. מנהרות אלו פועלות על תשתית רשת מלאה התומכת ברוחב פס גבוה, הזרמת מידע רציפה ושמירה על חיבורים פתוחים לזמן ממושך ללא חסימות.
- לא: המשיכו לשאלה הבאה.
שאלה 3: האם אתם זקוקים לבדיקה מקומית מהירה וחד-פעמית, ללא צורך ברישום חשבון, הגדרת דומיינים או הגדרות מוקדמות כלשהן?
- כן: בחרו ב-Quick Tunnel (trycloudflare). הוא מעניק לכם כתובת אקראית וזמנית (תחת הדומיין
trycloudflare.com) תוך שניות ספורות, ומיועד לבדיקות מהירות במיוחד שאינן כוללות סטרימינג או עומס של בקשות.
מדוע המעבר ל-Named Tunnels קריטי לאפליקציות AI מודרניות?
כאשר בונים ממשקי משתמש מבוססי AI, חוויית המשתמש (UX) היא קריטית. במקום להמתין 10-20 שניות עד שמודל שפה גדול (LLM) יסיים להפיק את כל התשובה שלו ורק אז להציג אותה, הסטנדרט כיום הוא שימוש בטכנולוגיית SSE (Server-Sent Events) כדי להזרים (Stream) את חלקי המילים למסך בזמן אמת, בדיוק כפי שקורה ב-ChatGPT או ב-Claude. בפרוטוקול זה, השרת שומר על חיבור HTTP פתוח ומזרים נתונים אסינכרוניים ללקוח.
כאן טמון המוקש הגדול של מנהרות זמניות (Quick Tunnels). המנהרות החינמיות והמהירות שמבוססות על הדומיין
trycloudflare.comמשתמשות בשרתי תיווך מוגבלים מאוד. הן נועדו לבדיקות בסיסיות בלבד, ולכן קלאודפלייר אינה מאפשרת בהן שימוש בחיבורי סטרימינג מתמשכים כמו SSE, ובנוסף מגבילה אותן לתקרה קשיחה של עד 200 בקשות מקבילות (Concurrent requests). מפתח שמנסה לבדוק ממשק סטרימינג מקומי דרך Quick Tunnel יגלה שהתגובות נתקעות, החיבורים נזרקים, והממשק מרגיש שבור לחלוטין, מבלי להבין שהבעיה היא בכלל בצינור התקשורת ולא בקוד האפליקציה שלו.טעות נפוצה: שימוש ב-Quick Tunnel לצורך פיתוח אפליקציות עם UI המבוסס על SSE או Streamingלמה זה מפתה: להריץ פקודה מהירה בטרמינל ולקבל בשנייה אחת כתובת אינטרנט ציבורית זמנית בחינם, בלי לעבור תהליך הזדהות, בלי לרשום דומיין ובלי להתעסק עם הגדרות DNS בלוח הבקרה.
למה זה טעות: מנהרות זמניות מסוג Quick Tunnel אינן תומכות בפרוטוקול Server-Sent Events (SSE). כשאתם מנסים להזרים תשובות ממודל AI (כמו Llama או GPT) לממשק שלכם דרך מנהרה כזו, הזרמת המידע תיכשל במפתיע או שכל התגובה תיעצר ותישלח רק בסיום הפעולה (בבת אחת), מה שיכול להוביל לקריסת החיבור עקב פסק זמן (Timeout). בנוסף, מגבלת 200 הבקשות המקבילות תחסום אתכם ברגע שתתחילו לבצע קריאות API תכופות או בדיקות עומס קלות.
מה לעשות במקום: הגדרו Named Tunnel יציב ומאובטח המקושר לדומיין מותאם אישית בתוך החשבון שלכם ב-Cloudflare (אפילו בדומיין חינמי או זול שרשום אצלם). הגדרה זו פותחת את כל חסמי הרשת ומאפשרת תמיכה מלאה בסטרימינג חלק של SSE, מהירות תגובה גבוהה יותר ואמינות מוחלטת ללא הגבלות חיבורים נמוכות.
טבלת השוואה: סוגי מנהרות ב-Cloudflare (נכון לשנת 2026)
כדי לעשות סדר בבחירה שלכם, להלן השוואה ממוקדת בין שני מצבי העבודה העיקריים של מנהרות קלאודפלייר:
תכונה Quick Tunnel (trycloudflare.com) Named Tunnel (Wrangler-managed) צורך בחשבון Cloudflare לא נדרש חובה (חשבון חינמי מספיק בהחלט) כתובת אינטרנט (URL) אקראית ומשתנה בכל הפעלה קבועה ומבוססת על דומיין מותאם אישית תמיכה ב-Streaming / SSE לא נתמך (נחסם או נכשל) נתמך באופן מלא וללא הגבלות מגבלת בקשות מקבילות עד 200 בקשות בו-זמנית ללא הגבלה מוצהרת (מותאם לפרודקשן) ניהול ואבטחה (Zero Trust) אין ניהול, פתוח לחלוטין לעולם ניתן להגביל גישה באמצעות אימות (SSO, סיסמה) היתרון הגדול של כלי ה-CLI החדשים של Wrangler הוא בכך שהם הופכים את תהליך היצירה של Named Tunnel לפשוט כמעט כמו הפעלה של Quick Tunnel. בעזרת מספר פקודות בסיסיות, Wrangler מטפל בכל הלוגיקה המורכבת מאחורי הקלעים: הוא מאמת אתכם מול חשבון ה-Cloudflare שלכם, מוריד את קובץ הריצה הנכון של
cloudflaredלסביבה שלכם, יוצר את קובצי המפתח (Credentials) הייחודיים של המנהרה, ומגדיר את רשומות ה-DNS הנדרשות בדומיין שלכם באופן אוטומטי לחלוטין.הקמה והרצה של Named Tunnel בתוך 5 דקות בלבד 5 דקותבצעו את הצעדים הבאים כדי להקים מנהרה מנוהלת ויציבה התומכת בסטרימינג ישירות מהמחשב המקומי שלכם:
- תנאי מקדים: ודאו שיש לכם חשבון Cloudflare פעיל ודומיין אחד לפחות שמנוהל תחתיו (ניתן להשתמש בחבילה החינמית של Cloudflare).
- פתחו את הטרמינל בתיקיית הפרויקט שלכם ובצעו התחברות לחשבון שלכם בעזרת Wrangler:
הפלט הצפוי: הדפדפן ייפתח באופן אוטומטי, יבקש מכם לאשר את החיבור ל-Wrangler, ולאחר האישור תראו בטרמינל הודעת הצלחה:npx wrangler loginSuccessfully logged in!. - צרו את המנהרה החדשה שלכם על ידי בחירת שם ייחודי עבורה (למשל:
ai-dev-tunnel):
הפלט הצפוי: הטרמינל יציג את מזהה ה-UUID הייחודי של המנהרה שנוצרה ואת המיקום שבו נשמר קובץ האבטחה (JSON credential file). למשל:npx wrangler tunnel create ai-dev-tunnelCreated tunnel ai-dev-tunnel with UUID: 1234abcd-56ef-78gh-90ij-1234567890kl - קשרו את המנהרה החדשה לתת-דומיין ייעודי לבחירתכם תחת הדומיין הרשום שלכם (החליפו את
yourdomain.comבדומיין האמיתי שלכם):
הפלט הצפוי: הודעה המאשרת כי רשומת ה-CNAME המתאימה התווספה אוטומטית להגדרות ה-DNS של הדומיין שלכם:npx wrangler tunnel route dns ai-dev-tunnel local-api.yourdomain.comAdded route local-api.yourdomain.com pointing to tunnel.... - כעת, הפעילו את המנהרה ונתבו את כל התעבורה הנכנסת אליה ישירות אל שרת ה-localhost שלכם (נניח שהוא רץ על פורט 3000):
הפלט הצפוי: המנהרה תיכנס למצב פעיל ותציג לוגים המראים חיבור מוצלח למרכזי הנתונים של Cloudflare:npx wrangler tunnel run --url http://localhost:3000 ai-dev-tunnelConnection established at....
פלט נראה לעין שתסיים איתו: המחשב המקומי שלכם חשוף כעת בכתובת המאובטחת והקבועה
https://local-api.yourdomain.com. כל פנייה לכתובת זו (כולל בקשות אסינכרוניות מורכבות או חיבורי סטרימינג מסוג SSE) תגיע באופן מיידי ובאבטחה מלאה לשרת הפיתוח שלכם שרץ על פורט 3000.ניתוב אימיילים נכנסים (Email Routing) בחינם ללא הגבלה
כשבונים אפליקציות אמיתיות, האינטראקציה עם המשתמשים לא חייבת להתרחש רק בתוך ממשק הדפדפן. אימייל הוא עדיין אחד הערוצים החזקים ביותר לתקשורת, אוטומציות וניהול משימות. אלא שבעבר, כדי לאפשר לאפליקציה שלכם לקבל אימיילים נכנסים, הייתם צריכים לשלם על שירותי תיבות דואר יקרים כמו Google Workspace או להסתבך עם שרתי SMTP מורכבים. כאן נכנס לתמונה השירות החינמי לחלוטין של Cloudflare שנקרא Email Routing (ניתוב אימיילים). שירות זה מאפשר לכם להגדיר חוקים שמקבלים כל אימייל שנשלח לדומיין שלכם ומנתבים אותו באופן מיידי ליעד אחר. זה יכול להיות כתובת אימייל פרטית שלכם, או — וזה הכוח האמיתי של ה-Vibe Coders — ישירות לתוך קוד ה-Worker שלכם באמצעות Worker email triggers (טריגרים של אימייל ב-Workers) שמפעילים פונקציית Serverless (קוד הרץ בענן ללא צורך בניהול שרת) בכל פעם שמגיע אימייל חדש.
איך זה עובד מאחורי הקלעים?
התהליך מתחיל בכך ש-Cloudflare משתלטת על רשומות ה-MX (קיצור של Mail Exchanger, רשומות ה-DNS שמורות לשרתים לאן לשלוח אימיילים ברשת) של הדומיין שלכם. ברגע שאימייל מגיע אל שרתי הקצה של Cloudflare, המערכת בודקת את החוקים שהגדרתם. היא יכולה לבצע הפנייה פשוטה אל destination addresses (כתובות יעד) מאומתות (כמו תיבת ה-Gmail האישית שלכם), או לבצע
מלכודת ה-Email Service: שליחת אימיילים ומגבלות ה-Paid
כמעט כל אפליקציה מודרנית או סוכן בינה מלאכותית (AI Agent) שתבנו יצטרכו בשלב כלשהו לתקשר עם העולם החיצון דרך אימייל. בין אם מדובר באישור הרשמה, התראה על פעולה קריטית במערכת או שליחת דוח יומי שהופק על ידי מודל שפה. כאן בדיוק Vibe Coders רבים נופלים במלכודת של Cloudflare: ההבדל המבלבל בין קבלת אימיילים (Inbound) לבין שליחת אימיילים (Outbound). במשך שנים, שירות בשם Email Routing אפשר לנו לקבל אימיילים בחינם לחלוטין, לנתב אותם ל-Worker (פונקציית שרת ללא שרת — Serverless Function) ולעבד את התוכן שלהם. באפריל 2026, במהלך שבוע הסוכנים (Agents Week), השיקה קלאודפליי את ה-Email Service בגרסת בטא ציבורית (Public Beta). השירות החדש מאפשר ל-Workers לשלוח, לקבל ולעבד אימיילים בצורה נייטיבית (Native — מובנית במערכת). אולם, בעוד שקבלת אימיילים נשארה חינמית ולא מוגבלת, שליחת אימיילים יוצאים (Outbound Email) חסומה לחלוטין בחשבונות החינמיים. כדי לשלוח אפילו מייל אחד דרך הפלטפורמה, תצטרכו לשדרג לתוכנית ה-Paid של Workers בעלות של לפחות 5 דולר בחודש.מגבלות ה-Paid וסוגיית ה-Deliverability
תוכנית ה-Workers Paid פותחת בפניכם מכסה של 3,000 אימיילים יוצאים בחודש (עם עלות של 0.35 דולר לכל 1,000 אימיילים נוספים). מעבר לתשלום עצמו, המכשול הגדול ביותר בשליחת אימיילים בעידן המודרני הוא עבירות (Deliverability — היכולת של האימייל להגיע בהצלחה לתיבת הדואר הנכנס ולא להיחסם בדרך). לשם כך, קלאודפליי דורשת הגדרה קפדנית של DKIM (DomainKeys Identified Mail — פרוטוקול אימות דואר אלקטרוני המבוסס על מפתח ציבורי). הגדרת DKIM מוסיפה חתימה דיגיטלית לכל אימייל שנשלח מהדומיין שלכם, ובכך מוכיחה לשרתי היעד (כמו Gmail או Outlook) שהמייל אכן נשלח מכם ולא מכתובת מזויפת. ללא הגדרה זו, שרתים יחסמו את המיילים שלכם באופן מיידי או יזרקו אותם לתיקיית הספאם. כדי להבין את ההבדלים בין האפשרויות השונות העומדות בפניכם, מומלץ להשוות את הפתרונות הזמינים כיום:
אם תרצו לעבוד בצורה נייטיבית בתוך האקוסיסטם של קלאודפליי וליהנות מביצועים מהירים במיוחד ללא קריאות ל-APIs חיצוניים, תצטרכו להגדיר את הקשר (Binding) בקובץ ה-מאפיין Email Service (נייטיבי ב-Paid) Email Routing (חינמי) ספק חיצוני (כמו Resend/SendGrid) כיוון התעבורה דו-כיווני (שליחה וקבלה) נכנס בלבד (Inbound) דו-כיווני (דרך API ייעודי) מחיר בסיס $5 לחודש (חלק מ-Workers Paid) חינם לחלוטין חינם (במגבלות חבילות החינם שלהם) מכסה כלולה 3,000 אימיילים יוצאים בחודש ללא הגבלה מוצהרת (רק נכנסים) למשל ב-Resend: כ-3,000 אימיילים בחודש חינם מורכבות הגדרה בינונית (דורש הגדרת DKIM ב-DNS) קלה מאוד (ניתוב בלחיצת כפתור) קלה (שימוש ב-SDK או API Key פשוט) wrangler.tomlשלכם וליצור את הלוגיקה בתוך ה-Worker.טעות נפוצה: ניסיון לשלוח אימיילים יוצאים ישירות מה-Free Tier ללא תוכנית Workers Paid.למה זה מפתה: אתם קוראים מדריכים שמראים כמה פשוט להשתמש ב-Email Service API החדש של קלאודפליי בתוך ה-Worker שלכם, ורואים שקבלת אימיילים (Email Routing) עובדת נהדר ובחינם. אתם מניחים שגם השליחה תעבוד באותו האופן וממהרים לכתוב קוד שליחה.
למה זה טעות: ה-Email Service עבור הודעות יוצאות חסום לחלוטין בחשבון החינמי (0 הודעות בחודש). אם תנסו לפרוס קוד כזה ללא שדרוג לתוכנית ה-Paid של 5 דולר בחודש, תקבלו שגיאות ריצה מבלבלות או שהאימיילים פשוט ייחסמו בשקט בתוך מערכת הניתוב של קלאודפליי.
מה לעשות במקום: אם אתם עדיין בשלב הפיתוח והניסוי ורוצים להישאר ב-Free Tier, השתמשו ב-API של ספק חיצוני כמו Resend (שמציע תוכנית חינמית נדיבה) באמצעות קריאת
fetchפשוטה מה-Worker שלכם. אם האפליקציה שלכם מוכנה לייצור (Production) ואתם זקוקים לאינטגרציה נייטיבית מהירה של סוכני ה-AI שלכם עם תיבות דואר, שדרגו ל-Workers Paid כדי לפתוח את ה-Email Service המובנה.כיצד נראה קוד השליחה הנייטיבי?
עבור מי שמשדרג לתוכנית ה-Paid, קלאודפליי מספקת ממשק פשוט להפליא. תחילה עליכם להוסיף את ההגדרה לקובץ ה-wrangler.tomlשלכם:
לאחר מכן, בתוך קוד ה-Worker, תוכלו לגשת למשתנה הסביבה שהגדרתם (ה-Binding) ולשלוח מייל בצורה אסינכרונית:# wrangler.toml name = "my-ai-agent-email" main = "src/index.js" compatibility_date = "2026-05-01" [[email_services]] binding = "SEND_EMAIL"export default { async fetch(request, env, ctx) { try { // שליחת המייל מתבצעת ישירות דרך האובייקט שנקשר ל-Worker await env.SEND_EMAIL.send({ to: "client@example.com", from: "agent@yourdomain.com", subject: "עדכון חשוב מסוכן ה-AI שלך", text: "שלום, סיימתי לעבד את המידע שביקשת. הנה התוצאות..." }); return new Response("האימייל נשלח בהצלחה!"); } catch (err) { return new Response("שגיאה בשליחת האימייל: " + err.message, { status: 500 }); } } };הגדרת רשומות DNS לאימות הדומיין שלכם 10 דקותכדי שתוכלו לשלוח אימיילים מותאמים אישית (בין אם דרך ה-Paid Tier של קלאודפליי או באמצעות ספק חיצוני כמו Resend), עליכם להגדיר רשומות SPF ו-DKIM ב-DNS שלכם. בצעו את השלבים הבאים:
- היכנסו ללוח הבקרה (Dashboard) של Cloudflare ובחרו בדומיין שלכם.
- נווטו לתפריט DNS ואז ל-Records.
- הוסיפו רשומת TXT עבור SPF כדי לאשר לשרתים לשלוח מיילים בשמכם. לחצו על Add Record, הגדירו את ה-Type ל-
TXT, את ה-Name ל-@(או השאירו ריק לדומיין הראשי), ובשדה ה-Content הזינו:v=spf1 include:cloudflare_email_service.com ~all(או את הערך הספציפי שספק המייל שלכם מספק). - כעת הוסיפו את רשומת ה-DKIM שקיבלתם מקלאודפליי או מספק ה-API החיצוני. לחצו שוב על Add Record, הגדירו את ה-Type כ-
TXT, תחת Name הזינו את הסלקטור (למשל:cloudflare-email-service._domainkey), ותחת Content הזינו את המפתח הציבורי הארוך שסופק לכם. - לחצו על Save והמתינו מספר דקות לשפעול הרשומות ברחבי הרשת.
פרויקט אימייל חכם: Email Routing פוגש Workers AI ו-D1
quotes for classes, single class only: `class="do-now"`, `class="exercise"`. No chaining! No `class="do-now warning"` or something. - Media comments must be formatted exactly: ``. - Commands and files in ``. - Comparisons in ``. Let's build a rich table of comparison between traditional email processing and the modern Serverless Email Routing pipeline to provide high-quality structural text.
מאפיין הגישה המסורתית (שרת ייעודי) הגישה המודרנית (Edge Serverless) זמני טעינה ראשוניים אין (השרת דולק תמיד אך עולה כסף) אפס זמני טעינה (V8 Isolates) תחזוקת שרת דואר (SMTP) קשה ומסובכת, דורשת הגדרות אבטחה מורכבות אפס תחזוקה, מנוהל לחלוטין על ידי Cloudflare עיבוד בינה מלאכותית ניתוח נתונים ב-$0: הכרת Cloudflare Analytics Engine
Analytics Engine והרצת איוונט ראשון 10 דקותבצעו את הצעדים הבאים כדי להגדיר את קישור בסיס הנתונים ולרשום את נקודת המידע הראשונה שלכם:
- אם עדיין לא עשיתם זאת, התקינו את ה-CLI של Cloudflare באמצעות הרצת הפקודה הבאה בטרמינל והתחברו לחשבון שלכם:
npm install -g wrangler && wrangler login - פתחו את קובץ ה-
wrangler.tomlשל הפרויקט שלכם והוסיפו את הגדרות הקישור (Binding) הבאות בתחתית הקובץ:[[analytics_engines]] binding = "ANALYTICS" dataset = "user_actions" - בתוך קוד ה-Worker שלכם (קובץ
index.tsאוsrc/index.ts), עדכנו את ממשק הטיפוסים (Env) והוסיפו קריאת כתיבה פשוטה בנתיב ה-API שלכם:import { Hono } from 'hono'; type Env = { ANALYפרויקט אנליטיקס פרטי: לוח בקרה (Dashboard) מבוסס SQL
בעולם שבו תקנות הגנת הפרטיות (כמו GDPR) מחמירות וחוסמי פרסומות מעלימים מעל 30% מנתוני התנועה שלכם ב-Google Analytics, הצורך בפתרון מעקב עצמאי מעולם לא היה דחוף יותר. כאן נכנס לתמונה המושג zero-cookie tracking (מעקב ללא עוגיות) – גישה שבה אנו אוספים נתונים סטטיסטיים ישירות מקצה הרשת (Edge), מבלי לשתול עוגיות בדפדפן המשתמש ומבלי לפגוע בפרטיותו. פתרון זה חסין לחלוטין בפני חוסמי פרסומות, כיוון שהבקשות נשלחות ישירות לדומיין שלכם ולא לשרת צד שלישי.
הכלי המרכזי שלקבוצת הכלים של Cloudflare להשגת מטרה זו הוא ה-Analytics Engine (מנוע אנליטיקס). זהו מסד נתונים מסוג סדרות עיתיות (Time-series database) המובנה ישירות בתוך ה-Workers שלכם. במקום להגדיר שרתים יקרים או לכתוב למסדי נתונים איטיים, ה-Worker רושם אירועים (data points) בזמן אמת תוך פחות ממילישנייה אחת של זמן מעבד (CPU time). הנתונים נשמרים בצורה מובנית ומאפשרים שליפה מהירה במיוחד.
הקסם שבפנים: שאילתות SQL ישירות מהדפדפן
אחת התכונות החזקות ביותר של ה-Analytics Engine היא היכולת לבצע SQL API calls (קריאות API מבוססות שפת SQL). בניגוד למערכות אנליטיקס סגורות שמחייבות אתכם להשתמש בממשקים מורכבים או בתוספים כבדים, כאן אתם יכולים לכתוב שאילתת
SELECTסטנדרטית ישירות מול קצה הרשת של Cloudflare. המערכת מחזירה תשובת JSON מובנית שאותה ניתן לעבד בשניות.השילוב של כתיבה מהירה בקצה (Edge Write) ויכולת תשאול ב-SQL מאפשר לכם לבנות analytics visualizer (מציג נתונים חזותי) משלכם. זהו למעשה לוח בקרה (Dashboard) פרטי שמציג גרפים, פילוחים לפי מדינות, דפים פופולריים ומקורות תנועה – והכל ללא שימוש בספריות צד שלישי כבדות, ללא עוגיות, ועם שליטה מלאה שלכם על המידע.
הכנה מהירה לקראת בנייה 3 דקותודאו שיש לכם חשבון Cloudflare פעיל ושמותקנת אצלכם גרסה עדכנית של Node.js. אנו נשתמש ב-Wrangler CLI כדי להקים ולנהל את הפרויקט שלנו במהירות, ללא צורך בהגדרות ידניות מסובכות בלוח הבקרה הדפדפדפני.
כדי להבטיח ביצועים אופטימליים ומניעת חריגה ממכסות החינמיות של Cloudflare, הנה השוואה קצרה בין שיטות המעקב השונות:
מאפיין Google Analytics (צד שלישי) מסד נתונים קלאסי (D1/SQL) Cloudflare Analytics Engine השפעה על חוסמי פרסומות נחסם ברוב המקרים (~30% איבוד מידע) לא נחסם (רץ בדומיין שלכם) לא נחסם (חלק בלתי נפרד מה-Worker) שימוש בעוגיות כן (דורש באנר הסכמה מעצבן) לא (תלוי מימוש) אפס עוגיות (Zero-Cookie) מהירות כתיבה (Latency) תלוי ברשת המשתמש בינונית (דורש חיבור וכתיבה למסד נתונים) פחות מ-1ms (רץ ישירות ב-V8 Isolate) שיטת שליפת הנתונים לוח בקרה סגור / API מורכב שאילתות SQL רגילות SQL Query API ישיר ומהיר כעת, נרתום את כל הכלים האלה כדי לבנות מערכת אנליטיקס עצמאית מאפס, שתתעד כל כניסה לאתר ותציג לוח בקרה מעוצב בזמן אמת.
Build a Zero-Cookie Analytics Dashboard 35 דקותבתרגיל זה נבנה פרויקט מלא מאפס: נגדיר Worker, נחבר אותו ל-Analytics Engine, נאסוף נתוני כניסות בצורה אנונימית ונציג גרף SVG דינמי של צפיות יומיות בלוח בקרה פרטי ומעוצב.
-
בדיקה והתקנה של תנאי קדם:
פתח את הטרמינל והרד את הפקודה הבאה כדי לוודא שמותקן אצלך Node.js (נדרשת גרסה 18 ומעלה):
פלט צפוי: גרסה כדוגמתnode -vv20.11.0. אם הפקודה לא מזוהה, יש להתקין את Node.js מהאתר הרשמי שלהם. -
התחברות ל-Cloudflare דרך ה-CLI:
נבצע התחברות לחשבון Cloudflare כדי שנוכל להפיץ את הפרויקט שלנו:
פלט צפוי: ייפתח דפדפן המבקש מכם לאשר את החיבור ל-Wrangler. לאחר האישור, תראו בטרמינל הודעה המבשרת על התחברות מוצלחת (Successfully logged in).npx wrangler login -
יצירת פרויקט חדש:
ניצור תיקיית פרויקט חדשה וניכנס אליה:
כעת נאתחל פרויקט Node.js בסיסי ונתקין את Wrangler מקומית:mkdir private-analytics && cd private-analytics
פלט צפוי: קובץnpm init -y && npm install wrangler --save-devpackage.jsonייווצר בתיקייה ויושלם תהליך ההתקנה של Wrangler. -
יצירת קובץ קונפיגורציה של Wrangler:
צור קובץ בשם
wrangler.tomlבשורש התיקייה, והעתק לתוכו את התוכן הבא. קובץ זה מגדיר את ה-Worker ואת הקישור (Binding) ל-Analytics Engine:name = "private-analytics-app" main = "src/index.js" compatibility_date = "2026-03-19" [[analytics_engine_datasets]] binding = "ANALYTICS" dataset = "site_traffic_events" -
כתיבת קוד ה-Worker:
ניצור תיקייה בשם
srcובתוכה קובץ בשםindex.js:
העתק את הקוד הבא במלואו לתוךmkdir src && touch src/index.jssrc/index.js. הקוד מטפל בשני דברים: רישום אוטומטי של כל כניסה לאתר, והגשת לוח הבקרה (Dashboard) שמציג את הנתונים מתוך ה-API:export default { async fetch(request, env) { const url = new URL(request.url); // 1. רישום הנתונים בקצה (Edge Tracking) עבור כל פנייה שאינה לדף הניהול if (url.pathname !== "/dashboard" && url.pathname !== "/api/data") { try { env.ANALYTICS.writeDataPoint({ blobs: [ url.pathname, // blob1: הדף אליו נכנסו request.headers.get("cf-ipcountry") || "XX", // blob2: מדינת המקור request.headers.get("user-agent") || "Unknown" // blob3: סוג הדפדפן ], doubles: [ 1 // double1: משמש כמונה (Counter) ] }); } catch (err) { console.error("Failed to write analytics data:", err); } } // 2. נקודת קצה להחזרת נתונים סטטיסטיים מדומים (למטרת פיתוח ובדיקה מקומית) if (url.pathname === "/api/data") { // נחזיר נתונים מדומים במבנה התואם לזה של ה-Analytics Engine const mockData = { rows: [ { path: "/", views: 120 }, { path: "/about", views: 45 }, { path: "/blog/first-post", views: 80 }, { path: "/contact", views: 15 } ] }; return new Response(JSON.stringify(mockData), { headers: { "Content-Type": "application/json" } }); } // 3. הגשת לוח הבקרה המעוצב (Dashboard UI) עם גרף SVG דינמי if (url.pathname === "/dashboard") { const html = ` <!DOCTYPE html> <html lang="he" dir="rtl"> <head> <meta charset="UTF-8"> <title>לוח בקרה - אנליטיקס פרטי</title> <style> body { font-family: system-ui, sans-serif; background: #f3f4f6; margin: 0; padding: 40px; color: #1f2937; } .container { max-width: 800px; margin: 0 auto; background: white; padding: 30px; border-radius: 12px; box-shadow: 0 4px 6px rgba(0,0,0,0.05); } h1 { color: #2563eb; margin-bottom: 5px; } p { color: #6b7280; margin-bottom: 30px; } .bar-chart { display: flex; flex-direction: column; gap: 15px; margin-top: 20px; } .bar-row { display: flex; align-items: center; gap: 15px; } .bar-label { width: 150px; font-weight: bold; font-size: 14px; text-align: left; } .bar-wrapper { flex-grow: 1; background: #e5e7eb; height: 24px; border-radius: 4px; overflow: hidden; } .bar-fill { height: 100%; background: #3b82f6; transition: width 0.5s ease; } .bar-value { width: 50px; font-size: 14px; color: #4b5563; text-align: right; } </style> </head> <body> <div class="container"> <h1>מערכת האנליטיקס הפרטית שלי</h1> <p>נתונים בזמן אמת ללא עוגיות (Zero-Cookie Analytics)</p> <div id="chart" class="bar-chart">טוען נתונים...</div> </div> <script> async function loadChart() { try { const res = await fetch('/api/data'); const data = await res.json(); const chartContainer = document.getElementById('chart'); chartContainer.innerHTML = ''; const maxViews = Math.max(...data.rows.map(r => r.views)); data.rows.forEach(row => { const percentage = (row.views / maxViews) * 100; chartContainer.innerHTML += \` <div class="bar-row"> <div class="bar-label">\${row.path}</div> <div class="bar-wrapper"> <div class="bar-fill" style="width: \${percentage}%"></div> </div> <div class="bar-value">\${row.views} צפיות</div> </div> \`; }); } catch (e) { document.getElementById('chart').innerText = 'שגיאה בטעינת הנתונים'; } } loadChart(); </script> </body> </html> `; return new Response(html, { headers: { "Content-Type": "text/html; charset=utf-8" } }); } // ברירת מחדל: דף נחיתה פשוט שישמש אותנו לייצור תנועה return new Response(` <html> <body style="font-family: sans-serif; text-align: center; padding: 50px;"> <h1>ברוכים הבאים לאתר המאובטח שלנו!</h1> <p>הביקור שלך נרשם במערכת האנליטיקס המאובטחת ללא שימוש בעוגיות.</p> <p><a href="/dashboard" style="color: blue; text-decoration: underline;">מעבר ללוח הבקרה ←</a></p> </body> </html> `, { headers: { "Content-Type": "text/html; charset=utf-8" } }); } }; -
הרצה מקומית של הפרויקט:
נריץ את שרת הפיתוח המקומי כדי לוודא שהכל תקין:
פלט צפוי: הטרמינל יציג הודעה שהשרת רץ בכתובתnpx wrangler devhttp://localhost:8787. פתחו את הדפדפן בכתובת הזו, עברו בין דף הבית לכתובת/dashboardוראו את הגרף החלק והמעוצב מוצג ללא עיכובים! -
פרסום האפליקציה לרשת:
כדי להעלות את הפרויקט לאוויר בשרתים הגלובליים של Cloudflare, הריצו:
פלט צפוי: קישור ייחודי המאפשר לכם לגשת לאתר שלכם מכל מקום בעולם (לדוגמה:npx wrangler deployhttps://private-analytics-app.yoursubdomain.workers.dev).
פלט נראה לעין שתסיים איתו: דף אינטרנט מעוצב ונקי בכתובת
/dashboardהמציג לוח בקרה עצמאי עם גרף עמודות אופקי דינמי שמחשב את אחוזי התנועה לכל דף באתר, מוזן ישירות מ-API פנימי ללא ספריות חיצוניות ובמהירות שיא.ניהול סודות מרכזי ב-Secrets Store (beta) וסיכום הפרק
כשאתם בונים אפליקציות מבוססות בינה מלאכותית (AI Agents), אתם מוצאים את עצמכם מהר מאוד מתעסקים עם עשרות מפתחות API (מפתחות גישה לשירותים חיצוניים) — החל מ-OpenAI ו-Anthropic, דרך כלי שליחת אימיילים כמו Resend ועד לחיבורי בסיסי נתונים. בעבר, הדרך הסטנדרטית לנהל את המידע הרגיש הזה ב-Cloudflare Workers הייתה באמצעות הפקודהwrangler secret put SECRET_NAME. הגישה הזו יצרה סודות ברמת הוורקר הבודד (Worker-level secrets). כלומר, אם בניתם מערכת המורכבת משלושה וורקרים שונים (למשל: אחד לניהול ה-UI, אחד לעיבוד ברקע ואחד לתזמון משימות), נאלצתם להגדיר את מפתח ה-OpenAI שלכם שלוש פעמים בנפרד. זה לא רק מתיש, זה גם פתח קלאסי לטעויות, חוסר סנכרון ובעיות אבטחה חמורות בעת עדכון מפתחות. כדי לפתור את הכאב הזה, Cloudflare הציגה את ה-**Secrets Store** (נכון לשנת 2026, הכלי נמצא בגרסת בטא ציבורית). בניגוד לשיטה הישנה, ה-Secrets Store מאפשר לכם להגדיר **account-level secrets** — סודות ברמת החשבון כולו. אתם מגדירים את מפתח ה-API פעם אחת בלבד בכספת מרכזית ומאובטחת, ויכולים "למשוך" או לקשר אותו באמצעות Binding (קישור תוכנתי ישיר) לכל Worker שתרצו באותו החשבון. בנוסף לחיסכון בזמן, ה-Secrets Store מביא איתו יכולות ארגוניות מתקדמות כמו בקרת גישה מבוססת תפקידים (RBAC - Role-Based Access Control) המאפשרת לקבוע בדיוק מי מהצוות רשאי לקרוא או לעדכן את הסוד, ותיעוד פעולות מלא (Audit Logging) שעוקב אחרי כל שינוי או גישה לסוד. כרגע בגרסת הבטא, השירות מוגבל ל-20 סודות בחינם לחשבון, מה שמספיק בהחלט לכל פרויקט vibe-coding ממוצע. בואו נעשה סדר בהבדלים בין שתי הגישות כדי שתדעו מתי להשתמש בכל אחת:מאפיין Wrangler Secret Put (השיטה הישנה) Secrets Store (השיטה המרכזית) טווח השפעה (Scope) Worker בודד בלבד. יש להגדיר מחדש לכל פרויקט. רמת החשבון (Account-level). מוגדר פעם אחת לכולם. ממשק ניהול שורת הפקודה (CLI) בלבד בעת ההקמה. ממשק וויזואלי מלא בתוך ה-Dashboard של Cloudflare. אבטחה והרשאות כל מי שיכול לפרוס את הוורקר חשוף לסוד. תמיכה ב-RBAC (מניעת גישה למפתחים זמניים). מעקב (Audit Trail) חלקי מאוד, קשה לדעת מתי הסוד עודכן ומדוע. תיעוד מלא של היסטוריית עדכונים ושימוש. מגבלת חינם (2026) עד 64 משתני סביבה לוורקר בחינם (128 בתשלום). עד 20 סודות מרכזיים לחשבון במסגרת הבטא. סיכום הפרק: ה-Glue שמחבר את הפאזל
ניהול סודות נכון הוא הבורג האחרון שסוגר את "הדבק" (The Glue) של האפליקציה שלכם. לאורך הפרק הזה ראינו איך הופכים קוד מבודד למערכת אמיתית ועובדת: הגנו על ממשקי הניהול שלנו בעזרת Auth (אימות משתמשים) ללא קוד של **Zero Trust**, חיברנו תיבות דואר חכמות עם **Email Routing** ו-**Email Service**, חשפנו את סביבת הפיתוח המקומית בבטחה לעולם בעזרת פקודות הטנל החדשות (wrangler tunnel), והזרמנו נתונים בזמן אמת ל-**Analytics Engine**. שילוב הכלים האלה מאפשר לכם להתמקד אך ורק בלוגיקה של ה-AI, בזמן ש-Cloudflare סוגרת עבורכם את כל פינות התשתית ברמה של חברות ענק, ובאפס עלות תחת מגבלות השכבה החינמית המפנקת.הגדרת סוד מרכזי ראשון וקישורו לוורקר 15 דקותבצעד זה נקים סוד מרכזי ב-Secrets Store של Cloudflare ונחבר אותו לוורקר מבוסס Hono (ספריית ניתוב קלה במיוחד ל-Workers) כדי לראות איך הגישה המרכזית חוסכת לנו זמן פיתוח יקר.
- פתחו את הדפדפן, היכנסו ל-Cloudflare Dashboard והתחברו לחשבון שלכם.
- בתפריט הצדדי, ניווטו אל Developer Platform ולאחר מכן בחרו ב-Secrets Store (ייתכן שיופיע תחת תגית Beta).
- לחצו על Create Secret. בשדה השם הקלידו
SHARED_AI_KEYובשדה הערך הקלידו מפתח בדיקה כלשהו, למשל:super-secret-key-12345. לחצו על שמירה. - פתחו את מסוף הפקודות (Terminal) שלכם במחשב וצרו פרויקט וורקר חדש על ידי הרצת הפקודה הבאה (הקפידו לבצע התחברות לחשבונכם באמצעות
wrangler loginבמידה ולא עשיתם זאת בעבר):
npm create cloudflare@latest vibe-secrets-demo -- --framework=honoלאחר סיום הקימום (Scaffolding), פתחו את תיקיית הפרויקט שנוצרה בתוך עורך הקוד שלכם.
- עדכנו את קובץ ההגדרות
wrangler.tomlבנתיב הראשי של הפרויקט. נגדיר לוורקר להשתמש בסוד המרכזי שהרגע יצרנו בחשבון:
name = "vibe-secrets-demo" main = "src/index.ts" compatibility_date = "2026-05-29" [secrets] SHARED_AI_KEY = { account_secret = true }- כעת, פתחו את קובץ הקוד הראשי
src/index.tsוהחליפו את תוכנו בקוד הבא. הקוד מאמת שהסוד נטען בהצלחה ומציג תצוגה מוגנת שלו (מסכה של התווים הראשונים בלבד כדי לא לחשוף את הסוד האמיתי החוצה):
import { Hono } from 'hono' type Bindings = { SHARED_AI_KEY: string } const app = new Hono<{ Bindings: Bindings }>() app.get('/', (c) => { const secret = c.env.SHARED_AI_KEY if (!secret) { return c.json({ error: "הסוד המבוקש לא נמצא או לא קושר כראוי!" }, 400) } // הצגת תווים ראשונים בלבד לצורכי אבטחה const maskedSecret = secret.substring(0, 4) + "••••••••" return c.json({ message: "שלום Vibe Coder!", status: "הסוד נטען בהצלחה מה-Secrets Store המרכזי!", preview: maskedSecret }) }) export default app- פרסו את הוורקר לרשת של Cloudflare באמצעות הרצת הפקודה הבאה במסוף:
npx wrangler deployפלט נראה לעין שתסיים איתו: לאחר הרצת הפקודה
wrangler deploy, תקבלו בטרמינל כתובת URL ייחודית של הוורקר שלכם באוויר (למשל:https://vibe-secrets-demo.username.workers.dev). כשתגלשו לכתובת זו בדפדפן, תקבלו מענה JSON בפורמט הבא, המוכיח שהוורקר שלכם קרא ישירות מהכספת המרכזית של החשבון מבלי שהגדרתם את הסוד ידנית בתוך הפרויקט הספציפי הזה:{ "message": "שלום Vibe Coder!", "status": "הסוד נטען בהצלחה מה-Secrets Store המרכזי!", "preview": "supe••••••••" }שגרת עבודהתדירות פעולה יומי בדיקת לוגים של Access (אימות זהות) כדי לזהות ניסיונות כניסה חריגים או חסימות של משתמשים אמיתיים. שבועי סקירת אחוזי המעבר (Pass Rate) בלוח הבקרה של Turnstile (קאפצ'ה בלתי נראית) לוודא שאין עלייה חריגה בפתרון אתגרים על ידי בוטים. חודשי בדיקת תוקף מפתחות ה-API השמורים ב-Secrets Store (מאגר המפתחות הסודיים) ורענון הגדרות ה-Tunnels (מנהרות קישור ל-localhost) הפעילים. דבר אחד שכדאי לעשות עכשיוהקימו פוליסת Cloudflare Access (מערכת אבטחת אפס אמון) אחת עבור אזור הניהול או סביבת הפיתוח שלכם. זה לוקח פחות מ-5 דקות, אינו דורש כתיבת שורת קוד אחת או ניהול מסד נתונים של משתמשים, ומעניק לכם הגנה ברמת ארגון (Enterprise) עם אימות באמצעות אימייל (Magic Link) או חשבון GitHub/Google שלכם לחלוטין בחינם (עד 50 משתמשים).
בדוק את עצמך — 5 שאלות- בניתם אפליקציה ציבורית עם Cloudflare Access וחיברתם אליה 60 משתמשים רשומים. מה יקרה כשהמשתמש ה-51 ינסה להתחבר? (רמז: שימו לב למגבלת ה-Seats החינמית הקשיחה של Access ומתי צריך לעבור למודל בתשלום לפי משתמש).
- מדוע לא מומלץ להשתמש ב-Quick Tunnels (מנהרות מהירות זמניות) של Wrangler עבור סביבת ייצור (Production) המציגה נתונים בזמן אמת באמצעות Server-Sent Events (SSE)? (רמז: חשבו על מגבלות הקישורים הסימולטניים ותמיכת הפרוטוקולים של trycloudflare לעומת מנהרה ייעודית).
- האם הגדרת ניתוב אימיילים (Email Routing) כדי לקבל מיילים ולנתב אותם ל-Worker שלכם כרוכה בתשלום חודשי כלשהו? (רמז: הבדילו בין קבלה ועיבוד של אימיילים נכנסים לבין מנגנוני שליחת אימיילים מהשרת).
- כיצד שומרים מפתחות API וסודות בצורה מאובטחת כך שיהיו נגישים לכל ה-Workers בחשבון מבלי להגדיר אותם מחדש בכל פרויקט בנפרד? (רמז: השתמשו ברכיב החדש שנמצא כעת בגרסת הבטא ומוגבל ל-20 רשומות בחינם).
- האם אתם חייבים להציג למשתמש פאזל או תיבת סימון (Checkbox) כדי להגן על טופס יצירת קשר באמצעות Turnstile? (רמז: זכרו מהו ה-Smart Challenge וכיצד הוא פועל מאחורי הקלעים בצורה שקופה).
סיכום הפרקבפרק זה צללנו אל ה"דבק" (The Glue) של עולם השרתים של Cloudflare — אותם כלים קטנים אך קריטיים שהופכים קוד מבודד לאפליקציה מאובטחת, שלמה ומקצועית. למדנו כיצד להגן על טפסים מבוטים באמצעות Turnstile ללא פגיעה בחוויית המשתמש, וכיצד לגדר אזורים רגישים באמצעות מערכת Zero Trust Access ללא שורת קוד אחת של אימות. בנוסף, חקרנו את עבודה עם מנהרות תקשורת (Tunnels) ישירות מהמחשב המקומי, פיתחנו מעבד אימיילים מבוסס בינה מלאכותית המבוסס על Email Routing, והקמנו מערכת מעקב (Analytics) פנימית שאינה דורשת שימוש בעוגיות (Cookies) או קבלת הסכמת משתמש.
כל הכלים הללו מאפשרים לכם, כ-Vibe Coders, לחסוך זמן פיתוח עצום, להימנע מתשלומים מנופחים לשירותי צד-שלישי יקרים, ולשמור על האפליקציה שלכם יציבה ומאובטחת מהרגע הראשון.
בפרק הבא נבצע אינטגרציה מלאה של כלל הרכיבים שבנינו לכדי מוצר full-stack מושלם על ה-Free Tier, תוך ניתוח מלא של מגבלות העלות.
צ'קליסט — סיכום
- הגדרתי ווידג'ט Turnstile בלוח הבקרה של Cloudflare וקיבלתי מפתחות אתר ומפתחות סודיים.
- הטמעתי את קוד ה-HTML וה-JavaScript של Turnstile בצד הלקוח של האפליקציה שלי.
- כתבתי פונקציית אימות (Server-side validation) בתוך Worker כדי לבדוק את אמינות ה-Token שהתקבל מ-Turnstile.
- הפעלתי את שירות Zero Trust בלוח הבקרה ויצרתי ארגון אבטחה בסיסי.
- הגדרתי פוליסת אבטחה ב-Access המגנה על נתיב (URL) מסוים באתר שלי.
- חיברתי מנגנון אימות מבוסס קוד חד-פעמי באימייל (Email OTP) או ספק זהות חיצוני (Google/GitHub).
- בדקתי את מגבלת 50 המשתמשים החינמיים של Access כדי לוודא שאינני חורג ממנה.
- הרצתי מנהרה מהירה (Quick Tunnel) באמצעות פקודת Wrangler כדי לחשוף את ה-localhost שלי לרשת.
- הקמתי מנהרה קבועה (Named Tunnel) המקושרת לדומיין מותאם אישית ומאפשרת תמיכה ב-SSE.
- הגדרתי חוקי ניתוב אימיילים (Email Routing) לקבלת אימיילים בדומיין שלי וניתובם ל-Worker.
- כתבתי לוגיקת עיבוד (Parsing) בתוך Worker שמנתחת קבצים מצורפים וטקסט מתוך אימיילים נכנסים.
- שילבתי את ה-Worker עם Workers AI כדי לבצע סיכום או סיווג אוטומטי של הודעות האימייל.
- הגדרתי מסד נתונים של Analytics Engine והזרמתי אליו אירועים (Events) מהקוד שלי בזמן אמת.
- בניתי לוח בקרה סטטי המשתמש ב-SQL API כדי לשלוף נתוני אנליטיקס ללא שימוש בעוגיות צד שלישי.
- שמרתי מפתחות סודיים גלובליים באמצעות ה-Secrets Store המרכזי לשימוש מהיר ומאובטח בפרויקטים השונים.
-
בדיקה והתקנה של תנאי קדם:
פתח את הטרמינל והרד את הפקודה הבאה כדי לוודא שמותקן אצלך Node.js (נדרשת גרסה 18 ומעלה):
- כן: בצעו הגדרה של Named Tunnel. מנהרה בעלת שם משויכת לחשבון ה-Cloudflare שלכם ומאפשרת לקשור את ה-localhost ישירות לדומיין הרשום שלכם (למשל,