Финальный проект: защита и первые шаги в профессии
Сегодня вы показываете всё, чему научились за два месяца: защищаете собственный проект, повторяете курс целиком, собираете резюме и GitHub-профиль и забираете с собой личную шпаргалку промптов. Это не конец, а витрина: именно по ней работодатель или заказчик решит, стоит ли с вами разговаривать.
Понять требования к финальному проекту и критерии оценки 0–100
Повторить ключевые темы всех модулей и проверить себя на 16 задачах итогового самотеста
Провести защиту за 5 минут: демо, объяснение кода, ответы на вопросы
Дать полезный отзыв на чужое решение и спокойно принять отзыв на своё
Оформить GitHub-профиль, README и честное резюме для позиции junior frontend
Собрать личную шпаргалку из 10 рабочих промптов по формуле курса
Как работать с этой страницей
Это урок-финал, поэтому в нём много текста для чтения и подготовки: требования, критерии, план защиты, карьерный блок. Но практика тоже есть. Раздел 04 — итоговый самотест на 16 задач по всему курсу (функции, массивы, объекты, DOM, события, формы, async). В остальных разделах тоже есть небольшие задачи, и каждая проверяется автоматически, как на прошлых уроках. DOM-задачи решаются в песочнице с превью. Сам проект вы собираете у себя в VS Code, а здесь сверяетесь и тренируетесь.
01 Финальный проект: что нужно сдать
В мини-проектах идею вам давали. В финальном проекте идея ваша: вы сами решаете, какую задачу решает приложение, но обязательно согласовываете её с преподавателем до начала работы. Это защита от двух крайностей: слишком простой идеи («кнопка меняет цвет») и слишком огромной («свой Instagram»). Нужен проект, который вы реально можете довести до конца и объяснить.
Аналогия из жизни
Мастер-портной в Душанбе, прежде чем кроить дорогую ткань, показывает заказчику эскиз и договаривается о сроках. Идея проекта — это эскиз: пять минут разговора с преподавателем экономят вам неделю переделок.
Что должно быть в проекте
Проект проверяет весь курс сразу: JavaScript, DOM, async, а ещё Git, деплой и README. Обязательный минимум:
№
Требование
Откуда это знание
1
Своя идея, согласованная с преподавателем (описание в 3–5 предложениях: для кого, какую задачу решает, что умеет)
Урок 12: декомпозиция
2
Чистый JavaScript или JavaScript + Vite: функции, массивы, объекты; код разбит на понятные функции или модули
Уроки 2–7, 17, 20
3
Работа с DOM и событиями: интерфейс строится из данных, есть форма с валидацией, делегирование событий
Уроки 8–11
4
Данные: либо внешний API через fetch с состояниями «загрузка / ошибка / пусто / успех», либо состояние в localStorage (желательно и то и другое)
Уроки 11, 13–16
5
Git: репозиторий на GitHub, не менее 10 осмысленных коммитов, хотя бы одна ветка для новой возможности
Урок 19
6
Деплой: проект открывается по публичной ссылке (Vercel или GitHub Pages), а не только на вашем ноутбуке
Курс: деплой
7
README: что это, стек, как запустить, скриншот, ссылка на демо, что можно улучшить
Урок 20
8
Чистый код: понятные имена, нет мёртвого кода и лишних console.log, нет копипасты
Урок 20
Примеры идей подходящего размера
Подходит
Калькулятор расходов семьи в сомони с категориями и сохранением
Расписание занятий с фильтром по дням и «ближайшим уроком»
Приложение погоды по городам Таджикистана на публичном API
Каталог рецептов с поиском и избранным
Словарь «русский — таджикский» с карточками для повторения
Квиз по JavaScript с подсчётом результата и рекордом
Не подходит
Один экран без логики («красивый лендинг»)
Копия мини-проекта 1 или 2 с другим названием
Идея, которой нужен сервер, база данных и вход по паролю (это материал Уровня 3)
Проект из чужого туториала без своих изменений
Что-то слишком большое: «соцсеть», «онлайн-банк», «игра как GTA»
Правила курса действуют и здесь
ИИ разрешён, но по правилам: сначала 15 минут сами, никакого кода, который вы не можете объяснить строчку за строчкой, и на защите преподаватель вправе спросить про любую строку. Не смогли объяснить — баллы за эту часть снимаются. «Напиши мне весь проект» — гарантированный способ получить 0 на защите.
02 Как оценивается проект (0–100) и как считается итог курса
Финальный проект оценивается по шкале 0–100 и даёт 30% итоговой оценки курса. Это самый тяжёлый компонент, поэтому критерии прозрачны заранее.
Критерий
Баллы
Максимум ставим, если…
Частично, если…
Идея и функциональность
20
идея согласована, приложение решает заявленную задачу от начала до конца, нет «мёртвых» кнопок
часть возможностей не работает или сделана «для вида»
JavaScript, DOM, события
20
интерфейс строится из данных, есть валидация формы, делегирование, ошибки обработаны, нет дублирования
много ручных правок DOM, обработчики на каждый элемент
Данные и async
15
fetch или localStorage через try/catch, четыре состояния экрана, сломанные данные не роняют приложение
данные грузятся, но ошибка или пустой ответ ломают страницу
Git и деплой
10
10+ осмысленных коммитов, ветка с PR или merge, публичная ссылка работает
1–3 больших коммита или деплой «только у меня»
README и чистота кода
10
README со скриншотом и инструкцией своими словами, понятные имена, нет мусора
README формальный, в коде есть закомментированные куски
Интерфейс
5
аккуратный, работает на телефоне, есть состояния «пусто», :hover, :focus
работает, но как черновик
Защита
20
уложились в 5 минут, показали сценарий, объяснили код, честно ответили на вопросы, в том числе про ИИ
общие слова, потерялись на «объясни эту строку»
ИТОГО
100
Что снимает баллы
Не можете объяснить свой код — теряете баллы в том критерии, к которому он относится.
Нет публичной ссылки — максимум 5 из 10 за «Git и деплой».
Код скопирован у другого студента или целиком из чата без понимания — 0 за проект. Помогать друг другу можно, но каждый пишет и понимает своё.
Просрочка — по договорённости с преподавателем, до −10 баллов.
Итоговая оценка курса
Компонент
Вес
Как считается
Посещаемость
15%
доля посещённых уроков из проведённых
Домашние задания
30%
средний балл за 24 ДЗ (0–10 за каждое)
Мини-проекты (2 шт.)
25%
средний балл за мини-проект 1 и 2 (0–100)
Финальный проект
30%
защита на уроке 21 (0–100)
ИТОГО
100%
Шкала оценок
90–100 — Отлично
75–89 — Хорошо
60–74 — Удовлетворительно
менее 60 — Не аттестован
Условия выдачи сертификата
Посещаемость не ниже 70%
Сдано не менее 18 из 24 домашних заданий
Сданы оба мини-проекта
Финальный проект защищён с оценкой не ниже 60
Все четыре условия нужно выполнить одновременно. Посчитаем это кодом: правила — это просто числа и сравнения, а с ними вы уже умеете работать.
Практика: считаем свой итог
ЗАДАЧА 2.1
Итоговый балл
лёгкая
Допишите функцию finalScore(att, hw, mini, final). Посещаемость att — в процентах (0–100), среднее по ДЗ hw — от 0 до 10 (умножьте на 10, чтобы привести к 100), мини-проекты mini и финал final — от 0 до 100. Вес каждого компонента — из таблицы выше. Результат округлите до одного знака: Math.round(x * 10) / 10. Функция gradeLabel уже готова.
Алишер: 82.4 Хорошо
Мадина: 93.1 Отлично
Рустам: 56 Не аттестован
Подсказка 1
Каждый компонент приводим к 100 баллам и умножаем на вес: att * 0.15, hw * 10 * 0.30, mini * 0.25, final * 0.30.
Подсказка 2
const sum = att * 0.15 + hw * 10 * 0.3 + mini * 0.25 + final * 0.3; return Math.round(sum * 10) / 10;
ЗАДАЧА 2.2
Получит ли студент сертификат
средняя
Напишите функцию blockers(s): она возвращает массив названий невыполненных условий сертификата (пустой массив — всё выполнено). Названия: "посещаемость", "ДЗ", "мини-проекты", "финал", именно в таком порядке. Дальше код выводит вердикт.
Можно редактировать · Ctrl + Enter
functionblockers(s) {
const list = [];
// посещаемость >= 70, ДЗ сдано >= 18, оба мини-проекта сданы (2), финал >= 60return list;
}
const students = [
{ name: "Алишер", attendance: 85, homework: 20, miniProjects: 2, finalScore: 78 },
{ name: "Зарина", attendance: 65, homework: 17, miniProjects: 2, finalScore: 90 },
{ name: "Фарход", attendance: 90, homework: 24, miniProjects: 1, finalScore: 55 },
];
for (const s of students) {
const bad = blockers(s);
console.log(bad.length ===0 ? `${s.name}: сертификат` : `${s.name}: нет, не хватает — ${bad.join(", ")}`);
}
Ожидаемый результат
Алишер: сертификат
Зарина: нет, не хватает — посещаемость, ДЗ
Фарход: нет, не хватает — мини-проекты, финал
Подсказка 1
Четыре отдельных if: если условие не выполнено — list.push("название"). Не else if: проверять нужно все условия.
Подсказка 2
if (s.attendance < 70) list.push("посещаемость"); и так далее. Для мини-проектов: s.miniProjects < 2.
ЗАДАЧА 2.3
Сколько нужно набрать на защите
лёгкая
У Алишера уже известны посещаемость (90%), среднее по ДЗ (8) и мини-проекты (86). Сколько баллов на защите ему нужно, чтобы итог был не ниже 75 («Хорошо»)? Недостающие баллы — это target - known; они дают 30% итога, поэтому поделите на вес финала (0.3) и округлите вверх через Math.ceil. Выведите строку Нужно на защите: N.
Можно редактировать · Ctrl + Enter
const known = 90 * 0.15 + 8 * 10 * 0.3 + 86 * 0.25;
const target = 75;
// сколько баллов нужно на финале?
Ожидаемый результат
Нужно на защите: 54
Подсказка 1
Формула: (target - known) / 0.3. Результат дробный, поэтому его нужно округлить вверх.
Подсказка 2
const need = Math.ceil((target - known) / 0.3); console.log("Нужно на защите: " + need);
03 Повторение курса: пять модулей на одной странице
Перед защитой полезно пройтись по всему пути одним взглядом. Ниже — по одному компактному блоку на модуль: что вы умеете и что стоит вспомнить. Если какой-то пункт вызывает тревогу — откройте урок по ссылке и перечитайте его. Потом проверьте себя в разделе 04.
Аналогия из жизни
Перед экзаменом по вождению инструктор не учит заново, а даёт проехать маршрут: парковка, поворот, разворот. Повторение курса — тот же маршрут: пройдите все «остановки» и отметьте, где вы едете уверенно, а где притормаживаете.
Модуль 1 · JS-фундамент (уроки 1–6)
Урок 1. Старт: как JS живёт в браузере, script, консоль, DevTools.
Урок 2. Переменные:let / const, типы, typeof, приведение типов ("5" + 3 и "5" - 3).
Урок 24. Эффекты:useEffect + fetch, дорожная карта к Уровню 3 (React Pro + Next.js).
Как использовать этот список
Возьмите карандаш и поставьте напротив каждого урока: «могу объяснить другу», «понимаю, но с подсказкой» или «надо перечитать». На защите вас спросят именно про то, что отмечено «могу объяснить», поэтому честная оценка полезнее красивой.
04 Итоговый самотест: 16 задач по всему курсу
Это закрепление, а не экзамен: оценки за него нет, но результат покажет, где у вас слабые места. Правила простые: сначала решайте сами, без ИИ (как на контрольных уроков 6 и 18), подсказки открывайте только после честной попытки. Задачи идут по модулям: сначала фундамент (4.1–4.8), потом DOM, события и формы (4.9–4.11), потом async (4.12–4.14) и в конце — отладка и безопасная работа с данными (4.15–4.16).
Две ошибки, которые стоят баллов на защите
Первая: читать свойство у undefined. Вторая: забыть, что async-функция (и fetch) возвращает Promise, а не готовое значение. Вот как это выглядит:
Этот код выдаст ошибку · Ctrl + Enter
const user = { name: "Мадина" };
console.log(user.address.city); // ✖ TypeError: Cannot read properties of undefined (reading 'city')
Этот код выведет не то, что вы ожидаете · Ctrl + Enter
Починка: user.address?.city (или проверка перед чтением) и const price = await getPrice(); внутри async-функции. Если вы сразу видите, где ошибка, значит модуль 3 вы усвоили.
Модуль 1: функции, массивы, замыкания
ЗАДАЧА 4.1
Цена со скидкой
лёгкая
Напишите стрелочную функцию withDiscount(price, percent). Если скидка не передана, она равна 10%. Вызовы в коде внизу уже есть.
Значение параметра по умолчанию пишется прямо в скобках: (price, percent = 10). Обратите внимание: ноль тоже настоящее значение, percent = 10 сработает только при undefined.
Сначала не запуская код, запишите, что выведут шесть строк. Потом запустите и сверьтесь. Затем добавьте седьмую строку: преобразуйте строку "12px" в число через Number и выведите результат. Что получится и почему?
Оператор + со строкой склеивает, а - всегда считает как числа. Строки сравниваются посимвольно: "1" меньше "9".
Подсказка 2
console.log(Number("12px")); — строка не является числом целиком, поэтому результат NaN («не число»).
ЗАДАЧА 4.3
Оценки группы
лёгкая
Допишите функцию label(score) (шкала курса: от 90 — «Отлично», от 75 — «Хорошо», от 60 — «Удовлетворительно», иначе «Не аттестован») и цикл for...of, который выводит строки вида 95: Отлично. В конце выведите, сколько студентов не аттестованы.
Можно редактировать · Ctrl + Enter
const scores = [95, 82, 67, 45, 75];
// function label(score) { ... }// цикл for...of: выводим "балл: оценка", считаем не аттестованных
Ожидаемый результат
95: Отлично
82: Хорошо
67: Удовлетворительно
45: Не аттестован
75: Хорошо
Не аттестовано: 1
Подсказка 1
Заведите счётчик let failed = 0 до цикла и увеличивайте его, когда label(score) вернул «Не аттестован».
Подсказка 2
Условия идут сверху вниз: if (score >= 90) return "Отлично"; и так далее. Последняя строка функции — return "Не аттестован";.
ЗАДАЧА 4.4
Фильтр и среднее
средняя
Выведите двумя строками: имена всех, у кого балл не ниже 75 (через запятую, в исходном порядке), и средний балл группы A с одним знаком после запятой. Используйте filter, map и reduce.
Можно редактировать · Ctrl + Enter
const students = [
{ name: "Алишер", score: 92, group: "A" },
{ name: "Мадина", score: 78, group: "B" },
{ name: "Фарход", score: 64, group: "A" },
{ name: "Зарина", score: 88, group: "B" },
{ name: "Рустам", score: 55, group: "A" },
];
// 1) имена с баллом >= 75// 2) средний балл группы A, toFixed(1)
Ожидаемый результат
Алишер, Мадина, Зарина
Среднее по группе A: 70.3
Подсказка 1
Для имён: students.filter(...).map((s) => s.name).join(", "). Для среднего сначала отфильтруйте группу A.
Подсказка 2
const a = students.filter((s) => s.group === "A"); const avg = a.reduce((sum, s) => sum + s.score, 0) / a.length; и затем avg.toFixed(1).
ЗАДАЧА 4.5
Рейтинг без порчи исходного массива
средняя
Выведите тройку лучших в формате 1. Алишер — 92, не меняя исходный массив students. Последней строкой докажите, что исходный порядок цел: выведите имя первого студента в исходном массиве.
Можно редактировать · Ctrl + Enter
const students = [
{ name: "Мадина", score: 78 },
{ name: "Алишер", score: 92 },
{ name: "Фарход", score: 64 },
{ name: "Зарина", score: 88 },
];
// отсортируйте КОПИЮ по убыванию балла, выведите первых трёх
Ожидаемый результат
1. Алишер — 92
2. Зарина — 88
3. Мадина — 78
Первый в исходном списке: Мадина
Подсказка 1
sort меняет сам массив. Сделайте копию: [...students] или students.slice().
Подсказка 2
Сравнение для убывания: .sort((a, b) => b.score - a.score). Потом .slice(0, 3).forEach((s, i) => ...), номер — i + 1.
ЗАДАЧА 4.6
Обновляем объект, не ломая старый
средняя
Создайте через spread два новых объекта: paidOrder (копия order с paid: true) и movedOrder (копия, где у клиента город «Бохтар», остальные поля клиента сохранены). Исходный order меняться не должен. Проверочные строки уже написаны.
Для верхнего уровня: { ...order, paid: true }. Вложенный объект тоже нужно скопировать, иначе вы измените оригинал.
Подсказка 2
const movedOrder = { ...order, customer: { ...order.customer, city: "Бохтар" } }; Последняя строка выводит true: spread делает поверхностную копию, массив items у копий общий.
ЗАДАЧА 4.7
Считаем блюда по категориям
средняя
Постройте объект-счётчик { категория: количество } (через reduce или цикл), затем выведите его через Object.entries строками категория: N в порядке появления категорий.
Шаблон счётчика: counts[item.cat] = (counts[item.cat] ?? 0) + 1. Если ключа ещё нет, берём 0.
Подсказка 2
for (const [cat, n] of Object.entries(counts)) console.log(`${cat}: ${n}`);
ЗАДАЧА 4.8
Счётчик на замыкании
сложная
Напишите функцию makeCounter(step), которая возвращает объект с тремя методами: inc() (увеличивает значение на step), reset() (сбрасывает в 0) и value() (возвращает текущее значение). Значение хранится в замыкании, снаружи его нельзя изменить напрямую. У каждого счётчика своё значение.
Можно редактировать · Ctrl + Enter
// function makeCounter(step) { ... }const a = makeCounter(2);
a.inc();
a.inc();
console.log(a.value());
const b = makeCounter(5);
b.inc();
console.log(b.value(), a.value());
a.reset();
console.log(a.value());
Ожидаемый результат
4
5 4
0
Подсказка 1
Объявите let count = 0 внутри makeCounter, а не снаружи, иначе все счётчики будут делить одно значение.
Подсказка 2
return { inc() { count += step; }, reset() { count = 0; }, value() { return count; } }; Методы «помнят» count и step — это и есть замыкание.
Модуль 2: DOM, события, формы
ЗАДАЧА 4.9
Меню из массива
средняя
Постройте список блюд из массива dishes. Каждый пункт: <li> с текстом Название — N сомони. Блюда дороже 20 сомони получают класс hot. Используйте createElement, textContent, classList. Проверочные строки уже есть.
Меню из массива · Ctrl + Enter
<ulid="menu"></ul>
const menu = document.querySelector("#menu");
const dishes = [
{ name: "Плов", price: 25 },
{ name: "Салат", price: 12 },
{ name: "Лагман", price: 22 },
{ name: "Самбуса", price: 8 },
];
// для каждого блюда создайте li и добавьте в menu
console.log(menu.children.length);
console.log(menu.querySelectorAll(".hot").length);
console.log(menu.lastElementChild.textContent);
Предпросмотр
Нажмите «Запустить», чтобы увидеть результат.
Ожидаемый результат
4
2
Самбуса — 8 сомони
Подсказка 1
В цикле: const li = document.createElement("li"); li.textContent = ...;, затем menu.append(li).
Подсказка 2
if (dish.price > 20) li.classList.add("hot"); Текст: `${dish.name} — ${dish.price} сомони`.
ЗАДАЧА 4.10
Корзина: делегирование
средняя
Повесьте один обработчик click на список #cart: если клик пришёл по кнопке, удалите её пункт <li>. Код внизу сам «кликает» по кнопкам, в том числе по пункту, добавленному уже после навешивания обработчика, — делегирование должно сработать и для него.
Допишите обработчик submit: отмените отправку, возьмите значение поля через trim(). Если оно пустое, покажите в #err текст Введите название и ничего не добавляйте. Иначе добавьте <li> в список, очистите поле и сообщение об ошибке. Код внизу отправляет форму два раза.
Первая строка обработчика: event.preventDefault();. Потом const text = input.value.trim(); и ранний возврат при пустой строке.
Подсказка 2
Не забудьте очистить ошибку в успешной ветке: err.textContent = "";. Текст пункта задавайте через textContent, а не вставкой HTML-строки.
Модуль 3: async и ошибки
ЗАДАЧА 4.12
Загрузка списка с обработкой ошибки
средняя
Настоящую сеть в проверке использовать нельзя, поэтому «сервер» изображает fakeFetch: она отвечает через 30 мс, а по неизвестному адресу возвращает ok: false и статус 404. Напишите async-функцию loadList(url): она вызывает fakeFetch, при !res.ok бросает Error("HTTP " + res.status), иначе возвращает массив из res.json(). Затем вызовите её для двух адресов с try / catch / finally.
Внутри async-функции перед Promise ставим await: const res = await fakeFetch(url);. Ошибка через throw new Error(...) попадёт в catch вызывающего кода.
Подсказка 2
Сообщение ошибки — err.message. Блок finally выполняется и после успеха, и после ошибки. В main не забудьте await loadList(url).
ЗАДАЧА 4.13
Три запроса, один упал
сложная
Три запроса идут параллельно, один из них падает. Обычный Promise.all отбросил бы весь результат, поэтому используйте Promise.allSettled: выведите для каждого запроса строку название: ok (результат) или название: ошибка (сообщение), а в конце — сколько запросов прошло успешно.
студенты: ok (12)
преподаватели: ok (3)
оплаты: ошибка (Нет сети)
Успешно: 2 из 3
Подсказка 1
Promise.allSettled(requests.map((r) => r.run())) возвращает массив объектов { status: "fulfilled", value } или { status: "rejected", reason } в том же порядке, что и запросы.
Подсказка 2
Проходите по результатам с индексом: название берите из requests[i].name. Текст ошибки — result.reason.message. Успешные считайте фильтром по status === "fulfilled".
ЗАДАЧА 4.14
Порядок выполнения: предскажите event loop
сложная
Запишите в массив prediction порядок, в котором выполнятся шесть меток. Код сам запускает программу, собирает реальный порядок и сравнивает его с вашим. Сначала подумайте над ответом, потом запускайте: синхронный код идёт первым, затем микрозадачи (then, продолжение после await), и только потом таймеры.
start → A → end → B → promise → timeout
Прогноз верный: да
Подсказка 1
Синхронно выполнятся: start, затем тело f() до первого await (то есть A), затем end. Всё остальное ждёт.
Подсказка 2
В очередь микрозадач первым попало продолжение f() (B), вторым — then (promise). Последним, как макрозадача, идёт timeout.
Отладка и безопасные данные
ЗАДАЧА 4.15
Найди баги
лёгкая
Функция должна считать среднее арифметическое, а для пустого массива возвращать 0. Сейчас она выводит NaN. В ней два бага и не хватает одной защиты: найдите их по очереди, читая вывод, и исправьте.
Можно редактировать · Ctrl + Enter
functionaverage(numbers) {
let sum;
for (let i = 0; i <= numbers.length; i++) {
sum += numbers[i];
}
return sum / numbers.length;
}
console.log(average([4, 8, 6]));
console.log(average([]));
Ожидаемый результат
6
0
Подсказка 1
Что лежит в sum до первого сложения? А какой индекс у последнего элемента массива из трёх элементов?
Подсказка 2
let sum = 0;, условие цикла i < numbers.length, а в начале функции — if (numbers.length === 0) return 0;.
ЗАДАЧА 4.16
Безопасное чтение JSON
средняя
В localStorage может оказаться что угодно: пустая строка, мусор, неполный JSON. Напишите функцию safeParse(text, fallback): она возвращает результат JSON.parse(text), а при любой ошибке — значение fallback.
Защита — это короткий рассказ о том, что вы сделали и как это работает. Не презентация и не допрос: вам нужно показать, что проект ваш и вы его понимаете. Поэтому на защиту отведено 20 баллов из 100. Вы уже защищали мини-проект на уроке 12, сегодня то же самое, только проект крупнее и работает по публичной ссылке.
Аналогия из жизни
Мастер приносит заказчику готовый шкаф. Он не читает лекцию про дерево, а открывает дверцы, показывает ящики и отвечает: «Почему этот материал? Что если сломается петля?» Хороший мастер знает ответы, потому что сам сделал каждое соединение. Так и вы со своим кодом.
Структура защиты на 5 минут
Время
Что делаете
0:00–0:30
Представление. Одной фразой: что за приложение, для кого, какую проблему решает. «Это расписание занятий: открываешь и сразу видишь, какой урок ближайший».
0:30–2:00
Демо по сценарию. Открываете публичную ссылку (не localhost), проходите основной сценарий, показываете состояние ошибки или пустой список, обновляете страницу и показываете, что данные на месте.
2:00–3:30
Код и архитектура. Структура папок или файлов, где состояние, где отрисовка, где запросы к данным; один кусок кода, которым гордитесь; история коммитов на GitHub.
3:30–5:00
Вопросы. Преподаватель и группа спрашивают. Не знаете — скажите честно и предложите, как бы искали ответ.
Сценарий демо: готовим заранее
Демо ломается чаще всего не из-за кода, а из-за неподготовленности. Запишите сценарий на бумаге и прогоните его вслух хотя бы один раз с секундомером.
Откройте нужные вкладки заранее: задеплоенный сайт, репозиторий на GitHub, редактор с файлами. Увеличьте шрифт в редакторе и масштаб страницы (Ctrl +).
Основной сценарий — три-четыре действия, которые показывают главную ценность: например «ввёл город → увидел погоду → добавил в избранное».
Покажите, что приложение не падает: пустой ввод, отключённый интернет (во вкладке Network в DevTools можно выбрать Offline) или неверный запрос.
Обновите страницу (F5) и покажите, что данные восстановились.
Запасной план: заранее сделайте скриншот или короткую запись экрана. Если интернет в аудитории подведёт, вы не растеряетесь.
Закончите фразой-мостиком: «Теперь покажу, как это устроено в коде».
12 типичных вопросов и о чём на них нужно сказать
1. Почему ты выбрал эту идею и для кого она?
Один реальный пользователь (вы сами, семья, одногруппники) и одна проблема. Не «всем нужно», а «мне нужно, потому что…».
2. Как устроен проект: какие файлы и за что они отвечают?
Назовите роли: данные и запросы, состояние, отрисовка, обработчики событий. Если модули — какой файл что экспортирует.
3. Что такое state и где он у тебя?
Один объект со всеми данными приложения, страница рисуется из него. Покажите его в коде и скажите, что в нём лежит.
4. Что происходит от клика по кнопке до изменения на экране?
Событие → обработчик → изменение состояния → render → сохранение. Прочертите цепочку на своём коде.
5. Откуда берутся данные и как ты обрабатываешь ошибку?
Покажите fetch, проверку response.ok, try / catch и четыре состояния экрана: загрузка, ошибка, пусто, успех.
6. Объясни async / await на своём примере.
await ждёт Promise и не блокирует страницу; функция с await обязана быть async; ошибки ловим try / catch. Если есть параллельные запросы — Promise.all.
7. Что в localStorage и что если там мусор?
JSON-строка по ключу проекта. Хранилище понимает только строки: JSON.stringify при записи, JSON.parse в try / catch при чтении, при ошибке стартуем с пустого состояния.
8. Как ты работал с Git: ветки, коммиты, как откатишь ошибку?
Покажите историю: осмысленные сообщения, ветку под новую функцию. Откат: git revert (безопасно) или возврат к коммиту; чего нельзя делать с общей веткой — переписывать историю.
9. Как развёрнут проект и что будет, если сборка упадёт?
Где задеплоено (Vercel или GitHub Pages), как обновляется (push в ветку), где смотреть лог сборки. Честно: «ошибку в логе читаю сверху, ищу первую красную строку».
10. Какой баг был самым сложным и как ты его нашёл?
Конкретика: что ожидали, что получили, какие гипотезы проверили, чем помогли DevTools и console.log. История поиска ценится выше, чем «у меня не было багов».
11. Где ты использовал ИИ? Объясни вот эту строку.
Скажите правду: что просили (план, объяснение ошибки, проверка), что изменили сами. Любую строку из показанных нужно объяснить своими словами. Не можете — честно скажите и разберите вслух.
12. Что бы ты улучшил, будь у тебя ещё неделя?
Один-два конкретных пункта: тесты, редактирование, адаптив, перенос на React. Это показывает, что вы видите границы своего проекта.
Что ломает защиту
Читать код вслух строка за строкой, оправдываться («я не успел») и придумывать ответ, когда не знаете. Лучше: «этого нет, потому что… вот как я бы это добавил» и «не помню, но найду в документации и покажу». Преподаватель оценивает понимание, а не идеальность.
Как обсуждать чужие решения
Во время защит остальные не отдыхают: слушайте, смотрите и записывайте. После каждого выступления есть минута на реакцию группы. Правила простые: говорим о проекте, а не о человеке, и каждое замечание содержит четыре части.
Полезная реакция
«Мне понравилось, что при ошибке сети показывается кнопка „Повторить“»
«В функции render много условий; можно вынести часть в отдельную функцию, тогда её будет проще читать»
«А что будет, если API вернёт пустой массив?»
«Как бы ты это сделал иначе, если бы данных было в десять раз больше?»
Бесполезная реакция
«Нормально» и «ужас», без пояснений
«У меня лучше» или «я бы сделал не так»
Обсуждение автора («ты вечно не успеваешь»)
Подсказка, как «правильно», без вопроса о причинах решения
Что получилось: два-три конкретных плюса.
Где вижу риск: место, где приложение может сломаться, и как вы это проверили.
Вопрос: «почему так?» вместо «это неправильно».
Предложение: одно конкретное улучшение. Автор решает, принимать ли его.
Принимать отзыв тоже нужно уметь: не спорьте сразу, запишите замечание, поблагодарите и подумайте после защиты. Автор вправе не согласиться, но должен объяснить почему.
Практика: репетиция защиты
ЗАДАЧА 5.1
Тайминг защиты
лёгкая
Составьте расписание защиты: для каждого блока выведите строку начало–конец название в формате м:сс, а в конце — общую длительность. Время начала каждого следующего блока — это конец предыдущего. Функция fmt переводит секунды в м:сс, она уже готова.
0:00–0:30 Представление
0:30–2:00 Демо
2:00–3:30 Код и архитектура
3:30–5:00 Вопросы
Итого: 5:00
Подсказка 1
Заведите переменную let t = 0. В цикле запомните начало (t), прибавьте part.sec, и конец — это новое значение t.
Подсказка 2
console.log(`${fmt(start)}–${fmt(t)} ${part.name}`);, а после цикла — console.log("Итого: " + fmt(t));.
ЗАДАЧА 5.2
Сводка обратной связи
сложная
После защит собрали заметки группы: каждая — это { to, kind, text }, где kind — "plus" (что хорошо) или "minus" (что улучшить). Сгруппируйте заметки по проектам (в порядке первого появления) и выведите для каждого Имя: плюсов N, улучшений M. В конце назовите проект с наибольшим числом улучшений.
Можно редактировать · Ctrl + Enter
const notes = [
{ to: "Мадина", kind: "plus", text: "Понятное демо" },
{ to: "Фарход", kind: "minus", text: "Нет обработки ошибки сети" },
{ to: "Мадина", kind: "plus", text: "Аккуратный код" },
{ to: "Зарина", kind: "plus", text: "Хороший README" },
{ to: "Фарход", kind: "plus", text: "Интересная идея" },
{ to: "Мадина", kind: "minus", text: "Длинная функция render" },
{ to: "Фарход", kind: "minus", text: "Много console.log" },
{ to: "Зарина", kind: "plus", text: "Есть состояния загрузки" },
{ to: "Фарход", kind: "minus", text: "Нет деплоя" },
{ to: "Зарина", kind: "plus", text: "Чистая история коммитов" },
];
// 1) stats = { имя: { plus, minus } }// 2) выведите строки, затем проект с максимумом minus
Ожидаемый результат
Мадина: плюсов 2, улучшений 1
Фарход: плюсов 1, улучшений 3
Зарина: плюсов 3, улучшений 0
Больше всего улучшений: Фарход (3)
Подсказка 1
Для каждой заметки: если у stats[note.to] ещё нет записи, создайте { plus: 0, minus: 0 }. Потом stats[note.to][note.kind]++ (ключи совпадают со значением kind).
Подсказка 2
Порядок ключей объекта — порядок добавления, поэтому Object.entries(stats) уже даст нужный порядок. Максимум ищите циклом, сравнивая minus с лучшим на данный момент.
Хороший проект, который никто не видел, не помогает найти работу. Этот раздел про то, как показать себя честно и ясно. Помните главный принцип: всё написанное в профиле и резюме вы должны уметь объяснить вслух. Работодатель проверит, а на собеседовании спросит.
Аналогия из жизни
Бозор осенью: хороший продавец раскладывает товар так, чтобы покупатель сразу увидел лучшее, а не прячет арбузы в мешок. GitHub-профиль, README и резюме — ваш прилавок. Раскладываем честно: лучшее спереди, и ничего, чего нет в лавке.
Чек-лист GitHub-профиля
☐ Фото и имя: настоящее имя латиницей, нормальная фотография или аккуратный аватар.
☐ Bio в одну строку: «Junior frontend · JavaScript · учусь в MakeFirstStep», без громких слов.
☐ Локация (Dushanbe, Tajikistan) и контакт: Telegram или рабочая почта. Телефон публиковать не нужно.
☐ Профильный README (репозиторий с именем, совпадающим с вашим логином): 5–8 строк о себе, стек, ссылки на проекты.
☐ 3–6 закреплённых репозиториев (pin): лучшие проекты, а не заготовки «test» и «untitled».
☐ В каждом закреплённом проекте: описание, topics, ссылка на демо в поле Website, README со скриншотом.
☐ Чистая история: коммиты с понятными сообщениями на английском, а не «fix», «asdf», «1».
☐ Нет секретов: в репозитории нет файлов .env, ключей, паролей и токенов. Если случайно закоммитили ключ, считайте его скомпрометированным и сразу замените.
☐ Нет мусора: node_modules в .gitignore, старые пустые репозитории удалены или в архиве.
☐ Честная активность: не накручивайте «зелёные квадраты» пустыми коммитами. Опытный глаз это сразу видит.
Резюме junior frontend: что должно быть на одной странице
На позицию без опыта работодатель смотрит на три вещи: что вы умеете показать (проекты), как вы учитесь и можно ли с вами работать (ясность, честность). Резюме — одна страница, PDF, имя файла вроде Name-Surname-Frontend.pdf.
Структура резюме (пример)
Мадина Рахимова
Junior Frontend Developer · Душанбе, Таджикистан
Telegram: @username · email@example.com
GitHub: github.com/username · Портфолио: username.github.io
О себе
Закончила курс «Frontend + ИИ» (MakeFirstStep, 2 месяца, JavaScript, DOM, fetch, Git).
Ищу стажировку или junior-позицию, готова работать в команде и быстро учиться.
Навыки
JavaScript (ES6+), HTML5, CSS3 (flexbox, grid), DOM и события, fetch и async/await,
Git и GitHub, Vite и npm, основы React (компоненты, useState, useEffect).
Проекты
Трекер привычек — чистый JavaScript, localStorage, фильтры, серии дней.
Демо: ссылка · Код: ссылка
Погода по городам — fetch к публичному API, состояния загрузки и ошибки.
Демо: ссылка · Код: ссылка
Образование и курсы
MakeFirstStep · Frontend + ИИ, Уровень 2 (2026)
Школа / вуз (если есть, одной строкой)
Языки
Таджикский — родной · Русский — свободно · Английский — чтение документации
Так не пишем
«Уникальный специалист», «эксперт по JavaScript», «лучший ученик»
«Опыт работы 2 года», если был только учебный проект
«Знаю React», если прошли три урока введения
Шкалы «JavaScript — 90%», «HTML — 100%»: непонятно, что они значат
Список из 25 технологий, половину из которых видели один раз
Проект без ссылок: «делал сайт»
Так пишем
«Трекер привычек на JavaScript, данные сохраняются в localStorage»
«Прошла вводный блок по React: компоненты, useState, useEffect + fetch»
Навыки группами: «Уверенно», «Использовал в проектах», «Знакомство»
У каждого проекта: что решает, на чём сделан, ссылки на демо и код
2–3 лучших проекта вместо десяти слабых
Дата и название курса, который вы действительно прошли
ИИ-блок: резюме и профиль с помощью ИИ — по правилам курса
Это ситуация №21 из библиотеки промптов. ИИ хорошо шлифует формулировки, но легко «добавляет» то, чего у вас нет: годы опыта, технологии, достижения. Проверяйте каждое слово: если вы не можете объяснить строку на собеседовании, её не должно быть в резюме.
напиши мне крутое резюме фронтенд разработчика
Контекст: я junior, закончила 2-месячный курс по JavaScript (DOM, fetch, Git), живу в Душанбе. Коммерческого опыта нет. Проект: «Трекер привычек» на чистом JavaScript, данные в localStorage, фильтры и серии дней.
Задача: опиши этот проект для резюме в 3 строки: задача, стек, результат.
Ограничения: без слов «уникальный», «лучший», «эксперт»; не добавляй технологии и опыт, которых я не называла; без выдуманных цифр.
Формат ответа: три коротких пункта, по одному на строку.
Проверка: после ответа перечисли, какие слова ты добавил от себя, чтобы я могла проверить их на честность.
Сначала напишите описание проекта сами, 15 минут, потом дайте ИИ его улучшить, а не придумать. Сравните два варианта и выберите свой. Проверим формулировки кодом:
Практика: проверяем формулировки и README
ЗАДАЧА 6.1
Детектор пафоса в резюме
лёгкая
Допишите функцию flags(text): она возвращает массив «стоп-слов» (основ из списка STOP), которые встречаются в тексте без учёта регистра. Если массив пуст, пункт «ок», иначе пафос (слово, слово).
Можно редактировать · Ctrl + Enter
const STOP = ["уникальн", "лучш", "эксперт", "гуру", "опытн"];
functionflags(text) {
// верните массив основ из STOP, которые есть в тексте (toLowerCase + includes)
}
const bullets = [
"Трекер задач на чистом JavaScript: добавление, фильтры, сохранение в localStorage",
"Уникальный проект, который меняет мир",
"Опытный эксперт по JavaScript",
"Приложение погоды на fetch и Open-Meteo API: состояния загрузки и ошибки",
];
bullets.forEach((b, i) => {
const found = flags(b);
console.log(`${i + 1}: ${found.length ? "пафос (" + found.join(", ") + ")" : "ок"}`);
});
Ожидаемый результат
1: ок
2: пафос (уникальн)
3: пафос (эксперт, опытн)
4: ок
Подсказка 1
Используйте STOP.filter(...): оставляем те основы, для которых text.toLowerCase().includes(основа) истинно.
Подсказка 2
Порядок слов в ответе — это порядок в массиве STOP, поэтому в третьей строке сначала «эксперт», потом «опытн».
ЗАДАЧА 6.2
Проверка README
средняя
В хорошем README есть пять разделов: «Что это», «Стек», «Запуск», «Скриншот», «Что дальше». Заголовок раздела начинается с ## . Выведите для каждого раздела ✓ название или ✗ название, а потом Готово: N из 5. В этом README нет скриншота, и проверка должна это заметить. Потом допишите раздел в свой реальный README.
Можно редактировать · Ctrl + Enter
const readme = `# Трекер привычек
## Что это
Приложение для отметки привычек и подсчёта серии дней.
## Стек
JavaScript, HTML, CSS, localStorage.
## Запуск
Откройте index.html в браузере.
## Что дальше
Редактирование привычек и тёмная тема.`;
const required = ["Что это", "Стек", "Запуск", "Скриншот", "Что дальше"];
// проверьте каждый раздел через includes("## " + name)
Ожидаемый результат
✓ Что это
✓ Стек
✓ Запуск
✗ Скриншот
✓ Что дальше
Готово: 4 из 5
Подсказка 1
Заведите счётчик let ok = 0. В цикле for...of по required проверьте readme.includes("## " + name).
Подсказка 2
В цикле: const has = readme.includes("## " + name); if (has) ok++; console.log((has ? "✓ " : "✗ ") + name); После цикла — итоговая строка с ok и required.length.
README как портфолио
Для junior без опыта README и есть витрина проекта. Рекрутер открывает репозиторий на 30 секунд: ему должно быть сразу понятно, что это, как выглядит и как запустить. Минимальный шаблон:
README.md (шаблон)
# Название проекта
Одно предложение: что это и для кого.
[Демо](ссылка) · [Код](ссылка)

## Что умеет
- добавление и удаление записей
- фильтры и поиск
- данные сохраняются после перезагрузки
## Стек
JavaScript (ES6+), HTML, CSS, Vite, Open-Meteo API
## Запуск
npm install
npm run dev
## Чему научился
Коротко, своими словами: что было сложно и как решил.
## Что дальше
- тёмная тема
- тесты на основные функции
Раздел «Чему научился» пишите сами, без ИИ: именно он показывает, что вы понимаете проект. Закрепите на профиле два-три лучших проекта с таким README и со скриншотами; остальное можно оставить, но не закреплять.
Где искать стажировку
Никто не гарантирует вам место, и это нормально. Ниже — направления, где обычно ищут первый опыт. Конкретных компаний мы не обещаем: рынок меняется, проверяйте актуальность сами.
IT-сообщества Таджикистана и русскоязычные каналы с вакансиями для начинающих. Читайте условия, остерегайтесь «стажировок за ваши деньги».
Прямые письма в компании
Студии и IT-компании Душанбе: найдите страницу «Контакты» или специалиста по найму, отправьте короткое письмо (шаблон ниже).
Люди вокруг
Преподаватель, выпускники курса, одногруппники, знакомые в IT. Большая часть первых мест находится через людей.
Митапы, хакатоны, конференции
Ходите, знакомьтесь, показывайте проект. Даже участие без победы даёт контакты и опыт.
Небольшие реальные задачи
Сайт для знакомого бизнеса, помощь в open-source проекте (маленький issue с пометкой «good first issue»). Это уже опыт, который можно положить в резюме.
Короткое письмо в компанию (пример)
Здравствуйте, [Имя]!
Меня зовут Мадина, я junior frontend: закончила курс «Frontend + ИИ»
(JavaScript, DOM, fetch, Git). Ищу стажировку, готова выполнить тестовое задание.
Мои проекты: [ссылка на портфолио], GitHub: [ссылка].
Если у вас есть возможность взять стажёра или подсказать, куда обратиться,
буду благодарна за ответ.
С уважением,
Мадина, Telegram: @username
Реалистичные ожидания
Откликов потребуется много: 20–30 и больше, и это нормальная статистика для начинающих. Каждые две недели улучшайте проект по итогам отзывов, а не просто рассылайте то же резюме. Параллельно продолжайте учиться: после этого курса вас ждёт Уровень 3 (React Pro + Next.js), а сильный React на реальном проекте заметно повышает шансы.
07 Личная шпаргалка промптов: соберите свои 10
С первого урока мы учились работать с ИИ как с помощником: он ускоряет, но не думает за вас. Сегодня собираем всё в личную шпаргалку: десять промптов, которые реально помогли вам за курс, переписанные по формуле и готовые к повторному использованию. Это документ, который пригодится и на работе: через год вы откроете его и сэкономите час.
Аналогия из жизни
У каждой хозяйки есть своя тетрадь с рецептами: не «как готовить вообще», а «как готовлю я». Шаблон промпта — рецепт: контекст — это продукты, задача — блюдо, ограничения — «без острого», формат ответа — как подать, проверка — попробовать на соль.
Формула промпта (правило курса №4)
Элемент
Что писать
Пример
Контекст
Проект, язык, стек, твой уровень
Я пишу на чистом JavaScript без библиотек, уровень — новичок, проект учебный
Задача
Одно конкретное действие
Напиши функцию, которая фильтрует массив товаров по цене
Ограничения
Чего нельзя и что обязательно
Без внешних библиотек, только ES6, HTML не менять
Формат ответа
Как отдать результат
Сначала код, потом 3 строки объяснения, без таблиц
Проверка
Что попросить дополнительно
Назови 2 крайних случая, где этот код сломается
Правила работы с ИИ: без них шпаргалка не работает
Сначала пробуешь сам 15 минут, только потом промпт.
Не вставляешь код, который не можешь объяснить строчку за строчкой.
Всегда просишь объяснение, а не только код.
Имена переменных, крайние случаи и логику проверяешь руками.
На контрольных (уроки 6 и 18) ИИ выключен полностью.
Библиотека промптов курса: 26 шаблонов по модулям
Это общая библиотека, которая собиралась по ходу курса. Для каждой ситуации указано, что проверить в ответе: без проверки промпт не закончен. Квадратные скобки […] — места, куда вы подставляете своё.
№
Модуль · урок
Ситуация
Шаблон промпта
Что проверить в ответе
1
M1 · Урок 2–3
Не понимаю, почему код ведёт себя странно
Вот код: [код]. Объясни построчно, что происходит и почему результат такой. Не переписывай код — только объясни.
Совпадает ли объяснение с тем, что реально выводит консоль
2
M1 · Урок 4
Нужны тренировочные задачи
Дай 5 задач на [тема] уровня новичка, от простой к сложной, без решений.
Что задачи по теме и без готовых ответов
3
M1 · Урок 5
Функция получилась громоздкой
Предложи 3 варианта этой функции: короткий, читаемый и производительный. Скажи, какой выбрать для учебного проекта и почему.
Выбор делаешь ты, а не первый вариант из ответа
4
M1 · Урок 6
Нужны данные для теста
Сгенерируй массив из 100 объектов вида {id, name, price, category} как JS-код. Цены от 10 до 500.
Проверь 2–3 объекта руками и типы полей
5
M2 · Урок 7
Незнакомый JSON из API
Вот фрагмент JSON: [json]. Опиши схему: какие поля, какие типы, какие могут отсутствовать.
Сверь схему с реальным ответом API
6
M2 · Урок 8
Нужна разметка под задачу
Сделай HTML-шаблон карточки товара с классами по BEM. Только разметка и CSS, без JavaScript.
Логику пишешь сам — это правило курса
7
M2 · Урок 9
Много одинаковых обработчиков
Объясни делегирование событий на этом примере: [код]. Покажи минимальную версию через один обработчик на родителе.
Понимаешь ли, почему работает event.target
8
M2 · Урок 10
Валидация формы
Составь правила валидации для полей: [список]. Для каждого — условие, сообщение об ошибке и регулярное выражение, если нужно.
Проверь регулярки на своих реальных данных
9
M2 · Урок 11
Не знаю, как хранить состояние
Предложи структуру объекта состояния для приложения [описание]. Объясни, почему такие поля и что положить в localStorage.
Сравни со своей версией и реши сам
10
M2 · Урок 12
Большая задача, непонятно с чего начать
Разбей задачу «[идея проекта]» на 10–15 подзадач по 20–40 минут, в порядке выполнения.
Убери лишнее и оцени время сам
11
M3 · Урок 13
Путаюсь в асинхронности
Объясни event loop на примере этого кода: [код]. Покажи порядок вывода в консоль и почему такой.
Запусти код и сверь порядок вывода
12
M3 · Урок 14
Промисы и async/await
Перепиши этот код с промисов на async/await, сохранив обработку ошибок: [код].
Проверь, что try/catch реально ловит ошибку
13
M3 · Урок 15
Нужна обёртка над fetch
Напиши обёртку над fetch: базовый URL, таймаут, проверка response.ok, понятные ошибки. Чистый JS, без библиотек.
Проверь на 404 и при выключенной сети
14
M3 · Урок 16
Не разбираюсь в документации API
Вот документация API: [текст или ссылка]. Мне нужно [задача]. Какой эндпоинт, какие параметры, пример запроса?
Сверь параметры с реальным ответом API
15
M3 · Урок 17
Состояния загрузки и ошибок
Опиши все состояния экрана со списком из API: загрузка, пусто, ошибка, успех. Для каждого — что видит пользователь.
Что все 4 состояния есть в твоём интерфейсе
16
M3 · Урок 17
Модули и сборка
Разбей этот файл на ES-модули: [код]. Предложи структуру папок для проекта на Vite.
Импорты и пути проверь сам, запусти сборку
17
M4 · Урок 19
Коммиты и pull request
Вот diff: [diff]. Напиши коммит-сообщение в стиле Conventional Commits и краткое описание PR: что сделано и зачем.
Сообщение должно отражать смысл, а не «fix»
18
M4 · Урок 19
Баг вместо «не работает»
Баг: ожидаю [что], получаю [что]. Минимальный код: [код]. Ошибка в консоли: [текст]. Дай 3 гипотезы причины по вероятности.
Проверяй гипотезы по очереди, не правь всё сразу
19
M4 · Урок 20
Ревью своего кода
Проверь код по чек-листу: имена, размер функций, дублирование, ранний возврат, разделение логики и отображения. Только замечания, без переписывания.
Принимай не все советы — обоснуй каждую правку
20
M4 · Урок 20
README и портфолио
Напиши README для проекта: [описание, стек, функции]. Разделы: что это, стек, запуск, скриншот, что дальше.
Перепиши своими словами — иначе видно ИИ
21
M4 · Урок 21
Резюме и защита проекта
Опиши проект [название] для резюме в 3 строки: задача, стек, результат. Без пафоса и слова «уникальный».
Всё написанное ты должен уметь объяснить
22
M5 · Урок 22
Переход с DOM на React
Вот код на чистом JS: [код]. Перепиши как React-компонент и объясни построчно, что заменило querySelector и addEventListener.
Понимаешь, где состояние, а где разметка
23
M5 · Урок 23
Состояние не обновляется
UI не обновляется. Компонент: [код]. Объясни, почему useState не сработал и как исправить.
Не мутируешь ли ты состояние напрямую
24
M5 · Урок 23
Зачем нужен key
Объясни на моём примере, зачем React нужен key в .map() и что сломается без него: [код].
Проверь на удалении элемента из середины списка
25
M5 · Урок 24
Загрузка данных в React
Напиши React-компонент, который грузит данные из [API] в useEffect и показывает состояния loading, error, empty, success. Без библиотек.
Проверь повторный рендер и отмену запроса
26
M5 · Урок 24
Что делать после курса
Составь план на 8 недель для перехода от новичка в React к уверенному React + Next.js: темы по неделям и по одному проекту на каждые 2 недели.
Сверь план с программой Уровня 3
Чего не делать
Антипаттерны
«Напиши мне весь проект»: получите код, который не сможете защитить
«Исправь» без описания ошибки и ожидаемого поведения
Вставлять чужой код без чтения: на защите просят объяснить любую строку
Пользоваться ИИ на контрольных: это незачёт
Верить первому ответу: просите 2–3 варианта и выбирайте сами
Что делать вместо
Разбить задачу на шаги и просить помощь по одному шагу
Описать так: «ожидаю X, получаю Y, вот код и текст ошибки»
Прочитать, запустить, поменять имена, объяснить своими словами
Готовиться к контрольным без подсказок, как сегодня в разделе 04
Спросить: «какие у этого решения минусы?»
Как собрать свои 10 промптов
Вспомните десять ситуаций, где ИИ реально помог (или, наоборот, подвёл, и вы поняли, как надо писать). Откройте историю чатов, библиотеку выше и домашние задания.
Для каждой напишите шаблон по формуле: все пять элементов, с метками «Контекст:», «Задача:», «Ограничения:», «Формат ответа:», «Проверка:».
Запишите пометку «чему верить после проверки»: что вы проверяете в ответе руками.
Оцените 1–5, насколько промпт помог. Тройки и двойки не прячьте: именно их стоит переписать.
Сохраните в удобный документ (Google Docs, Notion, файл prompts.md в репозитории) и сдайте преподавателю.
Ниже — таблица-шаблон для вашей шпаргалки. Скопируйте её в свой документ и заполните:
Можно попросить ИИ проверить ваш промпт, но не написать его вместо вас. Сравните два способа:
придумай мне 10 хороших промптов для программиста
Контекст: я студент курса JavaScript (уровень новичок), собираю личную шпаргалку из 10 промптов. Вот мой промпт №3: [мой промпт].
Задача: оцени его по формуле «контекст, задача, ограничения, формат ответа, проверка».
Ограничения: ничего не переписывай; только перечисли, каких элементов не хватает и какие слова неоднозначны.
Формат ответа: список из 5 пунктов, по одному на каждый элемент формулы, с оценкой «есть / слабо / нет».
Проверка: назови одну ситуацию, в которой этот промпт даст плохой ответ.
Практика: тренируем формулу кодом
Промпт — это тоже текст, а с текстом мы работать умеем. Три задачи: собрать промпт функцией, проверить чужие и, наконец, заполнить собственные 10 с автоматической проверкой.
ЗАДАЧА 7.1
Сборщик промптов
лёгкая
Напишите функцию buildPrompt: она получает объект с пятью полями и возвращает текст из пяти строк с метками Контекст:, Задача:, Ограничения:, Формат ответа:, Проверка:. Строки склейте через "\n".
Можно редактировать · Ctrl + Enter
functionbuildPrompt({ context, task, limits, format, check }) {
// верните пять строк с метками, склеенных через "\n"
}
console.log(buildPrompt({
context: "Я пишу на чистом JavaScript без библиотек, уровень — новичок",
task: "Напиши обёртку над fetch с базовым URL и таймаутом",
limits: "Без внешних библиотек, только ES6",
format: "Сначала код, потом 3 строки объяснения",
check: "Назови 2 случая, где код сломается",
}));
Ожидаемый результат
Контекст: Я пишу на чистом JavaScript без библиотек, уровень — новичок
Задача: Напиши обёртку над fetch с базовым URL и таймаутом
Ограничения: Без внешних библиотек, только ES6
Формат ответа: Сначала код, потом 3 строки объяснения
Проверка: Назови 2 случая, где код сломается
Подсказка 1
Соберите массив из пяти шаблонных строк, например `Контекст: ${context}`, и вызовите у него .join("\n").
Напишите функцию missing(text): она возвращает массив названий элементов формулы, которых нет в тексте. Элемент считается присутствующим, если в тексте есть его название с двоеточием, например "Задача:". Порядок результата — как в массиве LABELS.
Можно редактировать · Ctrl + Enter
const LABELS = ["Контекст", "Задача", "Ограничения", "Формат ответа", "Проверка"];
functionmissing(text) {
// верните названия из LABELS, для которых в тексте нет "название:"
}
const prompts = [
"сделай калькулятор",
"Контекст: новичок. Задача: калькулятор. Ограничения: без библиотек.",
"Контекст: новичок. Задача: калькулятор. Ограничения: ES6. Формат ответа: код. Проверка: 2 бага.",
];
prompts.forEach((p, i) => {
const lost = missing(p);
console.log(`${i + 1}: ${lost.length ? "не хватает: " + lost.join(", ") : "полный"}`);
});
Ожидаемый результат
1: не хватает: Контекст, Задача, Ограничения, Формат ответа, Проверка
2: не хватает: Формат ответа, Проверка
3: полный
Подсказка 1
Нужен LABELS.filter(...): оставляем те названия, для которых проверка «есть в тексте» ложна.
Заполните массив myPrompts: десять записей { task, prompt, helped }. В task — для какой задачи (минимум 5 символов), в prompt — полный текст промпта с пятью метками формулы (удобно писать в обратных кавычках на нескольких строках), в helped — ваша оценка от 1 до 5. Проверка уже написана. Задача считается решённой, когда выведено Готово: 10 из 10. Это и есть ваша шпаргалка, перенесите готовые тексты в свой документ.
Можно редактировать · Ctrl + Enter
const LABELS = ["Контекст:", "Задача:", "Ограничения:", "Формат ответа:", "Проверка:"];
const myPrompts = [
{
task: "Объяснить, почему код ведёт себя странно",
prompt: `Контекст: я новичок, пишу на чистом JavaScript, учебный проект.
Задача: объясни построчно, что делает этот код: [код].
Ограничения: не переписывай код, только объясни.
Формат ответа: нумерованный список по строкам кода.
Проверка: назови одну строку, где новичок чаще всего ошибается.`,
helped: 4,
},
// 2–10: скопируйте блок выше и заполните своими данными
{ task: "", prompt: "", helped: 0 },
{ task: "", prompt: "", helped: 0 },
{ task: "", prompt: "", helped: 0 },
{ task: "", prompt: "", helped: 0 },
{ task: "", prompt: "", helped: 0 },
{ task: "", prompt: "", helped: 0 },
{ task: "", prompt: "", helped: 0 },
{ task: "", prompt: "", helped: 0 },
{ task: "", prompt: "", helped: 0 },
];
functionproblems(item) {
const list = [];
if (item.task.trim().length < 5) list.push("не указана задача");
const lost = LABELS.filter((label) => !item.prompt.includes(label));
if (lost.length) list.push("нет: " + lost.join(" "));
if (!(item.helped >= 1&& item.helped <= 5)) list.push("оценка должна быть от 1 до 5");
return list;
}
let ok = 0;
myPrompts.forEach((item, i) => {
const list = problems(item);
if (list.length ===0) ok++;
console.log(`${i + 1}: ${list.length ? list.join("; ") : "ок"}`);
});
console.log(`Готово: ${ok} из ${myPrompts.length}`);
Ожидаемый результат
1: ок
2: ок
3: ок
4: ок
5: ок
6: ок
7: ок
8: ок
9: ок
10: ок
Готово: 10 из 10
Подсказка 1
Пустые записи подсвечены в выводе: например 2: не указана задача; нет: Контекст: Задача: …. Идите сверху вниз и добивайтесь строки «ок» для каждой.
Подсказка 2
Возьмите шаблоны из библиотеки выше (например №10, №13, №17, №18, №19) и перепишите их по формуле со всеми пятью метками. Оценку helped ставьте честно после того, как попробуете промпт на деле.
08 Практика на уроке: защиты и обратная связь
Основное время занятия — защиты финальных проектов. Если группа большая, они займут весь урок: тогда карьерный блок и шпаргалка промптов делаются дома (и входят в ДЗ).
0–5 мин · Организация. Преподаватель называет порядок защит. Откройте свой проект по публичной ссылке и убедитесь, что он загружается.
5–70 мин · Защиты. По 5 минут на проект и минуту на смену выступающего. Остальные слушают и заполняют листок: два плюса, один риск, один вопрос по каждому проекту.
70–85 мин · Разбор. Преподаватель называет общие находки и частые ошибки: что получилось у многих, что чаще всего ломается. Каждый получает обратную связь по своему проекту.
85–90 мин · Итоги. Что дальше: дорожная карта к Уровню 3 (React Pro + Next.js), сроки сдачи шпаргалки и ссылок.
Если вы ждёте своей очереди
Не листайте телефон: отвечайте себе на вопросы разбора, которые зададут вашему соседу, и записывайте идеи для своего проекта. Лучший способ подготовиться к защите — послушать три чужих.
ИИ на уроке
Во время защит ИИ не используется. После занятия можно попросить его перечитать ваши заметки обратной связи и составить план улучшений (по правилам курса: идеи принимаете или отклоняете вы сами).
09 Домашнее задание
Домашнее задание урока 21: прислать ссылку на задеплоенный проект и подготовить защиту на 5 минут, а затем довести до конца портфолио и личную шпаргалку.
Что нужно сделать
☐ Прислать ссылку на задеплоенный проект и ссылку на репозиторий (до защиты).
☐ Подготовить защиту на 5 минут по разделу 05: сценарий демо, запасной скриншот, ответы на 12 вопросов хотя бы вслух перед зеркалом.
☐ Пройти итоговый самотест (раздел 04): решены все 16 задач; те, что не получились, перечитаны по ссылкам на уроки.
☐ Заполнить личную шпаргалку из 10 промптов (раздел 07) и сдать документ.
☐ Обновить GitHub-профиль по чек-листу из раздела 06: закреплённые репозитории, README профиля.
☐ Написать резюме на одну страницу в PDF и портфолио-README лучшего проекта. Все формулировки честные.
☐ Составить список из 10 мест для отклика (каналы, компании, люди) и отправить минимум три письма.
Что сдать
В чат группы (Telegram): ссылка на проект, ссылка на репозиторий, ссылка или файл с личной шпаргалкой, ссылка на ваш GitHub-профиль и резюме в PDF. Одним сообщением, с подписью вашего имени.
Как оценивается ДЗ (0–10)
Что проверяем
Баллы
Проект задеплоен, ссылка открывается без входа и без ошибок в консоли
2
Шпаргалка: 10 промптов по формуле, с оценкой и пометкой «что проверить»
3
GitHub-профиль: описание, закреплённые репозитории, README у проектов
2
Резюме на одну страницу, без пафоса и выдуманных фактов, со ссылками на проекты
2
Самотест: все 16 задач решены
1
Это оценка за домашнее задание урока (0–10). Оценка за финальный проект (0–100, 30% итога) выставляется по таблице из раздела 02 и учитывается отдельно.
✓ Шпаргалка урока
Финальный проект: своя идея, согласованная с преподавателем; весь курс (JS, DOM, async) + Git (10+ коммитов) + деплой по публичной ссылке + README. Это 30% итога курса.
Оценка 0–100: идея и функциональность 20, JS/DOM/события 20, данные и async 15, Git и деплой 10, README и чистота кода 10, интерфейс 5, защита 20.
Итог курса: посещаемость 15% + ДЗ 30% + мини-проекты 25% + финал 30%. Шкала: 90–100 отлично, 75–89 хорошо, 60–74 удовлетворительно, меньше 60 не аттестован.
Сертификат: посещаемость ≥ 70%, сдано ≥ 18 из 24 ДЗ, оба мини-проекта, финал ≥ 60.
Защита (5 мин): 0:30 представление, 1:30 демо по публичной ссылке с F5, 1:30 код и архитектура, 1:30 вопросы. Не читать код вслух, не оправдываться, честно сказать «не знаю, но найду».
Вопросы защиты: идея, структура, state, путь от клика до экрана, fetch и ошибки, async/await, localStorage, Git, деплой, самый сложный баг, где был ИИ, что улучшить.
Чужие решения: что получилось, где риск, вопрос «почему так?», одно предложение. О проекте, а не о человеке.
GitHub: имя и bio, профильный README, 3–6 закреплённых репозиториев с README, скриншотом и демо, чистая история, никаких секретов и накрученных квадратов.
Резюме junior: одна страница, PDF; о себе, навыки, 2–3 проекта со ссылками, курсы, языки. Без пафоса и выдуманного опыта: каждую строку нужно уметь объяснить.
Стажировка: профессиональные сети и сайты вакансий, Telegram-каналы, письма напрямую, знакомые, митапы, небольшие реальные задачи. Готовьтесь к 20–30 откликам и продолжайте учиться.
Шпаргалка промптов: формула «контекст → задача → ограничения → формат ответа → проверка»; 10 своих промптов с оценкой 1–5 и пометкой «что проверить»; чего не делать: «напиши весь проект», «исправь» без описания, чужой код без чтения, ИИ на контрольных, вера первому ответу.