The studio's own site and admin panel: portfolio, orders with bank-transfer payment, two themes, three languages. Live at it2.uz.
The studio's entire website: a portfolio, project pages with a live preview of each site, order intake, and an owner's admin panel.
What is inside:
— A project catalogue with filters, detail pages and an embedded window showing the live site.
— Bank-transfer payment: the buyer transfers the money and marks it, the owner confirms receipt in the panel. Card details never reach the server at all.
— Owner's panel: projects, services, team, orders, messages, visitors, an audit log and settings.
— Google sign-in plus a password login for the owner, with two-factor verification by one-time code.
— Three languages (Russian, English, Uzbek) on separate URLs with hreflang markup.
— Light and dark themes; the choice is remembered and applied before the first paint.
How it is built: Next.js 15 on the App Router, React 19, TypeScript, Prisma with PostgreSQL on Neon (Frankfurt), Auth.js, Tailwind CSS v4, animation with Motion. Pages are statically generated with a one-day revalidation window and served from whichever Vercel edge node is closest to the visitor.
Speed was a separate piece of work. The first version asked for the session inside the shared layout, which made every page rebuild on the server and disabled caching entirely. Moving the session read into the browser cut the response from roughly 880 ms to about 300 ms — the fix was one line, but finding it meant first ruling out geography.
A fragment of the project's real code — so you can see what's inside.
/** * Переключатель темы. * * Переходы снимаются на время смены. Без этого Chrome оставляет * старый цвет всему, у чего есть transition на color: заголовки * карточек висели почти чёрными на чёрном до перезагрузки — * браузер не считает изменение переменной поводом пересчитать * анимируемое свойство. */function toggle() { const next = theme === "dark" ? "light" : "dark"; const root = document.documentElement; root.classList.add("theme-switching"); if (next === "dark") { root.setAttribute("data-theme", "dark"); } else { root.removeAttribute("data-theme"); } // Чтение offsetHeight заставляет пересчитать стили прямо здесь, // пока переходы выключены. Именно так, а не через // requestAnimationFrame: в фоновой вкладке кадры не рисуются, // обработчик бы не вызвался, и класс завис бы навсегда. void root.offsetHeight; root.classList.remove("theme-switching"); localStorage.setItem("ithub:theme", next); setTheme(next);}Project request
Fill in the form — we'll discuss scope and timing.
Zarifa Material — fabrics from Dubai
