diff --git a/CHANGELOG.md b/CHANGELOG.md index a678bb1..707e504 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ Формат основан на [Keep a Changelog](https://keepachangelog.com/). +## [1.4.0] — 2026-08-01 + +### Added +- Интерактивные квизы «Проверь себя» (4 вопроса/неделя, мгновенный feedback) +- Переключатель трека Полный / Лайт с фильтрацией блоков практики +- Карта прогресса на главной + умный «Продолжить» (первый незакрытый день) +- Экспорт `progress.json` для learning-log / gist +- Страница Changelog на сайте (`#changelog`) + ## [1.3.0] — 2026-08-01 ### Added diff --git a/README.md b/README.md index cc2b552..f22a6dc 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ 22 weeks 6-7h per day full-stack - v1.3.0 + v1.4.0

--- diff --git a/docs/app.js b/docs/app.js index 3f3063d..1f6ec89 100644 --- a/docs/app.js +++ b/docs/app.js @@ -11,7 +11,10 @@ const DAY_PROGRESS_KEY = 'web-roadmap-day-progress'; const READING_KEY = 'web-roadmap-reading'; const LAST_ROUTE_KEY = 'web-roadmap-last-route'; + const TRACK_KEY = 'web-roadmap-track'; + const QUIZ_KEY = 'web-roadmap-quiz'; const TOTAL_DAYS = 154; + const DAY_INDEX = ROUTES.dayIndex || []; const weekCache = {}; let currentRoute = ''; @@ -25,6 +28,48 @@ return ``; } + function getTrackMode() { + const v = localStorage.getItem(TRACK_KEY); + return v === 'lite' ? 'lite' : 'full'; + } + function setTrackMode(mode) { + localStorage.setItem(TRACK_KEY, mode === 'lite' ? 'lite' : 'full'); + syncTrackChips(); + applyTrackFilter(document); + } + function syncTrackChips() { + const mode = getTrackMode(); + $$('[data-track-mode]').forEach(btn => { + btn.classList.toggle('active', btn.getAttribute('data-track-mode') === mode); + }); + document.body.dataset.track = mode; + } + function applyTrackFilter(root = document) { + const mode = getTrackMode(); + $$('.practice-track', root).forEach(el => { + const track = el.getAttribute('data-track'); + el.hidden = mode === 'lite' ? track === 'full' : track === 'lite'; + }); + } + + function getQuizProgress() { + try { return JSON.parse(localStorage.getItem(QUIZ_KEY) || '{}'); } + catch { return {}; } + } + function setQuizScore(weekId, score, total) { + const p = getQuizProgress(); + p[weekId] = { score, total, ts: Date.now() }; + localStorage.setItem(QUIZ_KEY, JSON.stringify(p)); + } + + function findNextIncomplete() { + const days = getDayProgress(); + for (const d of DAY_INDEX) { + if (!days[d.id]) return d; + } + return null; + } + function getProgress() { try { return JSON.parse(localStorage.getItem(PROGRESS_KEY) || '{}'); } catch { return {}; } @@ -36,6 +81,7 @@ updateProgressUI(); updateCards(); updateResumeBanner(); + renderProgressMap(); } function toggleWeekDone(id) { const p = getProgress(); @@ -66,7 +112,24 @@ const metaEl = $('#resume-meta'); if (!banner || !link) return; + const next = findNextIncomplete(); const last = getLastRoute(); + + if (next) { + banner.hidden = false; + if (titleEl) titleEl.textContent = 'Продолжить обучение'; + if (metaEl) metaEl.textContent = `${next.weekTitle}: ${next.label}`; + link.href = `#${next.week}--${next.id}`; + link.setAttribute('data-route', next.week); + const cta = $('#cta-start'); + if (cta) { + cta.textContent = 'Продолжить'; + cta.href = `#${next.week}--${next.id}`; + cta.setAttribute('data-route', next.week); + } + return; + } + if (!last?.route) { banner.hidden = true; return; @@ -74,17 +137,46 @@ const weekTitle = ROUTES.weeks?.[last.route] || last.title || last.route; banner.hidden = false; - if (titleEl) titleEl.textContent = 'Продолжить обучение'; - if (metaEl) { - metaEl.textContent = last.anchor - ? `${weekTitle} · ${last.anchor.replace(/^week-\d{2}-/, '').replace(/-/g, ' ')}` - : weekTitle; - } + if (titleEl) titleEl.textContent = 'Курс пройден — повторить'; + if (metaEl) metaEl.textContent = weekTitle; const hash = last.anchor ? `${last.route}--${last.anchor}` : last.route; link.href = `#${hash}`; link.setAttribute('data-route', last.route); } + function renderProgressMap() { + const grid = $('#progress-map-grid'); + const sub = $('#progress-map-sub'); + if (!grid) return; + const daysDone = getDayProgress(); + const weeksDone = getProgress(); + const byWeek = {}; + DAY_INDEX.forEach(d => { + if (!byWeek[d.week]) byWeek[d.week] = []; + byWeek[d.week].push(d); + }); + const next = findNextIncomplete(); + let stuckLabel = next ? `Следующий шаг: ${next.weekTitle} · ${next.label}` : 'Все дни отмечены — можно ревьюить слабые места'; + if (sub) sub.textContent = stuckLabel; + + grid.innerHTML = WEEK_IDS.map(wid => { + const days = byWeek[wid] || []; + const doneCount = days.filter(d => daysDone[d.id]).length; + const weekDone = !!weeksDone[wid]; + const title = ROUTES.weeks?.[wid] || wid; + const dots = days.map(d => { + const done = !!daysDone[d.id]; + const isNext = next && next.id === d.id; + return ``; + }).join(''); + return `
+ ${wid.replace('week-', '')}. ${title} +
${dots || ''}
+ ${doneCount}/${days.length || '—'} +
`; + }).join(''); + } + function getDayProgress() { try { return JSON.parse(localStorage.getItem(DAY_PROGRESS_KEY) || '{}'); } catch { return {}; } @@ -94,21 +186,43 @@ if (done) p[dayId] = Date.now(); else delete p[dayId]; localStorage.setItem(DAY_PROGRESS_KEY, JSON.stringify(p)); updateProgressUI(); + updateResumeBanner(); + renderProgressMap(); } function exportProgress() { return JSON.stringify({ weeks: getProgress(), days: getDayProgress(), + quizzes: getQuizProgress(), + track: getTrackMode(), + exportedAt: new Date().toISOString(), + version: 2, + }, null, 2); + } + function exportLearningLogPayload() { + const next = findNextIncomplete(); + return JSON.stringify({ + schema: 'web-roadmap/learning-log-progress', + version: 2, exportedAt: new Date().toISOString(), - version: 1, + track: getTrackMode(), + resume: next ? { week: next.week, day: next.id, label: next.label } : null, + weeks: getProgress(), + days: getDayProgress(), + quizzes: getQuizProgress(), + tip: 'Положите этот файл в learning-log/progress.json и коммитьте раз в неделю.', }, null, 2); } function importProgress(json) { const data = typeof json === 'string' ? JSON.parse(json) : json; if (data.weeks) localStorage.setItem(PROGRESS_KEY, JSON.stringify(data.weeks)); if (data.days) localStorage.setItem(DAY_PROGRESS_KEY, JSON.stringify(data.days)); + if (data.quizzes) localStorage.setItem(QUIZ_KEY, JSON.stringify(data.quizzes)); + if (data.track) setTrackMode(data.track); updateProgressUI(); updateCards(); + updateResumeBanner(); + renderProgressMap(); } function updateProgressUI() { @@ -392,6 +506,86 @@ container.appendChild(script); } + function renderQuizBlock(quizzes, weekId) { + if (!quizzes?.length) return ''; + const saved = getQuizProgress()[weekId]; + const header = saved + ? `

Прошлый результат: ${saved.score}/${saved.total}

` + : ''; + const items = quizzes.map((q, qi) => { + const opts = (q.options || []).map((o, oi) => + `` + ).join(''); + return `
+

${qi + 1} ${q.q}

+
${opts}
+ +
`; + }).join(''); + return `
+

${icon('quiz')} Интерактивный тест

+

Выберите ответ — feedback сразу. Можно пройти заново.

+ ${header} + ${items} + + +
`; + } + + function setupQuizzes(root, weekId, quizzes) { + const block = root.querySelector('.quiz-block'); + if (!block || !quizzes?.length) return; + const state = quizzes.map(() => null); + const scoreEl = block.querySelector('.quiz-score'); + const resetBtn = block.querySelector('.quiz-reset'); + + function finishIfDone() { + if (state.some(s => s === null)) return; + const score = state.filter(Boolean).length; + setQuizScore(weekId, score, quizzes.length); + if (scoreEl) { + scoreEl.hidden = false; + scoreEl.textContent = `Итого: ${score} / ${quizzes.length}`; + scoreEl.className = 'quiz-score ' + (score === quizzes.length ? 'perfect' : score >= quizzes.length * 0.7 ? 'good' : 'retry'); + } + if (resetBtn) resetBtn.hidden = false; + } + + block.addEventListener('click', e => { + const btn = e.target.closest('.quiz-opt'); + if (!btn || btn.disabled) return; + const qi = +btn.dataset.q; + const ok = btn.dataset.ok === '1'; + const item = block.querySelector(`.quiz-item[data-qi="${qi}"]`); + if (!item || state[qi] !== null) return; + state[qi] = ok; + item.querySelectorAll('.quiz-opt').forEach(b => { + b.disabled = true; + if (b.dataset.ok === '1') b.classList.add('correct'); + if (b === btn && !ok) b.classList.add('wrong'); + }); + const fb = item.querySelector('.quiz-feedback'); + const explain = quizzes[qi].explain || ''; + if (fb) { + fb.hidden = false; + fb.className = 'quiz-feedback ' + (ok ? 'ok' : 'bad'); + fb.textContent = (ok ? 'Верно. ' : 'Неверно. ') + explain; + } + finishIfDone(); + }); + + resetBtn?.addEventListener('click', () => { + const wrap = block.parentElement; + if (!wrap) return; + const fresh = renderQuizBlock(quizzes, weekId); + const tmp = document.createElement('div'); + tmp.innerHTML = fresh; + const next = tmp.firstElementChild; + block.replaceWith(next); + setupQuizzes(wrap, weekId, quizzes); + }); + } + function renderWeekHub(data, routeId) { const sections = lessonSections(data); const daysDone = getDayProgress(); @@ -433,6 +627,7 @@ if (content) { content.innerHTML = `
${data.html}
`; highlightCode(content); + applyTrackFilter(content); } updateMarkDoneBtn(routeId); updateMarkDayBtn(null); @@ -441,15 +636,14 @@ const bar = $('#lesson-next'); if (bar) bar.hidden = true; loadGiscus(null); - $('#comments-block').hidden = true; + const comments = $('#comments-block'); + if (comments) comments.hidden = true; window.scrollTo(0, 0); return; } - // Week: open specific lesson or hub let section = anchor ? sections.find(s => s.id === anchor) : null; if (!section && !anchor && sections.length) { - // Default: first day (separate page UX) — redirect hash const first = sections.find(s => s.kind === 'day') || sections[0]; if (first && location.hash !== `#${routeId}--${first.id}`) { history.replaceState(null, '', `#${routeId}--${first.id}`); @@ -459,7 +653,6 @@ } if (!section) { - // Hub fallback if (title) title.textContent = pageTitle; document.title = `${pageTitle} · web-roadmap`; if (subtitle) { @@ -468,7 +661,10 @@ } updateBreadcrumb(data.title || pageTitle, { label: 'Оглавление' }); if (tocEl) tocEl.innerHTML = buildToc(sections, routeId, ''); - if (content) content.innerHTML = renderWeekHub(data, routeId); + if (content) { + content.innerHTML = renderWeekHub(data, routeId); + applyTrackFilter(content); + } updateMarkDoneBtn(routeId); updateMarkDayBtn(null); updateGithubToolbar(routeId, '', data); @@ -491,11 +687,14 @@ updateBreadcrumb(data.title || pageTitle, section); if (tocEl) tocEl.innerHTML = buildToc(sections, routeId, section.id); if (content) { - const intro = section.kind === 'day' && data.introHtml && sections[0]?.id === section.id - ? '' // keep day clean; intro only on hub - : ''; - content.innerHTML = `
${intro}${html}
`; + let body = html; + if (section.kind === 'review' && data.quizzes?.length) { + body = html + renderQuizBlock(data.quizzes, routeId); + } + content.innerHTML = `
${body}
`; highlightCode(content); + applyTrackFilter(content); + if (section.kind === 'review') setupQuizzes(content, routeId, data.quizzes || []); } updateMarkDoneBtn(routeId); updateMarkDayBtn(section); @@ -528,6 +727,7 @@ document.title = 'web-roadmap — Full-Stack за 22 недели'; updateCards(); updateResumeBanner(); + renderProgressMap(); return; } @@ -623,7 +823,6 @@ } function initGithubFeatures() { - // Live star count fetch(`https://api.github.com/repos/${REPO}`) .then(r => r.ok ? r.json() : null) .then(data => { @@ -636,22 +835,34 @@ }) .catch(() => {}); - $('#progress-export-btn')?.addEventListener('click', async () => { + async function copyProgress() { const json = exportProgress(); try { await navigator.clipboard.writeText(json); - alert('Прогресс скопирован в буфер. Сохраните в learning-log/progress.json'); + alert('Прогресс скопирован. Сохраните в learning-log/progress.json'); } catch { - const blob = new Blob([json], { type: 'application/json' }); - const a = document.createElement('a'); - a.href = URL.createObjectURL(blob); - a.download = 'web-roadmap-progress.json'; - a.click(); + downloadText('web-roadmap-progress.json', json); } + } + + function downloadText(name, text) { + const blob = new Blob([text], { type: 'application/json' }); + const a = document.createElement('a'); + a.href = URL.createObjectURL(blob); + a.download = name; + a.click(); + URL.revokeObjectURL(a.href); + } + + $$('#progress-export-btn').forEach(btn => btn.addEventListener('click', copyProgress)); + + $('#export-learning-log-btn')?.addEventListener('click', () => { + downloadText('progress.json', exportLearningLogPayload()); + alert('Скачан progress.json — положите в learning-log/ и сделайте коммит.\nИли создайте private gist на gist.github.com и вставьте JSON.'); }); const fileInput = $('#progress-import-file'); - $('#progress-import-btn')?.addEventListener('click', () => fileInput?.click()); + $$('#progress-import-btn').forEach(btn => btn.addEventListener('click', () => fileInput?.click())); fileInput?.addEventListener('change', async () => { const file = fileInput.files?.[0]; if (!file) return; @@ -675,6 +886,15 @@ }); } + function initTrackToggle() { + syncTrackChips(); + document.addEventListener('click', e => { + const btn = e.target.closest('[data-track-mode]'); + if (!btn) return; + setTrackMode(btn.getAttribute('data-track-mode')); + }); + } + document.addEventListener('click', e => { const a = e.target.closest('[data-route]'); if (a) { @@ -701,11 +921,13 @@ updateProgressUI(); updateCards(); updateResumeBanner(); + renderProgressMap(); initSearch(); initReadingMode(); initPhaseFilters(); initBurger(); initGithubFeatures(); + initTrackToggle(); route(); window.webRoadmapProgress = { export: exportProgress, import: importProgress }; diff --git a/docs/d/00-0-1.html b/docs/d/00-0-1.html index e95f334..9eb279a 100644 --- a/docs/d/00-0-1.html +++ b/docs/d/00-0-1.html @@ -26,7 +26,7 @@

Теория

Частая ошибка новичков — писать код без Git «чтобы не тратить время на настройку», откладывая репозиторий «на потом, когда будет что показать». Тогда первые недели прогресса нигде не задокументированы. Такая же ошибка — отлаживать вёрстку методом «поменял файл — обновил страницу — посмотрел», хотя Elements с редактированием стилей на лету делает это быстрее.

Ключевая мысль: стабильная среда важнее скорости «сразу писать код» — сегодняшняя практика единственный раз в маршруте посвящена только настройке, чтобы дальше ничего не отвлекало от обучения.

Читать: Как начать — таблица инструментов.

-

Практика (полный трек)

+

Практика (полный трек)

  1. Установи VS Code, Chrome (или Chromium), Git
  2. В VS Code: Live Server, GitLens, ESLint, Prettier, Error Lens
  3. @@ -34,7 +34,7 @@

    Практика (полный трек)

  4. Node.js LTS можно поставить сейчас или перед неделей 11; Python — перед 15; Docker — перед 21
  5. Открой DevTools (F12 / ⌥⌘I) → Elements, Console, Network — кликни по каждой вкладке
-

Практика (лайт / MVP)

+

Практика (лайт / MVP)

  1. VS Code + Git + Chrome
  2. Live Server + одно расширение на выбор
  3. @@ -43,7 +43,7 @@

    Практика (лайт / MVP)

    Лайт-DoD: редактор, браузер с DevTools и Git установлены.

    -

    Если застрял

    +

Если застрял

Установка зависла — перезапусти установщик, проверь PATH (echo $PATH / «Переменные среды» на Windows). Git «не найден» после установки — закрой и открой терминал заново.


diff --git a/docs/d/00-0-2.html b/docs/d/00-0-2.html index 78c6620..d37d6af 100644 --- a/docs/d/00-0-2.html +++ b/docs/d/00-0-2.html @@ -25,7 +25,7 @@

Теория

Почему это важно для всего маршрута: начиная с недели 1 каждый день заканчивается коммитом в эту же папку. Если репозиторий настроен неправильно сегодня — с чужой историей или без .gitignore — проблему придётся решать посреди недели 1, отвлекаясь от HTML.

Частое заблуждение — думать, что показывать портфолио стоит только после «идеального» результата, поэтому можно закоммитить всё одним большим коммитом в конце. На деле частые маленькие коммиты с понятными сообщениями (feat: add contact form, а не fix) сами по себе сигнал профессионализма — и заметны раньше, чем содержимое кода.

Ключевая мысль: репозиторий появляется до первой строки HTML — сегодняшняя практика это подтверждает: вы создаёте learning-log, .gitignore и README.md ещё до того, как напишете хоть один тег.

-

Практика (полный трек)

+

Практика (полный трек)

  1. Аккаунт GitHub (если нет) + 2FA по возможности
  2. New repository → имя learning-log → Public → без README / .gitignore / license
  3. @@ -45,7 +45,7 @@

    Практика (полный трек)

    1. Создайте минимальный README.md: название, цель («прохожу web-roadmap»), ссылка на https://github.com/krwg/web-roadmap — закоммитьте
    -

    Практика (лайт / MVP)

    +

Практика (лайт / MVP)

  1. Создать пустой learning-log под своим аккаунтом
  2. Clone → .gitignore → первый push
  3. @@ -53,7 +53,7 @@

    Практика (лайт / MVP)

    Лайт-DoD: репозиторий виден на github.com/ваш-логин/learning-log

    -

    Если застрял

    +

Если застрял

Permission denied / auth — используйте HTTPS + Personal Access Token или GitHub CLI (gh auth login). Ветка называется master вместо main — переименуйте: git branch -M main.


diff --git a/docs/d/00-0-3.html b/docs/d/00-0-3.html index 573ba7a..ce7f63a 100644 --- a/docs/d/00-0-3.html +++ b/docs/d/00-0-3.html @@ -57,7 +57,7 @@

Теория

Читать: - Введение - Каталог 22 проектов

-

Практика (полный трек)

+

Практика (полный трек)

  1. Прочитай introduction и обзор проектов
  2. В learning-log создай journal.md — цель на 22 недели одним абзацем
  3. @@ -65,12 +65,12 @@

    Практика (полный трек)

  4. Выбери трек (полный / лайт) и запиши выбор в journal
  5. Коммит: chore: add learning journal
-

Практика (лайт / MVP)

+

Практика (лайт / MVP)

  1. Прочитай introduction (хотя бы разделы «для кого» и «как устроен день»)
  2. journal.md с целью + закладка на сайт
-

Если застрял

+

Если застрял

Не знаете, полный или лайт — начните лайт на 3 дня. Если стабильно укладываетесь с запасом — переключитесь на полный со следующей недели.


diff --git a/docs/d/01-0.html b/docs/d/01-0.html index c8ae1e7..f868686 100644 --- a/docs/d/01-0.html +++ b/docs/d/01-0.html @@ -29,7 +29,7 @@

Теория

Ключевая мысль: коммит — это именованный снимок проекта, а не просто «сохранить файл»; сегодняшняя практика — прогнать этот цикл от установки Git до первого git push вручную, чтобы завтра, в день 1, писать index.html и коммитить его уже не задумываясь о механике.

Читать: - Pro Git: Введение — зачем VCS: история, откат, ветки

-

Практика (полный трек)

+

Практика (полный трек)

  1. Установи Git, проверь: git --version
  2. Настрой имя и email (они попадут в каждый коммит):
  3. @@ -56,10 +56,10 @@

    Практика (полный трек)

    - [ ] git status работает в папке learning-log - [ ] Репозиторий виден на GitHub - [ ] .gitignore закоммичен

    -

    Если застрял

    +

Если застрял

Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.


-

Практика (лайт / MVP)

+

Практика (лайт / MVP)

  1. Установи Git, проверь: git --version
  2. Настрой имя и email (они попадут в каждый коммит):
  3. @@ -68,7 +68,8 @@

    Практика (лайт / MVP)

Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

-
+ +
diff --git a/docs/d/01-1.html b/docs/d/01-1.html index e846e5a..8a56fa8 100644 --- a/docs/d/01-1.html +++ b/docs/d/01-1.html @@ -29,7 +29,7 @@

Теория

Ключевая мысль: HTML описывает структуру и смысл; браузер из неё строит DOM-дерево, а CSS и JS лишь надстраиваются сверху.

Читать: - MDN: Введение в HTML — разметка описывает смысл, браузер строит DOM-дерево

-

Практика (полный трек)

+

Практика (полный трек)

  1. В learning-log создай папку week-01/
  2. Файл week-01/index.html — корректный DOCTYPE, lang="ru", meta charset="UTF-8", viewport
  3. @@ -44,7 +44,7 @@

    Практика (полный трек)

    - [ ] Валидный HTML - [ ] Один h1, логичные h2 - [ ] У img есть alt

    -

    Практика (лайт / MVP)

    +

Практика (лайт / MVP)

  1. В learning-log создай папку week-01/
  2. Файл week-01/index.html — корректный DOCTYPE, lang="ru", meta charset="UTF-8", viewport
  3. @@ -54,7 +54,7 @@

    Практика (лайт / MVP)

    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

    -

    Если застрял

    +

Если застрял

Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

Git

cd learning-log
diff --git a/docs/d/01-2.html b/docs/d/01-2.html
index 0eec2c8..81c64e2 100644
--- a/docs/d/01-2.html
+++ b/docs/d/01-2.html
@@ -29,7 +29,7 @@ 

Теория

Ключевая мысль: правильный тег — это документация для людей и машин; div — последний выбор, не первый.

Читать: - MDN: Семантика — тег несёт смысл для браузера, скринридера, SEO

-

Практика (полный трек)

+

Практика (полный трек)

  1. Рефакторинг index.html: убери «суп из div», введи header, nav, main, section, footer
  2. article — мини-пост «Почему я учу веб» с time
  3. @@ -41,7 +41,7 @@

    Практика (полный трек)

    - [ ] Один main на страницу - [ ] nav только для навигации - [ ] Структура читается без CSS

    -

    Практика (лайт / MVP)

    +

Практика (лайт / MVP)

  1. Рефакторинг index.html: убери «суп из div», введи header, nav, main, section, footer
  2. article — мини-пост «Почему я учу веб» с time
  3. @@ -50,7 +50,7 @@

    Практика (лайт / MVP)

    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

    -

    Если застрял

    +

Если застрял

Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

Git

git add week-01/index.html
diff --git a/docs/d/01-3.html b/docs/d/01-3.html
index c87c2d2..311b53d 100644
--- a/docs/d/01-3.html
+++ b/docs/d/01-3.html
@@ -30,7 +30,7 @@ 

Теория

Читать: - MDN: Изображения в HTML - MDN: Responsive images

-

Практика (полный трек)

+

Практика (полный трек)

  1. week-01/about.html, week-01/gallery.html — единый header/nav/footer
  2. Относительные ссылки между страницами + якоря #section-id
  3. @@ -43,7 +43,7 @@

    Практика (полный трек)

    - [ ] Нет битых ссылок - [ ] Внешние ссылки с rel="noopener noreferrer" - [ ] aria-current на активном пункте nav

    -

    Практика (лайт / MVP)

    +

Практика (лайт / MVP)

  1. week-01/about.html, week-01/gallery.html — единый header/nav/footer
  2. Относительные ссылки между страницами + якоря #section-id
  3. @@ -52,7 +52,7 @@

    Практика (лайт / MVP)

    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

    -

    Если застрял

    +

Если застрял

Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

Git

git add week-01/
diff --git a/docs/d/01-4.html b/docs/d/01-4.html
index 3cc4891..d0e43e8 100644
--- a/docs/d/01-4.html
+++ b/docs/d/01-4.html
@@ -29,7 +29,7 @@ 

Теория

Ключевая мысль: каждое поле — с видимым label; name — имя данных при отправке, а не декоративный атрибут.

Читать: - MDN: Your first form

-

Практика (полный трек)

+

Практика (полный трек)

  1. На contact.html — форма: имя, email, тема (select), сообщение (textarea)
  2. Radio «Способ связи», checkbox «Согласие» с required
  3. @@ -41,7 +41,7 @@

    Практика (полный трек)

    - [ ] Все поля с labels - [ ] Radio с общим name - [ ] email type даёт нативную валидацию

    -

    Практика (лайт / MVP)

    +

Практика (лайт / MVP)

  1. На contact.html — форма: имя, email, тема (select), сообщение (textarea)
  2. Radio «Способ связи», checkbox «Согласие» с required
  3. @@ -50,7 +50,7 @@

    Практика (лайт / MVP)

    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

    -

    Если застрял

    +

Если застрял

Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

Git

git add week-01/contact.html week-01/
diff --git a/docs/d/01-5.html b/docs/d/01-5.html
index 150c903..7d8648a 100644
--- a/docs/d/01-5.html
+++ b/docs/d/01-5.html
@@ -29,7 +29,7 @@ 

Теория

Ключевая мысль: placeholder — подсказка, label — подпись; не путай их роли, и не путай клиентскую валидацию с настоящей защитой данных.

Читать: - MDN: Form validation

-

Практика (полный трек)

+

Практика (полный трек)

  1. Форма регистрации на отдельной секции или register.html
  2. Пароль minlength="8", логин pattern="[A-Za-z0-9_]{3,20}"
  3. @@ -41,7 +41,7 @@

    Практика (полный трек)

    - [ ] Нативная валидация без JS - [ ] placeholder не единственная подпись - [ ] Понятные title у полей с pattern

    -

    Практика (лайт / MVP)

    +

Практика (лайт / MVP)

  1. Форма регистрации на отдельной секции или register.html
  2. Пароль minlength="8", логин pattern="[A-Za-z0-9_]{3,20}"
  3. @@ -50,7 +50,7 @@

    Практика (лайт / MVP)

    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

    -

    Если застрял

    +

Если застрял

Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

Git

git add week-01/
diff --git a/docs/d/01-6.html b/docs/d/01-6.html
index 9f18080..c4260db 100644
--- a/docs/d/01-6.html
+++ b/docs/d/01-6.html
@@ -29,7 +29,7 @@ 

Теория

Ключевая мысль: если страницу нельзя пройти Tab-ом — она недоступна, даже с идеальным дизайном; сегодняшний аудит A11Y.md — тренировка смотреть на свою вёрстку глазами другого пользователя.

Читать: - web.dev: Learn Accessibility — POUR: Perceivable, Operable, Understandable, Robust

-

Практика (полный трек)

+

Практика (полный трек)

  1. Пройди все страницы только Tab/Enter/Space
  2. Skip-link в начале body на каждой странице
  3. @@ -41,7 +41,7 @@

    Практика (полный трек)

    - [ ] Skip-link работает - [ ] Видимый :focus-visible на ссылках - [ ] Lighthouse ≥ 90

    -

    Практика (лайт / MVP)

    +

Практика (лайт / MVP)

  1. Пройди все страницы только Tab/Enter/Space
  2. Skip-link в начале body на каждой странице
  3. @@ -50,7 +50,7 @@

    Практика (лайт / MVP)

    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

    -

    Если застрял

    +

Если застрял

Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

Git

git add week-01/
diff --git a/docs/d/01-7.html b/docs/d/01-7.html
index 0bdb14a..6e96987 100644
--- a/docs/d/01-7.html
+++ b/docs/d/01-7.html
@@ -28,7 +28,7 @@ 

Теория

Ключевая мысль: таблица = данные с заголовками; для сетки страницы — CSS, не <table>, а для видимости в поиске и мессенджерах — метаданные, а не только красивый дизайн.

Читать: - MDN: Tablesth scope="col|row", caption

-

Практика (полный трек)

+

Практика (полный трек)

  1. Таблица «План обучения» (неделя, тема, статус) на index.html
  2. Уникальные title и description на каждой странице
  3. @@ -41,7 +41,7 @@

    Практика (полный трек)

    - [ ] Таблица с thead/tbody/th - [ ] Все страницы валидны - [ ] Проект недели выполнен

    -

    Практика (лайт / MVP)

    +

Практика (лайт / MVP)

  1. Таблица «План обучения» (неделя, тема, статус) на index.html
  2. Уникальные title и description на каждой странице
  3. @@ -50,7 +50,7 @@

    Практика (лайт / MVP)

    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

    -

    Если застрял

    +

Если застрял

Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

Git

git add week-01/
diff --git a/docs/d/02-1.html b/docs/d/02-1.html
index 5aec672..5343d96 100644
--- a/docs/d/02-1.html
+++ b/docs/d/02-1.html
@@ -29,7 +29,7 @@ 

Теория

Ключевая мысль: внешний CSS + селекторы по классу — основа поддерживаемых стилей, и сегодняшняя практика с :hover/:focus-visible/:nth-child() — это тренировка думать в терминах «состояние + класс», а не «id под каждый частный случай».

Читать: - MDN: CSS first steps — inline, <style>, внешний файл

-

Практика (полный трек)

+

Практика (полный трек)

  1. Создай styles.css и подключи к HTML из недели 1
  2. Стилизуй навигацию: базовый вид, :hover, :focus-visible
  3. @@ -43,7 +43,7 @@

    Практика (полный трек)

    - [ ] CSS вынесен во внешний файл, нет inline-стилей в HTML - [ ] Использованы минимум 3 типа селекторов - [ ] Состояния :hover и :focus-visible различимы

    -

    Практика (лайт / MVP)

    +

Практика (лайт / MVP)

  1. Создай styles.css и подключи к HTML из недели 1
  2. Стилизуй навигацию: базовый вид, :hover, :focus-visible
  3. @@ -53,7 +53,7 @@

    Практика (лайт / MVP)

    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

    -

    Если застрял

    +

Если застрял

UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

Git

    diff --git a/docs/d/02-2.html b/docs/d/02-2.html index a056e4b..beda832 100644 --- a/docs/d/02-2.html +++ b/docs/d/02-2.html @@ -29,7 +29,7 @@

    Теория

    Ключевая мысль: каскад — не баг, а механизм разрешения конфликтов; специфичность — его валюта, и сегодняшняя практика с ручным вычислением специфичности трёх селекторов — тренировка читать эту «валюту» без обращения к DevTools.

    Читать: - MDN: Cascade and inheritance

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Создай конфликт специфичности: стилизуй p тремя способами, предскажи результат
    2. Проверь предсказание в браузере, зафиксируй в комментарии CSS
    3. @@ -43,7 +43,7 @@

      Практика (полный трек)

      - [ ] Могу объяснить, какое правило победит в конфликте - [ ] Нет !important без веской причины - [ ] Наследование используется осознанно

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Создай конфликт специфичности: стилизуй p тремя способами, предскажи результат
    2. Проверь предсказание в браузере, зафиксируй в комментарии CSS
    3. @@ -53,7 +53,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

    Git

      diff --git a/docs/d/02-3.html b/docs/d/02-3.html index abfd1d1..5be1e47 100644 --- a/docs/d/02-3.html +++ b/docs/d/02-3.html @@ -29,7 +29,7 @@

      Теория

      Ключевая мысль: border-box + понимание margin collapse = контроль над размерами без магии, а не жонглирование случайными пикселями до тех пор, пока «не встанет на место».

      Читать: - MDN: Box model

      -

      Практика (полный трек)

      +

      Практика (полный трек)

      1. Нарисуй на бумаге box model для карточки, затем сверстай её
      2. Примени box-sizing: border-box глобально через *, *::before, *::after
      3. @@ -43,7 +43,7 @@

        Практика (полный трек)

        - [ ] border-box подключён глобально - [ ] Карточки визуально одинаковой ширины при разном padding - [ ] Понимаю разницу inline vs inline-block

        -

        Практика (лайт / MVP)

        +

      Практика (лайт / MVP)

      1. Нарисуй на бумаге box model для карточки, затем сверстай её
      2. Примени box-sizing: border-box глобально через *, *::before, *::after
      3. @@ -53,7 +53,7 @@

        Практика (лайт / MVP)

        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

        -

        Если застрял

        +

      Если застрял

      Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

      Git

        diff --git a/docs/d/02-4.html b/docs/d/02-4.html index 7e4f768..f77c576 100644 --- a/docs/d/02-4.html +++ b/docs/d/02-4.html @@ -30,7 +30,7 @@

        Теория

        Читать: - MDN: Typography - web.dev: Learn Typography — вертикальный ритм

        -

        Практика (полный трек)

        +

        Практика (полный трек)

        1. Подключи пару шрифтов (заголовки + текст) через Google Fonts
        2. Задай базовый font-size: 16px, line-height: 1.6 для body
        3. @@ -44,7 +44,7 @@

          Практика (полный трек)

          - [ ] Текст читаем на мобильном и десктопе - [ ] Не более 2–3 семейств шрифтов на странице - [ ] line-height задан для основного текста

          -

          Практика (лайт / MVP)

          +

        Практика (лайт / MVP)

        1. Подключи пару шрифтов (заголовки + текст) через Google Fonts
        2. Задай базовый font-size: 16px, line-height: 1.6 для body
        3. @@ -54,7 +54,7 @@

          Практика (лайт / MVP)

          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

          -

          Если застрял

          +

        Если застрял

        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

        Git

          diff --git a/docs/d/02-5.html b/docs/d/02-5.html index 7c330b0..c60b882 100644 --- a/docs/d/02-5.html +++ b/docs/d/02-5.html @@ -29,7 +29,7 @@

          Теория

          Ключевая мысль: rgba для полупрозрачного фона, opacity — когда прозрачным должен быть весь блок целиком, а системная палитра сегодня — фундамент для темизации завтра.

          Читать: - MDN color

          -

          Практика (полный трек)

          +

          Практика (полный трек)

          1. Создай hero-секцию с градиентным фоном и полупрозрачным оверлеем
          2. Стилизуй кнопки: обычное, hover, active состояния с плавным переходом цвета
          3. @@ -43,7 +43,7 @@

            Практика (полный трек)

            - [ ] Контраст текста соответствует WCAG AA - [ ] Градиент не мешает читаемости - [ ] Кнопки имеют distinct states

            -

            Практика (лайт / MVP)

            +

          Практика (лайт / MVP)

          1. Создай hero-секцию с градиентным фоном и полупрозрачным оверлеем
          2. Стилизуй кнопки: обычное, hover, active состояния с плавным переходом цвета
          3. @@ -53,7 +53,7 @@

            Практика (лайт / MVP)

            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

            -

            Если застрял

            +

          Если застрял

          UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

          Git

            diff --git a/docs/d/02-6.html b/docs/d/02-6.html index 78ecdf7..1946bd8 100644 --- a/docs/d/02-6.html +++ b/docs/d/02-6.html @@ -29,7 +29,7 @@

            Теория

            Ключевая мысль: CSS-переменные — живые токены, которые наследуются и меняются в runtime, и именно поэтому они, а не hex-коды в каждом правиле, — правильный фундамент дизайн-системы.

            Читать: - MDN: Using CSS custom properties

            -

            Практика (полный трек)

            +

            Практика (полный трек)

            1. Вынеси палитру в :root: primary, secondary, text, bg, border
            2. Переведи все цвета страницы на var(--...)
            3. @@ -43,7 +43,7 @@

              Практика (полный трек)

              - [ ] Нет «магических» hex-значений вне :root - [ ] Тёмная тема работает через переопределение переменных - [ ] Есть fallback у критичных var()

              -

              Практика (лайт / MVP)

              +

            Практика (лайт / MVP)

            1. Вынеси палитру в :root: primary, secondary, text, bg, border
            2. Переведи все цвета страницы на var(--...)
            3. @@ -53,7 +53,7 @@

              Практика (лайт / MVP)

              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

              -

              Если застрял

              +

            Если застрял

            Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

            Git

              diff --git a/docs/d/02-7.html b/docs/d/02-7.html index fe5f2fb..141a6f7 100644 --- a/docs/d/02-7.html +++ b/docs/d/02-7.html @@ -29,7 +29,7 @@

              Теория

              Ключевая мысль: rem для масштабируемости, clamp() для плавной адаптивности без десятка breakpoints — и то, и другое станет рабочим инструментом уже завтра, на первом дне недели про Flexbox.

              Читать: - MDN: CSS values and units

              -

              Практика (полный трек)

              +

              Практика (полный трек)

              1. Переведи все font-size на rem (база 16px в html)
              2. Отступы секций задай через rem или spacing-переменные
              3. @@ -43,7 +43,7 @@

                Практика (полный трек)

                - [ ] Размеры шрифтов в rem, не в произвольных px - [ ] Страница выглядит цельно: палитра, типографика, отступы - [ ] Lighthouse Performance ≥ 85 на статике

                -

                Практика (лайт / MVP)

                +

              Практика (лайт / MVP)

              1. Переведи все font-size на rem (база 16px в html)
              2. Отступы секций задай через rem или spacing-переменные
              3. @@ -53,7 +53,7 @@

                Практика (лайт / MVP)

                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                -

                Если застрял

                +

              Если застрял

              Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

              Git

                diff --git a/docs/d/03-1.html b/docs/d/03-1.html index 74a2731..e07b8d3 100644 --- a/docs/d/03-1.html +++ b/docs/d/03-1.html @@ -29,7 +29,7 @@

                Теория

                Ключевая мысль: Flexbox — одна ось, три свойства выравнивания; gap вместо margin между элементами, и сегодняшняя практика с шапкой и рядом карточек — это как раз тот повседневный паттерн, который встретится в 90% проектов впереди.

                Читать: - MDN: Flexbox

                -

                Практика (полный трек)

                +

                Практика (полный трек)

                1. Сверстай шапку сайта: логотип слева, навигация справа (justify-content: space-between)
                2. Сделай ряд из 3 карточек одинаковой высоты с align-items: stretch
                3. @@ -43,7 +43,7 @@

                  Практика (полный трек)

                  - [ ] Шапка не ломается при 768px ширине - [ ] Карточки одной высоты без фиксированного height - [ ] Flexbox Froggy пройден

                  -

                  Практика (лайт / MVP)

                  +

                Практика (лайт / MVP)

                1. Сверстай шапку сайта: логотип слева, навигация справа (justify-content: space-between)
                2. Сделай ряд из 3 карточек одинаковой высоты с align-items: stretch
                3. @@ -53,7 +53,7 @@

                  Практика (лайт / MVP)

                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                  -

                  Если застрял

                  +

                Если застрял

                UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                Git

                  diff --git a/docs/d/03-2.html b/docs/d/03-2.html index 50ff061..ab67b1d 100644 --- a/docs/d/03-2.html +++ b/docs/d/03-2.html @@ -29,7 +29,7 @@

                  Теория

                  Ключевая мысль: margin-top: auto — flex-паттерн «прижать к краю»; min-width: 0 — страховка от переполнения, и оба паттерна сегодня в практике встретятся напрямую в карточке товара и sticky footer.

                  Читать: - CSS Tricks: Flexbox Guide

                  -

                  Практика (полный трек)

                  +

                  Практика (полный трек)

                  1. Карточка товара: изображение, заголовок, описание, цена, кнопка прижата к низу
                  2. Sticky footer: body как flex-column, main { flex: 1 }
                  3. @@ -43,7 +43,7 @@

                    Практика (полный трек)

                    - [ ] Кнопка в карточке всегда внизу при разной длине текста - [ ] Footer прижат к низу viewport на короткой странице - [ ] Галерея скроллится горизонтально на мобильном

                    -

                    Практика (лайт / MVP)

                    +

                  Практика (лайт / MVP)

                  1. Карточка товара: изображение, заголовок, описание, цена, кнопка прижата к низу
                  2. Sticky footer: body как flex-column, main { flex: 1 }
                  3. @@ -53,7 +53,7 @@

                    Практика (лайт / MVP)

                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                    -

                    Если застрял

                    +

                  Если застрял

                  Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                  Git

                    diff --git a/docs/d/03-3.html b/docs/d/03-3.html index dd1c779..625aafb 100644 --- a/docs/d/03-3.html +++ b/docs/d/03-3.html @@ -29,7 +29,7 @@

                    Теория

                    Ключевая мысль: Grid — две оси и именованные зоны; fr делит пространство, а не проценты от неизвестной ширины, и сегодняшняя практика с areas — тренировка «рисовать» макет прямо в CSS, а не вычислять его на бумаге отдельно.

                    Читать: - MDN: Grid Layout

                    -

                    Практика (полный трек)

                    +

                    Практика (полный трек)

                    1. Сетка 3×2 карточек через grid-template-columns: repeat(3, 1fr)
                    2. Макет страницы через areas: header, sidebar, main, footer
                    3. @@ -43,7 +43,7 @@

                      Практика (полный трек)

                      - [ ] Grid Garden пройден - [ ] Макет с areas читаем в CSS без HTML-подсказок - [ ] Адаптив: при 600px — одна колонка

                      -

                      Практика (лайт / MVP)

                      +

                    Практика (лайт / MVP)

                    1. Сетка 3×2 карточек через grid-template-columns: repeat(3, 1fr)
                    2. Макет страницы через areas: header, sidebar, main, footer
                    3. @@ -53,7 +53,7 @@

                      Практика (лайт / MVP)

                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                      -

                      Если застрял

                      +

                    Если застрял

                    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

                    Git

                      diff --git a/docs/d/03-4.html b/docs/d/03-4.html index 6ec3289..5228b1c 100644 --- a/docs/d/03-4.html +++ b/docs/d/03-4.html @@ -29,7 +29,7 @@

                      Теория

                      Ключевая мысль: auto-fill/auto-fit + minmax() — адаптивная сетка без ручных breakpoints, и разница между ними стоит того, чтобы проверить её сегодня на практике вживую, а не запоминать теоретически.

                      Читать: - CSS Tricks: Grid Guide

                      -

                      Практика (полный трек)

                      +

                      Практика (полный трек)

                      1. Галерея с grid-template-columns: repeat(auto-fill, minmax(200px, 1fr))
                      2. Dashboard: sidebar 250px, main 1fr, виджеты внутри main — вложенный grid
                      3. @@ -43,7 +43,7 @@

                        Практика (полный трек)

                        - [ ] Галерея адаптируется без единой media query - [ ] Dashboard читаем на 1024px и 375px - [ ] Осознанный выбор flex vs grid в каждом блоке

                        -

                        Практика (лайт / MVP)

                        +

                      Практика (лайт / MVP)

                      1. Галерея с grid-template-columns: repeat(auto-fill, minmax(200px, 1fr))
                      2. Dashboard: sidebar 250px, main 1fr, виджеты внутри main — вложенный grid
                      3. @@ -53,7 +53,7 @@

                        Практика (лайт / MVP)

                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                        -

                        Если застрял

                        +

                      Если застрял

                      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                      Git

                        diff --git a/docs/d/03-5.html b/docs/d/03-5.html index 39b82ac..5bc8601 100644 --- a/docs/d/03-5.html +++ b/docs/d/03-5.html @@ -29,7 +29,7 @@

                        Теория

                        Ключевая мысль: mobile-first + breakpoint по поломке контента, не по модели телефона — и сегодняшняя практика с перепиской стилей от 375px вверх — это тренировка именно такого мышления.

                        Читать: - MDN: Responsive design

                        -

                        Практика (полный трек)

                        +

                        Практика (полный трек)

                        1. Перепиши стили mobile-first: база 375px, затем 768px, 1024px
                        2. Навигация: горизонтальная на десктопе, вертикальный список на мобильном
                        3. @@ -43,7 +43,7 @@

                          Практика (полный трек)

                          - [ ] Нет горизонтального скролла на 375px - [ ] Touch targets ≥ 44×44px на мобильном - [ ] Breakpoints логичны, не «магические» без причины

                          -

                          Практика (лайт / MVP)

                          +

                        Практика (лайт / MVP)

                        1. Перепиши стили mobile-first: база 375px, затем 768px, 1024px
                        2. Навигация: горизонтальная на десктопе, вертикальный список на мобильном
                        3. @@ -53,7 +53,7 @@

                          Практика (лайт / MVP)

                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                          -

                          Если застрял

                          +

                        Если застрял

                        Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

                        Git

                          diff --git a/docs/d/03-6.html b/docs/d/03-6.html index 183bef2..453728a 100644 --- a/docs/d/03-6.html +++ b/docs/d/03-6.html @@ -30,7 +30,7 @@

                          Теория

                          Читать: - MDN: CSS transitions - MDN: CSS animations

                          -

                          Практика (полный трек)

                          +

                          Практика (полный трек)

                          1. Плавные hover-эффекты на кнопках и карточках (transition: 0.2s ease)
                          2. Анимация появления модального блока через @keyframes fadeIn
                          3. @@ -44,7 +44,7 @@

                            Практика (полный трек)

                            - [ ] Анимации на GPU-свойствах (transform, opacity) - [ ] prefers-reduced-motion учтён - [ ] Переходы не медленнее 300ms для UI-интеракций

                            -

                            Практика (лайт / MVP)

                            +

                          Практика (лайт / MVP)

                          1. Плавные hover-эффекты на кнопках и карточках (transition: 0.2s ease)
                          2. Анимация появления модального блока через @keyframes fadeIn
                          3. @@ -54,7 +54,7 @@

                            Практика (лайт / MVP)

                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                            -

                            Если застрял

                            +

                          Если застрял

                          Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                          Git

                            diff --git a/docs/d/03-7.html b/docs/d/03-7.html index 030c2c1..6a7c220 100644 --- a/docs/d/03-7.html +++ b/docs/d/03-7.html @@ -30,7 +30,7 @@

                            Теория

                            Читать: - MDN: position - MDN: aspect-ratio

                            -

                            Практика (полный трек)

                            +

                            Практика (полный трек)

                            1. Собери полноценный лендинг: hero, features (grid), testimonials (flex), CTA, footer
                            2. Sticky header с тенью при скролле (CSS position: sticky)
                            3. @@ -44,7 +44,7 @@

                              Практика (полный трек)

                              - [ ] Лендинг адаптивен 375px–1440px - [ ] Использованы и flex, и grid осознанно - [ ] Lighthouse ≥ 85 по трём категориям

                              -

                              Практика (лайт / MVP)

                              +

                            Практика (лайт / MVP)

                            1. Собери полноценный лендинг: hero, features (grid), testimonials (flex), CTA, footer
                            2. Sticky header с тенью при скролле (CSS position: sticky)
                            3. @@ -54,7 +54,7 @@

                              Практика (лайт / MVP)

                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                              -

                              Если застрял

                              +

                            Если застрял

                            Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                            Git

                              diff --git a/docs/d/04-1.html b/docs/d/04-1.html index 5820273..c2aa884 100644 --- a/docs/d/04-1.html +++ b/docs/d/04-1.html @@ -30,7 +30,7 @@

                              Теория

                              Читать: - Pro Git: Основы — три состояния, SHA коммитов - Conventional Commits

                              -

                              Практика (полный трек)

                              +

                              Практика (полный трек)

                              1. В learning-log выполни git log --oneline -15 — опиши в week-04/REFLECTION.md паттерн своих сообщений
                              2. Исправь 2 слабых commit message через git rebase -i HEAD~3 только если ещё не пушил; иначе — лучше не переписывать историю
                              3. @@ -42,7 +42,7 @@

                                Практика (полный трек)

                                - [ ] Репозиторий инициализирован, секреты не в git - [ ] Минимум 3 коммита с понятными сообщениями - [ ] git status чист после коммита

                                -

                                Практика (лайт / MVP)

                                +

                              Практика (лайт / MVP)

                              1. В learning-log выполни git log --oneline -15 — опиши в week-04/REFLECTION.md паттерн своих сообщений
                              2. Исправь 2 слабых commit message через git rebase -i HEAD~3 только если ещё не пушил; иначе — лучше не переписывать историю
                              3. @@ -51,7 +51,7 @@

                                Практика (лайт / MVP)

                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                -

                                Если застрял

                                +

                              Если застрял

                              Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

                              Git

                                diff --git a/docs/d/04-2.html b/docs/d/04-2.html index 0122672..0e96cbd 100644 --- a/docs/d/04-2.html +++ b/docs/d/04-2.html @@ -29,7 +29,7 @@

                                Теория

                                Ключевая мысль: ветка — дешёвый черновик; merge — слияние черновика с основной линией.

                                Читать: - Pro Git: Ветвление

                                -

                                Практика (полный трек)

                                +

                                Практика (полный трек)

                                1. Создай ветку feature/dark-theme, добавь тёмную тему
                                2. Вернись на main, измени тот же файл — спровоцируй конфликт
                                3. @@ -43,7 +43,7 @@

                                  Практика (полный трек)

                                  - [ ] Конфликт разрешён осознанно, не удалён «всё чужое» - [ ] История показывает merge (или осознанный ff) - [ ] Понимаю разницу между branch и commit

                                  -

                                  Практика (лайт / MVP)

                                  +

                                Практика (лайт / MVP)

                                1. Создай ветку feature/dark-theme, добавь тёмную тему
                                2. Вернись на main, измени тот же файл — спровоцируй конфликт
                                3. @@ -53,7 +53,7 @@

                                  Практика (лайт / MVP)

                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                  -

                                  Если застрял

                                  +

                                Если застрял

                                Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                Git

                                  diff --git a/docs/d/04-3.html b/docs/d/04-3.html index dab5fc9..cfdd014 100644 --- a/docs/d/04-3.html +++ b/docs/d/04-3.html @@ -29,7 +29,7 @@

                                  Теория

                                  Ключевая мысль: GitHub = remote + социальный слой; PR — разговор о коде до попадания в main.

                                  Читать: - GitHub: Hello World

                                  -

                                  Практика (полный трек)

                                  +

                                  Практика (полный трек)

                                  1. Создай репозиторий на GitHub (public), подключи remote
                                  2. Запушь main, создай ветку feature/readme, добавь README.md
                                  3. @@ -43,7 +43,7 @@

                                    Практика (полный трек)

                                    - [ ] Код на GitHub, локальный и remote синхронизированы - [ ] Минимум 1 PR с описанием - [ ] README содержит название, описание, как запустить

                                    -

                                    Практика (лайт / MVP)

                                    +

                                  Практика (лайт / MVP)

                                  1. Создай репозиторий на GitHub (public), подключи remote
                                  2. Запушь main, создай ветку feature/readme, добавь README.md
                                  3. @@ -53,7 +53,7 @@

                                    Практика (лайт / MVP)

                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                    -

                                    Если застрял

                                    +

                                  Если застрял

                                  Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                  Git

                                    diff --git a/docs/d/04-4.html b/docs/d/04-4.html index 9d2bdb4..30b2668 100644 --- a/docs/d/04-4.html +++ b/docs/d/04-4.html @@ -29,7 +29,7 @@

                                    Теория

                                    Ключевая мысль: Styles — «кто перебил?», Computed — «что в итоге?»; overlay — «как устроена сетка?».

                                    Читать: - Chrome DevTools: Overview

                                    -

                                    Практика (полный трек)

                                    +

                                    Практика (полный трек)

                                    1. Открой лендинг, исследуй box model каждой секции в Elements
                                    2. Включи flex/grid overlay для layout-контейнеров
                                    3. @@ -43,7 +43,7 @@

                                      Практика (полный трек)

                                      - [ ] Умею найти источник стиля в панели Styles (файл и строка) - [ ] Использовал flex/grid overlay - [ ] Знаю разницу Computed vs Styles

                                      -

                                      Практика (лайт / MVP)

                                      +

                                    Практика (лайт / MVP)

                                    1. Открой лендинг, исследуй box model каждой секции в Elements
                                    2. Включи flex/grid overlay для layout-контейнеров
                                    3. @@ -53,7 +53,7 @@

                                      Практика (лайт / MVP)

                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                      -

                                      Если застрял

                                      +

                                    Если застрял

                                    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                    Git

                                      diff --git a/docs/d/04-5.html b/docs/d/04-5.html index 84699e4..153c0cf 100644 --- a/docs/d/04-5.html +++ b/docs/d/04-5.html @@ -30,7 +30,7 @@

                                      Теория

                                      Читать: - Chrome DevTools: Network - Chrome DevTools: Performance

                                      -

                                      Практика (полный трек)

                                      +

                                      Практика (полный трек)

                                      1. Перезагрузи страницу с Network open — проанализируй waterfall
                                      2. Найди самый тяжёлый ресурс, оптимизируй (сжатие изображения)
                                      3. @@ -44,7 +44,7 @@

                                        Практика (полный трек)

                                        - [ ] Понимаю статусы 200, 304, 404 в Network - [ ] Lighthouse score улучшен после правок - [ ] Умею ставить breakpoint и читать call stack

                                        -

                                        Практика (лайт / MVP)

                                        +

                                      Практика (лайт / MVP)

                                      1. Перезагрузи страницу с Network open — проанализируй waterfall
                                      2. Найди самый тяжёлый ресурс, оптимизируй (сжатие изображения)
                                      3. @@ -54,7 +54,7 @@

                                        Практика (лайт / MVP)

                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                        -

                                        Если застрял

                                        +

                                      Если застрял

                                      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                      Git

                                        diff --git a/docs/d/04-6.html b/docs/d/04-6.html index 5f41e7c..9d767ce 100644 --- a/docs/d/04-6.html +++ b/docs/d/04-6.html @@ -30,7 +30,7 @@

                                        Теория

                                        Читать: - Conventional Commits - GitHub Flow

                                        -

                                        Практика (полный трек)

                                        +

                                        Практика (полный трек)

                                        1. Переименуй последние коммиты сообщениями в стиле Conventional Commits (если нужно — git rebase осторожно или новые коммиты)
                                        2. Настрой Prettier в VS Code, отформатируй CSS/HTML
                                        3. @@ -44,7 +44,7 @@

                                          Практика (полный трек)

                                          - [ ] Коммиты следуют единому стилю сообщений - [ ] Prettier настроен и применён - [ ] Есть PR template или чеклист в заметках

                                          -

                                          Практика (лайт / MVP)

                                          +

                                        Практика (лайт / MVP)

                                        1. Переименуй последние коммиты сообщениями в стиле Conventional Commits (если нужно — git rebase осторожно или новые коммиты)
                                        2. Настрой Prettier в VS Code, отформатируй CSS/HTML
                                        3. @@ -54,7 +54,7 @@

                                          Практика (лайт / MVP)

                                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                          -

                                          Если застрял

                                          +

                                        Если застрял

                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                        Git

                                          diff --git a/docs/d/04-7.html b/docs/d/04-7.html index 52979b0..8a60d83 100644 --- a/docs/d/04-7.html +++ b/docs/d/04-7.html @@ -30,7 +30,7 @@

                                          Теория

                                          Читать: - Pro Git: Отмена изменений - GitHub Pages

                                          -

                                          Практика (полный трек)

                                          +

                                          Практика (полный трек)

                                          1. Клонируй свой репозиторий в новую папку — проверь, что всё работает
                                          2. Найди автора строки через git blame для одного CSS-файла
                                          3. @@ -44,7 +44,7 @@

                                            Практика (полный трек)

                                            - [ ] Сайт доступен по публичному URL - [ ] Clone → open работает без ручных правок - [ ] CONTRIBUTING.md или раздел в README описывает workflow

                                            -

                                            Практика (лайт / MVP)

                                            +

                                          Практика (лайт / MVP)

                                          1. Клонируй свой репозиторий в новую папку — проверь, что всё работает
                                          2. Найди автора строки через git blame для одного CSS-файла
                                          3. @@ -54,7 +54,7 @@

                                            Практика (лайт / MVP)

                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                            -

                                            Если застрял

                                            +

                                          Если застрял

                                          Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                          Git

                                            diff --git a/docs/d/05-1.html b/docs/d/05-1.html index 377f3a9..318a60b 100644 --- a/docs/d/05-1.html +++ b/docs/d/05-1.html @@ -30,7 +30,7 @@

                                            Теория

                                            Читать: - learn.javascript.ru: Введение — как выполняется JS в браузере - learn.javascript.ru: var — разница let/const/var и TDZ

                                            -

                                            Практика (полный трек)

                                            +

                                            Практика (полный трек)

                                            1. Создай app.js, подключи к HTML через defer
                                            2. Объяви переменные let и const разных типов, выведи в console
                                            3. @@ -44,7 +44,7 @@

                                              Практика (полный трек)

                                              - [ ] Используются только let/const, не var - [ ] Скрипт подключён корректно, нет ошибок в Console - [ ] Понимаю разницу переприсвоения и мутации объекта

                                              -

                                              Практика (лайт / MVP)

                                              +

                                            Практика (лайт / MVP)

                                            1. Создай app.js, подключи к HTML через defer
                                            2. Объяви переменные let и const разных типов, выведи в console
                                            3. @@ -54,7 +54,7 @@

                                              Практика (лайт / MVP)

                                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                              -

                                              Если застрял

                                              +

                                            Если застрял

                                            UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                            Git

                                              diff --git a/docs/d/05-2.html b/docs/d/05-2.html index 70de386..de78a05 100644 --- a/docs/d/05-2.html +++ b/docs/d/05-2.html @@ -30,7 +30,7 @@

                                              Теория

                                              Читать: - learn.javascript.ru: Типы — примитивы и объекты - learn.javascript.ru: Операторы — арифметика, сравнение, логика

                                              -

                                              Практика (полный трек)

                                              +

                                              Практика (полный трек)

                                              1. Напиши функцию describeType(value) — возвращает строку с typeof и значением
                                              2. Таблица сравнений: 0 == false, '' == false, null == undefined — предскажи, проверь
                                              3. @@ -44,7 +44,7 @@

                                                Практика (полный трек)

                                                - [ ] Все сравнения через === - [ ] Нет неявных приведений без понимания - [ ] Template literals для интерполяции строк

                                                -

                                                Практика (лайт / MVP)

                                                +

                                              Практика (лайт / MVP)

                                              1. Напиши функцию describeType(value) — возвращает строку с typeof и значением
                                              2. Таблица сравнений: 0 == false, '' == false, null == undefined — предскажи, проверь
                                              3. @@ -54,7 +54,7 @@

                                                Практика (лайт / MVP)

                                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                -

                                                Если застрял

                                                +

                                              Если застрял

                                              Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                              Git

                                                diff --git a/docs/d/05-3.html b/docs/d/05-3.html index 985d4ff..0d0f540 100644 --- a/docs/d/05-3.html +++ b/docs/d/05-3.html @@ -30,7 +30,7 @@

                                                Теория

                                                Читать: - learn.javascript.ru: Условное ветвление - learn.javascript.ru: Циклы — while, do...while, for

                                                -

                                                Практика (полный трек)

                                                +

                                                Практика (полный трек)

                                                1. Программа «FizzBuzz» (1–100) — вывод в Console
                                                2. Калькулятор оценок: число → буква (A/B/C/D/F) через switch
                                                3. @@ -44,7 +44,7 @@

                                                  Практика (полный трек)

                                                  - [ ] FizzBuzz работает корректно - [ ] Нет бесконечных циклов - [ ] Код читаем, переменные с понятными именами

                                                  -

                                                  Практика (лайт / MVP)

                                                  +

                                                Практика (лайт / MVP)

                                                1. Программа «FizzBuzz» (1–100) — вывод в Console
                                                2. Калькулятор оценок: число → буква (A/B/C/D/F) через switch
                                                3. @@ -54,7 +54,7 @@

                                                  Практика (лайт / MVP)

                                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                  -

                                                  Если застрял

                                                  +

                                                Если застрял

                                                Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                Git

                                                  diff --git a/docs/d/05-4.html b/docs/d/05-4.html index 63eb219..7690c1f 100644 --- a/docs/d/05-4.html +++ b/docs/d/05-4.html @@ -29,7 +29,7 @@

                                                  Теория

                                                  Ключевая мысль: чистые функции + SRP = код, который можно читать, тестировать и переиспользовать.

                                                  Читать: - learn.javascript.ru: Функции

                                                  -

                                                  Практика (полный трек)

                                                  +

                                                  Практика (полный трек)

                                                  1. Напиши greet(name, greeting = 'Привет') — declaration
                                                  2. Перепиши как arrow function; сравни поведение this (пока без углубления)
                                                  3. @@ -43,7 +43,7 @@

                                                    Практика (полный трек)

                                                    - [ ] Минимум 5 переиспользуемых функций - [ ] Default parameters и rest использованы - [ ] Функции делают одну вещь (SRP)

                                                    -

                                                    Практика (лайт / MVP)

                                                    +

                                                  Практика (лайт / MVP)

                                                  1. Напиши greet(name, greeting = 'Привет') — declaration
                                                  2. Перепиши как arrow function; сравни поведение this (пока без углубления)
                                                  3. @@ -53,7 +53,7 @@

                                                    Практика (лайт / MVP)

                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                    -

                                                    Если застрял

                                                    +

                                                  Если застрял

                                                  Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                  Git

                                                    diff --git a/docs/d/05-5.html b/docs/d/05-5.html index 81f917c..99d34df 100644 --- a/docs/d/05-5.html +++ b/docs/d/05-5.html @@ -29,7 +29,7 @@

                                                    Теория

                                                    Ключевая мысль: slice — копия без мутации; splice — мутация; for...of, не for...in.

                                                    Читать: - learn.javascript.ru: Массивы

                                                    -

                                                    Практика (полный трек)

                                                    +

                                                    Практика (полный трек)

                                                    1. Список покупок: добавление, удаление, вывод через for...of
                                                    2. Найди min/max в массиве чисел без Math.min на входе массива
                                                    3. @@ -43,7 +43,7 @@

                                                      Практика (полный трек)

                                                      - [ ] Понимаю разницу slice и splice - [ ] Итерация через for...of, не for...in для массивов - [ ] Spread не мутирует оригинал

                                                      -

                                                      Практика (лайт / MVP)

                                                      +

                                                    Практика (лайт / MVP)

                                                    1. Список покупок: добавление, удаление, вывод через for...of
                                                    2. Найди min/max в массиве чисел без Math.min на входе массива
                                                    3. @@ -53,7 +53,7 @@

                                                      Практика (лайт / MVP)

                                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                      -

                                                      Если застрял

                                                      +

                                                    Если застрял

                                                    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

                                                    Git

                                                      diff --git a/docs/d/05-6.html b/docs/d/05-6.html index 5c33122..b7536b5 100644 --- a/docs/d/05-6.html +++ b/docs/d/05-6.html @@ -29,7 +29,7 @@

                                                      Теория

                                                      Ключевая мысль: map/filter/reduce — декларативный стиль; sort всегда с compare-функцией для чисел.

                                                      Читать: - learn.javascript.ru: Методы массивов

                                                      -

                                                      Практика (полный трек)

                                                      +

                                                      Практика (полный трек)

                                                      1. Массив пользователей {name, age}: фильтр 18+, map в имена
                                                      2. Сумма цен корзины через reduce
                                                      3. @@ -43,7 +43,7 @@

                                                        Практика (полный трек)

                                                        - [ ] Использованы map, filter, reduce в реальных задачах - [ ] Сортировка чисел корректна - [ ] Цепочка из 3+ методов в одной задаче

                                                        -

                                                        Практика (лайт / MVP)

                                                        +

                                                      Практика (лайт / MVP)

                                                      1. Массив пользователей {name, age}: фильтр 18+, map в имена
                                                      2. Сумма цен корзины через reduce
                                                      3. @@ -53,7 +53,7 @@

                                                        Практика (лайт / MVP)

                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                        -

                                                        Если застрял

                                                        +

                                                      Если застрял

                                                      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                      Git

                                                        diff --git a/docs/d/05-7.html b/docs/d/05-7.html index 860b5c9..8a01126 100644 --- a/docs/d/05-7.html +++ b/docs/d/05-7.html @@ -29,7 +29,7 @@

                                                        Теория

                                                        Ключевая мысль: stack trace + breakpoint > десять console.log; функции — единицы отладки.

                                                        Читать: - Chrome DevTools: JavaScript

                                                        -

                                                        Практика (полный трек)

                                                        +

                                                        Практика (полный трек)

                                                        1. Консольное приложение «Todo List» (массив + функции add/remove/list)
                                                        2. Поиск по задачам через filter
                                                        3. @@ -43,7 +43,7 @@

                                                          Практика (полный трек)

                                                          - [ ] Todo list работает в Console без DOM - [ ] Код разбит на логические функции - [ ] Отладка через breakpoint, не только console.log

                                                          -

                                                          Практика (лайт / MVP)

                                                          +

                                                        Практика (лайт / MVP)

                                                        1. Консольное приложение «Todo List» (массив + функции add/remove/list)
                                                        2. Поиск по задачам через filter
                                                        3. @@ -53,7 +53,7 @@

                                                          Практика (лайт / MVP)

                                                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                          -

                                                          Если застрял

                                                          +

                                                        Если застрял

                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                        Git

                                                          diff --git a/docs/d/06-1.html b/docs/d/06-1.html index 47a53ae..07a8944 100644 --- a/docs/d/06-1.html +++ b/docs/d/06-1.html @@ -29,7 +29,7 @@

                                                          Теория

                                                          Ключевая мысль: объект — словарь по ссылке; spread копирует поверхностно, не глубоко.

                                                          Читать: - learn.javascript.ru: Объекты — литералы, свойства, методы

                                                          -

                                                          Практика (полный трек)

                                                          +

                                                          Практика (полный трек)

                                                          1. Объект user с полями name, email, age — чтение и изменение
                                                          2. Метод user.greet() — function внутри объекта
                                                          3. @@ -43,7 +43,7 @@

                                                            Практика (полный трек)

                                                            - [ ] Объект с минимум одним методом - [ ] Использованы keys/values/entries - [ ] Понимаю shallow vs deep copy (на уровне концепции)

                                                            -

                                                            Практика (лайт / MVP)

                                                            +

                                                          Практика (лайт / MVP)

                                                          1. Объект user с полями name, email, age — чтение и изменение
                                                          2. Метод user.greet() — function внутри объекта
                                                          3. @@ -53,7 +53,7 @@

                                                            Практика (лайт / MVP)

                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                            -

                                                            Если застрял

                                                            +

                                                          Если застрял

                                                          UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                          Git

                                                            diff --git a/docs/d/06-2.html b/docs/d/06-2.html index 542d600..c1a2199 100644 --- a/docs/d/06-2.html +++ b/docs/d/06-2.html @@ -29,7 +29,7 @@

                                                            Теория

                                                            Ключевая мысль: spread для merge и иммутабельного update; rest для «всё кроме».

                                                            Читать: - learn.javascript.ru: Деструктурирующее присваивание

                                                            -

                                                            Практика (полный трек)

                                                            +

                                                            Практика (полный трек)

                                                            1. Функция printUser({name, email, role = 'user'}) — деструктуризация параметров
                                                            2. Объедини настройки: const config = {...defaults, ...userConfig}
                                                            3. @@ -43,7 +43,7 @@

                                                              Практика (полный трек)

                                                              - [ ] Деструктуризация в параметрах функций - [ ] Spread для иммутабельного обновления объекта - [ ] Rest для исключения полей

                                                              -

                                                              Практика (лайт / MVP)

                                                              +

                                                            Практика (лайт / MVP)

                                                            1. Функция printUser({name, email, role = 'user'}) — деструктуризация параметров
                                                            2. Объедини настройки: const config = {...defaults, ...userConfig}
                                                            3. @@ -53,7 +53,7 @@

                                                              Практика (лайт / MVP)

                                                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                              -

                                                              Если застрял

                                                              +

                                                            Если застрял

                                                            Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                            Git

                                                              diff --git a/docs/d/06-3.html b/docs/d/06-3.html index 2c885a6..a1094a6 100644 --- a/docs/d/06-3.html +++ b/docs/d/06-3.html @@ -30,7 +30,7 @@

                                                              Теория

                                                              Читать: - learn.javascript.ru: DOM-дерево - MDN DOM

                                                              -

                                                              Практика (полный трек)

                                                              +

                                                              Практика (полный трек)

                                                              1. Подключи JS к лендингу, выбери заголовок и измени textContent
                                                              2. По клику на кнопку меняй класс theme-dark на document.documentElement
                                                              3. @@ -44,7 +44,7 @@

                                                                Практика (полный трек)

                                                                - [ ] Используется querySelector, не устаревшие методы без причины - [ ] textContent для текста, не innerHTML с пользовательскими данными - [ ] Элементы создаются через DOM API, не строками HTML

                                                                -

                                                                Практика (лайт / MVP)

                                                                +

                                                              Практика (лайт / MVP)

                                                              1. Подключи JS к лендингу, выбери заголовок и измени textContent
                                                              2. По клику на кнопку меняй класс theme-dark на document.documentElement
                                                              3. @@ -54,7 +54,7 @@

                                                                Практика (лайт / MVP)

                                                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                -

                                                                Если застрял

                                                                +

                                                              Если застрял

                                                              Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                              Git

                                                                diff --git a/docs/d/06-4.html b/docs/d/06-4.html index 0557195..a6869e7 100644 --- a/docs/d/06-4.html +++ b/docs/d/06-4.html @@ -29,7 +29,7 @@

                                                                Теория

                                                                Ключевая мысль: bubbling — основа делегирования; preventDefaultstopPropagation.

                                                                Читать: - learn.javascript.ru: Введение в события

                                                                -

                                                                Практика (полный трек)

                                                                +

                                                                Практика (полный трек)

                                                                1. Кнопка «Наверх» — плавный скролл (пока window.scrollTo, событие click)
                                                                2. Форма: submitpreventDefault(), вывод данных в Console
                                                                3. @@ -43,7 +43,7 @@

                                                                  Практика (полный трек)

                                                                  - [ ] preventDefault на форме предотвращает перезагрузку - [ ] Event delegation на списке - [ ] Именованные handler-функции для removeEventListener

                                                                  -

                                                                  Практика (лайт / MVP)

                                                                  +

                                                                Практика (лайт / MVP)

                                                                1. Кнопка «Наверх» — плавный скролл (пока window.scrollTo, событие click)
                                                                2. Форма: submitpreventDefault(), вывод данных в Console
                                                                3. @@ -53,7 +53,7 @@

                                                                  Практика (лайт / MVP)

                                                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                  -

                                                                  Если застрял

                                                                  +

                                                                Если застрял

                                                                Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                Git

                                                                  diff --git a/docs/d/06-5.html b/docs/d/06-5.html index bb6f6aa..584ca27 100644 --- a/docs/d/06-5.html +++ b/docs/d/06-5.html @@ -29,7 +29,7 @@

                                                                  Теория

                                                                  Ключевая мысль: UI = состояние + DOM; ARIA синхронизирует визуал со скринридером.

                                                                  Читать: - learn.javascript.ru: Действия браузера

                                                                  -

                                                                  Практика (полный трек)

                                                                  +

                                                                  Практика (полный трек)

                                                                  1. Аккордеон: 3 секции, открыта одна; клик переключает
                                                                  2. Табы: панели контента показываются по активному табу
                                                                  3. @@ -43,7 +43,7 @@

                                                                    Практика (полный трек)

                                                                    - [ ] Аккордеон и табы работают без библиотек - [ ] Модалка закрывается по Escape и клику вне - [ ] ARIA-атрибуты на интерактивных элементах

                                                                    -

                                                                    Практика (лайт / MVP)

                                                                    +

                                                                  Практика (лайт / MVP)

                                                                  1. Аккордеон: 3 секции, открыта одна; клик переключает
                                                                  2. Табы: панели контента показываются по активному табу
                                                                  3. @@ -53,7 +53,7 @@

                                                                    Практика (лайт / MVP)

                                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                    -

                                                                    Если застрял

                                                                    +

                                                                  Если застрял

                                                                  UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                  Git

                                                                    diff --git a/docs/d/06-6.html b/docs/d/06-6.html index a0254c9..c4660f4 100644 --- a/docs/d/06-6.html +++ b/docs/d/06-6.html @@ -29,7 +29,7 @@

                                                                    Теория

                                                                    Ключевая мысль: input для live-валидации; ошибки у поля, не в alert; setCustomValidity для своих правил.

                                                                    Читать: - learn.javascript.ru: Формы, элементы управления

                                                                    -

                                                                    Практика (полный трек)

                                                                    +

                                                                    Практика (полный трек)

                                                                    1. Валидация формы регистрации перед отправкой
                                                                    2. Live-валидация email при input
                                                                    3. @@ -43,7 +43,7 @@

                                                                      Практика (полный трек)

                                                                      - [ ] HTML5 + JS валидация работают вместе - [ ] Ошибки понятны и привязаны к полям - [ ] Форма не сабмитится при невалидных данных

                                                                      -

                                                                      Практика (лайт / MVP)

                                                                      +

                                                                    Практика (лайт / MVP)

                                                                    1. Валидация формы регистрации перед отправкой
                                                                    2. Live-валидация email при input
                                                                    3. @@ -53,7 +53,7 @@

                                                                      Практика (лайт / MVP)

                                                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                      -

                                                                      Если застрял

                                                                      +

                                                                    Если застрял

                                                                    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                    Git

                                                                      diff --git a/docs/d/06-7.html b/docs/d/06-7.html index db3e297..330b65f 100644 --- a/docs/d/06-7.html +++ b/docs/d/06-7.html @@ -29,7 +29,7 @@

                                                                      Теория

                                                                      Ключевая мысль: data отдельно от DOM; render* — мост; fragment — batch insert без лишних reflow.

                                                                      Читать: - MDN: DocumentFragment

                                                                      -

                                                                      Практика (полный трек)

                                                                      +

                                                                      Практика (полный трек)

                                                                      1. Оживи лендинг: тёмная тема, мобильное меню, плавный скролл к секциям
                                                                      2. Фильтр портфолио: кнопки категорий скрывают/показывают карточки
                                                                      3. @@ -43,7 +43,7 @@

                                                                        Практика (полный трек)

                                                                        - [ ] Минимум 5 интерактивных фич - [ ] Код структурирован: utils, dom, app - [ ] Нет ошибок в Console при типичном сценарии

                                                                        -

                                                                        Практика (лайт / MVP)

                                                                        +

                                                                      Практика (лайт / MVP)

                                                                      1. Оживи лендинг: тёмная тема, мобильное меню, плавный скролл к секциям
                                                                      2. Фильтр портфолио: кнопки категорий скрывают/показывают карточки
                                                                      3. @@ -53,7 +53,7 @@

                                                                        Практика (лайт / MVP)

                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                        -

                                                                        Если застрял

                                                                        +

                                                                      Если застрял

                                                                      Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                      Git

                                                                        diff --git a/docs/d/07-1.html b/docs/d/07-1.html index 8d9f55d..8486895 100644 --- a/docs/d/07-1.html +++ b/docs/d/07-1.html @@ -31,7 +31,7 @@

                                                                        Теория

                                                                        - MDN: Web Storage API - web.dev: Storage for the web

                                                                        Ключевая мысль: localStorage — удобный кэш для UI-состояния, но не сейф для секретов и не замена серверной базе данных.

                                                                        -

                                                                        Практика (полный трек)

                                                                        +

                                                                        Практика (полный трек)

                                                                        1. Сохрани Todo-список в localStorage при каждом изменении
                                                                        2. При загрузке страницы восстанови задачи из storage
                                                                        3. @@ -45,7 +45,7 @@

                                                                          Практика (полный трек)

                                                                          - [ ] Данные переживают перезагрузку страницы - [ ] Объекты сериализуются через JSON - [ ] Ошибки парсинга обработаны gracefully

                                                                          -

                                                                          Практика (лайт / MVP)

                                                                          +

                                                                        Практика (лайт / MVP)

                                                                        1. Сохрани Todo-список в localStorage при каждом изменении
                                                                        2. При загрузке страницы восстанови задачи из storage
                                                                        3. @@ -55,7 +55,7 @@

                                                                          Практика (лайт / MVP)

                                                                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                          -

                                                                          Если застрял

                                                                          +

                                                                        Если застрял

                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                        Git

                                                                          diff --git a/docs/d/07-2.html b/docs/d/07-2.html index 0083521..23dd10e 100644 --- a/docs/d/07-2.html +++ b/docs/d/07-2.html @@ -31,7 +31,7 @@

                                                                          Теория

                                                                          - MDN: JSON.stringify() - learn.javascript.ru: Формат JSON

                                                                          Ключевая мысль: JSON — контракт обмена данными; валидация и версионирование схемы защищают приложение от битых импортов и устаревших сохранений.

                                                                          -

                                                                          Практика (полный трек)

                                                                          +

                                                                          Практика (полный трек)

                                                                          1. Экспорт Todo в JSON-файл (download через Blob + URL.createObjectURL)
                                                                          2. Импорт: <input type="file"> → FileReader → parse → merge в список
                                                                          3. @@ -45,7 +45,7 @@

                                                                            Практика (полный трек)

                                                                            - [ ] Экспорт/импорт JSON работает - [ ] Валидация отклоняет невалидные данные - [ ] Иммутабельные обновления, не мутация массива напрямую

                                                                            -

                                                                            Практика (лайт / MVP)

                                                                            +

                                                                          Практика (лайт / MVP)

                                                                          1. Экспорт Todo в JSON-файл (download через Blob + URL.createObjectURL)
                                                                          2. Импорт: <input type="file"> → FileReader → parse → merge в список
                                                                          3. @@ -55,7 +55,7 @@

                                                                            Практика (лайт / MVP)

                                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                            -

                                                                            Если застрял

                                                                            +

                                                                          Если застрял

                                                                          Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                          Git

                                                                            diff --git a/docs/d/07-3.html b/docs/d/07-3.html index 2a16651..85182e6 100644 --- a/docs/d/07-3.html +++ b/docs/d/07-3.html @@ -31,7 +31,7 @@

                                                                            Теория

                                                                            - MDN: Using Fetch - JSONPlaceholder Guide

                                                                            Ключевая мысль: fetch различает «сеть упала» (reject) и «сервер ответил ошибкой» (resolve с ok: false) — проверяй оба случая.

                                                                            -

                                                                            Практика (полный трек)

                                                                            +

                                                                            Практика (полный трек)

                                                                            1. Загрузи посты с JSONPlaceholder
                                                                            2. Отобрази список заголовков в DOM
                                                                            3. @@ -45,7 +45,7 @@

                                                                              Практика (полный трек)

                                                                              - [ ] Данные с API отображаются в UI - [ ] Обработаны loading и error - [ ] Проверяется response.ok

                                                                              -

                                                                              Практика (лайт / MVP)

                                                                              +

                                                                            Практика (лайт / MVP)

                                                                            1. Загрузи посты с JSONPlaceholder
                                                                            2. Отобрази список заголовков в DOM
                                                                            3. @@ -55,7 +55,7 @@

                                                                              Практика (лайт / MVP)

                                                                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                              -

                                                                              Если застрял

                                                                              +

                                                                            Если застрял

                                                                            Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                            Git

                                                                              diff --git a/docs/d/07-4.html b/docs/d/07-4.html index 62fe5ce..10e2c05 100644 --- a/docs/d/07-4.html +++ b/docs/d/07-4.html @@ -31,7 +31,7 @@

                                                                              Теория

                                                                              - MDN: HTTP Overview - Open-Meteo API

                                                                              Ключевая мысль: интеграция с API начинается с чтения документации и понимания HTTP-семантики, а не с написания fetch.

                                                                              -

                                                                              Практика (полный трек)

                                                                              +

                                                                              Практика (полный трек)

                                                                              1. Погода: Open-Meteo API — без ключа
                                                                              2. Форма поиска города → fetch → отображение температуры и иконки
                                                                              3. @@ -45,7 +45,7 @@

                                                                                Практика (полный трек)

                                                                                - [ ] Реальный API интегрирован в UI - [ ] Пользователь видит понятные сообщения об ошибках - [ ] Network panel использован для отладки

                                                                                -

                                                                                Практика (лайт / MVP)

                                                                                +

                                                                              Практика (лайт / MVP)

                                                                              1. Погода: Open-Meteo API — без ключа
                                                                              2. Форма поиска города → fetch → отображение температуры и иконки
                                                                              3. @@ -55,7 +55,7 @@

                                                                                Практика (лайт / MVP)

                                                                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                -

                                                                                Если застрял

                                                                                +

                                                                              Если застрял

                                                                              Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                              Git

                                                                                diff --git a/docs/d/07-5.html b/docs/d/07-5.html index 3397935..66a577c 100644 --- a/docs/d/07-5.html +++ b/docs/d/07-5.html @@ -31,7 +31,7 @@

                                                                                Теория

                                                                                - MDN: JavaScript modules - javascript.info: Модули

                                                                                Ключевая мысль: модули превращают монолитный скрипт в граф зависимостей с изолированными областями видимости — основа масштабируемого фронтенда.

                                                                                -

                                                                                Практика (полный трек)

                                                                                +

                                                                                Практика (полный трек)

                                                                                1. Разбей Todo App на модули: storage.js, todo.js, render.js, main.js
                                                                                2. api.js — функции fetch с экспортом
                                                                                3. @@ -45,7 +45,7 @@

                                                                                  Практика (полный трек)

                                                                                  - [ ] Все скрипты — ES modules с type="module" - [ ] Нет глобальных переменных в window - [ ] Логичная структура папок js/

                                                                                  -

                                                                                  Практика (лайт / MVP)

                                                                                  +

                                                                                Практика (лайт / MVP)

                                                                                1. Разбей Todo App на модули: storage.js, todo.js, render.js, main.js
                                                                                2. api.js — функции fetch с экспортом
                                                                                3. @@ -55,7 +55,7 @@

                                                                                  Практика (лайт / MVP)

                                                                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                  -

                                                                                  Если застрял

                                                                                  +

                                                                                Если застрял

                                                                                Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

                                                                                Git

                                                                                  diff --git a/docs/d/07-6.html b/docs/d/07-6.html index b166aa9..8c8c366 100644 --- a/docs/d/07-6.html +++ b/docs/d/07-6.html @@ -31,7 +31,7 @@

                                                                                  Теория

                                                                                  - MDN: AbortController - learn.javascript.ru: debounce

                                                                                  Ключевая мысль: форма + fetch требуют защиты от двойной отправки, debounce для поиска и отмены устаревших запросов.

                                                                                  -

                                                                                  Практика (полный трек)

                                                                                  +

                                                                                  Практика (полный трек)

                                                                                  1. Форма «Добавить пост» → POST на JSONPlaceholder → добавь в список
                                                                                  2. Поиск пользователей GitHub API с debounce 300ms
                                                                                  3. @@ -45,7 +45,7 @@

                                                                                    Практика (полный трек)

                                                                                    - [ ] POST отправляет корректный JSON - [ ] Debounce на поиске работает - [ ] UI не дублирует запросы при быстром вводе

                                                                                    -

                                                                                    Практика (лайт / MVP)

                                                                                    +

                                                                                  Практика (лайт / MVP)

                                                                                  1. Форма «Добавить пост» → POST на JSONPlaceholder → добавь в список
                                                                                  2. Поиск пользователей GitHub API с debounce 300ms
                                                                                  3. @@ -55,7 +55,7 @@

                                                                                    Практика (лайт / MVP)

                                                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                    -

                                                                                    Если застрял

                                                                                    +

                                                                                  Если застрял

                                                                                  Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                  Git

                                                                                    diff --git a/docs/d/07-7.html b/docs/d/07-7.html index 5ffa0a4..7bc1f43 100644 --- a/docs/d/07-7.html +++ b/docs/d/07-7.html @@ -31,7 +31,7 @@

                                                                                    Теория

                                                                                    - MDN: Fetch API - learn.javascript.ru: Промисы — подготовка к неделе 8

                                                                                    Ключевая мысль: зрелое клиентское приложение — это слои (api/cache/ui) плюс явная обработка ошибок, кэша и offline-сценариев.

                                                                                    -

                                                                                    Практика (полный трек)

                                                                                    +

                                                                                    Практика (полный трек)

                                                                                    1. Собери «Панель постов»: список + детали + форма создания
                                                                                    2. Кэшируй список постов в localStorage на 5 минут
                                                                                    3. @@ -45,7 +45,7 @@

                                                                                      Практика (полный трек)

                                                                                      - [ ] Полный CRUD UI (create + read, delete опционально) - [ ] Кэш с TTL работает - [ ] Модульная архитектура

                                                                                      -

                                                                                      Практика (лайт / MVP)

                                                                                      +

                                                                                    Практика (лайт / MVP)

                                                                                    1. Собери «Панель постов»: список + детали + форма создания
                                                                                    2. Кэшируй список постов в localStorage на 5 минут
                                                                                    3. @@ -55,7 +55,7 @@

                                                                                      Практика (лайт / MVP)

                                                                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                      -

                                                                                      Если застрял

                                                                                      +

                                                                                    Если застрял

                                                                                    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                    Git

                                                                                      diff --git a/docs/d/08-1.html b/docs/d/08-1.html index 35d7ead..7e09195 100644 --- a/docs/d/08-1.html +++ b/docs/d/08-1.html @@ -31,7 +31,7 @@

                                                                                      Теория

                                                                                      - MDN: Event Loop - Loupe — визуализация Event Loop

                                                                                      Ключевая мысль: microtasks (Promise) всегда опережают macrotasks (setTimeout) — запомни это правило, и половина async-багов исчезнет.

                                                                                      -

                                                                                      Практика (полный трек)

                                                                                      +

                                                                                      Практика (полный трек)

                                                                                      1. Предскажи порядок вывода 5 задач с console.log, setTimeout, Promise.resolve().then
                                                                                      2. Проверь в браузере, объясни через Event Loop
                                                                                      3. @@ -45,7 +45,7 @@

                                                                                        Практика (полный трек)

                                                                                        - [ ] Могу предсказать порядок вывода в 4 из 5 примеров - [ ] Понимаю разницу microtask и macrotask - [ ] Есть конспект Event Loop своими словами

                                                                                        -

                                                                                        Практика (лайт / MVP)

                                                                                        +

                                                                                      Практика (лайт / MVP)

                                                                                      1. Предскажи порядок вывода 5 задач с console.log, setTimeout, Promise.resolve().then
                                                                                      2. Проверь в браузере, объясни через Event Loop
                                                                                      3. @@ -55,7 +55,7 @@

                                                                                        Практика (лайт / MVP)

                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                        -

                                                                                        Если застрял

                                                                                        +

                                                                                      Если застрял

                                                                                      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                      Git

                                                                                        diff --git a/docs/d/08-2.html b/docs/d/08-2.html index 397bdd7..869666c 100644 --- a/docs/d/08-2.html +++ b/docs/d/08-2.html @@ -31,7 +31,7 @@

                                                                                        Теория

                                                                                        - learn.javascript.ru: Цепочка промисов - MDN: Promise

                                                                                        Ключевая мысль: Promise — это цепочка, а не вложенность; .then возвращает новый Promise, и один .catch обслуживает всю цепочку.

                                                                                        -

                                                                                        Практика (полный трек)

                                                                                        +

                                                                                        Практика (полный трек)

                                                                                        1. Оберни setTimeout в функцию delay(ms) → Promise
                                                                                        2. Цепочка: delay(1000) → «Шаг 1» → delay(500) → «Шаг 2»
                                                                                        3. @@ -45,7 +45,7 @@

                                                                                          Практика (полный трек)

                                                                                          - [ ] Цепочка then без callback hell - [ ] Ошибки ловятся в catch - [ ] Promise.all для параллельных запросов

                                                                                          -

                                                                                          Практика (лайт / MVP)

                                                                                          +

                                                                                        Практика (лайт / MVP)

                                                                                        1. Оберни setTimeout в функцию delay(ms) → Promise
                                                                                        2. Цепочка: delay(1000) → «Шаг 1» → delay(500) → «Шаг 2»
                                                                                        3. @@ -55,7 +55,7 @@

                                                                                          Практика (лайт / MVP)

                                                                                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                          -

                                                                                          Если застрял

                                                                                          +

                                                                                        Если застрял

                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                        Git

                                                                                          diff --git a/docs/d/08-3.html b/docs/d/08-3.html index ff130bc..52b3250 100644 --- a/docs/d/08-3.html +++ b/docs/d/08-3.html @@ -37,7 +37,7 @@

                                                                                          Теория

                                                                                          - MDN: async function - javascript.info: Async/await

                                                                                          Ключевая мысль: await не блокирует браузер — он лишь ставит на паузу текущую async-функцию, пока Promise не разрешится.

                                                                                          -

                                                                                          Практика (полный трек)

                                                                                          +

                                                                                          Практика (полный трек)

                                                                                          1. Рефакторинг fetch-функций на async/await
                                                                                          2. Функция loadUserWithPosts(userId) — user, затем его posts
                                                                                          3. @@ -51,7 +51,7 @@

                                                                                            Практика (полный трек)

                                                                                            - [ ] Весь API-слой на async/await - [ ] Параллельные запросы не последовательные без причины - [ ] try/catch на каждом публичном API-вызове

                                                                                            -

                                                                                            Практика (лайт / MVP)

                                                                                            +

                                                                                          Практика (лайт / MVP)

                                                                                          1. Рефакторинг fetch-функций на async/await
                                                                                          2. Функция loadUserWithPosts(userId) — user, затем его posts
                                                                                          3. @@ -61,7 +61,7 @@

                                                                                            Практика (лайт / MVP)

                                                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                            -

                                                                                            Если застрял

                                                                                            +

                                                                                          Если застрял

                                                                                          Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                          Git

                                                                                            diff --git a/docs/d/08-4.html b/docs/d/08-4.html index a6e839e..113fc70 100644 --- a/docs/d/08-4.html +++ b/docs/d/08-4.html @@ -30,7 +30,7 @@

                                                                                            Теория

                                                                                            - MDN: CORS - MDN: HTTP response status codes

                                                                                            Ключевая мысль: HTTP-метод + статус-код + заголовки — это язык, на котором клиент и сервер договариваются о результате операции.

                                                                                            -

                                                                                            Практика (полный трек)

                                                                                            +

                                                                                            Практика (полный трек)

                                                                                            1. В Network изучи headers реального запроса к API
                                                                                            2. Реализуй wrapper api.get/post/put/delete с базовым URL
                                                                                            3. @@ -44,7 +44,7 @@

                                                                                              Практика (полный трек)

                                                                                              - [ ] API wrapper переиспользуемый - [ ] Разные HTTP-ошибки — разные сообщения UI - [ ] Понимаю CORS на уровне «почему fetch заблокирован»

                                                                                              -

                                                                                              Практика (лайт / MVP)

                                                                                              +

                                                                                            Практика (лайт / MVP)

                                                                                            1. В Network изучи headers реального запроса к API
                                                                                            2. Реализуй wrapper api.get/post/put/delete с базовым URL
                                                                                            3. @@ -54,7 +54,7 @@

                                                                                              Практика (лайт / MVP)

                                                                                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                              -

                                                                                              Если застрял

                                                                                              +

                                                                                            Если застрял

                                                                                            Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                            Git

                                                                                              diff --git a/docs/d/08-5.html b/docs/d/08-5.html index c4d6a0b..5f7a6af 100644 --- a/docs/d/08-5.html +++ b/docs/d/08-5.html @@ -30,7 +30,7 @@

                                                                                              Теория

                                                                                              - web.dev: Optimize LCP — skeleton и perceived performance - MDN: AbortController

                                                                                              Ключевая мысль: надёжный API-клиент обрабатывает не только успех, но и повторы, гонки запросов, пагинацию и кэширование.

                                                                                              -

                                                                                              Практика (полный трек)

                                                                                              +

                                                                                              Практика (полный трек)

                                                                                              1. Пагинация постов: кнопка «Загрузить ещё» с cursor (id последнего)
                                                                                              2. Retry: 3 попытки с задержкой 1s, 2s, 4s при сетевой ошибке
                                                                                              3. @@ -44,7 +44,7 @@

                                                                                                Практика (полный трек)

                                                                                                - [ ] Retry реализован - [ ] Нет race condition в поиске - [ ] Pagination работает без дубликатов

                                                                                                -

                                                                                                Практика (лайт / MVP)

                                                                                                +

                                                                                              Практика (лайт / MVP)

                                                                                              1. Пагинация постов: кнопка «Загрузить ещё» с cursor (id последнего)
                                                                                              2. Retry: 3 попытки с задержкой 1s, 2s, 4s при сетевой ошибке
                                                                                              3. @@ -54,7 +54,7 @@

                                                                                                Практика (лайт / MVP)

                                                                                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                -

                                                                                                Если застрял

                                                                                                +

                                                                                              Если застрял

                                                                                              Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                              Git

                                                                                                diff --git a/docs/d/08-6.html b/docs/d/08-6.html index 110b462..028db10 100644 --- a/docs/d/08-6.html +++ b/docs/d/08-6.html @@ -31,7 +31,7 @@

                                                                                                Теория

                                                                                                - MDN: Promise.race() - learn.javascript.ru: Promise API

                                                                                                Ключевая мысль: выбирай Promise-утилиту по сценарию — all для «всё или ничего», allSettled для «что получилось», race для таймаутов.

                                                                                                -

                                                                                                Практика (полный трек)

                                                                                                +

                                                                                                Практика (полный трек)

                                                                                                1. Загрузи 5 URL через Promise.allSettled, покажи успешные и failed
                                                                                                2. Timeout wrapper: withTimeout(promise, 5000) через Promise.race
                                                                                                3. @@ -45,7 +45,7 @@

                                                                                                  Практика (полный трек)

                                                                                                  - [ ] allSettled и race использованы по назначению - [ ] Timeout на долгие запросы - [ ] Нет unhandled promise rejections в Console

                                                                                                  -

                                                                                                  Практика (лайт / MVP)

                                                                                                  +

                                                                                                Практика (лайт / MVP)

                                                                                                1. Загрузи 5 URL через Promise.allSettled, покажи успешные и failed
                                                                                                2. Timeout wrapper: withTimeout(promise, 5000) через Promise.race
                                                                                                3. @@ -55,7 +55,7 @@

                                                                                                  Практика (лайт / MVP)

                                                                                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                  -

                                                                                                  Если застрял

                                                                                                  +

                                                                                                Если застрял

                                                                                                Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                Git

                                                                                                  diff --git a/docs/d/08-7.html b/docs/d/08-7.html index cbd511e..b09d443 100644 --- a/docs/d/08-7.html +++ b/docs/d/08-7.html @@ -30,7 +30,7 @@

                                                                                                  Теория

                                                                                                  - patterns.dev: Observer Pattern - TypeScript Handbook: Generics — подготовка к неделе 10

                                                                                                  Ключевая мысль: async-архитектура — это явные состояния UI и чёткие границы между api, state и render.

                                                                                                  -

                                                                                                  Практика (полный трек)

                                                                                                  +

                                                                                                  Практика (полный трек)

                                                                                                  1. Реализуй хук-подобный паттерн createAsyncState() — subscribe на изменения
                                                                                                  2. UI автоматически реагирует на idle/loading/success/error
                                                                                                  3. @@ -44,7 +44,7 @@

                                                                                                    Практика (полный трек)

                                                                                                    - [ ] Явные состояния async-операций в UI - [ ] api / state / ui разделены - [ ] Проект работает без ошибок в Console

                                                                                                    -

                                                                                                    Практика (лайт / MVP)

                                                                                                    +

                                                                                                  Практика (лайт / MVP)

                                                                                                  1. Реализуй хук-подобный паттерн createAsyncState() — subscribe на изменения
                                                                                                  2. UI автоматически реагирует на idle/loading/success/error
                                                                                                  3. @@ -54,7 +54,7 @@

                                                                                                    Практика (лайт / MVP)

                                                                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                    -

                                                                                                    Если застрял

                                                                                                    +

                                                                                                  Если застрял

                                                                                                  Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                  Git

                                                                                                    diff --git a/docs/d/09-1.html b/docs/d/09-1.html index f474313..9ec705c 100644 --- a/docs/d/09-1.html +++ b/docs/d/09-1.html @@ -30,7 +30,7 @@

                                                                                                    Теория

                                                                                                    - MDN: Closures - javascript.info: Замыкание

                                                                                                    Ключевая мысль: замыкание — это функция плюс её лексическое окружение; на этом строятся приватность, фабрики и модульный паттерн.

                                                                                                    -

                                                                                                    Практика (полный трек)

                                                                                                    +

                                                                                                    Практика (полный трек)

                                                                                                    1. createCounter() — increment, decrement, getValue через closure
                                                                                                    2. Ловушка цикла: for (var i=0; ...) + setTimeout — исправь через let и closure
                                                                                                    3. @@ -52,7 +52,7 @@

                                                                                                      Практика (полный трек)

                                                                                                      [ ] Могу объяснить closure своими словами

                                                                                                  -

                                                                                                  Практика (лайт / MVP)

                                                                                                  +

                                                                                                  Практика (лайт / MVP)

                                                                                                  1. createCounter() — increment, decrement, getValue через closure
                                                                                                  2. Ловушка цикла: for (var i=0; ...) + setTimeout — исправь через let и closure
                                                                                                  3. @@ -62,7 +62,7 @@

                                                                                                    Практика (лайт / MVP)

                                                                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                    -

                                                                                                    Если застрял

                                                                                                    +

                                                                                                  Если застрял

                                                                                                  Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

                                                                                                  Git

                                                                                                  
                                                                                                  diff --git a/docs/d/09-2.html b/docs/d/09-2.html
                                                                                                  index 87871bf..e7560fd 100644
                                                                                                  --- a/docs/d/09-2.html
                                                                                                  +++ b/docs/d/09-2.html
                                                                                                  @@ -30,7 +30,7 @@ 

                                                                                                  Теория

                                                                                                  - learn.javascript.ru: Справка по оператору this - MDN: this

                                                                                                  Ключевая мысль: this — не переменная, а результат вызова; потеря контекста лечится bind, а стрелочные функции наследуют this снаружи.

                                                                                                  -

                                                                                                  Практика (полный трек)

                                                                                                  +

                                                                                                  Практика (полный трек)

                                                                                                  1. Демонстрация 4 правил this — 4 примера в Console
                                                                                                  2. Исправь button.addEventListener('click', obj.handleClick) через bind
                                                                                                  3. @@ -52,7 +52,7 @@

                                                                                                    Практика (полный трек)

                                                                                                    [ ] 4 правила this — конспект

                                                                                                -

                                                                                                Практика (лайт / MVP)

                                                                                                +

                                                                                                Практика (лайт / MVP)

                                                                                                1. Демонстрация 4 правил this — 4 примера в Console
                                                                                                2. Исправь button.addEventListener('click', obj.handleClick) через bind
                                                                                                3. @@ -62,7 +62,7 @@

                                                                                                  Практика (лайт / MVP)

                                                                                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                  -

                                                                                                  Если застрял

                                                                                                  +

                                                                                                Если застрял

                                                                                                Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                Git

                                                                                                
                                                                                                diff --git a/docs/d/09-3.html b/docs/d/09-3.html
                                                                                                index 1071b4b..64e000a 100644
                                                                                                --- a/docs/d/09-3.html
                                                                                                +++ b/docs/d/09-3.html
                                                                                                @@ -30,7 +30,7 @@ 

                                                                                                Теория

                                                                                                - learn.javascript.ru: F.prototype - MDN: Object.create()

                                                                                                Ключевая мысль: прототипная цепочка — механизм делегирования свойств; class лишь удобная обёртка над ним.

                                                                                                -

                                                                                                Практика (полный трек)

                                                                                                +

                                                                                                Практика (полный трек)

                                                                                                1. Constructor Person(name) + Person.prototype.greet
                                                                                                2. Student наследует Person через Object.create(Person.prototype)
                                                                                                3. @@ -52,7 +52,7 @@

                                                                                                  Практика (полный трек)

                                                                                                  [ ] Не поллю глобальные прототипы в production-коде

                                                                                              -

                                                                                              Практика (лайт / MVP)

                                                                                              +

                                                                                              Практика (лайт / MVP)

                                                                                              1. Constructor Person(name) + Person.prototype.greet
                                                                                              2. Student наследует Person через Object.create(Person.prototype)
                                                                                              3. @@ -62,7 +62,7 @@

                                                                                                Практика (лайт / MVP)

                                                                                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                -

                                                                                                Если застрял

                                                                                                +

                                                                                              Если застрял

                                                                                              Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                              Git

                                                                                              
                                                                                              diff --git a/docs/d/09-4.html b/docs/d/09-4.html
                                                                                              index 5a3958c..067388f 100644
                                                                                              --- a/docs/d/09-4.html
                                                                                              +++ b/docs/d/09-4.html
                                                                                              @@ -30,7 +30,7 @@ 

                                                                                              Теория

                                                                                              - learn.javascript.ru: Наследование классов - MDN: Classes

                                                                                              Ключевая мысль: class — это читаемый синтаксис над прототипами; #private и static делают модель данных явной и безопасной.

                                                                                              -

                                                                                              Практика (полный трек)

                                                                                              +

                                                                                              Практика (полный трек)

                                                                                              1. class TodoItem { constructor(title) ... toggle() }
                                                                                              2. class TodoList extends Array или композиция — список с методами add/remove
                                                                                              3. @@ -52,7 +52,7 @@

                                                                                                Практика (полный трек)

                                                                                                [ ] Private field использован

                                                                                            -

                                                                                            Практика (лайт / MVP)

                                                                                            +

                                                                                            Практика (лайт / MVP)

                                                                                            1. class TodoItem { constructor(title) ... toggle() }
                                                                                            2. class TodoList extends Array или композиция — список с методами add/remove
                                                                                            3. @@ -62,7 +62,7 @@

                                                                                              Практика (лайт / MVP)

                                                                                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                              -

                                                                                              Если застрял

                                                                                              +

                                                                                            Если застрял

                                                                                            Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                            Git

                                                                                            
                                                                                            diff --git a/docs/d/09-5.html b/docs/d/09-5.html
                                                                                            index bba704c..5f331f3 100644
                                                                                            --- a/docs/d/09-5.html
                                                                                            +++ b/docs/d/09-5.html
                                                                                            @@ -30,7 +30,7 @@ 

                                                                                            Теория

                                                                                            - patterns.dev: Module Pattern - patterns.dev

                                                                                            Ключевая мысль: паттерн оправдан, когда он снижает связанность или упрощает расширение — не когда добавляет абстракцию ради абстракции.

                                                                                            -

                                                                                            Практика (полный трек)

                                                                                            +

                                                                                            Практика (полный трек)

                                                                                            1. EventEmitter: on, off, emit — 50 строк
                                                                                            2. Подпиши UI на изменения store через Observer
                                                                                            3. @@ -52,7 +52,7 @@

                                                                                              Практика (полный трек)

                                                                                              [ ] Минимум 2 паттерна применены осознанно

                                                                                          -

                                                                                          Практика (лайт / MVP)

                                                                                          +

                                                                                          Практика (лайт / MVP)

                                                                                          1. EventEmitter: on, off, emit — 50 строк
                                                                                          2. Подпиши UI на изменения store через Observer
                                                                                          3. @@ -62,7 +62,7 @@

                                                                                            Практика (лайт / MVP)

                                                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                            -

                                                                                            Если застрял

                                                                                            +

                                                                                          Если застрял

                                                                                          UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                          Git

                                                                                          
                                                                                          diff --git a/docs/d/09-6.html b/docs/d/09-6.html
                                                                                          index da25088..a3b4809 100644
                                                                                          --- a/docs/d/09-6.html
                                                                                          +++ b/docs/d/09-6.html
                                                                                          @@ -31,7 +31,7 @@ 

                                                                                          Теория

                                                                                          - MDN: Array.prototype.reduce() - javascript.info: Рекурсия и стек

                                                                                          Ключевая мысль: pure functions + immutability + composition дают код, который легко тестировать, переиспользовать и рассуждать о нём.

                                                                                          -

                                                                                          Практика (полный трек)

                                                                                          +

                                                                                          Практика (полный трек)

                                                                                          1. Перепиши обработку списка только pure functions
                                                                                          2. pipe(...fns) — композиция справа налево
                                                                                          3. @@ -53,7 +53,7 @@

                                                                                            Практика (полный трек)

                                                                                            [ ] Понимаю риск stack overflow в рекурсии

                                                                                        -

                                                                                        Практика (лайт / MVP)

                                                                                        +

                                                                                        Практика (лайт / MVP)

                                                                                        1. Перепиши обработку списка только pure functions
                                                                                        2. pipe(...fns) — композиция справа налево
                                                                                        3. @@ -63,7 +63,7 @@

                                                                                          Практика (лайт / MVP)

                                                                                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                          -

                                                                                          Если застрял

                                                                                          +

                                                                                        Если застрял

                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                        Git

                                                                                        
                                                                                        diff --git a/docs/d/09-7.html b/docs/d/09-7.html
                                                                                        index 8394d95..58361a0 100644
                                                                                        --- a/docs/d/09-7.html
                                                                                        +++ b/docs/d/09-7.html
                                                                                        @@ -30,7 +30,7 @@ 

                                                                                        Теория

                                                                                        - ESLint: Getting Started - adr.github.io — формат Architecture Decision Records

                                                                                        Ключевая мысль: инструменты (ESLint, JSDoc, ADR) и принципы (SRP, явные контракты) готовят кодовую базу к росту и TypeScript.

                                                                                        -

                                                                                        Практика (полный трек)

                                                                                        +

                                                                                        Практика (полный трек)

                                                                                        1. Подключи ESLint (eslint:recommended) к проекту
                                                                                        2. Исправь все warnings
                                                                                        3. @@ -52,7 +52,7 @@

                                                                                          Практика (полный трек)

                                                                                          [ ] JSDoc на ключевых экспортах

                                                                                      -

                                                                                      Практика (лайт / MVP)

                                                                                      +

                                                                                      Практика (лайт / MVP)

                                                                                      1. Подключи ESLint (eslint:recommended) к проекту
                                                                                      2. Исправь все warnings
                                                                                      3. @@ -62,7 +62,7 @@

                                                                                        Практика (лайт / MVP)

                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                        -

                                                                                        Если застрял

                                                                                        +

                                                                                      Если застрял

                                                                                      Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                      Git

                                                                                      
                                                                                      diff --git a/docs/d/10-1.html b/docs/d/10-1.html
                                                                                      index b985cf9..1c2bd9b 100644
                                                                                      --- a/docs/d/10-1.html
                                                                                      +++ b/docs/d/10-1.html
                                                                                      @@ -30,7 +30,7 @@ 

                                                                                      Теория

                                                                                      - learn.javascript.ru: Типы - TSConfig Reference

                                                                                      Ключевая мысль: TypeScript ловит целый класс ошибок на этапе компиляции — типы это документация, которую нельзя проигнорировать.

                                                                                      -

                                                                                      Практика (полный трек)

                                                                                      +

                                                                                      Практика (полный трек)

                                                                                      1. Создай проект learning-log/week-10, инициализируй TypeScript
                                                                                      2. Перепиши utils.js из прошлых недель в utils.ts
                                                                                      3. @@ -52,7 +52,7 @@

                                                                                        Практика (полный трек)

                                                                                        [ ] Понимаю разницу .ts и .js на выходе

                                                                                    -

                                                                                    Практика (лайт / MVP)

                                                                                    +

                                                                                    Практика (лайт / MVP)

                                                                                    1. Создай проект learning-log/week-10, инициализируй TypeScript
                                                                                    2. Перепиши utils.js из прошлых недель в utils.ts
                                                                                    3. @@ -62,7 +62,7 @@

                                                                                      Практика (лайт / MVP)

                                                                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                      -

                                                                                      Если застрял

                                                                                      +

                                                                                    Если застрял

                                                                                    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                    Git

                                                                                    
                                                                                    diff --git a/docs/d/10-2.html b/docs/d/10-2.html
                                                                                    index d66da17..5779479 100644
                                                                                    --- a/docs/d/10-2.html
                                                                                    +++ b/docs/d/10-2.html
                                                                                    @@ -30,7 +30,7 @@ 

                                                                                    Теория

                                                                                    - Handbook: Narrowing - Total TypeScript: Beginners

                                                                                    Ключевая мысль: union + narrowing превращают TypeScript в инструмент моделирования состояний; unknown безопаснее any.

                                                                                    -

                                                                                    Практика (полный трек)

                                                                                    +

                                                                                    Практика (полный трек)

                                                                                    1. Тип Theme = 'light' | 'dark' для переключателя темы
                                                                                    2. Функция formatId(id: string | number): string с narrowing
                                                                                    3. @@ -52,7 +52,7 @@

                                                                                      Практика (полный трек)

                                                                                      [ ] Result pattern для ошибок API

                                                                                  -

                                                                                  Практика (лайт / MVP)

                                                                                  +

                                                                                  Практика (лайт / MVP)

                                                                                  1. Тип Theme = 'light' | 'dark' для переключателя темы
                                                                                  2. Функция formatId(id: string | number): string с narrowing
                                                                                  3. @@ -62,7 +62,7 @@

                                                                                    Практика (лайт / MVP)

                                                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                    -

                                                                                    Если застрял

                                                                                    +

                                                                                  Если застрял

                                                                                  Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                  Git

                                                                                  
                                                                                  diff --git a/docs/d/10-3.html b/docs/d/10-3.html
                                                                                  index f9d2dfa..e80d0b1 100644
                                                                                  --- a/docs/d/10-3.html
                                                                                  +++ b/docs/d/10-3.html
                                                                                  @@ -30,7 +30,7 @@ 

                                                                                  Теория

                                                                                  - Handbook: Utility Types - React TypeScript Cheatsheet

                                                                                  Ключевая мысль: interface/type — это контракт формы данных; DTO в отдельных файлах делают API и доменную модель явными.

                                                                                  -

                                                                                  Практика (полный трек)

                                                                                  +

                                                                                  Практика (полный трек)

                                                                                  1. Интерфейсы Todo, TodoFilter, TodoState для Todo App
                                                                                  2. interface ApiResponse<T> { data: T; meta: PaginationMeta }
                                                                                  3. @@ -52,7 +52,7 @@

                                                                                    Практика (полный трек)

                                                                                    [ ] Опциональные и readonly поля использованы

                                                                                -

                                                                                Практика (лайт / MVP)

                                                                                +

                                                                                Практика (лайт / MVP)

                                                                                1. Интерфейсы Todo, TodoFilter, TodoState для Todo App
                                                                                2. interface ApiResponse<T> { data: T; meta: PaginationMeta }
                                                                                3. @@ -62,7 +62,7 @@

                                                                                  Практика (лайт / MVP)

                                                                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                  -

                                                                                  Если застрял

                                                                                  +

                                                                                Если застрял

                                                                                Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                Git

                                                                                
                                                                                diff --git a/docs/d/10-4.html b/docs/d/10-4.html
                                                                                index 6d44000..8268545 100644
                                                                                --- a/docs/d/10-4.html
                                                                                +++ b/docs/d/10-4.html
                                                                                @@ -31,7 +31,7 @@ 

                                                                                Теория

                                                                                - Handbook: Keyof Types - Total TypeScript: Beginners

                                                                                Ключевая мысль: generics связывают типы входа и выхода — fetchJson<User> безопаснее fetchJson<any>.

                                                                                -

                                                                                Практика (полный трек)

                                                                                +

                                                                                Практика (полный трек)

                                                                                1. function first<T>(arr: T[]): T | undefined
                                                                                2. async function fetchJson<T>(url: string): Promise<T> — типизированный fetch
                                                                                3. @@ -53,7 +53,7 @@

                                                                                  Практика (полный трек)

                                                                                  [ ] Constraints использован хотя бы раз

                                                                              -

                                                                              Практика (лайт / MVP)

                                                                              +

                                                                              Практика (лайт / MVP)

                                                                              1. function first<T>(arr: T[]): T | undefined
                                                                              2. async function fetchJson<T>(url: string): Promise<T> — типизированный fetch
                                                                              3. @@ -63,7 +63,7 @@

                                                                                Практика (лайт / MVP)

                                                                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                -

                                                                                Если застрял

                                                                                +

                                                                              Если застрял

                                                                              Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                              Git

                                                                              
                                                                              diff --git a/docs/d/10-5.html b/docs/d/10-5.html
                                                                              index e12b364..9f349aa 100644
                                                                              --- a/docs/d/10-5.html
                                                                              +++ b/docs/d/10-5.html
                                                                              @@ -30,7 +30,7 @@ 

                                                                              Теория

                                                                              - Handbook: More on Functions - TypeScript 4.9: satisfies

                                                                              Ключевая мысль: utility types — конструктор из существующих типов; Partial/Pick/Omit заменяют ручное дублирование DTO.

                                                                              -

                                                                              Практика (полный трек)

                                                                              +

                                                                              Практика (полный трек)

                                                                              1. UpdateTodo = Partial<Pick<Todo, 'title' | 'done'>>
                                                                              2. Record<Theme, string> для CSS-переменных по темам
                                                                              3. @@ -52,7 +52,7 @@

                                                                                Практика (полный трек)

                                                                                [ ] EventEmitter типизирован

                                                                            -

                                                                            Практика (лайт / MVP)

                                                                            +

                                                                            Практика (лайт / MVP)

                                                                            1. UpdateTodo = Partial<Pick<Todo, 'title' | 'done'>>
                                                                            2. Record<Theme, string> для CSS-переменных по темам
                                                                            3. @@ -62,7 +62,7 @@

                                                                              Практика (лайт / MVP)

                                                                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                              -

                                                                              Если застрял

                                                                              +

                                                                            Если застрял

                                                                            Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                            Git

                                                                            
                                                                            diff --git a/docs/d/10-6.html b/docs/d/10-6.html
                                                                            index 4287151..1527b1c 100644
                                                                            --- a/docs/d/10-6.html
                                                                            +++ b/docs/d/10-6.html
                                                                            @@ -31,7 +31,7 @@ 

                                                                            Теория

                                                                            - Vite Guide - react.dev: Quick Start

                                                                            Ключевая мысль: Vite + react-ts даёт типизированный старт за минуту; props типизируй через interface, не через React.FC.

                                                                            -

                                                                            Практика (полный трек)

                                                                            +

                                                                            Практика (полный трек)

                                                                            1. Создай проект Vite + React + TypeScript в week-10/
                                                                            2. Перенеси типы Todo в src/types/todo.ts
                                                                            3. @@ -53,7 +53,7 @@

                                                                              Практика (полный трек)

                                                                              [ ] Типы вынесены в отдельные файлы

                                                                          -

                                                                          Практика (лайт / MVP)

                                                                          +

                                                                          Практика (лайт / MVP)

                                                                          1. Создай проект Vite + React + TypeScript в week-10/
                                                                          2. Перенеси типы Todo в src/types/todo.ts
                                                                          3. @@ -63,7 +63,7 @@

                                                                            Практика (лайт / MVP)

                                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                            -

                                                                            Если застрял

                                                                            +

                                                                          Если застрял

                                                                          Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                          Git

                                                                          
                                                                          diff --git a/docs/d/10-7.html b/docs/d/10-7.html
                                                                          index fb7a8fe..6b5b28b 100644
                                                                          --- a/docs/d/10-7.html
                                                                          +++ b/docs/d/10-7.html
                                                                          @@ -31,7 +31,7 @@ 

                                                                          Теория

                                                                          - DefinitelyTyped - TSConfig: noUncheckedIndexedAccess

                                                                          Ключевая мысль: миграция на TS — итеративный процесс; strict-опции и path aliases делают кодовую базу надёжнее с каждым коммитом.

                                                                          -

                                                                          Практика (полный трек)

                                                                          +

                                                                          Практика (полный трек)

                                                                          1. Настрой alias @/ в tsconfig и vite.config
                                                                          2. Мигрируй api-модуль в TS с полной типизацией
                                                                          3. @@ -53,7 +53,7 @@

                                                                            Практика (полный трек)

                                                                            [ ] noUncheckedIndexedAccess не ломает сборку

                                                                        -

                                                                        Практика (лайт / MVP)

                                                                        +

                                                                        Практика (лайт / MVP)

                                                                        1. Настрой alias @/ в tsconfig и vite.config
                                                                        2. Мигрируй api-модуль в TS с полной типизацией
                                                                        3. @@ -63,7 +63,7 @@

                                                                          Практика (лайт / MVP)

                                                                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                          -

                                                                          Если застрял

                                                                          +

                                                                        Если застрял

                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                        Git

                                                                        
                                                                        diff --git a/docs/d/11-1.html b/docs/d/11-1.html
                                                                        index 5637b26..6fb51e2 100644
                                                                        --- a/docs/d/11-1.html
                                                                        +++ b/docs/d/11-1.html
                                                                        @@ -30,7 +30,7 @@ 

                                                                        Теория

                                                                        - react.dev: Writing Markup with JSX - React — Quick Start

                                                                        Ключевая мысль: компонент — функция от props к UI; JSX — удобный синтаксис описания, а не HTML.

                                                                        -

                                                                        Практика (полный трек)

                                                                        +

                                                                        Практика (полный трек)

                                                                        1. Изучи структуру Vite react-ts проекта из недели 10
                                                                        2. Очисти App.tsx, создай разметку лендинга в JSX
                                                                        3. @@ -52,7 +52,7 @@

                                                                          Практика (полный трек)

                                                                          [ ] className вместо class

                                                                      -

                                                                      Практика (лайт / MVP)

                                                                      +

                                                                      Практика (лайт / MVP)

                                                                      1. Изучи структуру Vite react-ts проекта из недели 10
                                                                      2. Очисти App.tsx, создай разметку лендинга в JSX
                                                                      3. @@ -62,7 +62,7 @@

                                                                        Практика (лайт / MVP)

                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                        -

                                                                        Если застрял

                                                                        +

                                                                      Если застрял

                                                                      Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                      Git

                                                                      
                                                                      diff --git a/docs/d/11-2.html b/docs/d/11-2.html
                                                                      index 7f51938..fde74c4 100644
                                                                      --- a/docs/d/11-2.html
                                                                      +++ b/docs/d/11-2.html
                                                                      @@ -30,7 +30,7 @@ 

                                                                      Теория

                                                                      - react.dev: Thinking in React - React TypeScript Cheatsheet: Components

                                                                      Ключевая мысль: props — read-only вход компонента; данные вниз, события вверх через callbacks.

                                                                      -

                                                                      Практика (полный трек)

                                                                      +

                                                                      Практика (полный трек)

                                                                      1. Button с props: variant: 'primary' | 'secondary', size, disabled, onClick
                                                                      2. Card с title, children, опциональным footer
                                                                      3. @@ -52,7 +52,7 @@

                                                                        Практика (полный трек)

                                                                        [ ] Default props через деструктуризацию

                                                                    -

                                                                    Практика (лайт / MVP)

                                                                    +

                                                                    Практика (лайт / MVP)

                                                                    1. Button с props: variant: 'primary' | 'secondary', size, disabled, onClick
                                                                    2. Card с title, children, опциональным footer
                                                                    3. @@ -62,7 +62,7 @@

                                                                      Практика (лайт / MVP)

                                                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                      -

                                                                      Если застрял

                                                                      +

                                                                    Если застрял

                                                                    Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                    Git

                                                                    
                                                                    diff --git a/docs/d/11-3.html b/docs/d/11-3.html
                                                                    index 4adee10..7b556b3 100644
                                                                    --- a/docs/d/11-3.html
                                                                    +++ b/docs/d/11-3.html
                                                                    @@ -30,7 +30,7 @@ 

                                                                    Теория

                                                                    - react.dev: Conditional Rendering - react.dev: Fragment

                                                                    Ключевая мысль: стабильный key по id — не оптимизация, а корректность при изменении порядка и удалении элементов.

                                                                    -

                                                                    Практика (полный трек)

                                                                    +

                                                                    Практика (полный трек)

                                                                    1. Компонент TodoList — рендер массива Todo[]
                                                                    2. TodoItem с props: todo, onToggle, onDelete
                                                                    3. @@ -52,7 +52,7 @@

                                                                      Практика (полный трек)

                                                                      [ ] map возвращает JSX, не side effects

                                                                  -

                                                                  Практика (лайт / MVP)

                                                                  +

                                                                  Практика (лайт / MVP)

                                                                  1. Компонент TodoList — рендер массива Todo[]
                                                                  2. TodoItem с props: todo, onToggle, onDelete
                                                                  3. @@ -62,7 +62,7 @@

                                                                    Практика (лайт / MVP)

                                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                    -

                                                                    Если застрял

                                                                    +

                                                                  Если застрял

                                                                  Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                  Git

                                                                  
                                                                  diff --git a/docs/d/11-4.html b/docs/d/11-4.html
                                                                  index b905e08..1d7fed2 100644
                                                                  --- a/docs/d/11-4.html
                                                                  +++ b/docs/d/11-4.html
                                                                  @@ -30,7 +30,7 @@ 

                                                                  Теория

                                                                  - react.dev: Adding Interactivity - react.dev: Queueing a Series of State Updates

                                                                  Ключевая мысль: state обновляй иммутабельно; функциональный апдейт setX(x => ...) даёт актуальное значение при batching.

                                                                  -

                                                                  Практика (полный трек)

                                                                  +

                                                                  Практика (полный трек)

                                                                  1. Счётчик в Hero с useState
                                                                  2. Controlled input: value + onChange для поля новой задачи
                                                                  3. @@ -52,7 +52,7 @@

                                                                    Практика (полный трек)

                                                                    [ ] Нет прямой мутации массива todos

                                                                -

                                                                Практика (лайт / MVP)

                                                                +

                                                                Практика (лайт / MVP)

                                                                1. Счётчик в Hero с useState
                                                                2. Controlled input: value + onChange для поля новой задачи
                                                                3. @@ -62,7 +62,7 @@

                                                                  Практика (лайт / MVP)

                                                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                  -

                                                                  Если застрял

                                                                  +

                                                                Если застрял

                                                                Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                Git

                                                                
                                                                diff --git a/docs/d/11-5.html b/docs/d/11-5.html
                                                                index 213a5eb..3c42faa 100644
                                                                --- a/docs/d/11-5.html
                                                                +++ b/docs/d/11-5.html
                                                                @@ -30,7 +30,7 @@ 

                                                                Теория

                                                                - react.dev: Sharing State Between Components - react.dev: Form

                                                                Ключевая мысль: общий state — у ближайшего общего родителя; форма controlled, события — через callbacks вверх.

                                                                -

                                                                Практика (полный трек)

                                                                +

                                                                Практика (полный трек)

                                                                1. TodoApp — state todos, filter наверху
                                                                2. AddTodoForm — submit добавляет задачу, очищает input
                                                                3. @@ -52,7 +52,7 @@

                                                                  Практика (полный трек)

                                                                  [ ] Валидация пустого ввода

                                                              -

                                                              Практика (лайт / MVP)

                                                              +

                                                              Практика (лайт / MVP)

                                                              1. TodoApp — state todos, filter наверху
                                                              2. AddTodoForm — submit добавляет задачу, очищает input
                                                              3. @@ -62,7 +62,7 @@

                                                                Практика (лайт / MVP)

                                                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                -

                                                                Если застрял

                                                                +

                                                              Если застрял

                                                              UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                              Git

                                                              
                                                              diff --git a/docs/d/11-6.html b/docs/d/11-6.html
                                                              index b2ac344..7981dac 100644
                                                              --- a/docs/d/11-6.html
                                                              +++ b/docs/d/11-6.html
                                                              @@ -30,7 +30,7 @@ 

                                                              Теория

                                                              - CSS Modules — spec - MDN: CSS custom properties

                                                              Ключевая мысль: CSS Modules + логичная структура папок + CSS variables для темы — достаточный фундамент без CSS-in-JS.

                                                              -

                                                              Практика (полный трек)

                                                              +

                                                              Практика (полный трек)

                                                              1. CSS Modules для Button, Card, TodoItem
                                                              2. Утилита cn(...classes) для объединения классов
                                                              3. @@ -52,7 +52,7 @@

                                                                Практика (полный трек)

                                                                [ ] Тема переключается через state + class

                                                            -

                                                            Практика (лайт / MVP)

                                                            +

                                                            Практика (лайт / MVP)

                                                            1. CSS Modules для Button, Card, TodoItem
                                                            2. Утилита cn(...classes) для объединения классов
                                                            3. @@ -62,7 +62,7 @@

                                                              Практика (лайт / MVP)

                                                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                              -

                                                              Если застрял

                                                              +

                                                            Если застрял

                                                            Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                            Git

                                                            
                                                            diff --git a/docs/d/11-7.html b/docs/d/11-7.html
                                                            index d4d20c4..34cf470 100644
                                                            --- a/docs/d/11-7.html
                                                            +++ b/docs/d/11-7.html
                                                            @@ -30,7 +30,7 @@ 

                                                            Теория

                                                            - react.dev: useEffect - Vite: Deploy

                                                            Ключевая мысль: useEffect связывает React с внешним миром; production build + deploy завершают цикл от кода до живого приложения.

                                                            -

                                                            Практика (полный трек)

                                                            +

                                                            Практика (полный трек)

                                                            1. Persist todos в localStorage через useEffect
                                                            2. Загрузка начального state из localStorage (lazy init useState)
                                                            3. @@ -52,7 +52,7 @@

                                                              Практика (полный трек)

                                                              [ ] Live demo доступен по URL

                                                          -

                                                          Практика (лайт / MVP)

                                                          +

                                                          Практика (лайт / MVP)

                                                          1. Persist todos в localStorage через useEffect
                                                          2. Загрузка начального state из localStorage (lazy init useState)
                                                          3. @@ -62,7 +62,7 @@

                                                            Практика (лайт / MVP)

                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                            -

                                                            Если застрял

                                                            +

                                                          Если застрял

                                                          Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                          Git

                                                          
                                                          diff --git a/docs/d/12-78.html b/docs/d/12-78.html
                                                          index 5534c18..b2c2c8b 100644
                                                          --- a/docs/d/12-78.html
                                                          +++ b/docs/d/12-78.html
                                                          @@ -31,7 +31,7 @@ 

                                                          Теория

                                                          - react.dev: State: A Component's Memory - react.dev: Queueing a Series of State Updates

                                                          Ключевая мысль: state — снимок на рендер; обновляй иммутабельно и используй функциональный апдейт при последовательных изменениях.

                                                          -

                                                          Практика (полный трек)

                                                          +

                                                          Практика (полный трек)

                                                          1. Создай Vite-проект: npm create vite@latest week-12 -- --template react-ts в learning-log/
                                                          2. Компонент Counter с кнопками +1, -1, Сброс
                                                          3. @@ -53,7 +53,7 @@

                                                            Практика (полный трек)

                                                            [ ] DevTools React показывает обновления state

                                                        -

                                                        Практика (лайт / MVP)

                                                        +

                                                        Практика (лайт / MVP)

                                                        1. Создай Vite-проект: npm create vite@latest week-12 -- --template react-ts в learning-log/
                                                        2. Компонент Counter с кнопками +1, -1, Сброс
                                                        3. @@ -63,7 +63,7 @@

                                                          Практика (лайт / MVP)

                                                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                          -

                                                          Если застрял

                                                          +

                                                        Если застрял

                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                        Git

                                                        
                                                        diff --git a/docs/d/12-79.html b/docs/d/12-79.html
                                                        index e63b645..3fbbfe8 100644
                                                        --- a/docs/d/12-79.html
                                                        +++ b/docs/d/12-79.html
                                                        @@ -31,7 +31,7 @@ 

                                                        Теория

                                                        - React — Forms - react.dev: Controlled vs Uncontrolled

                                                        Ключевая мысль: controlled input = React state единственный источник правды; value + onChange для каждого поля.

                                                        -

                                                        Практика (полный трек)

                                                        +

                                                        Практика (полный трек)

                                                        1. Перепиши Todo App (vanilla JS) на React с useState
                                                        2. Поля: добавление задачи, чекбокс «выполнено», удаление
                                                        3. @@ -53,7 +53,7 @@

                                                          Практика (полный трек)

                                                          [ ] Фильтрация не мутирует исходный массив

                                                      -

                                                      Практика (лайт / MVP)

                                                      +

                                                      Практика (лайт / MVP)

                                                      1. Перепиши Todo App (vanilla JS) на React с useState
                                                      2. Поля: добавление задачи, чекбокс «выполнено», удаление
                                                      3. @@ -63,7 +63,7 @@

                                                        Практика (лайт / MVP)

                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                        -

                                                        Если застрял

                                                        +

                                                      Если застрял

                                                      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                      Git

                                                      
                                                      diff --git a/docs/d/12-80.html b/docs/d/12-80.html
                                                      index 57f709e..3a44c64 100644
                                                      --- a/docs/d/12-80.html
                                                      +++ b/docs/d/12-80.html
                                                      @@ -31,7 +31,7 @@ 

                                                      Теория

                                                      - You Might Not Need an Effect - react.dev: Synchronizing with Effects

                                                      Ключевая мысль: useEffect — для синхронизации с внешним миром; cleanup обязателен; не дублируй логику обработчиков событий.

                                                      -

                                                      Практика (полный трек)

                                                      +

                                                      Практика (полный трек)

                                                      1. DocumentTitle — меняет document.title при смене страницы/задачи
                                                      2. Таймер Pomodoro: 25 мин countdown, cleanup при unmount
                                                      3. @@ -53,7 +53,7 @@

                                                        Практика (полный трек)

                                                        [ ] Нет бесконечного цикла effect → setState → effect

                                                    -

                                                    Практика (лайт / MVP)

                                                    +

                                                    Практика (лайт / MVP)

                                                    1. DocumentTitle — меняет document.title при смене страницы/задачи
                                                    2. Таймер Pomodoro: 25 мин countdown, cleanup при unmount
                                                    3. @@ -63,7 +63,7 @@

                                                      Практика (лайт / MVP)

                                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                      -

                                                      Если застрял

                                                      +

                                                    Если застрял

                                                    Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                    Git

                                                    
                                                    diff --git a/docs/d/12-81.html b/docs/d/12-81.html
                                                    index 3d90c6c..00ae97f 100644
                                                    --- a/docs/d/12-81.html
                                                    +++ b/docs/d/12-81.html
                                                    @@ -31,7 +31,7 @@ 

                                                    Теория

                                                    - MDN: AbortController - JSONPlaceholder

                                                    Ключевая мысль: fetch в effect требует loading/error states, проверки res.ok, abort в cleanup и защиты от race condition.

                                                    -

                                                    Практика (полный трек)

                                                    +

                                                    Практика (полный трек)

                                                    1. Компонент PostList — GET /posts, спиннер при загрузке
                                                    2. Обработка ошибки сети — блок с кнопкой «Повторить»
                                                    3. @@ -53,7 +53,7 @@

                                                      Практика (полный трек)

                                                      [ ] Нет setState на размонтированном компоненте

                                                  -

                                                  Практика (лайт / MVP)

                                                  +

                                                  Практика (лайт / MVP)

                                                  1. Компонент PostList — GET /posts, спиннер при загрузке
                                                  2. Обработка ошибки сети — блок с кнопкой «Повторить»
                                                  3. @@ -63,7 +63,7 @@

                                                    Практика (лайт / MVP)

                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                    -

                                                    Если застрял

                                                    +

                                                  Если застрял

                                                  Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                  Git

                                                  
                                                  diff --git a/docs/d/12-82.html b/docs/d/12-82.html
                                                  index 47270b9..cd5fb86 100644
                                                  --- a/docs/d/12-82.html
                                                  +++ b/docs/d/12-82.html
                                                  @@ -31,7 +31,7 @@ 

                                                  Теория

                                                  - React — input - useId

                                                  Ключевая мысль: форма = набор controlled fields + валидация + сброс state; ошибки показывай после blur/submit, не мгновенно.

                                                  -

                                                  Практика (полный трек)

                                                  +

                                                  Практика (полный трек)

                                                  1. Форма регистрации: имя, email, пароль, роль (select)
                                                  2. Валидация перед submit: email формат, пароль ≥ 8 символов
                                                  3. @@ -53,7 +53,7 @@

                                                    Практика (полный трек)

                                                    [ ] type="password" и autoComplete настроены

                                                -

                                                Практика (лайт / MVP)

                                                +

                                                Практика (лайт / MVP)

                                                1. Форма регистрации: имя, email, пароль, роль (select)
                                                2. Валидация перед submit: email формат, пароль ≥ 8 символов
                                                3. @@ -63,7 +63,7 @@

                                                  Практика (лайт / MVP)

                                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                  -

                                                  Если застрял

                                                  +

                                                Если застрял

                                                Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                Git

                                                
                                                diff --git a/docs/d/12-83.html b/docs/d/12-83.html
                                                index 48daf50..80124b1 100644
                                                --- a/docs/d/12-83.html
                                                +++ b/docs/d/12-83.html
                                                @@ -31,7 +31,7 @@ 

                                                Теория

                                                - react.dev: Extracting State Logic into a Reducer — preview - useMemo

                                                Ключевая мысль: общий state — у ближайшего родителя; derived values вычисляй, не дублируй в useState.

                                                -

                                                Практика (полный трек)

                                                +

                                                Практика (полный трек)

                                                1. FilterableList: родитель хранит items + searchQuery
                                                2. SearchBar — только input, вызывает onSearchChange
                                                3. @@ -53,7 +53,7 @@

                                                  Практика (полный трек)

                                                  [ ] Нет дублирования state в siblings

                                              -

                                              Практика (лайт / MVP)

                                              +

                                              Практика (лайт / MVP)

                                              1. FilterableList: родитель хранит items + searchQuery
                                              2. SearchBar — только input, вызывает onSearchChange
                                              3. @@ -63,7 +63,7 @@

                                                Практика (лайт / MVP)

                                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                -

                                                Если застрял

                                                +

                                              Если застрял

                                              Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                              Git

                                              
                                              diff --git a/docs/d/12-84.html b/docs/d/12-84.html
                                              index d1611f8..c23a77b 100644
                                              --- a/docs/d/12-84.html
                                              +++ b/docs/d/12-84.html
                                              @@ -31,7 +31,7 @@ 

                                              Теория

                                              - Rules of Hooks - React Strict Mode

                                              Ключевая мысль: custom hooks выносят логику из компонентов; правила hooks и exhaustive-deps — страховка от типичных багов.

                                              -

                                              Практика (полный трек)

                                              +

                                              Практика (полный трек)

                                              1. Пройди React Tutorial — Tic-Tac-Toe до конца
                                              2. Рефакторинг Todo App: вынеси логику в useTodos (заготовка под custom hook)
                                              3. @@ -53,7 +53,7 @@

                                                Практика (полный трек)

                                                [ ] Конспект «useState vs useEffect — когда что» на 1 страницу

                                            -

                                            Практика (лайт / MVP)

                                            +

                                            Практика (лайт / MVP)

                                            1. Пройди React Tutorial — Tic-Tac-Toe до конца
                                            2. Рефакторинг Todo App: вынеси логику в useTodos (заготовка под custom hook)
                                            3. @@ -63,7 +63,7 @@

                                              Практика (лайт / MVP)

                                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                              -

                                              Если застрял

                                              +

                                            Если застрял

                                            Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                            Git

                                            
                                            diff --git a/docs/d/13-85.html b/docs/d/13-85.html
                                            index 7ecfd80..b53f0fb 100644
                                            --- a/docs/d/13-85.html
                                            +++ b/docs/d/13-85.html
                                            @@ -34,7 +34,7 @@ 

                                            Теория

                                          • useNavigate

                                          Ключевая мысль: SPA-навигация — смена компонентов без перезагрузки; для внутренних ссылок — Link, не <a>.

                                          -

                                          Практика (полный трек)

                                          +

                                          Практика (полный трек)

                                          1. npm install react-router-dom в learning-log/week-13/
                                          2. Страницы: / Home, /about About, /contact Contact
                                          3. @@ -56,7 +56,7 @@

                                            Практика (полный трек)

                                            [ ] Layout оборачивает все маршруты

                                        -

                                        Практика (лайт / MVP)

                                        +

                                        Практика (лайт / MVP)

                                        1. npm install react-router-dom в learning-log/week-13/
                                        2. Страницы: / Home, /about About, /contact Contact
                                        3. @@ -66,7 +66,7 @@

                                          Практика (лайт / MVP)

                                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                          -

                                          Если застрял

                                          +

                                        Если застрял

                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                        Git

                                        
                                        diff --git a/docs/d/13-86.html b/docs/d/13-86.html
                                        index 142ec8c..7071774 100644
                                        --- a/docs/d/13-86.html
                                        +++ b/docs/d/13-86.html
                                        @@ -33,7 +33,7 @@ 

                                        Теория

                                      • useLocation

                                      Ключевая мысль: путь описывает «где», query — «как показать»; параметры маршрута всегда строки.

                                      -

                                      Практика (полный трек)

                                      +

                                      Практика (полный трек)

                                      1. /blog — список постов, /blog/:slug — детальная страница
                                      2. Данные постов — mock JSON или JSONPlaceholder
                                      3. @@ -55,7 +55,7 @@

                                        Практика (полный трек)

                                        [ ] Breadcrumbs обновляются при навигации

                                    -

                                    Практика (лайт / MVP)

                                    +

                                    Практика (лайт / MVP)

                                    1. /blog — список постов, /blog/:slug — детальная страница
                                    2. Данные постов — mock JSON или JSONPlaceholder
                                    3. @@ -65,7 +65,7 @@

                                      Практика (лайт / MVP)

                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                      -

                                      Если застрял

                                      +

                                    Если застрял

                                    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                    Git

                                    
                                    diff --git a/docs/d/13-87.html b/docs/d/13-87.html
                                    index 573561e..9788ecc 100644
                                    --- a/docs/d/13-87.html
                                    +++ b/docs/d/13-87.html
                                    @@ -33,7 +33,7 @@ 

                                    Теория

                                  • renderHook (Testing Library)

                                  Ключевая мысль: custom hook извлекает логику, а не UI; правила хуков обязательны внутри него.

                                  -

                                  Практика (полный трек)

                                  +

                                  Практика (полный трек)

                                  1. Реализуй useLocalStorage с JSON parse/stringify
                                  2. useFetch(url) — возвращает { data, loading, error, refetch }
                                  3. @@ -55,7 +55,7 @@

                                    Практика (полный трек)

                                    [ ] useDebounce уменьшает количество фильтраций

                                -

                                Практика (лайт / MVP)

                                +

                                Практика (лайт / MVP)

                                1. Реализуй useLocalStorage с JSON parse/stringify
                                2. useFetch(url) — возвращает { data, loading, error, refetch }
                                3. @@ -65,7 +65,7 @@

                                  Практика (лайт / MVP)

                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                  -

                                  Если застрял

                                  +

                                Если застрял

                                Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                Git

                                
                                diff --git a/docs/d/13-88.html b/docs/d/13-88.html
                                index 5777fa7..b7a3f74 100644
                                --- a/docs/d/13-88.html
                                +++ b/docs/d/13-88.html
                                @@ -33,7 +33,7 @@ 

                                Теория

                              • Context — Caveats

                              Ключевая мысль: Context — для редко меняющихся глобальных данных; разделяй провайдеры и мемоизируй value.

                              -

                              Практика (полный трек)

                              +

                              Практика (полный трек)

                              1. ThemeContext: theme, toggleTheme, CSS-класс dark на <html>
                              2. UserContext: имя пользователя, setName — форма в Settings
                              3. @@ -55,7 +55,7 @@

                                Практика (полный трек)

                                [ ] Default value в createContext для dev-подсказок

                            -

                            Практика (лайт / MVP)

                            +

                            Практика (лайт / MVP)

                            1. ThemeContext: theme, toggleTheme, CSS-класс dark на <html>
                            2. UserContext: имя пользователя, setName — форма в Settings
                            3. @@ -65,7 +65,7 @@

                              Практика (лайт / MVP)

                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                              -

                              Если застрял

                              +

                            Если застрял

                            Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                            Git

                            
                            diff --git a/docs/d/13-89.html b/docs/d/13-89.html
                            index 5d7761f..3d0d97f 100644
                            --- a/docs/d/13-89.html
                            +++ b/docs/d/13-89.html
                            @@ -33,7 +33,7 @@ 

                            Теория

                          • useNavigate

                          Ключевая мысль: protected route проверяет сессию на уровне маршрута; persist в storage переживает перезагрузку.

                          -

                          Практика (полный трек)

                          +

                          Практика (полный трек)

                          1. AuthContext с user, login, logout (mock, без реального API)
                          2. ProtectedRoute — children или <Navigate to="/login" />
                          3. @@ -55,7 +55,7 @@

                            Практика (полный трек)

                            [ ] Login form — controlled inputs

                        -

                        Практика (лайт / MVP)

                        +

                        Практика (лайт / MVP)

                        1. AuthContext с user, login, logout (mock, без реального API)
                        2. ProtectedRoute — children или <Navigate to="/login" />
                        3. @@ -65,7 +65,7 @@

                          Практика (лайт / MVP)

                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                          -

                          Если застрял

                          +

                        Если застрял

                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                        Git

                        
                        diff --git a/docs/d/13-90.html b/docs/d/13-90.html
                        index c3a4431..53eb48b 100644
                        --- a/docs/d/13-90.html
                        +++ b/docs/d/13-90.html
                        @@ -34,7 +34,7 @@ 

                        Теория

                      • React.lazy

                      Ключевая мысль: оптимизируй после профилирования; lazy routes уменьшают начальный bundle.

                      -

                      Практика (полный трек)

                      +

                      Практика (полный трек)

                      1. Реорганизуй проект недели по папкам
                      2. Lazy-load страницу /admin с fallback-спиннером
                      3. @@ -56,7 +56,7 @@

                        Практика (полный трек)

                        [ ] Понятная структура папок

                    -

                    Практика (лайт / MVP)

                    +

                    Практика (лайт / MVP)

                    1. Реорганизуй проект недели по папкам
                    2. Lazy-load страницу /admin с fallback-спиннером
                    3. @@ -66,7 +66,7 @@

                      Практика (лайт / MVP)

                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                      -

                      Если застрял

                      +

                    Если застрял

                    Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                    Git

                    
                    diff --git a/docs/d/13-91.html b/docs/d/13-91.html
                    index 22f7456..7d80bce 100644
                    --- a/docs/d/13-91.html
                    +++ b/docs/d/13-91.html
                    @@ -32,7 +32,7 @@ 

                    Теория

                  • Error Boundaries

                  Ключевая мысль: выбор инструмента state — по частоте изменений и глубине дерева, не «всё в Context».

                  -

                  Практика (полный трек)

                  +

                  Практика (полный трек)

                  1. Добавь простой Error Boundary вокруг <Routes>
                  2. Пройди чеклист своего многостраничного приложения
                  3. @@ -54,7 +54,7 @@

                    Практика (полный трек)

                    [ ] Git commit за каждый день недели

                -

                Практика (лайт / MVP)

                +

                Практика (лайт / MVP)

                1. Добавь простой Error Boundary вокруг <Routes>
                2. Пройди чеклист своего многостраничного приложения
                3. @@ -64,7 +64,7 @@

                  Практика (лайт / MVP)

                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                  -

                  Если застрял

                  +

                Если застрял

                Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                Git

                
                diff --git a/docs/d/14-92.html b/docs/d/14-92.html
                index fe220d8..7f30922 100644
                --- a/docs/d/14-92.html
                +++ b/docs/d/14-92.html
                @@ -33,7 +33,7 @@ 

                Теория

              • Mobile-first CSS (MDN)

              Ключевая мысль: спланируй страницы и state до кода; секреты — только через VITE_* и .env.

              -

              Практика (полный трек)

              +

              Практика (полный трек)

              1. npm create vite@latest week-14 -- --template react-ts в learning-log/
              2. Установи react-router-dom, настрой Layout + 4 маршрута
              3. @@ -55,7 +55,7 @@

                Практика (полный трек)

                [ ] .env в .gitignore

            -

            Практика (лайт / MVP)

            +

            Практика (лайт / MVP)

            1. npm create vite@latest week-14 -- --template react-ts в learning-log/
            2. Установи react-router-dom, настрой Layout + 4 маршрута
            3. @@ -65,7 +65,7 @@

              Практика (лайт / MVP)

              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

              -

              Если застрял

              +

            Если застрял

            Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

            Git

            
            diff --git a/docs/d/14-93.html b/docs/d/14-93.html
            index 81fcadd..13457ab 100644
            --- a/docs/d/14-93.html
            +++ b/docs/d/14-93.html
            @@ -33,7 +33,7 @@ 

            Теория

          • Web Vitals — CLS

          Ключевая мысль: статистика — производная от данных tasks, не отдельный источник правды.

          -

          Практика (полный трек)

          +

          Практика (полный трек)

          1. Главная / — 4 карточки: задачи (total/done), погода, имя user, дата
          2. Данные задач из useLocalStorage('tasks')
          3. @@ -55,7 +55,7 @@

            Практика (полный трек)

            [ ] Контраст текста ≥ WCAG AA (проверь в DevTools)

        -

        Практика (лайт / MVP)

        +

        Практика (лайт / MVP)

        1. Главная / — 4 карточки: задачи (total/done), погода, имя user, дата
        2. Данные задач из useLocalStorage('tasks')
        3. @@ -65,7 +65,7 @@

          Практика (лайт / MVP)

          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

          -

          Если застрял

          +

        Если застрял

        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

        Git

        
        diff --git a/docs/d/14-94.html b/docs/d/14-94.html
        index ce52a2e..33e5db3 100644
        --- a/docs/d/14-94.html
        +++ b/docs/d/14-94.html
        @@ -33,7 +33,7 @@ 

        Теория

      • You Might Not Need an Effect

      Ключевая мысль: один useTasks на всё приложение; фильтры — derived state, не копия списка.

      -

      Практика (полный трек)

      +

      Практика (полный трек)

      1. Страница /tasks: форма добавления, список, фильтры (all/active/done)
      2. Редактирование inline или modal
      3. @@ -55,7 +55,7 @@

        Практика (полный трек)

        [ ] key стабильный (id), не index

    -

    Практика (лайт / MVP)

    +

    Практика (лайт / MVP)

    1. Страница /tasks: форма добавления, список, фильтры (all/active/done)
    2. Редактирование inline или modal
    3. @@ -65,7 +65,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

    
    diff --git a/docs/d/14-95.html b/docs/d/14-95.html
    index 6dd269d..5884bb3 100644
    --- a/docs/d/14-95.html
    +++ b/docs/d/14-95.html
    @@ -33,7 +33,7 @@ 

    Теория

  • Vite Env Variables

Ключевая мысль: API-слой отдельно от UI; loading/error/success — на каждом экране с данными.

-

Практика (полный трек)

+

Практика (полный трек)

  1. Страница /weather: input города, кнопка поиска
  2. Отображение: температура, описание, иконка, влажность, ветер
  3. @@ -55,7 +55,7 @@

    Практика (полный трек)

    [ ] Город по умолчанию из Settings

    -

    Практика (лайт / MVP)

    +

Практика (лайт / MVP)

  1. Страница /weather: input города, кнопка поиска
  2. Отображение: температура, описание, иконка, влажность, ветер
  3. @@ -65,7 +65,7 @@

    Практика (лайт / MVP)

    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

    -

    Если застрял

    +

Если застрял

Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

Git


diff --git a/docs/d/14-96.html b/docs/d/14-96.html
index 21d70ba..14e12c4 100644
--- a/docs/d/14-96.html
+++ b/docs/d/14-96.html
@@ -33,7 +33,7 @@ 

Теория

  • Context
  • Ключевая мысль: Settings — single source для темы, города и единиц; разделяй контексты по доменам.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. /settings: имя, город по умолчанию, переключатель темы, единицы °C/°F
    2. Изменения сразу отражаются на Dashboard и Weather
    3. @@ -55,7 +55,7 @@

      Практика (полный трек)

      [ ] Form labels связаны с inputs

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. /settings: имя, город по умолчанию, переключатель темы, единицы °C/°F
    2. Изменения сразу отражаются на Dashboard и Weather
    3. @@ -65,7 +65,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

    Git

    
    diff --git a/docs/d/14-97.html b/docs/d/14-97.html
    index 4e5d292..4d6eb3c 100644
    --- a/docs/d/14-97.html
    +++ b/docs/d/14-97.html
    @@ -33,7 +33,7 @@ 

    Теория

  • prefers-reduced-motion (MDN)
  • Ключевая мысль: a11y и mobile-first — часть Definition of Done, не «потом».

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Мобильное меню (hamburger → drawer)
    2. Toast-уведомления: задача добавлена, ошибка API
    3. @@ -55,7 +55,7 @@

      Практика (полный трек)

      [ ] Lighthouse Accessibility ≥ 90

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Мобильное меню (hamburger → drawer)
    2. Toast-уведомления: задача добавлена, ошибка API
    3. @@ -65,7 +65,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

    Git

    
    diff --git a/docs/d/14-98.html b/docs/d/14-98.html
    index 00bb091..2030476 100644
    --- a/docs/d/14-98.html
    +++ b/docs/d/14-98.html
    @@ -33,7 +33,7 @@ 

    Теория

  • Vitest (обзор для нед. 20)
  • Ключевая мысль: capstone-качество начинается с README, deploy preview и осмысленной git-истории.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Пройди user flow: первый визит → настройки → задачи → погода → смена темы → F5
    2. Напиши README с GIF или 3 скриншотами
    3. @@ -55,7 +55,7 @@

      Практика (полный трек)

      [ ] Preview URL в README

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Пройди user flow: первый визит → настройки → задачи → погода → смена темы → F5
    2. Напиши README с GIF или 3 скриншотами
    3. @@ -65,7 +65,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

    
    diff --git a/docs/d/15-100.html b/docs/d/15-100.html
    index 17fdb6f..bb26ea6 100644
    --- a/docs/d/15-100.html
    +++ b/docs/d/15-100.html
    @@ -33,7 +33,7 @@ 

    Теория

  • Truth Value Testing
  • Ключевая мысль: comprehension — сахар над циклом; is vs == — разные вещи для объектов.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. FizzBuzz 1–100
    2. Таблица умножения 10×10 через nested loops
    3. @@ -55,7 +55,7 @@

      Практика (полный трек)

      [ ] while с условием выхода, не while True без break

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. FizzBuzz 1–100
    2. Таблица умножения 10×10 через nested loops
    3. @@ -65,7 +65,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

    
    diff --git a/docs/d/15-101.html b/docs/d/15-101.html
    index 1d800fc..187198e 100644
    --- a/docs/d/15-101.html
    +++ b/docs/d/15-101.html
    @@ -33,7 +33,7 @@ 

    Теория

  • PEP 257 — Docstring Conventions
  • Ключевая мысль: mutable default argument — баг; type hints и docstrings — часть API функции.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Модуль utils.py: celsius_to_fahrenheit, format_currency, truncate_text
    2. CLI-конвертер валют (фиксированные курсы в dict)
    3. @@ -55,7 +55,7 @@

      Практика (полный трек)

      [ ] Модуль импортируется без запуска main-логики

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Модуль utils.py: celsius_to_fahrenheit, format_currency, truncate_text
    2. CLI-конвертер валют (фиксированные курсы в dict)
    3. @@ -65,7 +65,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

    Git

    
    diff --git a/docs/d/15-102.html b/docs/d/15-102.html
    index ca265b9..0fb096b 100644
    --- a/docs/d/15-102.html
    +++ b/docs/d/15-102.html
    @@ -33,7 +33,7 @@ 

    Теория

  • collections.Counter
  • Ключевая мысль: dict для поиска по ключу, list для порядка; выбор структуры — это Big-O.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Телефонная книга: dict[name] = phone, CRUD через меню
    2. Подсчёт частоты слов в тексте через dict
    3. @@ -55,7 +55,7 @@

      Практика (полный трек)

      [ ] Понимаешь O(1) lookup в dict vs O(n) в list

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Телефонная книга: dict[name] = phone, CRUD через меню
    2. Подсчёт частоты слов в тексте через dict
    3. @@ -65,7 +65,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

    Git

    
    diff --git a/docs/d/15-103.html b/docs/d/15-103.html
    index 24f1657..596ac01 100644
    --- a/docs/d/15-103.html
    +++ b/docs/d/15-103.html
    @@ -33,7 +33,7 @@ 

    Теория

  • pathlib
  • Ключевая мысль: всегда with open и encoding='utf-8'; JSON — контракт persist между запусками.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Расширь телефонную книгу: save/load contacts.json
    2. Логгер: append строки в app.log с timestamp
    3. @@ -55,7 +55,7 @@

      Практика (полный трек)

      [ ] Graceful handling если файл не существует

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Расширь телефонную книгу: save/load contacts.json
    2. Логгер: append строки в app.log с timestamp
    3. @@ -65,7 +65,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

    Git

    
    diff --git a/docs/d/15-104.html b/docs/d/15-104.html
    index 5e82a56..aa71c5c 100644
    --- a/docs/d/15-104.html
    +++ b/docs/d/15-104.html
    @@ -34,7 +34,7 @@ 

    Теория

  • rich
  • Ключевая мысль: пакетная структура + requirements.txt — основа любого Python-проекта.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Разбей телефонную книгу: models.py, storage.py, cli.py
    2. pip install rich — красивый вывод таблицы контактов
    3. @@ -56,7 +56,7 @@

      Практика (полный трек)

      [ ] rich Table для list contacts

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Разбей телефонную книгу: models.py, storage.py, cli.py
    2. pip install rich — красивый вывод таблицы контактов
    3. @@ -66,7 +66,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

    
    diff --git a/docs/d/15-105.html b/docs/d/15-105.html
    index b973297..9208954 100644
    --- a/docs/d/15-105.html
    +++ b/docs/d/15-105.html
    @@ -33,7 +33,7 @@ 

    Теория

  • HackerRank Python
  • Ключевая мысль: Python-проект = venv + модули + persist + README; стиль PEP 8 с первого коммита.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Реши 10 задач на HackerRank Python (Easy)
    2. Рефакторинг телефонной книги по PEP 8
    3. @@ -55,7 +55,7 @@

      Практика (полный трек)

      [ ] Шпаргалка в notes/python-structures.md

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Реши 10 задач на HackerRank Python (Easy)
    2. Рефакторинг телефонной книги по PEP 8
    3. @@ -65,7 +65,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

    Git

    
    diff --git a/docs/d/15-99.html b/docs/d/15-99.html
    index e4d22ec..0973efa 100644
    --- a/docs/d/15-99.html
    +++ b/docs/d/15-99.html
    @@ -33,7 +33,7 @@ 

    Теория

  • PEP 8
  • Ключевая мысль: venv на каждый проект; input() — всегда str, отступы — синтаксис.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Установи Python 3.11+, проверь python --version
    2. Создай проект learning-log/week-15, venv, pip install --upgrade pip
    3. @@ -55,7 +55,7 @@

      Практика (полный трек)

      [ ] Обработка деления на ноль

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Установи Python 3.11+, проверь python --version
    2. Создай проект learning-log/week-15, venv, pip install --upgrade pip
    3. @@ -65,7 +65,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

    Git

    
    diff --git a/docs/d/16-106.html b/docs/d/16-106.html
    index 2f140bf..7f33470 100644
    --- a/docs/d/16-106.html
    +++ b/docs/d/16-106.html
    @@ -32,7 +32,7 @@ 

    Теория

  • Real Python — OOP
  • Ключевая мысль: класс = данные + поведение; self обязателен; инкапсуляция через методы, не публичные поля.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Класс BankAccount: deposit, withdraw, balance, защита от отрицательного баланса
    2. Класс Transaction с датой, суммой, типом (deposit / withdraw)
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Инкапсуляция: баланс не меняется напрямую снаружи - [ ] __repr__ однозначно идентифицирует объект - [ ] Type hints на аргументах и return всех публичных методов

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Класс BankAccount: deposit, withdraw, balance, защита от отрицательного баланса
    2. Класс Transaction с датой, суммой, типом (deposit / withdraw)
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

    Git

      diff --git a/docs/d/16-107.html b/docs/d/16-107.html index a5db8d1..fa04aa9 100644 --- a/docs/d/16-107.html +++ b/docs/d/16-107.html @@ -32,7 +32,7 @@

      Теория

    • @dataclass

    Ключевая мысль: композиция чаще наследования; dataclass — для данных, class — для поведения.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. SavingsAccount с interest_rate, метод apply_interest() через super()
    2. Portfolio содержит list[Account] — композиция, не наследование
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] super().__init__() в дочернем классе - [ ] Portfolio не наследует Account — композиция - [ ] dataclass с валидацией суммы > 0

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. SavingsAccount с interest_rate, метод apply_interest() через super()
    2. Portfolio содержит list[Account] — композиция, не наследование
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

      diff --git a/docs/d/16-108.html b/docs/d/16-108.html index ac357fd..586f8fd 100644 --- a/docs/d/16-108.html +++ b/docs/d/16-108.html @@ -32,7 +32,7 @@

      Теория

    • Generators

    Ключевая мысль: dunder-методы — контракт с Python; generators — ленивость и экономия памяти.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Класс Playlist с __len__, __getitem__, итерацией по трекам
    2. Generator fibonacci(n) — первые n чисел без списка в памяти
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Playlist итерируется в for-loop - [ ] Generator не хранит весь ряд Фибоначчи в памяти - [ ] __eq__ согласован с hash (если используешь в set)

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Класс Playlist с __len__, __getitem__, итерацией по трекам
    2. Generator fibonacci(n) — первые n чисел без списка в памяти
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

    Git

      diff --git a/docs/d/16-109.html b/docs/d/16-109.html index d3abb17..c1d23f1 100644 --- a/docs/d/16-109.html +++ b/docs/d/16-109.html @@ -32,7 +32,7 @@

      Теория

    • Python TimeComplexity (wiki)

    Ключевая мысль: сначала правильная структура данных и алгоритм, потом микрооптимизации.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Реализуй linear search и binary search (sorted list)
    2. Замерь время на списке 10⁴ и 10⁶ элементов (time.perf_counter)
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Binary search работает только на sorted input - [ ] Замеры подтверждают разницу O(n) vs O(n²) - [ ] Two Sum hash map решение за один проход

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Реализуй linear search и binary search (sorted list)
    2. Замерь время на списке 10⁴ и 10⁶ элементов (time.perf_counter)
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

    Git

      diff --git a/docs/d/16-110.html b/docs/d/16-110.html index da3e450..d92b946 100644 --- a/docs/d/16-110.html +++ b/docs/d/16-110.html @@ -32,7 +32,7 @@

      Теория

    • argparse

    Ключевая мысль: Path(__file__).parent — якорь для путей; pathlib вместо строк.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Скрипт organize.py — сортирует файлы по расширению в подпапки
    2. Рекурсивный поиск *.py через rglob
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Только pathlib, не os.path (кроме env vars) - [ ] Dry-run режим работает - [ ] Обработка PermissionError

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Скрипт organize.py — сортирует файлы по расширению в подпапки
    2. Рекурсивный поиск *.py через rglob
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

    Git

      diff --git a/docs/d/16-111.html b/docs/d/16-111.html index 2d3ed8d..800de9c 100644 --- a/docs/d/16-111.html +++ b/docs/d/16-111.html @@ -32,7 +32,7 @@

      Теория

    • Regular Expression HOWTO

    Ключевая мысль: для поиска везде — search, не match; большие файлы — построчно.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Генератор mock server.log (1000 строк: timestamp, level, message)
    2. Парсер: извлечь все ERROR с датой через named groups
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Парсинг построчно (memory-efficient) - [ ] regex с named groups для timestamp и level - [ ] Итоговая статистика в читаемом виде

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Генератор mock server.log (1000 строк: timestamp, level, message)
    2. Парсер: извлечь все ERROR с датой через named groups
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

      diff --git a/docs/d/16-112.html b/docs/d/16-112.html index e23c0a5..48de035 100644 --- a/docs/d/16-112.html +++ b/docs/d/16-112.html @@ -32,7 +32,7 @@

      Теория

    • sqlite3

    Ключевая мысль: ООП — инструмент, не цель; простые данные — dataclass, сложная логика — классы.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Реши 3 задачи LeetCode Easy: Two Sum, Valid Parentheses, Merge Sorted Array
    2. Рефакторинг Expense Tracker на классы Expense, ExpenseStore
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] 3 LeetCode задачи приняты - [ ] ExpenseStore с save/load через pathlib - [ ] Конспект Big O на 1 страницу

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Реши 3 задачи LeetCode Easy: Two Sum, Valid Parentheses, Merge Sorted Array
    2. Рефакторинг Expense Tracker на классы Expense, ExpenseStore
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

    Git

      diff --git a/docs/d/17-113.html b/docs/d/17-113.html index c6ec031..9ebcf50 100644 --- a/docs/d/17-113.html +++ b/docs/d/17-113.html @@ -32,7 +32,7 @@

      Теория

    • SQL Style Guide

    Ключевая мысль: WHERE фильтрует строки, HAVING — группы; SQL описывает результат, не алгоритм.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Установи DB Browser for SQLite или sqlite3 CLI для быстрых экспериментов
    2. Создай БД «shop»: products, categories, orders с PRIMARY KEY
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Схема с PRIMARY KEY на каждой таблице - [ ] ≥ 10 осмысленных запросов в queries.sql - [ ] Понимаешь разницу WHERE vs HAVING

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Установи DB Browser for SQLite или sqlite3 CLI для быстрых экспериментов
    2. Создай БД «shop»: products, categories, orders с PRIMARY KEY
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

    Git

      diff --git a/docs/d/17-114.html b/docs/d/17-114.html index 63865b3..cad2932 100644 --- a/docs/d/17-114.html +++ b/docs/d/17-114.html @@ -32,7 +32,7 @@

      Теория

    • Transactions

    Ключевая мысль: JOIN связывает таблицы; DELETE/UPDATE без WHERE — инцидент.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Расширь shop: customers, order_items с FK
    2. Запрос: заказы с именами клиентов (INNER JOIN)
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] FOREIGN KEY между таблицами - [ ] JOIN-запрос возвращает ожидаемые строки - [ ] DELETE только с WHERE (не без него!)

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Расширь shop: customers, order_items с FK
    2. Запрос: заказы с именами клиентов (INNER JOIN)
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

    Git

      diff --git a/docs/d/17-115.html b/docs/d/17-115.html index 23c6d1b..b6ef3ca 100644 --- a/docs/d/17-115.html +++ b/docs/d/17-115.html @@ -32,7 +32,7 @@

      Теория

    • dbdiagram.io

    Ключевая мысль: нормализация защищает от дублирования; many-to-many — всегда junction table.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Спроектируй БД «Библиотека»: authors, books, borrowers, loans
    2. ER-диаграмма на dbdiagram.io или Mermaid в README
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Нет дублирования author name в books - [ ] Junction table для many-to-many (если нужна) - [ ] ER-диаграмма в repo

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Спроектируй БД «Библиотека»: authors, books, borrowers, loans
    2. ER-диаграмма на dbdiagram.io или Mermaid в README
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

    Git

      diff --git a/docs/d/17-116.html b/docs/d/17-116.html index ef7b165..40167c7 100644 --- a/docs/d/17-116.html +++ b/docs/d/17-116.html @@ -32,7 +32,7 @@

      Теория

    • Docker — postgres image

    Ключевая мысль: PostgreSQL — для multi-user и production; миграция учит диалектные различия.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Подними PostgreSQL (Docker или локально)
    2. Перенеси схему «Библиотека» в PostgreSQL через schema.sql
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Подключение к PG работает - [ ] Схема создана через SQL-скрипт schema.sql - [ ] Seed script seed.sql выполняется без ошибок

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Подними PostgreSQL (Docker или локально)
    2. Перенеси схему «Библиотека» в PostgreSQL через schema.sql
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

    Git

      diff --git a/docs/d/17-117.html b/docs/d/17-117.html index 8b2b547..6f081b8 100644 --- a/docs/d/17-117.html +++ b/docs/d/17-117.html @@ -32,7 +32,7 @@

      Теория

    • Use The Index, Luke

    Ключевая мысль: индекс — trade-off read vs write; EXPLAIN — единственный честный ответ «почему медленно».

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Таблица books с 10 000+ строк (скрипт scripts/generate_books.sql)
    2. EXPLAIN ANALYZE SELECT * FROM books WHERE title LIKE 'Python%' — без индекса
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Индекс создан на колонке поиска - [ ] EXPLAIN показывает Index Scan (или объясни почему Seq Scan) - [ ] Записаны выводы в notes/indexes.md

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Таблица books с 10 000+ строк (скрипт scripts/generate_books.sql)
    2. EXPLAIN ANALYZE SELECT * FROM books WHERE title LIKE 'Python%' — без индекса
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

    Git

      diff --git a/docs/d/17-118.html b/docs/d/17-118.html index 64a33f4..7ed6858 100644 --- a/docs/d/17-118.html +++ b/docs/d/17-118.html @@ -32,7 +32,7 @@

      Теория

    • python-dotenv

    Ключевая мысль: placeholders — не опция, а требование безопасности; commit явный или через context manager.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Расширь CLI Task Manager (нед.16): опция --db postgres vs sqlite
    2. DATABASE_URL из .env через python-dotenv
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Нет SQL injection — только placeholders - [ ] with conn: или try/finally close - [ ] .env.example с DATABASE_URL

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Расширь CLI Task Manager (нед.16): опция --db postgres vs sqlite
    2. DATABASE_URL из .env через python-dotenv
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

    Git

      diff --git a/docs/d/17-119.html b/docs/d/17-119.html index 2457916..3af4b8e 100644 --- a/docs/d/17-119.html +++ b/docs/d/17-119.html @@ -32,7 +32,7 @@

      Теория

    • SQL Style Guide

    Ключевая мысль: SQL — база; ORM — удобство поверх, не замена понимания JOIN и индексов.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Пройди 15 уроков SQLBolt без подсказок — отметь слабые темы
    2. Напиши 5 сложных запросов: JOIN + агрегат + HAVING + ORDER BY
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] 5 сложных запросов с JOIN и агрегатами - [ ] Ответы на «INNER vs LEFT JOIN» письменно - [ ] venv готов для недели 18

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Пройди 15 уроков SQLBolt без подсказок — отметь слабые темы
    2. Напиши 5 сложных запросов: JOIN + агрегат + HAVING + ORDER BY
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

    Git

      diff --git a/docs/d/18-120.html b/docs/d/18-120.html index 955e051..a3ad8ce 100644 --- a/docs/d/18-120.html +++ b/docs/d/18-120.html @@ -32,7 +32,7 @@

      Теория

    • Alembic

    Ключевая мысль: ORM model ≠ API schema; сессия — граница транзакции.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Проект library-api, venv, pip install sqlalchemy psycopg2-binary python-dotenv
    2. Модели Author, Book с one-to-many relationship
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] SQLAlchemy 2.0 style (Mapped, mapped_column) - [ ] relationship двусторонний с back_populates - [ ] Таблицы создаются в PostgreSQL

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Проект library-api, venv, pip install sqlalchemy psycopg2-binary python-dotenv
    2. Модели Author, Book с one-to-many relationship
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

    Git

      diff --git a/docs/d/18-121.html b/docs/d/18-121.html index 0187b03..8501b41 100644 --- a/docs/d/18-121.html +++ b/docs/d/18-121.html @@ -32,7 +32,7 @@

      Теория

    • N+1 problem (обзор)

    Ключевая мысль: N+1 лечится eager loading; select() API — стандарт SQLAlchemy 2.0.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. CRUD: create_author, get_authors, update_book, delete_book
    2. Запрос: все книги автора с join через relationship или explicit join
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] select() API, не legacy Query (1.x) - [ ] N+1 продемонстрирован и исправлен - [ ] Пагинация работает

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. CRUD: create_author, get_authors, update_book, delete_book
    2. Запрос: все книги автора с join через relationship или explicit join
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

    Git

      diff --git a/docs/d/18-122.html b/docs/d/18-122.html index e8c258b..6755ca5 100644 --- a/docs/d/18-122.html +++ b/docs/d/18-122.html @@ -32,7 +32,7 @@

      Теория

    • Pydantic Models

    Ключевая мысль: type hints + Pydantic = валидация и docs из коробки; response_model защищает API.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. main.py: FastAPI app, GET /health{"status": "ok"}
    2. In-memory CRUD для Note (id, title, body) — без БД пока
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] 422 при невалидном body - [ ] Response model отделён от create model - [ ] uvicorn --reload работает

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. main.py: FastAPI app, GET /health{"status": "ok"}
    2. In-memory CRUD для Note (id, title, body) — без БД пока
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

      diff --git a/docs/d/18-123.html b/docs/d/18-123.html index ec6f177..c55e13a 100644 --- a/docs/d/18-123.html +++ b/docs/d/18-123.html @@ -32,7 +32,7 @@

      Теория

    • Status Codes

    Ключевая мысль: одна DB session на request через Depends; HTTPException — явные ошибки API.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Подключи SQLAlchemy к FastAPI через Depends(get_db)
    2. GET /authors, POST /authors, GET /authors/{id}
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] DB session закрывается после каждого request - [ ] HTTPException с detail message - [ ] Endpoints покрывают CRUD authors

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Подключи SQLAlchemy к FastAPI через Depends(get_db)
    2. GET /authors, POST /authors, GET /authors/{id}
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

    Git

      diff --git a/docs/d/18-124.html b/docs/d/18-124.html index ff256cc..7954009 100644 --- a/docs/d/18-124.html +++ b/docs/d/18-124.html @@ -32,7 +32,7 @@

      Теория

    • HTTP Methods

    Ключевая мысль: REST = ресурсы + HTTP semantics; 409 для нарушения бизнес-правил.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Роутеры: routers/authors.py, books.py, loans.py
    2. CRUD для books и loans с Pydantic validation
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] APIRouter + prefix /api/v1 - [ ] Бизнес-правило: нельзя выдать уже выданную книгу → 409 - [ ] Swagger актуален

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Роутеры: routers/authors.py, books.py, loans.py
    2. CRUD для books и loans с Pydantic validation
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

    Git

      diff --git a/docs/d/18-125.html b/docs/d/18-125.html index 0104108..39d122e 100644 --- a/docs/d/18-125.html +++ b/docs/d/18-125.html @@ -32,7 +32,7 @@

      Теория

    • httpx

    Ключевая мысль: изолированная test DB; тесты на auth, 404, 409 — не только happy path.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. pip install pytest httpx
    2. Тесты: create author, get 404, create loan conflict → 409
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] ≥ 8 pytest тестов, все проходят - [ ] Test DB изолирована от dev - [ ] pytest -v в README

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. pip install pytest httpx
    2. Тесты: create author, get 404, create loan conflict → 409
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

    Git

      diff --git a/docs/d/18-126.html b/docs/d/18-126.html index fdd18bb..38fad48 100644 --- a/docs/d/18-126.html +++ b/docs/d/18-126.html @@ -32,7 +32,7 @@

      Теория

    • Mermaid

    Ключевая мысль: документация API — часть deliverable; OpenAPI из кода, не из Word.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. README: архитектура, запуск, env vars, примеры curl
    2. .env.example: DATABASE_URL, APP_ENV=development
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] curl примеры для всех основных endpoints - [ ] Структура проекта понятна новому разработчику - [ ] docker run postgres документирован

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. README: архитектура, запуск, env vars, примеры curl
    2. .env.example: DATABASE_URL, APP_ENV=development
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

      diff --git a/docs/d/19-127.html b/docs/d/19-127.html index 098c186..50cfd05 100644 --- a/docs/d/19-127.html +++ b/docs/d/19-127.html @@ -32,7 +32,7 @@

      Теория

    • fs.promises

    Ключевая мысль: Node — JS без браузера; ESM + fs.promises — современный baseline.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. mkdir notes-api && npm init -y, добавь "type": "module"
    2. CLI: node scripts/greet.js --name=Alex (parse process.argv)
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] ES modules (import/export) - [ ] fs.promises, не callback fs.readFile - [ ] npm script "greet" работает

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. mkdir notes-api && npm init -y, добавь "type": "module"
    2. CLI: node scripts/greet.js --name=Alex (parse process.argv)
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

    Git

      diff --git a/docs/d/19-128.html b/docs/d/19-128.html index 5f3c2bb..449a3fb 100644 --- a/docs/d/19-128.html +++ b/docs/d/19-128.html @@ -32,7 +32,7 @@

      Теория

    • async/await (MDN)

    Ключевая мысль: не блокируй event loop; await + try/catch на каждом I/O.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Перепиши file I/O на async/await с try/catch
    2. File watcher: логирует изменения notes.json, останавливается на SIGINT
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Нет callback hell — только async/await - [ ] Watcher корректно останавливается (SIGINT) - [ ] try/catch вокруг await

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Перепиши file I/O на async/await с try/catch
    2. File watcher: логирует изменения notes.json, останавливается на SIGINT
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

    Git

      diff --git a/docs/d/19-129.html b/docs/d/19-129.html index aae8f38..42bd882 100644 --- a/docs/d/19-129.html +++ b/docs/d/19-129.html @@ -32,7 +32,7 @@

      Теория

    • Express Routing

    Ключевая мысль: express.json() обязателен; app отдельно от server — тестируемость.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. npm install express, src/app.js, src/server.js
    2. CRUD /api/notes — хранение в JSON-файле через fs
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] express.json() подключён - [ ] RESTful URLs и методы - [ ] 201 на POST, 204 на DELETE

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. npm install express, src/app.js, src/server.js
    2. CRUD /api/notes — хранение в JSON-файле через fs
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

      diff --git a/docs/d/19-130.html b/docs/d/19-130.html index a529ff6..36a0677 100644 --- a/docs/d/19-130.html +++ b/docs/d/19-130.html @@ -32,7 +32,7 @@

      Теория

    • morgan

    Ключевая мысль: порядок middleware; Zod на входе, error handler на выходе цепочки.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Logger middleware: method, url, duration (Date.now до/после)
    2. Zod schema для Note: title min 1, body optional string
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Все ошибки проходят через error middleware - [ ] Zod на POST и PUT - [ ] morgan или custom logger

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Logger middleware: method, url, duration (Date.now до/после)
    2. Zod schema для Note: title min 1, body optional string
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

    Git

      diff --git a/docs/d/19-131.html b/docs/d/19-131.html index 09f1398..0570dfd 100644 --- a/docs/d/19-131.html +++ b/docs/d/19-131.html @@ -32,7 +32,7 @@

      Теория

    • dotenv

    Ключевая мысль: Pool, не Client; $1 placeholders — единственный безопасный способ.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. npm install pg dotenv
    2. src/db/pool.js — Pool из DATABASE_URL, тест SELECT NOW()
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Pool, не Client на каждый запрос - [ ] Параметризованные запросы ($1, $2) - [ ] dotenv, .env.example

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. npm install pg dotenv
    2. src/db/pool.js — Pool из DATABASE_URL, тест SELECT NOW()
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

    Git

      diff --git a/docs/d/19-132.html b/docs/d/19-132.html index af9323f..aebc11a 100644 --- a/docs/d/19-132.html +++ b/docs/d/19-132.html @@ -32,7 +32,7 @@

      Теория

    • Graceful Shutdown

    Ключевая мысль: routes тонкие, logic в services; health check — контракт с инфраструктурой.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Структура: src/routes/, controllers/, services/, db/pool.js
    2. Вынеси логику из routes в controller/service
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Routes тонкие — только маршрутизация - [ ] Service переиспользуется из controller - [ ] health check возвращает 503 если DB down

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Структура: src/routes/, controllers/, services/, db/pool.js
    2. Вынеси логику из routes в controller/service
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

    Git

      diff --git a/docs/d/19-133.html b/docs/d/19-133.html index 9c38f65..830ab81 100644 --- a/docs/d/19-133.html +++ b/docs/d/19-133.html @@ -32,7 +32,7 @@

      Теория

    • npm audit

    Ключевая мысль: Express и FastAPI решают одну задачу разными инструментами — выбор по команде и экосистеме.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Сравнительная таблица: FastAPI (нед.18) vs Express — 10 критериев в docs/compare.md
    2. Postman collection для Express API — export JSON
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] README полный (install, env, run, test) - [ ] Сравнительная таблица в docs - [ ] npm start и npm run dev работают

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Сравнительная таблица: FastAPI (нед.18) vs Express — 10 критериев в docs/compare.md
    2. Postman collection для Express API — export JSON
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

      diff --git a/docs/d/20-134.html b/docs/d/20-134.html index 4e08c9b..75f4f92 100644 --- a/docs/d/20-134.html +++ b/docs/d/20-134.html @@ -32,7 +32,7 @@

      Теория

    • OWASP Password Storage

    Ключевая мысль: hash + salt через bcrypt; одинаковые сообщения об ошибке login — против enumeration.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Таблица users(id, email UNIQUE, password_hash, created_at)
    2. Express: POST /auth/register, POST /auth/login
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Пароль никогда не логируется и не возвращается в JSON - [ ] Дубликат email → 409 - [ ] Неверный пароль → 401 (не 404)

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Таблица users(id, email UNIQUE, password_hash, created_at)
    2. Express: POST /auth/register, POST /auth/login
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

    Git

      diff --git a/docs/d/20-135.html b/docs/d/20-135.html index 0624eb2..b75f82a 100644 --- a/docs/d/20-135.html +++ b/docs/d/20-135.html @@ -32,7 +32,7 @@

      Теория

    • python-jose

    Ключевая мысль: JWT — подписанный контракт, не шифрование; user_id только из verified token.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Login возвращает { access_token, token_type: "bearer", expires_in }
    2. Middleware authenticateToken — verify JWT, req.user = { id, email }
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] JWT_SECRET в .env, не в коде - [ ] Expired token → 401 - [ ] user_id из token, не из body/query

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Login возвращает { access_token, token_type: "bearer", expires_in }
    2. Middleware authenticateToken — verify JWT, req.user = { id, email }
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

      diff --git a/docs/d/20-136.html b/docs/d/20-136.html index c252acc..1ef9de6 100644 --- a/docs/d/20-136.html +++ b/docs/d/20-136.html @@ -32,7 +32,7 @@

      Теория

    • express-rate-limit

    Ключевая мысль: безопасность — слои: hash, JWT, rate limit, headers, CORS, audit.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Rate limit на /auth/login: 5 попыток / 15 мин per IP
    2. helmet() в Express; FastAPI — security headers middleware (обзор)
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Rate limiting работает (429 Too Many Requests) - [ ] Helmet headers в response (проверь curl -I) - [ ] Чеклист OWASP заполнен в security-audit.md

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Rate limit на /auth/login: 5 попыток / 15 мин per IP
    2. helmet() в Express; FastAPI — security headers middleware (обзор)
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

    Git

      diff --git a/docs/d/20-137.html b/docs/d/20-137.html index 06b7ba2..8c6a732 100644 --- a/docs/d/20-137.html +++ b/docs/d/20-137.html @@ -32,7 +32,7 @@

      Теория

    • supertest

    Ключевая мысль: тестируй auth, 403 cross-user и 401 без token — не только happy path.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Тесты auth: register success, duplicate email 409, login, wrong password 401
    2. Fixture: test user + valid token в Authorization header
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] pytest все зелёные - [ ] Тесты не зависят от порядка выполнения - [ ] conftest.py с test database

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Тесты auth: register success, duplicate email 409, login, wrong password 401
    2. Fixture: test user + valid token в Authorization header
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

    Git

      diff --git a/docs/d/20-138.html b/docs/d/20-138.html index 384d168..cae6b2e 100644 --- a/docs/d/20-138.html +++ b/docs/d/20-138.html @@ -32,7 +32,7 @@

      Теория

    • userEvent

    Ключевая мысль: RTL — «как пользователь видит»; mock fetch, не implementation details.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom @testing-library/user-event
    2. Тест: Login form — submit вызывает API с email/password
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] vitest run проходит - [ ] Тесты ищут по role/label, не по className - [ ] ≥ 8 unit/component тестов

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom @testing-library/user-event
    2. Тест: Login form — submit вызывает API с email/password
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

    Git

      diff --git a/docs/d/20-139.html b/docs/d/20-139.html index c2ddb11..c464464 100644 --- a/docs/d/20-139.html +++ b/docs/d/20-139.html @@ -32,7 +32,7 @@

      Теория

    • MDN — HTTP Authentication

    Ключевая мысль: auth flow end-to-end — контракт между Context, api wrapper и protected routes.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. React (Vite + TS): Login/Register pages с валидацией форм
    2. AuthContext + useAuth() hook
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Full flow: register → login → access protected → logout - [ ] 401 от API → redirect login - [ ] Token не в URL query string

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. React (Vite + TS): Login/Register pages с валидацией форм
    2. AuthContext + useAuth() hook
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

    Git

      diff --git a/docs/d/20-140.html b/docs/d/20-140.html index 9469978..e8b2344 100644 --- a/docs/d/20-140.html +++ b/docs/d/20-140.html @@ -32,7 +32,7 @@

      Теория

    • pip-audit

    Ключевая мысль: CI + security audit — часть Definition of Done, не «после деплоя».

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. .github/workflows/ci.yml: pytest + vitest run на push
    2. npm audit и pip audit — отчёт в security-audit.md
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] CI workflow файл в .github/workflows/ - [ ] npm audit — нет critical без комментария - [ ] Auth flow задокументирован

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. .github/workflows/ci.yml: pytest + vitest run на push
    2. npm audit и pip audit — отчёт в security-audit.md
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

    Git

      diff --git a/docs/d/21-141.html b/docs/d/21-141.html index ef6ea94..2946253 100644 --- a/docs/d/21-141.html +++ b/docs/d/21-141.html @@ -32,7 +32,7 @@

      Теория

    • Vite proxy

    Ключевая мысль: CORS — согласие сервера; VITE_ prefix обязателен для клиентских env.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. React Dashboard (нед.14) или Secure Notes (нед.20) → fetch к Express/FastAPI API
    2. .env: VITE_API_URL=http://localhost:3000 (или 8000 для FastAPI)
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] CRUD через API, не localStorage - [ ] CORS настроен — нет ошибки в browser console - [ ] .env.example для обоих проектов

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. React Dashboard (нед.14) или Secure Notes (нед.20) → fetch к Express/FastAPI API
    2. .env: VITE_API_URL=http://localhost:3000 (или 8000 для FastAPI)
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

    Git

      diff --git a/docs/d/21-142.html b/docs/d/21-142.html index 3cd83e5..e59016a 100644 --- a/docs/d/21-142.html +++ b/docs/d/21-142.html @@ -32,7 +32,7 @@

      Теория

    • TanStack Query

    Ключевая мысль: один api module; loading/error/empty — не опциональный UX.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. services/api.ts — единый fetch wrapper с error parsing и auth header
    2. Все страницы: loading spinner, error message + retry button, empty state
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Один api module, не fetch в каждом компоненте - [ ] Network error показывает понятное сообщение - [ ] 4xx/5xx обрабатываются по-разному

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. services/api.ts — единый fetch wrapper с error parsing и auth header
    2. Все страницы: loading spinner, error message + retry button, empty state
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

    Git

      diff --git a/docs/d/21-143.html b/docs/d/21-143.html index 0d83cdf..bd7cb87 100644 --- a/docs/d/21-143.html +++ b/docs/d/21-143.html @@ -32,7 +32,7 @@

      Теория

    • .dockerignore

    Ключевая мысль: image = шаблон, container = процесс; слои Dockerfile — про скорость сборки.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Dockerfile для backend: node:20-alpine или python:3.12-slim
    2. COPY package files → install deps → COPY source → EXPOSE port → CMD
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Image собирается без ошибок - [ ] .dockerignore исключает node_modules - [ ] Container стартует и отвечает на /health

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Dockerfile для backend: node:20-alpine или python:3.12-slim
    2. COPY package files → install deps → COPY source → EXPOSE port → CMD
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

    Git

      diff --git a/docs/d/21-144.html b/docs/d/21-144.html index 915a7ed..7d5d592 100644 --- a/docs/d/21-144.html +++ b/docs/d/21-144.html @@ -32,7 +32,7 @@

      Теория

    • Multi-stage builds

    Ключевая мысль: в docker network хост БД — имя service, не localhost.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Frontend Dockerfile: stage 1 npm run build, stage 2 nginx:alpine + COPY dist
    2. docker run -d --name pg -e POSTGRES_PASSWORD=pass -v pgdata:/var/lib/postgresql/data postgres:16
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Frontend dist отдаётся nginx на port 80 - [ ] Postgres data сохраняется после restart container - [ ] Backend видит DB по hostname db (в compose network)

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Frontend Dockerfile: stage 1 npm run build, stage 2 nginx:alpine + COPY dist
    2. docker run -d --name pg -e POSTGRES_PASSWORD=pass -v pgdata:/var/lib/postgresql/data postgres:16
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

    Git

      diff --git a/docs/d/21-145.html b/docs/d/21-145.html index 4b42745..a3decc4 100644 --- a/docs/d/21-145.html +++ b/docs/d/21-145.html @@ -32,7 +32,7 @@

      Теория

    • docker compose CLI

    Ключевая мысль: compose + healthcheck + volumes = воспроизводимый full-stack локально.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. docker-compose.yml:
    2. DATABASE_URL=postgresql://user:pass@db:5432/tasks в backend env
    3. @@ -47,7 +47,7 @@

      Практика (полный трек)

      - [ ] Одна команда поднимает 3 сервиса - [ ] Данные PG в named volume pgdata - [ ] depends_on + healthcheck db

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. docker-compose.yml:
    2. DATABASE_URL=postgresql://user:pass@db:5432/tasks в backend env
    3. @@ -56,7 +56,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

    Git

      diff --git a/docs/d/21-146.html b/docs/d/21-146.html index e30426c..72e678b 100644 --- a/docs/d/21-146.html +++ b/docs/d/21-146.html @@ -32,7 +32,7 @@

      Теория

    • Docker secrets

    Ключевая мысль: dev/prod compose — разные файлы, одна документация в README.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. docker-compose.dev.yml — mount source, hot reload, exposed debug ports
    2. docker-compose.prod.yml — optimized builds, no volume mounts
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Dev и prod compose файлы документированы - [ ] Seed data появляется после первого up - [ ] Логи доступны через compose logs

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. docker-compose.dev.yml — mount source, hot reload, exposed debug ports
    2. docker-compose.prod.yml — optimized builds, no volume mounts
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

    Git

      diff --git a/docs/d/21-147.html b/docs/d/21-147.html index 4b3fa0e..9800526 100644 --- a/docs/d/21-147.html +++ b/docs/d/21-147.html @@ -32,7 +32,7 @@

      Теория

    • Health check pattern

    Ключевая мысль: smoke test + architecture diagram — входной билет в capstone неделю.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Smoke checklist в SMOKE_TEST.md: compose up → open app → login → CRUD task → refresh → persists
    2. Mermaid diagram в README: frontend, backend, db, volumes
    3. @@ -45,7 +45,7 @@

      Практика (полный трек)

      - [ ] Smoke test checklist пройден - [ ] Mermaid diagram в README - [ ] Все env vars в .env.example

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Smoke checklist в SMOKE_TEST.md: compose up → open app → login → CRUD task → refresh → persists
    2. Mermaid diagram в README: frontend, backend, db, volumes
    3. @@ -54,7 +54,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

    Git

      diff --git a/docs/d/22-148.html b/docs/d/22-148.html index ce8a8a2..74fbf9a 100644 --- a/docs/d/22-148.html +++ b/docs/d/22-148.html @@ -32,7 +32,7 @@

      Теория

    • Функции MVP

    Ключевая мысль: PLAN.md фиксирует scope; два backend одновременно — ловушка недели.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Прочитай весь раздел capstone и выпиши чеклист MVP (9 пунктов из projects.md)
    2. Выбери backend: FastAPI (нед. 18) или Express (нед. 19) — один основной стек
    3. @@ -48,7 +48,7 @@

      Практика (полный трек)

      - [ ] ≥ 10 user stories с acceptance criteria - [ ] ER-диаграмма и API list в repo - [ ] Repo создан, ветка main + strategy feature branches

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Прочитай весь раздел capstone и выпиши чеклист MVP (9 пунктов из projects.md)
    2. Выбери backend: FastAPI (нед. 18) или Express (нед. 19) — один основной стек
    3. @@ -58,7 +58,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

    Git

      diff --git a/docs/d/22-149.html b/docs/d/22-149.html index 42796b8..7123766 100644 --- a/docs/d/22-149.html +++ b/docs/d/22-149.html @@ -32,7 +32,7 @@

      Теория

    • FastAPI Bigger Applications

    Ключевая мысль: backend capstone = CRUD + schema + seed + OpenAPI до auth layer.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Инициализируй backend/ — FastAPI или Express по выбору из дня 148
    2. Модели/таблицы: users, tasks, notes, tags, note_tags (many-to-many)
    3. @@ -48,7 +48,7 @@

      Практика (полный трек)

      - [ ] Tasks и Notes CRUD работают (пока без auth — заглушка user_id) - [ ] OpenAPI/Swagger актуален - [ ] Seed выполняется одной командой

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Инициализируй backend/ — FastAPI или Express по выбору из дня 148
    2. Модели/таблицы: users, tasks, notes, tags, note_tags (many-to-many)
    3. @@ -58,7 +58,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

    Git

      diff --git a/docs/d/22-150.html b/docs/d/22-150.html index ce0524d..70cbb77 100644 --- a/docs/d/22-150.html +++ b/docs/d/22-150.html @@ -32,7 +32,7 @@

      Теория

    • Vite Env

    Ключевая мысль: один api.ts, три UI-состояния, shared components — фронтенд capstone в миниатюре.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. npm create vite@latest frontend -- --template react-ts
    2. React Router: Layout + routes /dashboard, /tasks, /notes, /profile
    3. @@ -48,7 +48,7 @@

      Практика (полный трек)

      - [ ] Tasks и Notes CRUD через API (без auth пока) - [ ] TypeScript strict, нет any в api layer - [ ] Loading и error states на всех data-fetching страницах

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. npm create vite@latest frontend -- --template react-ts
    2. React Router: Layout + routes /dashboard, /tasks, /notes, /profile
    3. @@ -58,7 +58,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

      diff --git a/docs/d/22-151.html b/docs/d/22-151.html index 606363e..7a5d1e5 100644 --- a/docs/d/22-151.html +++ b/docs/d/22-151.html @@ -32,7 +32,7 @@

      Теория

    • Auth в MVP

    Ключевая мысль: auth — сквозной слой; user_id только из verified JWT.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Backend auth: register, login, JWT middleware на все protected routes
    2. Привяжи tasks и notes к user_id из token — миграция если нужно
    3. @@ -48,7 +48,7 @@

      Практика (полный трек)

      - [ ] User A не видит данные User B - [ ] 401 без token, 403 на чужие ресурсы - [ ] SECURITY.md начат

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Backend auth: register, login, JWT middleware на все protected routes
    2. Привяжи tasks и notes к user_id из token — миграция если нужно
    3. @@ -58,7 +58,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

    Git

      diff --git a/docs/d/22-152.html b/docs/d/22-152.html index 09703aa..45b549f 100644 --- a/docs/d/22-152.html +++ b/docs/d/22-152.html @@ -32,7 +32,7 @@

      Теория

    • Infra в стеке

    Ключевая мысль: docker compose — часть MVP; VITE_API_URL для docker network, не localhost.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. docker-compose.yml: postgres + backend + frontend (nginx)
    2. Backend Dockerfile, Frontend multi-stage Dockerfile
    3. @@ -48,7 +48,7 @@

      Практика (полный трек)

      - [ ] Auth + CRUD работают через dockerized frontend - [ ] ARCHITECTURE.md с диаграммой - [ ] README local setup ≤ 5 команд

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. docker-compose.yml: postgres + backend + frontend (nginx)
    2. Backend Dockerfile, Frontend multi-stage Dockerfile
    3. @@ -58,7 +58,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

    Git

      diff --git a/docs/d/22-153.html b/docs/d/22-153.html index 48b5b03..5a1087b 100644 --- a/docs/d/22-153.html +++ b/docs/d/22-153.html @@ -32,7 +32,7 @@

      Теория

    • pytest · Vitest

    Ключевая мысль: CI green — критерий сдачи; тесты на auth и isolation обязательны.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Backend pytest: auth (register, login, 401), tasks CRUD, notes CRUD, 403 cross-user — ≥ 15 тестов
    2. Frontend Vitest: Login form, ProtectedRoute, TaskList, NoteEditor — ≥ 12 тестов
    3. @@ -47,7 +47,7 @@

      Практика (полный трек)

      - [ ] CI green on push - [ ] ESLint без ошибок (или задокументированные исключения) - [ ] Auth flow покрыт тестами

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Backend pytest: auth (register, login, 401), tasks CRUD, notes CRUD, 403 cross-user — ≥ 15 тестов
    2. Frontend Vitest: Login form, ProtectedRoute, TaskList, NoteEditor — ≥ 12 тестов
    3. @@ -57,7 +57,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному.

    Git

    Ключевая мысль: deploy + FINAL_REVIEW + profile README — три грани финиша capstone.

    -

    Практика (полный трек)

    +

    Практика (полный трек)

    1. Deploy backend: Render/Railway — connect repo, DATABASE_URL + JWT_SECRET
    2. Deploy DB: managed PostgreSQL, run migrations + seed
    3. @@ -50,7 +50,7 @@

      Практика (полный трек)

      - [ ] FINAL_REVIEW.md заполнен - [ ] GitHub profile README обновлён со ссылками на все 22 проекта - [ ] README DevHub — demo link, docker setup, architecture, tests

      -

      Практика (лайт / MVP)

      +

    Практика (лайт / MVP)

    1. Deploy backend: Render/Railway — connect repo, DATABASE_URL + JWT_SECRET
    2. Deploy DB: managed PostgreSQL, run migrations + seed
    3. @@ -61,7 +61,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      -

      Если застрял

      +

    Если застрял

    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

    Git

      diff --git a/docs/index.html b/docs/index.html index 72ee2b0..46a50ec 100644 --- a/docs/index.html +++ b/docs/index.html @@ -40,6 +40,7 @@ Введение Недели Проекты + Changelog Шпаргалки @@ -75,11 +76,15 @@

      Full-Stack разработчик за 22 недели

      Ваш прогресс: 0 / 23
      -
      Отмечайте недели и дни внутри урока — прогресс хранится локально
      +
      Отмечайте дни и недели — прогресс хранится локально и экспортируется в learning-log
      +
      + + +
      @@ -191,6 +196,22 @@

      Портфолио learning-log

      +
      +
      +
      +

      Карта прогресса

      +

      Отмеченные дни подсвечены. Следующий шаг — кнопка «Продолжить».

      +
      +
      +
      + + + +
      +

      Сохраните файл как learning-log/progress.json или создайте private gist и положите ссылку в README.

      +
      +
      +
      @@ -281,7 +302,7 @@

      Связь с GitHub

      @@ -295,6 +316,10 @@

      Связь с GitHub

      Загрузка…

      +
      + + +
      @@ -340,8 +365,8 @@

      forum

      - - + +