
Привет всем.
Расскажу про свой личный опыт разработки через Qwen 3.6 Plus и Qwen ClI. И да, статья полностью написана человеком.
Это небольшой pet-проект, сделанный в момент, когда Qwen 3.6 Plus был бесплатным с лимитом в 1000 запросов в день. Проект представляет из себя фронтенд вымышленного интернет-магазина по продаже микрокомпьютеров.
Цель была протестировать возможности Qwen. На весь проект у меня ушло 4 дня по 2-3 часа.
День 1. Планирование
Началось все с чата Qwen, где я спрашивал как лучше организовать работу с агентами через CLI, а также уточнял неясные для меня моменты.
В результате диалога появилось несколько ролей для агентов с небольшим описанием для каждой роли:
«Архитектор». Проектирует, разбивает проект на шаги, создает документацию для других агентов;
«Кодер». Собственно пишет код;
«Тестировщик». Пишет тесты;
«Ревьюер». Проводит ревью «Кодера»;
Контент-мейкер». Делает тексты-заглушки для сайта.
Я сам выбрал стек - Typescript, Next, React, Zustand, Chakra, Jest.
Далее в чате я набрал промпт, где собственными словами описал то, что хочу получить и попросил сделать уточняющий промпт для роли «Архитектора».
Обработав этот промпт, «Архитектор» сделал несколько md-файлов:
architecture - описание архитектуры проекта;
components - подробное описание компонентов;
data-flow - взаимосвязь компонентов через mermaid-диаграммы;
implementation - план реализации с поэтапной разбивкой (всего получилось 17 этапов)
Эти файлы пришлось переделать несколько раз. В первом варианте «Архитектор» сам начал писать код, а после уточнения роли еще и попытался прятать код в комментариях.
Далее я добавил mcp для работы с файловой системой и через «Архитектора» сделал скиллы для всего стека.
День 2. Подготовка
На второй день я вручную добавил информацию о товарах и картинки (с bananaPi).
Также я решил, что оставлю за собой всю работу с git и буду самостоятельно проверять каждый коммит (в итоге «Ревьюером» я воспользовался лишь один раз).
В этот день свою работу начал «Кодер», который установил все необходимые зависимости, сделал парсинг md-файлов, сторы Zustand и базовый layout.
День 3. Основной функционал
В этот день через «Кодера» был завершен весь основной функционал:
компоненты товаров;
главная страница;
страница товара;
страница избранного;
страница корзины;
страница контактов;
страница «о компании»;
404;
«Тестировщик» написал все тесты, а «Контент-мейкер» тексты-заглушки.
После каждого этапа я вручную и тщательно проводил ревью, а также вручную тестировал результаты работы. Я убедился в том, что с агентами нужно постоянно вести «диалог» и спрашивать почему они пришли к тому или иному решению, можно ли сделать лучше.
Стоит отметить, что «Кодер» иногда своевольничал и делал то, что его не просили (например, начинал писать тесты), а также «перепрыгивал» на следующий этап без подтверждения.
Крайне любопытно было читать рассуждения агентов. Особенно, меня поразил момент, когда «Кодер» при попытке исправить гидратационную ошибку выдал примерно следующие: «Стоп. Я несколько раз пытаюсь исправить баг через однотипные решения. Нужен совершенно иной подход».


День 4. Дополнительные фичи и полировка.
В этот день я решил посмотреть как «Кодер» работает с 3D (Three.js). В hero-section главной страницы я попробовал добавить 3D-модель микрокомпьютера. Однако результаты оказались посредственными (видимо общие модели пока плохо работают 3D графикой) и пришлось довольствоваться обычным SVG.
Также были добавлены некоторые фишки и завершено ручное тестирование.

Итог. За 4 дня работы удалось сделать вполне нормальный фронт для Интернет-магазина. Еще год назад я крайне скептически относился к возможностям ИИ в кодинге, однако нейросети в этом плане удивительно быстро развиваются. В своем проекте я фактически совместил роли техлида и ручного тестировщика. Всю остальную работу выполнили агенты (ручные правки — примерно 15%).
Главное, что я усвоил, программирование при при помощи ИИ — это нахождение баланса между скоростью и пониманием проекта, что с агентами нужно быть в постоянном диалоге.
Жаль, что Alibaba закрыла бесплатный доступ к облаку.
Значит будем пробовать локальные модели :-)
Комментарии (11)

martelle
25.04.2026 17:21>За 4 дня работы удалось сделать вполне нормальный фронт для Интернет-магазина
выглядит может и нормально, а под капотом, судя по всему не очень. в целом, фронт нейросети уже давно делают, что с бэком, деплоем, интеграциями?

Retro_tactic Автор
25.04.2026 17:21Ну так посмотрите код, ссылку на репо я оставил и после этого уже можете говорить, что под капотом "не очень". Я так понимаю ревью вы тоже провели нейросетью.

Retro_tactic Автор
25.04.2026 17:21Я не говорю, что нейросети сейчас могут во все и всех заменят. Еще год назад я был крайним скептиком насчет них, но они развиваются и в плане кодинга достаточно быстро.

Dhwtj
25.04.2026 17:21А не пытались сравнить с написанием одним LLM, есть ли смысл в этой своре агентов?
Метрики. Время создания, стоимость, качество, вмешательство человека
Судя по таймингу вы больше боролись со сворой агентов, чем решали практические задачи

Retro_tactic Автор
25.04.2026 17:21LLM была одна - Qwen3.6 Plus, просто несколько ролей, с которыми я работал последовательно. Время создания я указал в статье. Вмешательство от меня было не сильно большим (15% правок). Скорей это немного утомительно - постоянно проводить ревью.

CadMan
25.04.2026 17:21Есть большая необходимость назначать роли и использовать субагентов.
Субагент работает только в своём контекстном окне и строго по своим правилам. Делая ревью таким образом, он находит массу ошибок после условного субагента кодера.

r3code
25.04.2026 17:21Параграф Цитата Удалить Параграф Цитата Удалить а откуда новость про закрытие доступа? Вы через что подключались? Почему именно cli, а не готовая Lingma IDE от Alibaba?

Retro_tactic Автор
25.04.2026 17:21Цель была протестировать Qwen в кодинге, а не IDE. Поэтому я выбрал наиболее простой инструмент. Информация о закрытии доступа - с официального github, да и в самой cli теперь соответствующие сообщение появляется. Закрытие для бесплатного доступа, конечно же.

imintsev
25.04.2026 17:21Так Qwen CLI больше не работает через OAuth. Только через токены, а это дорого.
martelle
Here are the real problems I found in a quick pass. Ordered roughly by impact.
High impact
SSR is broken — entire page is empty until hydration. src/app/ClientShell.tsx:35-37 returns null until hydrated === true. Since ClientShell wraps {children} in the root layout, every server-rendered HTML response is an empty
. You lose SEO, lose initial paint, and break crawlers — for a product catalog this is the worst of both worlds (SSG pages built but never sent to the client). Fix: render the tree on the server too, and only guard the truly client-only bits (theme class, drawer state).
/api/order trusts client-supplied totals. src/app/api/order/route.ts:21-66 validates types but never recomputes subtotal, deliveryCost, or total from the catalog. A client can POST { items: […], total: 0 } and pass
validation. Even as a mock, the shape of this API teaches the wrong pattern. Fix: look up prices server-side from getAllProducts() and ignore the client’s totals.
Quantity is added by a loop instead of passed in. src/app/product/[slug]/ProductPageClient.tsx:38-40:
for (let i = 0; i < quantity; i++) { addItem(productData);
}
cartStore.addItem already takes a quantity argument (cartStore.ts:37). The loop triggers N store updates / N re-renders for one user action. Fix: addItem(product, quantity).
mounted flag in ProductPageClient is wrong. ProductPageClient.tsx:23-29 uses useState(() => typeof window !== “undefined”). The lazy initializer runs once per render on each environment: false on the server, true on the very
first client render. That mismatch is exactly what causes hydration warnings — the standard fix is useState(false) + useEffect(() => setMounted(true), []). Right now you may be papering over a hydration error rather than avoiding it.
Medium
Double error toast on contact form failure. ContactForm.tsx:83-87 toasts “Ошибка отправки”, but the page-level handleSubmit (contact/page.tsx:27-33) already toasted “Ошибка валидации” with the field list. User sees two toasts. Pick one layer to own error UI.
cartStore.migrate mutates its input and returns the wrong type. cartStore.ts:118-127 casts persistedState to Record<string, unknown>, mutates it, and returns it as unknown. The signature should be (state, version) => CartState. Mutating persistedState is also brittle — return a new object.
Hardcoded 5 for delivery cost in two places. cartStore.ts:107 (getDeliveryCost) and cart/CartPageClient.tsx:139 (). They will drift. Single source of truth.
Module-level products cache never invalidates. lib/products.ts:20 keeps the parsed Markdown in memory forever per server instance. Fine for prod SSG, but in next dev you’ll edit a .md file and not see the change without a
server restart unless clearProductsCache is called.
Redundant store calls re-run on every state change. cart/CartPageClient.tsx:31-33:
const subtotal = useCartStore((state) => state.getSubtotal()); The selector recomputes for every change anywhere in the store (delivery toggles, etc.), and Zustand re-renders only because the result is shallow-equal. Works for primitives, dangerous if you ever return an object. Cleaner: const items = useCartStore(s => s.items) and compute subtotal locally with useMemo.
Minor
package.json name is “pinapple-pi-2.0” (missing a p) — directory and project name are pineapple-pi-2.0.
Three files use eslint-disable react-hooks/set-state-in-effect (ClientShell.tsx, Header.tsx, CookieBanner.tsx). The pattern they’re disabling — setState inside useEffect to mark “hydrated” — is the same SSR anti-pattern as #1; the lint rule is telling you something real.
src/app/favicon.ico and metadata.icons.icon: “/favicon.svg” both exist; Next will auto-pick favicon.ico for / while metadata insists on .svg. Pick one.
ProductCard.tsx:58-68 wraps a
marked token cast in lib/markdown.ts:109 (as import(“marked”).Tokens.List & { items: … }) — fragile if marked changes shapes. Use the official Tokens.ListItem type.
The top three (SSR, server-side price trust, quantity loop) are the ones I’d fix first. Want me to patch any of them?