اعداد: عبدالرحمن محمود 👀❤
🎓 Qubedu — أكاديمية تطوير الويب الشاملة
تعلّم كل شيء تحتاجه
لتبني أي موقع
من أول وسم HTML حتى بناء مشروع مثل فيسبوك أو متجر إلكتروني — شرح عربي كامل مع كود جاهز للنسخ
60+
وسم HTML
80+
خاصية CSS
40+
مفهوم JS
4
مشاريع ضخمة
المرحلة الأولى
🏗️ HTML — هيكل كل صفحة ويب
كل وسم: لماذا يوجد؟ متى تستخدمه؟ مع كود جاهز للنسخ مباشرة
القالب الأساسي — انسخه لكل مشروع
📌 هذا القالب إلزامي — كل ملف HTML يبدأ هكذا. احفظه كـ snippet في VS Code.
HTML — القالب الكامل
<!-- السطر الأول دائماً --> <!DOCTYPE html> <html lang="ar" dir="rtl"> <head> <meta charset="UTF-8"> <!-- يدعم العربية --> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- موبايل --> <meta name="description" content="وصف الصفحة لجوجل"> <title>اسم الصفحة | Qubedu</title> <link rel="icon" href="favicon.ico"> <link rel="stylesheet" href="css/style.css"> </head> <body> <!-- كل المحتوى هنا --> <header></header> <main></main> <footer></footer> <!-- JS في آخر body دائماً --> <script src="js/main.js"></script> </body> </html>
وسوم النصوص
<h1> → <h6>العناوين من الأكبر للأصغرblock▶
<h1> = العنوان الرئيسي — مرة واحدة فقط في الصفحة (SEO). <h2> للأقسام. <h3> للأقسام الفرعية... حتى h6.
HTML
<h1>العنوان الرئيسي للصفحة — مرة واحدة</h1> <h2>عنوان قسم رئيسي</h2> <h3>عنوان فرعي</h3> <h4>أصغر منه</h4>
<p>الفقرة النصية — لكل نص طويل أو قصيرblock▶
كل فقرة مستقلة في <p>. المتصفح يضيف مسافة فوق وأسفل تلقائياً. لا تستخدم <br> بدلاً منها.
HTML
<p>هذه فقرة نصية عادية.</p> <p> نص به <strong>غامق مهم</strong> و<em>مائل مؤكد</em> و<mark>مظلل</mark> و<del>محذوف</del>. </p>
<strong> <em> <mark> <del> <span> <code>تنسيق النص inlineinline▶
HTML
<strong>غامق مهم — SEO يعرفه كمهم</strong> <em>مائل مؤكد</em> <mark>مظلل بالأصفر</mark> <del>سعر قديم 200 ج</del> <ins>سعر جديد 150 ج</ins> <small>ملاحظة صغيرة</small> H<sub>2</sub>O — E=mc<sup>2</sup> <code>console.log("كود برمجي")</code> <span style="color:green">نص ملوّن</span> <blockquote cite="المصدر">اقتباس مهم</blockquote>
<ul> <ol> <li> <dl>القوائم — نقاط وأرقام وتعريفاتblock▶
<ul> = نقاط (•). <ol> = أرقام (1,2,3). <li> = عنصر القائمة دائماً. <dl> = قائمة مصطلحات.
HTML
<ul> <!-- قائمة بنقاط --> <li>HTML</li> <li>CSS</li> <li>JavaScript</li> </ul> <ol> <!-- قائمة بأرقام --> <li>تنزيل VS Code</li> <li>إنشاء ملف index.html</li> <li>فتحه في المتصفح</li> </ol>
الروابط والصور
<a href="">الرابط التشعبي — ينقل لمكان آخرinline▶
href = الوجهة. target="_blank" = تبويب جديد (أضف
rel="noopener" معها). download = تنزيل ملف. يمكن أن يُحيط بصورة أو أي محتوى.HTML
<!-- رابط خارجي في تبويب جديد --> <a href="https://google.com" target="_blank" rel="noopener">جوجل</a> <!-- رابط داخلي لصفحة في نفس الموقع --> <a href="about.html">من نحن</a> <a href="products/phone.html">الهاتف</a> <!-- رابط لقسم في نفس الصفحة --> <a href="#contact">تواصل معنا</a> <section id="contact">...</section> <!-- رابط بريد وهاتف --> <a href="mailto:info@Qubedu.com">راسلنا</a> <a href="tel:+201234567890">اتصل بنا</a> <!-- تنزيل ملف --> <a href="cv.pdf" download="سيرة-ذاتية.pdf">تنزيل CV</a> <!-- صورة قابلة للنقر --> <a href="/"><img src="logo.png" alt="الشعار"></a>
<img src="" alt="">الصورة — عرض أي صورةinline▶
src = مصدر الصورة. alt = نص بديل — إلزامي للـ SEO وإمكانية الوصول. loading="lazy" = تحميل كسول يسرّع الموقع.
HTML
<!-- صورة محلية --> <img src="images/hero.jpg" alt="صورة رئيسية" width="800" height="450" loading="lazy"> <!-- صورة متجاوبة --> <img src="photo.jpg" alt="وصف" style="width:100%;height:auto"> <!-- صورة من الإنترنت --> <img src="https://picsum.photos/400/300" alt="صورة للتجربة"> <!-- صورة دائرية للأفاتار --> <img src="user.jpg" alt="صورة المستخدم" style="width:48px;height:48px;border-radius:50%;object-fit:cover"> <!-- figure: صورة مع تعليق --> <figure> <img src="product.jpg" alt="المنتج"> <figcaption>وصف المنتج يظهر تحت الصورة</figcaption> </figure>
النماذج — قلب كل موقع تفاعلي
⚠️ مهم: كل تسجيل دخول، شراء، تعليق، رسالة — يمر عبر نموذج HTML. إتقانها أساسي.
<form> + كل الحقولنموذج بيانات كامل جاهز للنسخform▶
HTML — نموذج تسجيل كامل
<form id="registerForm" action="/api/register" method="post"> <!-- نص -- اسم الشخص --> <label for="name">الاسم الكامل</label> <input type="text" id="name" name="name" placeholder="أدخل اسمك" required minlength="3"> <!-- بريد إلكتروني -- يتحقق من الشكل تلقائياً --> <label for="email">البريد الإلكتروني</label> <input type="email" id="email" name="email" placeholder="you@example.com" required> <!-- كلمة مرور -- تظهر نقاط --> <label for="pass">كلمة المرور</label> <input type="password" id="pass" name="password" minlength="8" required> <!-- رقم هاتف --> <input type="tel" name="phone" placeholder="01XXXXXXXXX"> <!-- رفع صورة --> <input type="file" name="avatar" accept="image/*"> <!-- نص طويل --> <textarea name="bio" rows="4" placeholder="اكتب نبذة عنك..."></textarea> <!-- قائمة منسدلة --> <select name="country"> <option value="">اختر دولتك</option> <option value="eg">🇪🇬 مصر</option> <option value="sa">🇸🇦 السعودية</option> <option value="ae">🇦🇪 الإمارات</option> </select> <!-- خيار واحد (radio) --> <input type="radio" name="gender" value="male" id="m"> <label for="m">ذكر</label> <input type="radio" name="gender" value="female" id="f"> <label for="f">أنثى</label> <!-- موافقة (checkbox) --> <input type="checkbox" name="terms" id="terms" required> <label for="terms">أوافق على الشروط والأحكام</label> <!-- الأزرار --> <button type="submit">إنشاء الحساب</button> <button type="reset">مسح الكل</button> <button type="button" onclick="doSomething()">زر JS</button> </form>
الوسائط — فيديو وصوت وiframe
<video> <audio> <iframe>تضمين وسائط في الصفحةوسائط▶
HTML
<!-- فيديو محلي --> <video src="video.mp4" controls autoplay muted loop poster="thumb.jpg" width="100%"> </video> <!-- صوت --> <audio src="audio.mp3" controls></audio> <!-- يوتيوب embed --> <iframe src="https://www.youtube.com/embed/VIDEO_ID" width="100%" height="400" frameborder="0" allowfullscreen></iframe> <!-- خريطة جوجل --> <iframe src="https://maps.google.com/maps?q=Cairo&output=embed" width="100%" height="350" style="border:0"></iframe>
الجداول
<table> <thead> <tbody> <tr> <th> <td>جدول بيانات منظم في صفوف وأعمدةblock▶
HTML
<table> <thead> <tr><th>المنتج</th><th>السعر</th><th>الحالة</th></tr> </thead> <tbody> <tr><td>هاتف</td><td>3500 ج</td><td>✅</td></tr> <tr> <td colspan="2">لابتوب (نفد)</td> <!-- يمتد عمودين --> <td>❌</td> </tr> </tbody> </table>
الوسوم الدلالية والـ SEO
<header> <nav> <main> <section> <article> <aside> <footer>هيكل جوجل يفهمهSEO▶
HTML — هيكل صفحة كاملة دلالية
<body> <header> <!-- رأس الموقع: شعار + قائمة --> <a href="/"><img src="logo.png" alt="Qubedu"></a> <nav> <!-- شريط التنقل --> <a href="/">الرئيسية</a> <a href="/courses">الدورات</a> </nav> </header> <main> <!-- المحتوى الرئيسي -- عنصر واحد فقط --> <section id="hero"> <h1>تعلم البرمجة مع Qubedu</h1> </section> <article> <!-- مقالة مستقلة / بوست --> <h2>ما هو HTML؟</h2> <p>HTML هي...</p> </article> </main> <aside> <!-- عمود جانبي --> <h3>مقالات ذات صلة</h3> </aside> <footer> <!-- تذييل الصفحة --> <p>© 2025 Qubedu</p> </footer> </body>
HTML — meta للـ SEO والسوشيال
<head> <!-- SEO أساسي --> <title>صفحتك | Qubedu</title> <meta name="description" content="ما يظهر في نتائج جوجل — 150 حرف"> <meta name="keywords" content="برمجة, HTML, تطوير مواقع"> <!-- Open Graph: صورة مشاركة السوشيال ميديا --> <meta property="og:title" content="Qubedu"> <meta property="og:description" content="أكاديمية تطوير الويب"> <meta property="og:image" content="https://Qubedu.com/og.jpg"> <meta property="og:url" content="https://Qubedu.com"> </head>
<div> <details> <dialog>حاويات تجميع العناصرblock▶
HTML
<!-- div: الحاوية الأكثر استخداماً --> <div class="card"> <h3>عنوان البطاقة</h3> <p>محتوى البطاقة</p> </div> <!-- details+summary: accordion بدون JS --> <details> <summary>اضغط لعرض التفاصيل ▼</summary> <p>المحتوى المخفي يظهر هنا</p> </details> <!-- dialog: modal نيتيف بدون JS --> <dialog id="modal"> <h2>هل أنت متأكد؟</h2> <button onclick="document.getElementById('modal').close()">إغلاق</button> </dialog> <button onclick="document.getElementById('modal').showModal()">فتح</button>
المرحلة الثانية
🎨 CSS — التصميم من الصفر للاحتراف
كل خاصية مع مثال — من الألوان والخطوط لـ Flexbox لـ Grid للأنيميشن
المحددات — كيف تختار العنصر
CSS — كل أنواع المحددات
/* باسم الوسم — يطبق على كل العناصر من هذا النوع */ p { color: #333; } h1 { font-size: 2.5rem; } button { cursor: pointer; } /* بالكلاس — الأكثر استخداماً */ .card { background: white; border-radius: 12px; } .btn-primary { background: #007bff; color: white; } /* بالـ id — لعنصر واحد */ #header { position: fixed; top: 0; } /* محددات متقدمة */ nav a { color: white; } /* <a> داخل <nav> فقط */ .card .title { font-weight: 700; } /* .title داخل .card */ input[type="email"]{ border-color: blue; } /* input نوعه email */ .item:nth-child(2) { background: #f0f0f0; } /* العنصر الثاني */ .item:nth-child(odd){ background: #fafafa; }/* الأفرادي */ li:last-child { border: none; } /* Pseudo-classes: حالات العنصر */ a:hover { color: #0056b3; } button:active { transform: scale(.97); } input:focus { outline: 2px solid #007bff; } input:valid { border-color: green; } input:invalid { border-color: red; } button:disabled{ opacity: .5; cursor: not-allowed; } /* ::before و ::after — عناصر وهمية بدون HTML */ .card::before { content: ""; /* مطلوب دائماً */ display: block; height: 3px; background: linear-gradient(90deg, #007bff, #9c27b0); } .required::after{ content: " *"; color: red; }
Box Model — الحجم والمسافات والحدود
CSS — Box Model
/* القاعدة الذهبية — ضعها في كل مشروع */ *, *::before, *::after { box-sizing: border-box; } .element { /* الحجم */ width: 300px; height: 200px; max-width: 100%; /* لا يتجاوز الأب */ min-height: 50px; width: 50vw; /* نسبة من عرض الشاشة */ height: 100vh; /* ارتفاع الشاشة كاملاً */ /* Padding: داخلي */ padding: 20px; /* كل الجهات */ padding: 10px 20px; /* أعلى/أسفل | يمين/يسار */ padding: 5px 10px 15px 20px; /* أعلى يمين أسفل يسار */ padding-top: 16px; padding-inline: 24px; /* يمين ويسار فقط */ padding-block: 12px; /* أعلى وأسفل فقط */ /* Margin: خارجي */ margin: 0 auto; /* توسيط أفقي */ margin-bottom:24px; /* Border */ border: 1px solid #ddd; border-top: 3px solid #007bff; border-radius: 8px; /* تدوير */ border-radius: 50%; /* دائرة */ outline: 2px solid #007bff; /* بدون تأثير على layout */ /* الظل */ box-shadow: 0 4px 16px rgba(0,0,0,.12); box-shadow: 0 0 0 3px rgba(0,123,255,.3); /* حلقة focus */ box-shadow: inset 0 2px 8px rgba(0,0,0,.1); /* ظل داخلي */ /* الخلفية */ background-color: #ffffff; background: linear-gradient(135deg, #667eea, #764ba2); background-image: url('bg.jpg'); background-size: cover; background-position: center; background-repeat: no-repeat; background-attachment: fixed; /* Parallax */ /* أخرى */ overflow: hidden; /* يقطع ما يخرج */ overflow-x: auto; /* scroll أفقي */ opacity: .8; cursor: pointer; visibility: hidden; /* مخفي لكن يحتفظ بمكانه */ display: none; /* مخفي ومكانه اختفى */ }
النص والخط
CSS — Typography
body { font-family: 'Cairo', sans-serif; font-size: 16px; font-weight: 400; /* 100-900 | normal=400 | bold=700 */ line-height: 1.6; color: #333; text-align: right; /* للعربية */ direction: rtl; } h1 { font-size: clamp(1.8rem, 5vw, 4rem); } /* مرن بين حدين */ .text-center { text-align: center; } .text-muted { color: #6c757d; } .font-bold { font-weight: 700; } .no-underline { text-decoration: none; } .uppercase { text-transform: uppercase; } .tracking-wide{ letter-spacing: 2px; } /* قطع النص بـ ... */ .truncate { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } /* نص بتدرج لوني */ .gradient-text { background: linear-gradient(135deg, #00d9ff, #7c3aed); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
Flexbox — توزيع العناصر في صف أو عمود
CSS — Flexbox
/* على الحاوية الأم */ .container { display: flex; flex-direction: row; /* row | column | row-reverse */ justify-content: space-between; /* flex-start|center|space-between|space-around */ align-items: center; /* flex-start|center|stretch|baseline */ gap: 16px; /* المسافة بين العناصر */ flex-wrap: wrap; /* ينتقل للسطر التالي لو ضاق */ } /* على الأبناء */ .child { flex: 1; } /* يتوسع بالتساوي */ .fixed { flex: 0 0 200px; } /* 200px ثابت */ .big { flex-grow: 2; } /* ينمو ضعف غيره */ .first { order: -1; } /* يظهر أول */ .self { align-self: flex-end; } /* ═══ وصفات جاهزة ═══ */ /* توسيط في منتصف الشاشة */ .center-screen { display: flex; justify-content: center; align-items: center; min-height: 100vh; } /* Navbar احترافي */ .navbar { display:flex; align-items:center; justify-content:space-between; padding:0 24px; height:60px; position:fixed; top:0; left:0; right:0; } /* بطاقات في صف يلفوا تلقائياً */ .cards-row { display:flex; flex-wrap:wrap; gap:20px; } .cards-row .card { flex: 1 1 280px; } /* حد أدنى 280px */
CSS Grid — لتصاميم الشبكة
CSS — Grid
.grid { display: grid; grid-template-columns: repeat(3, 1fr); /* 3 أعمدة متساوية */ grid-template-columns: 250px 1fr 1fr; /* sidebar + محتوى */ grid-template-columns: repeat(auto-fit, minmax(250px,1fr)); /* سحري! */ gap: 20px; } /* عنصر يمتد على كل العرض */ .full { grid-column: 1 / -1; } .span-2 { grid-column: span 2; } .row-2 { grid-row: span 2; } /* تصميم صفحة كاملة */ .page-layout { display: grid; grid-template-areas: "header header" "sidebar main" "footer footer"; grid-template-columns: 250px 1fr; min-height: 100vh; } .site-header { grid-area: header; } .site-sidebar { grid-area: sidebar; } .site-main { grid-area: main; } .site-footer { grid-area: footer; }
Position — تحكم دقيق في المواضع
CSS — Position
/* relative: يتحرك نسبياً ويصبح مرجعاً */ .parent { position: relative; } /* absolute: موضع دقيق داخل أقرب أب relative */ .badge { position: absolute; top: -8px; right: -8px; } /* fixed: ثابت في الشاشة عند التمرير */ .topbar { position: fixed; top:0; left:0; right:0; z-index:1000; } /* sticky: عادي ثم يلتصق لما تصل إليه */ .sticky-head{ position: sticky; top: 60px; } /* Modal overlay كامل */ .overlay { position: fixed; inset: 0; /* = top:0 right:0 bottom:0 left:0 */ background: rgba(0,0,0,.6); z-index: 999; display:flex; align-items:center; justify-content:center; }
الأنيميشن والحركة
CSS — Transitions وAnimations
/* Transition: انتقال سلس */ .btn { transition: all 0.25s ease; /* الخاصية | المدة | المنحنى */ } .btn:hover { background: #0056b3; transform: translateY(-2px); box-shadow: 0 8px 20px rgba(0,123,255,.4); } /* Transform */ .card:hover { transform: scale(1.03) translateY(-4px); } .icon { transform: rotate(45deg); } /* Keyframes: حركة كاملة بمراحل */ @keyframes fadeInUp { from { opacity:0; transform:translateY(30px); } to { opacity:1; transform:translateY(0); } } .hero-text { animation: fadeInUp .6s ease forwards; } .hero-btn { animation: fadeInUp .6s ease .2s forwards; opacity:0; } /* Loading Spinner */ @keyframes spin { to{ transform:rotate(360deg); } } .spinner { width:40px; height:40px; border-radius:50%; border:4px solid #eee; border-top-color:#007bff; animation: spin .8s linear infinite; } /* Skeleton Loading */ @keyframes shimmer { from { background-position: -200% 0; } to { background-position: 200% 0; } } .skeleton { background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%); background-size: 200%; animation: shimmer 1.5s infinite; }
الـ Responsive — موقعك على كل الأجهزة
CSS — Responsive Design
/* Mobile First: ابدأ بالموبايل */ .grid { grid-template-columns: 1fr; } @media (min-width: 640px) { .grid { grid-template-columns: repeat(2,1fr); } } @media (min-width: 768px) { .sidebar { display: block; } } @media (min-width: 1024px) { .grid { grid-template-columns: repeat(3,1fr); } } @media (min-width: 1280px) { .grid { grid-template-columns: repeat(4,1fr); } } /* إخفاء على الموبايل */ @media (max-width: 767px) { .desktop-only { display: none; } } @media (min-width: 768px) { .mobile-only { display: none; } } /* Dark Mode تلقائي */ @media (prefers-color-scheme: dark) { :root { --bg: #121212; --text: #e0e0e0; } } /* وحدات مرنة */ h1 { font-size: clamp(1.5rem, 5vw, 4rem); } .container { width: min(100%, 1200px); margin: 0 auto; padding: 0 16px; }
CSS Variables — ثيم احترافي
CSS Variables + Dark Mode
:root { --primary: #007bff; --secondary: #6c757d; --success: #28a745; --danger: #dc3545; --bg: #ffffff; --text: #212529; --border: #dee2e6; --radius: 8px; --shadow: 0 4px 16px rgba(0,0,0,.1); } .btn { background: var(--primary); border-radius: var(--radius); } .card { box-shadow: var(--shadow); } .error { color: var(--danger); } /* Dark Mode بـ JS: document.documentElement.setAttribute('data-theme','dark') */ [data-theme="dark"] { --bg: #0d1117; --text: #c9d1d9; --border:#30363d; }
المرحلة الثالثة
⚡ JavaScript — التفاعل والمنطق
من المتغيرات حتى async/await — كل ما تحتاجه لبناء تطبيقات حقيقية
المتغيرات والأنواع والعمليات
JavaScript — Variables & Types
// المتغيرات const siteName = "Qubedu"; // ثابت لا يتغير — استخدمه دائماً let counter = 0; // متغير يتغير لاحقاً // var — قديم، تجنبه تماماً // الأنواع الأساسية const name = "أحمد"; // String const age = 25; // Number const price = 3.14; // Float const active = true; // Boolean const data = null; // فارغ مقصود let undef; // undefined: لم يُعطَ قيمة // العمليات الحسابية 10 + 5 // 15 10 - 3 // 7 4 * 3 // 12 10 / 4 // 2.5 10 % 3 // 1 (باقي القسمة) 2 ** 3 // 8 (2 أس 3) counter++; // زيادة بمقدار 1 counter--; // نقصان بمقدار 1 counter += 5; // زيادة بمقدار 5 // التحقق من النوع typeof "hello" // "string" typeof 42 // "number" typeof true // "boolean" typeof {} // "object" typeof [] // "object" (مصفوفة!) Array.isArray([]) // true — الأصح للمصفوفات // التعامل مع النصوص `مرحباً يا ${name}! عمرك ${age} سنة` // Template Literal name.length // 4 name.toUpperCase() // "أحمد" (يؤثر على الإنجليزية) " hello ".trim() // "hello" "hello".includes("ell") // true "a,b,c".split(",") // ["a","b","c"] "hello".replace("hello","مرحبا") // "مرحبا" "hello".slice(0, 3) // "hel" ["أ","ب"].join(" - ") // "أ - ب" // Math Math.round(4.6) // 5 Math.floor(4.9) // 4 Math.ceil(4.1) // 5 Math.abs(-5) // 5 Math.max(3,7,2) // 7 Math.random() // 0 إلى 0.99 Math.floor(Math.random()*100) // رقم عشوائي 0-99
الدوال والشروط والحلقات
JavaScript — Functions, Conditions, Loops
// ══ الدوال ══ function greet(name) { return `مرحباً يا ${name}!`; } const add = (a, b) => a + b; // Arrow مختصر const square = n => n * n; // معامل واحد بدون أقواس const sayHi = () => console.log("مرحبا"); // بدون معاملات // Default Parameters function createUser(name, role = "user", active = true) { return { name, role, active }; } // ══ الشروط ══ if (score >= 90) { console.log("ممتاز"); } else if (score >= 70) { console.log("جيد جداً"); } else { console.log("راجع"); } // Ternary — شرط مختصر في سطر const label = score >= 50 ? "ناجح" : "راسب"; // Nullish Coalescing const username = user?.name ?? "زائر"; // لو null أو undefined const avatar = user?.profile?.image; // Optional Chaining // Switch switch(day) { case "الجمعة": case "السبت": console.log("عطلة!"); break; default: console.log("يوم عمل"); } // ══ الحلقات ══ for (let i = 0; i < 5; i++) { console.log(i); } for (const item of ["HTML","CSS","JS"]) { console.log(item); } for (const [key, val] of Object.entries(user)) { console.log(`${key}: ${val}`); } while (queue.length > 0) { const task = queue.shift(); task.execute(); }
DOM — التحكم في HTML بـ JavaScript
JavaScript — DOM
// ══ اختيار عناصر ══ const el = document.querySelector("#id"); // بالـ id const card = document.querySelector(".card"); // أول عنصر بالكلاس const all = document.querySelectorAll(".card"); // كلهم const first= document.querySelector("nav a:first-child"); // ══ قراءة وكتابة ══ el.textContent = "نص جديد"; // كتابة آمنة el.innerHTML = "<b>HTML</b>"; // HTML داخله const val = el.textContent; // قراءة const inputVal = document.querySelector("#email").value; // ══ الخصائص ══ el.setAttribute("href", "https://Qubedu.com"); el.removeAttribute("disabled"); el.dataset.id = "123"; // data-id="123" el.style.color = "red"; el.style.display = "none"; el.style.display = ""; // إزالة inline // ══ الكلاسات ══ el.classList.add("active"); el.classList.remove("hidden"); el.classList.toggle("dark"); // يضيف أو يحذف el.classList.contains("active"); // true/false el.classList.replace("old", "new"); // ══ إنشاء وإضافة ══ const card = document.createElement("div"); card.className = "product-card"; card.innerHTML = ` <img src="${p.image}" alt="${p.name}"> <h3>${p.name}</h3> <p>${p.price} ج</p> <button data-id="${p.id}" class="add-btn">أضف للسلة</button> `; document.querySelector("#grid").appendChild(card); card.remove(); // حذف // ══ التمرير ══ document.querySelector("#section").scrollIntoView({ behavior: 'smooth' }); window.scrollTo({ top: 0, behavior: 'smooth' });
الأحداث — استجب لتصرفات المستخدم
JavaScript — Events
// ══ إضافة حدث ══ btn.addEventListener("click", (e) => { e.preventDefault(); // منع السلوك الافتراضي e.stopPropagation(); // منع تصاعد الحدث console.log(e.target); // العنصر الذي تم النقر عليه }); // كل أنواع الأحداث: // click / dblclick — نقر // mouseenter / mouseleave — دخول/خروج الماوس // keydown / keyup — لوحة المفاتيح // input — تغيير قيمة حقل (كل حرف) // change — بعد انتهاء التغيير // submit — إرسال نموذج // scroll — تمرير الصفحة // resize — تغيير حجم النافذة // DOMContentLoaded — HTML جاهز // ══ نموذج كامل ══ document.querySelector("#loginForm").addEventListener("submit", async (e) => { e.preventDefault(); const email = e.target.querySelector("#email").value.trim(); const pass = e.target.querySelector("#pass").value; if (!email || !pass) { showError("أملأ كل الحقول"); return; } await login(email, pass); }); // ══ تفويض الأحداث (لعناصر تُنشأ لاحقاً) ══ document.querySelector("#feed").addEventListener("click", (e) => { if (e.target.matches(".like-btn")) likePost(e.target.dataset.id); if (e.target.matches(".delete-btn")) deletePost(e.target.dataset.id); }); // ══ LocalStorage — حفظ محلي ══ localStorage.setItem("token", "abc123"); const token = localStorage.getItem("token"); localStorage.removeItem("token"); localStorage.setItem("cart", JSON.stringify(items)); const cart = JSON.parse(localStorage.getItem("cart") || "[]");
المصفوفات — أساس كل قائمة
JavaScript — Arrays
const products = [ { id:1, name:"هاتف", price:3200, cat:"تقنية", stock:15 }, { id:2, name:"حذاء", price:350, cat:"ملابس", stock:30 }, { id:3, name:"كتاب", price:80, cat:"تعليم", stock:0 }, { id:4, name:"سماعة", price:650, cat:"تقنية", stock:8 }, ]; // map: حوّل كل عنصر const names = products.map(p => p.name); const disc = products.map(p => ({...p, price: p.price * .9})); const cards = products.map(p => `<div class="card">${p.name}</div>`).join(""); // filter: صفّي بشرط const inStock = products.filter(p => p.stock > 0); const tech = products.filter(p => p.cat === "تقنية"); const cheap = products.filter(p => p.price < 500); // find: أول عنصر يطابق const phone = products.find(p => p.id === 1); const idx = products.findIndex(p => p.id === 1); // الرقم التسلسلي // some / every const anyOut = products.some(p => p.stock === 0); // true const allIn = products.every(p => p.stock > 0); // false // reduce: جمع / تجميع const total = products.reduce((sum,p) => sum + p.price, 0); const maxPrice = products.reduce((max,p) => p.price>max ? p.price : max, 0); // sort const byPrice = [...products].sort((a,b) => a.price - b.price); const byName = [...products].sort((a,b) => a.name.localeCompare(b.name)); // إضافة / حذف products.push({id:5}); // أضف للنهاية products.unshift({id:0}); // أضف للبداية products.pop(); // احذف الأخير products.splice(2, 1); // احذف index 2 const merged = [...arr1, ...arr2];// دمج const unique = [...new Set(arr)]; // حذف المكرر
الكائنات وJSON
JavaScript — Objects & JSON
const user = { id: 1, name: "أحمد", email: "ahmed@Qubedu.com", address: { city: "القاهرة", country: "مصر" }, skills: ["HTML", "CSS", "JS"], greet() { return `مرحباً، أنا ${this.name}`; } }; // الوصول user.name // "أحمد" user["email"] // نفس الشيء user?.address?.city // "القاهرة" بأمان user.skills[0] // "HTML" // Destructuring: استخراج مختصر const { name, email, role = "user" } = user; const { city } = user.address; const [first, second] = user.skills; // Spread: نسخ ودمج const updated = { ...user, name: "علي" }; // نسخة محدّثة const merged = { ...defaults, ...userPrefs }; // دمج // JSON const json = JSON.stringify(user, null, 2); // كائن → نص جميل const parsed = JSON.parse(json); // نص → كائن // دوال الكائن Object.keys(user) // ["id","name","email",...] Object.values(user) // [1,"أحمد","ahmed@...",...] Object.entries(user) // [["id",1],["name","أحمد"],...]
Async / Fetch — التواصل مع السيرفر
JavaScript — Fetch API
// ══ GET: جلب بيانات ══ async function loadProducts() { const grid = document.querySelector("#grid"); grid.innerHTML = `<div class="spinner"></div>`; try { const res = await fetch("/api/products"); if (!res.ok) throw new Error(`خطأ ${res.status}`); const data = await res.json(); grid.innerHTML = data.map(p => ` <div class="card"> <img src="${p.image}" alt="${p.name}"> <h3>${p.name}</h3> <p>${p.price} ج</p> <button data-id="${p.id}" class="add-btn">أضف للسلة</button> </div> `).join(""); } catch(err) { grid.innerHTML = `<p class="error">⚠️ ${err.message}</p>`; } } // ══ POST: إرسال بيانات ══ async function register(email, password, name) { const res = await fetch("/api/auth/register", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password, name }) }); const data = await res.json(); if (data.token) localStorage.setItem("token", data.token); return data; } // ══ طلب مع توكن المصادقة ══ async function getProfile() { const token = localStorage.getItem("token"); const res = await fetch("/api/me", { headers: { "Authorization": `Bearer ${token}` } }); return res.json(); } // ══ رفع صورة ══ async function uploadImage(file) { const form = new FormData(); form.append("image", file); const res = await fetch("/api/upload", { method:"POST", body: form }); return (await res.json()).url; } // ══ طلبات متوازية ══ const [user, posts, products] = await Promise.all([ fetch("/api/me").then(r => r.json()), fetch("/api/posts").then(r => r.json()), fetch("/api/products").then(r => r.json()), ]);
المرحلة الرابعة — Backend
🖥️ Node.js + Express — بناء السيرفر والـ API
هنا تعيش البيانات — السيرفر يستقبل الطلبات ويرد عليها بـ JSON
🔄 كيف يعمل Backend؟
المتصفح يرسل طلب ← السيرفر يستقبله ← يتحقق من هوية المستخدم ← يجلب البيانات من قاعدة البيانات ← يرد بـ JSON ← المتصفح يعرضها.
المتصفح يرسل طلب ← السيرفر يستقبله ← يتحقق من هوية المستخدم ← يجلب البيانات من قاعدة البيانات ← يرد بـ JSON ← المتصفح يعرضها.
إعداد المشروع — هيكل الملفات
Terminal — تهيئة مشروع Node
# إنشاء مشروع جديد mkdir my-backend && cd my-backend npm init -y # تنزيل المكتبات الأساسية npm install express # سيرفر الويب npm install mongoose # MongoDB npm install jsonwebtoken # JWT npm install bcryptjs # تشفير كلمات المرور npm install dotenv # متغيرات البيئة npm install cors # السماح للمتصفح بالتواصل npm install multer # رفع الملفات npm install -D nodemon # إعادة تشغيل تلقائي أثناء التطوير # هيكل المجلدات المثالي 📁 backend/ ├── 📄 server.js ← نقطة البداية ├── 📄 .env ← أسرار لا ترفعها على GitHub! ├── 📄 .gitignore ← node_modules و .env ├── 📁 config/ │ └── database.js ← إعداد قاعدة البيانات ├── 📁 models/ │ ├── User.js ← نموذج المستخدم │ ├── Post.js ← نموذج المنشور │ └── Product.js ← نموذج المنتج ├── 📁 routes/ │ ├── auth.js ← تسجيل الدخول │ ├── users.js │ └── posts.js ├── 📁 controllers/ │ ├── authController.js │ └── postController.js └── 📁 middleware/ ├── authMiddleware.js ← التحقق من التوكن └── upload.js
Express — السيرفر الكامل + CRUD
server.js — السيرفر الرئيسي
const express = require('express'); const cors = require('cors'); const dotenv = require('dotenv'); const connectDB = require('./config/database'); dotenv.config(); const app = express(); // Middleware app.use(cors({ origin: process.env.CLIENT_URL })); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use('/uploads', express.static('uploads')); // Routes app.use('/api/auth', require('./routes/auth')); app.use('/api/users', require('./routes/users')); app.use('/api/posts', require('./routes/posts')); app.use('/api/products', require('./routes/products')); // معالجة الأخطاء العامة app.use((err, req, res, next) => { console.error(err.stack); res.status(err.status || 500).json({ message: err.message }); }); const PORT = process.env.PORT || 5000; app.listen(PORT, async () => { await connectDB(); console.log(`✅ السيرفر يعمل على http://localhost:${PORT}`); });
routes/posts.js — CRUD كامل
const router = require('express').Router(); const Post = require('../models/Post'); const auth = require('../middleware/authMiddleware'); // GET /api/posts — كل المنشورات مع Pagination router.get('/', async (req, res) => { try { const { page=1, limit=10 } = req.query; const posts = await Post .find() .populate('author', 'name avatar') .sort({ createdAt: -1 }) .skip((page-1) * limit) .limit(Number(limit)); res.json(posts); } catch(err) { res.status(500).json({ message: err.message }); } }); // GET /api/posts/:id — منشور واحد router.get('/:id', async (req, res) => { const post = await Post.findById(req.params.id).populate('author'); if (!post) return res.status(404).json({ message: "غير موجود" }); res.json(post); }); // POST /api/posts — إنشاء منشور (مسجل فقط) router.post('/', auth, async (req, res) => { const { content, image } = req.body; const post = await Post.create({ content, image, author: req.userId }); await post.populate('author', 'name avatar'); res.status(201).json(post); }); // PUT /api/posts/:id/like — إعجاب / إلغاء router.put('/:id/like', auth, async (req, res) => { const post = await Post.findById(req.params.id); const liked = post.likes.includes(req.userId); liked ? post.likes.pull(req.userId) : post.likes.push(req.userId); await post.save(); res.json({ likes: post.likes.length, liked: !liked }); }); // DELETE /api/posts/:id router.delete('/:id', auth, async (req, res) => { const post = await Post.findById(req.params.id); if (post.author.toString() !== req.userId) return res.status(403).json({ message: "غير مصرح" }); await post.deleteOne(); res.json({ message: "تم الحذف" }); }); module.exports = router;
JWT — نظام تسجيل الدخول والمصادقة
authController.js + authMiddleware.js
// ═══ controllers/authController.js ═══ const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const User = require('../models/User'); exports.register = async (req, res) => { const { name, email, password } = req.body; if (await User.findOne({ email })) return res.status(400).json({ message: "البريد مستخدم" }); const hashed = await bcrypt.hash(password, 12); const user = await User.create({ name, email, password: hashed }); const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '7d' }); res.status(201).json({ token, user: { id: user._id, name, email } }); }; exports.login = async (req, res) => { const { email, password } = req.body; const user = await User.findOne({ email }); if (!user || !(await bcrypt.compare(password, user.password))) return res.status(401).json({ message: "بيانات غير صحيحة" }); const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '7d' }); res.json({ token, user: { id: user._id, name: user.name, role: user.role } }); }; // ═══ middleware/authMiddleware.js ═══ module.exports = async (req, res, next) => { try { const token = req.headers.authorization?.split(' ')[1]; // Bearer TOKEN if (!token) return res.status(401).json({ message: "سجّل دخولك أولاً" }); const decoded = jwt.verify(token, process.env.JWT_SECRET); req.userId = decoded.userId; next(); } catch { res.status(401).json({ message: "توكن غير صالح" }); } };
المرحلة الخامسة
🗄️ قواعد البيانات — أين تعيش بياناتك
MongoDB للبيانات المرنة — PostgreSQL للبيانات العلاقية
MongoDB + Mongoose
models/User.js + Post.js
const mongoose = require('mongoose'); // ═══ User Schema ═══ const userSchema = new mongoose.Schema({ name: { type: String, required: true, trim: true }, email: { type: String, required: true, unique: true, lowercase: true }, password: { type: String, required: true, minlength: 8, select: false }, avatar: { type: String, default: 'default.jpg' }, bio: { type: String, maxlength: 500 }, role: { type: String, enum: ['user','admin'], default: 'user' }, followers: [{ type: mongoose.Types.ObjectId, ref: 'User' }], following: [{ type: mongoose.Types.ObjectId, ref: 'User' }], isVerified: { type: Boolean, default: false } }, { timestamps: true }); // يضيف createdAt وupdatedAt تلقائياً module.exports = mongoose.model('User', userSchema); // ═══ Post Schema ═══ const postSchema = new mongoose.Schema({ author: { type: mongoose.Types.ObjectId, ref: 'User', required: true }, content: { type: String, required: true, maxlength: 2000 }, image: String, likes: [{ type: mongoose.Types.ObjectId, ref: 'User' }], comments: [{ user: { type: mongoose.Types.ObjectId, ref: 'User' }, text: { type: String, required: true }, createdAt: { type: Date, default: Date.now } }], views: { type: Number, default: 0 }, tags: [String] }, { timestamps: true }); postSchema.index({ content: 'text' }); // بحث نصي module.exports = mongoose.model('Post', postSchema);
MongoDB Queries — الاستعلامات
// جلب كل المنشورات const posts = await Post.find(); // جلب بشرط const myPosts = await Post.find({ author: userId }); // جلب مع populate (بيانات مرتبطة) const post = await Post.findById(id).populate('author', 'name avatar'); // فرز + pagination const data = await Post .find({ views: { $gt: 100 } }) // أكثر من 100 مشاهدة .sort({ createdAt: -1 }) .skip((page-1) * 10) .limit(10); // إنشاء const user = await User.create({ name, email, password }); // تحديث await User.findByIdAndUpdate(id, { name: "اسم جديد" }, { new: true }); // حذف await Post.findByIdAndDelete(id); // عدد const count = await Post.countDocuments({ author: userId }); // بحث نصي const results = await Post.find({ $text: { $search: "برمجة" } }); // Operators مهمة // $gt / $lt / $gte / $lte — أكبر / أصغر // $in — داخل مصفوفة // $or / $and — شروط متعددة // $push / $pull — إضافة/حذف من مصفوفة // $inc — زيادة رقم await Post.findByIdAndUpdate(id, { $inc: { views: 1 } });
PostgreSQL — SQL
SQL — الجداول والاستعلامات
-- إنشاء الجداول CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, password TEXT NOT NULL, role VARCHAR(20) DEFAULT 'user', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE products ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, price DECIMAL(10,2) NOT NULL, stock INTEGER DEFAULT 0, category_id INTEGER REFERENCES categories(id), image_url TEXT, created_at TIMESTAMP DEFAULT NOW() ); CREATE TABLE orders ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, total DECIMAL(10,2), status VARCHAR(50) DEFAULT 'pending', created_at TIMESTAMP DEFAULT NOW() ); -- CRUD SELECT * FROM products WHERE price < 500 ORDER BY price ASC LIMIT 10; SELECT p.name, c.name AS category FROM products p JOIN categories c ON p.category_id = c.id WHERE p.stock > 0; INSERT INTO users (name, email, password) VALUES ($1, $2, $3); UPDATE products SET stock = stock - 1 WHERE id = $1; DELETE FROM products WHERE id = $1;
التطبيق الحقيقي
🚀 كيف تبني مواقع ضخمة؟
معمارية + خطوات + كود حقيقي لكل مشروع — فيسبوك، يوتيوب، واتساب، متجر
موقع تواصل اجتماعي — مثل فيسبوك وإنستجرام
نشر محتوى، إعجاب، تعليق، متابعة، رسائل مباشرة
React.js
→
REST API
→
Node.js
→
MongoDB
+
Socket.io
+
Cloudinary
React.jsNode.jsMongoDB
JWTSocket.ioCloudinaryRedis
- 1المصادقة: تسجيل وتسجيل دخول بـ
JWT— الـ token يُحفظ في localStorage ويُرسل مع كل طلب في Header. - 2الملف الشخصي: صورة، اسم، بيو — رفع الصور عبر
Cloudinaryمجاناً (10GB في الخطة المجانية). - 3الجدار الزمني (Feed): جلب منشورات الأصدقاء مرتبة بالتاريخ —
Paginationلتحميل المزيد عند التمرير للأسفل. - 4الإعجاب والتعليق: مصفوفة
likes[]داخل Post Schema — Toggle بضغطة واحدة. التعليقات فيcomments[]. - 5المتابعة: مصفوفتا
followersوfollowingفي User Schema — قائمة مقترحات من خلال المتابَعين المشتركين. - 6الإشعارات اللحظية:
Socket.io— كل مستخدم له غرفة خاصة. يُرسل إشعار فور الإعجاب أو التعليق أو المتابعة. - 7الرسائل المباشرة: غرف محادثة بـ Socket.io — الرسائل تُحفظ في MongoDB للتاريخ.
Socket.io — إشعارات لحظية
const { Server } = require('socket.io'); const io = new Server(server, { cors: { origin: '*' } }); const online = {}; io.on('connection', socket => { // المستخدم ينضم لغرفته الخاصة socket.on('join', userId => { online[userId] = socket.id; socket.join(userId); }); // إرسال رسالة socket.on('sendMessage', ({ to, message }) => { io.to(to).emit('newMessage', { from: socket.userId, message, time: new Date() }); }); socket.on('disconnect', () => delete online[socket.userId]); }); // من أي route: أرسل إشعار بعد الإعجاب io.to(post.author.toString()).emit('notification', { type: 'like', from: likerName, postId: post._id });
منصة مشاركة فيديو — مثل يوتيوب وتيك توك
رفع وضغط وتشغيل الفيديوهات + نظام القنوات والتوصيات
React.js
→
Node.js
→
FFmpeg
→
AWS S3
+
PostgreSQL
+
Redis
React.jsNode.jsFFmpeg
AWS S3PostgreSQLRedisVideo.js
- 1رفع الفيديو: المستخدم يرفع الملف عبر
multipart/form-data— يُحفظ مؤقتاً على السيرفر ثم يُعالج. - 2المعالجة بـ FFmpeg: يحوّل لجودات متعددة (1080p, 720p, 480p) في Background Job بـ
Bull Queue. - 3التخزين على AWS S3: كل جودة ترفع كملف منفصل — رابط CDN يُعطى للمستخدم. البديل المجاني: Cloudinary.
- 4مشغل الفيديو:
Video.jsأو HLS.js — يغير الجودة تلقائياً حسب سرعة الإنترنت. - 5عداد المشاهدات:
Redisيعدّ سريعاً ثم يحدّث قاعدة البيانات كل دقيقة دفعةً واحدة. - 6التوصيات: بناءً على تصنيفات الفيديو، تاريخ المشاهدة، والكلمات المفتاحية — يمكن البدء بـ Collaborative Filtering.
FFmpeg — ضغط وتحويل الفيديو
const ffmpeg = require('fluent-ffmpeg'); async function processVideo(inputPath, videoId) { const qualities = [ { label:'1080p', height:1080, bitrate:'4000k' }, { label:'720p', height:720, bitrate:'2500k' }, { label:'480p', height:480, bitrate:'1000k' }, ]; for (const q of qualities) { await new Promise((res, rej) => { ffmpeg(inputPath) .outputOptions([`-vf scale=-2:${q.height}`, `-b:v ${q.bitrate}`]) .output(`uploads/${videoId}_${q.label}.mp4`) .on('end', res).on('error', rej).run(); }); } }
تطبيق تراسل فوري — مثل واتساب وتيليجرام
رسائل لحظية مشفرة، حالة القراءة، إشعارات Push
React/RN
↕ WS
Socket.io
→
Node.js
→
PostgreSQL
+
Redis
+
Firebase FCM
Socket.ioReact Native
PostgreSQLRedisE2E EncryptionFirebase FCM
- 1WebSocket: خلافاً لـ HTTP، يفتح قناة مستمرة ثنائية الاتجاه — السيرفر يرسل للعميل بدون طلب منه.
- 2غرف المحادثة: كل محادثة لها
room_idفريد — Socket.io يوجه الرسائل للغرفة الصحيحة فقط. - 3حالة القراءة ✓✓: عند فتح المحادثة يُرسل
markAsReadevent — يغير لون العلامة في جانب المرسل. - 4التشفير E2E: المفاتيح تُولّد على جهاز المستخدم — السيرفر يرى الرسائل مشفرة فقط ولا يعرف محتواها.
- 5الإشعارات Push:
Firebase Cloud Messagingيرسل إشعار لما يكون التطبيق مغلقاً أو الجهاز في وضع السكون. - 6الرسائل الصوتية: تسجيل بـ
MediaRecorder APIفي المتصفح — رفع الـ blob — تشغيل بمشغل مخصص.
متجر إلكتروني — مثل أمازون ونون
منتجات، سلة، دفع إلكتروني، إدارة طلبات
Next.js
→
Node.js API
→
PostgreSQL
+
Stripe
+
Redis Cache
Next.jsNode.jsPostgreSQL
StripePaymob (مصر)RedisPrisma
- 1صفحات المنتجات بـ SSR:
Next.jsيُنشئ HTML على السيرفر — جوجل يراه كاملاً (SEO ممتاز). - 2سلة التسوق: تُحفظ في
localStorageللزوار — وفي قاعدة البيانات للمسجلين — تُدمجان عند تسجيل الدخول. - 3الدفع بـ Stripe: ينشئ
Payment Intentعلى السيرفر — يرسل clientSecret للمتصفح — المتصفح يكمل الدفع. - 4Webhook للتأكيد: Stripe يرسل تأكيد الدفع لسيرفرك — هنا تُنشئ الطلب وتُرسل إيميل التأكيد للعميل.
- 5لوحة التحكم: إضافة منتجات، إدارة الطلبات، تغيير حالة الشحن، تقارير المبيعات اليومية.
- 6كوبونات الخصم: جدول
couponsفي قاعدة البيانات — تحقق من الصلاحية وتطبيق الخصم قبل الدفع.
Stripe — بوابة الدفع
// السيرفر: إنشاء نية الدفع const stripe = require('stripe')(process.env.STRIPE_SECRET); router.post('/payment-intent', auth, async (req, res) => { const amount = req.body.items.reduce((s,i) => s + i.price * i.qty, 0); const intent = await stripe.paymentIntents.create({ amount: Math.round(amount * 100), currency: 'egp', metadata: { userId: req.userId } }); res.json({ clientSecret: intent.client_secret }); }); // المتصفح: تأكيد الدفع const { error } = await stripe.confirmCardPayment(clientSecret, { payment_method: { card: cardElement, billing_details: { name, email } } }); if (!error) confirmOrder();
مرجع سريع
📋 قوائم النسخ الفورية
كل ما تحتاجه جاهزاً للنسخ بضغطة واحدة — ابدأ مشروعك الآن
🏗️ كل وسوم HTML التي ستستخدمها
<!DOCTYPE html>إلزامي — السطر الأول دائماً يخبر المتصفح أن هذا HTML5
<html lang="ar" dir="rtl">جذر الصفحة مع اللغة العربية والاتجاه
<meta charset="UTF-8">دعم العربية والحروف الخاصة — إلزامي
<meta name="viewport">موقع يعمل صح على الموبايل — إلزامي
<title>اسم الصفحة</title>عنوان تبويب المتصفح ونتائج جوجل
<link rel="stylesheet" href="">ربط ملف CSS خارجي
<h1> إلى <h6>العناوين — h1 مرة واحدة فقط في الصفحة
<p>فقرة</p>فقرة نصية — الأكثر استخداماً
<a href="" target="_blank">رابط — href الوجهة، target="_blank" تبويب جديد
<img src="" alt="">صورة — alt إلزامي للـ SEO وإمكانية الوصول
<div class="">حاوية block — لتجميع العناصر
<span class="">حاوية inline — داخل النص
<ul> <ol> <li>قوائم — ul نقاط، ol أرقام
<strong> <em> <mark>غامق، مائل، مظلل — تنسيق النص
<form action="" method="post">نموذج — action الوجهة، method طريقة الإرسال
<input type="text">أنواع: text, email, password, number, tel, date, file, checkbox, radio
<textarea rows="4">نص متعدد الأسطر
<select> <option>قائمة منسدلة
<button type="submit">زر — submit إرسال، reset مسح، button برمجي
<label for="">تسمية الحقل — for يربطها بـ id الحقل
<table> <thead> <tbody> <tr> <th> <td>جدول كامل
<video src="" controls>فيديو — controls, autoplay, muted, loop, poster
<audio src="" controls>مشغل صوت
<iframe src="">تضمين — يوتيوب، خرائط جوجل، مواقع
<header> <nav> <main> <section> <article> <aside> <footer>الوسوم الدلالية — لـ SEO وجوجل
<details> <summary>Accordion بدون JavaScript
<script src=""></script>ربط ملف JavaScript — في آخر body دائماً
🎨 CSS — الخصائص الأكثر استخداماً
color: #333لون النص
background: #fffلون الخلفية أو تدرج
font-size: 1remحجم الخط — rem, px, clamp()
font-weight: 700وزن الخط — 100 إلى 900
padding: 16pxمسافة داخلية
margin: 0 autoتوسيط أفقي
border-radius: 8pxتدوير الزوايا — 50% للدائرة
box-shadow: 0 4px 16px...ظل العنصر
display: flexتفعيل Flexbox
display: gridتفعيل Grid
position: fixedثابت في الشاشة عند التمرير
transition: all .3s easeانتقال سلس عند hover
transform: translateY(-4px)تحريك عند hover
@media (min-width: 768px)Responsive — تغيير حسب الشاشة
:root { --color: #007bff }CSS Variables للثيم
width: min(100%, 1200px)Container متجاوب
⚡ JavaScript — الأوامر اليومية
querySelector("#id")اختيار عنصر بالـ id أو الكلاس
querySelectorAll(".cls")اختيار كل العناصر
el.textContent = "نص"تغيير النص
el.innerHTML = "<b>"تغيير HTML داخل العنصر
el.classList.toggle("cls")يضيف أو يحذف كلاس
addEventListener("click", fn)استماع للأحداث
arr.map(x => ...)تحويل كل عنصر في المصفوفة
arr.filter(x => cond)تصفية المصفوفة بشرط
arr.find(x => cond)البحث عن أول عنصر
JSON.stringify / parseتحويل بين كائن ونص JSON
localStorage.setItemحفظ بيانات محلياً
async / await / fetchجلب بيانات من API
خطتك
🗺️ خارطة الطريق — من الصفر للاحتراف
خطوات مرتبة بالتسلسل الصح مع وقت تقديري
📌 القاعدة الذهبية: تعلم شيئاً صغيراً ثم طبّقه فوراً. لا تقرأ ساعات بدون تطبيق. كل درس = مشروع صغير تبنيه.
المرحلة 1 — أساس
HTML + CSS — بناء الواجهة
وسوم HTML، CSS الأساسي، Flexbox، Grid، التصميم المتجاوب.
مشاريع: صفحة Landing Page، CV رقمي، موقع مطعم بسيط.
مشاريع: صفحة Landing Page، CV رقمي، موقع مطعم بسيط.
⏱️ 4–6 أسابيع (ساعتان يومياً)
🏗️
المرحلة 2 — تفاعل
JavaScript الأساسي
المتغيرات، الدوال، DOM، الأحداث، LocalStorage.
مشاريع: قائمة مهام (Todo App)، آلة حاسبة، ساعة رقمية.
مشاريع: قائمة مهام (Todo App)، آلة حاسبة، ساعة رقمية.
⏱️ 6–8 أسابيع
⚡
المرحلة 3 — بيانات حقيقية
JS المتقدم + Fetch APIs + Git
Fetch API، async/await، JSON، REST APIs، Git وGitHub.
مشاريع: تطبيق طقس، قائمة أفلام من API حقيقي، موقع أخبار.
مشاريع: تطبيق طقس، قائمة أفلام من API حقيقي، موقع أخبار.
⏱️ 4–6 أسابيع
🌐
المرحلة 4 — Framework
React.js
Components، Props، State، Hooks، React Router، Context API.
مشاريع: متجر بسيط، لوحة إدارة، تطبيق ملاحظات.
مشاريع: متجر بسيط، لوحة إدارة، تطبيق ملاحظات.
⏱️ 8–10 أسابيع
⚛️
المرحلة 5 — Backend
Node.js + قاعدة بيانات
Node.js، Express، MongoDB أو PostgreSQL، JWT، REST API.
مشاريع: API كاملة للمدونة، نظام تسجيل وتسجيل دخول.
مشاريع: API كاملة للمدونة، نظام تسجيل وتسجيل دخول.
⏱️ 10–12 أسبوع
🗄️
المرحلة 6 — احتراف
Full Stack + النشر على الإنترنت
Next.js، Docker، CI/CD، استضافة مجانية Vercel وRailway.
المشروع النهائي: تطبيق كامل منشور على الإنترنت = Portfolio حقيقي!
المشروع النهائي: تطبيق كامل منشور على الإنترنت = Portfolio حقيقي!
⏱️ مستمر
🚀
✅ افعل دائماً:
ابنِ مشروعاً بعد كل درس. شارك كودك على GitHub. اسأل جوجل عن كل خطأ. الخطأ أفضل من مشاهدة الحل.
ابنِ مشروعاً بعد كل درس. شارك كودك على GitHub. اسأل جوجل عن كل خطأ. الخطأ أفضل من مشاهدة الحل.
❌ تجنب:
تعلم لغتين في نفس الوقت. نسخ الكود بدون فهم. الانتظار حتى "تجهز" قبل التطبيق. إهمال الأساسيات.
تعلم لغتين في نفس الوقت. نسخ الكود بدون فهم. الانتظار حتى "تجهز" قبل التطبيق. إهمال الأساسيات.
💡 تذكر:
فيسبوك بدأت بـ PHP بسيط. جوجل كانت مشروع بحث. كل مطور محترف كان يوماً مبتدئاً مثلك تماماً.
فيسبوك بدأت بـ PHP بسيط. جوجل كانت مشروع بحث. كل مطور محترف كان يوماً مبتدئاً مثلك تماماً.