Обновить

Разработка фронтенда интернет-магазина через Qwen 3.6 Plus и Qwen ClI

Уровень сложностиПростой
Время на прочтение3 мин
Охват и читатели15K
Всего голосов 6: ↑6 и ↓0+7
Комментарии17

Комментарии 17

Here are the real problems I found in a quick pass. Ordered roughly by impact.

High impact

  1. 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).

  1. /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.

  2. 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).

  3. 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

  1. 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.

  2. 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.

  3. Hardcoded 5 for delivery cost in two places. cartStore.ts:107 (getDeliveryCost) and cart/CartPageClient.tsx:139 (). They will drift. Single source of truth.

  4. 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.

  5. 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?

>За 4 дня работы удалось сделать вполне нормальный фронт для Интернет-магазина

выглядит может и нормально, а под капотом, судя по всему не очень. в целом, фронт нейросети уже давно делают, что с бэком, деплоем, интеграциями?

Фронт нормально они научились не так и давно.

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

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

А не пытались сравнить с написанием одним LLM, есть ли смысл в этой своре агентов?

Метрики. Время создания, стоимость, качество, вмешательство человека

Судя по таймингу вы больше боролись со сворой агентов, чем решали практические задачи

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

Вы проверяли что был 3.6 plus? Зачастую показывало qwen3-coder и только в последние дни перешло на 3.6 plus.

Есть большая необходимость назначать роли и использовать субагентов.

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

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

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

Так Qwen CLI больше не работает через OAuth. Только через токены, а это дорого.

Так автор и говорит: «когда был бесплатным». Кроме токенов есть еще подписка за 50$

Ну 4 дня активные работы не выглядит как прорыв от ии автоматизации, и сайт выглядит обычно.

Какие MCP подключали? Каждому агенту свой? Или что-то общее? Что посоветуете?

Вопрос номер раз, вы общались с Агентами в терминале через это узинькое окошко в 2 строки на протяжении всего проекта?

Ставил qwen cli, но все попытки подключить его к телеге как openclaw не увенчались успехом. А работать просто в терминала, с телефона, прям неудобно

Хотелось бы уточнить по агентам - это точно были несколько агентов с разделением контекста и т.д или это был один агент со сменой ролей? Как вообще достигается это разделение? Знаю что по фолдерам можно md разбросать - этого достаточно?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации