React Development Services for 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
FAQ
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

React Development for 1C-Bitrix

CIBlockElement::GetList Returns JSON, React Renders It — Sounds Simple Until You Start

The main fork at the start: how exactly React will fetch data from Bitrix. Everything depends on this — how much code to write, how to deploy, what about SEO, and how to maintain it all later. Over ten years we've tried every option, and each has its own pitfalls.

Architectural Approaches

SPA on React + Bitrix REST API (BX.rest)

The most flexible option. The React application lives separately and calls /rest/ or custom endpoints via CRestServer. Maximum control, but also maximum effort.

  • Client-side routing via React Router — transitions without page reloads, but on F5 you need a catch-all on Nginx (try_files $uri /index.html)
  • Optimistic updates: the cart updates instantly, sale.basket.update fires in the background. If it fails — we roll back the state and show a toast
  • Caching via React Query with staleTime — the catalog doesn't hit the server on every back navigation
  • The frontend deploys to a CDN independently from Bitrix — update a button without touching the backend

SSR with Hydration — When Yandex Can't See the SPA

Yandex has learned to render JS, but poorly. Googlebot is better, but still not 100%. Server-side rendering of React components via Node.js solves the problem radically: the bot gets ready HTML, the user gets an interactive application after hydration.

  • FCP drops below one second on decent hosting
  • og:title, og:image work for social sharing — without SSR, WhatsApp will show an empty preview
  • Complexity: you need a Node.js process alongside Apache/Nginx serving Bitrix. Two runtimes, two deployments, two sets of logs
  • Bitrix cache (CPHPCache, Composite) can be used to warm up data that then feeds into SSR

Headless Bitrix — Admin Panel for Content Managers, React for Visitors

The content manager goes to /bitrix/admin/ and edits information blocks. The visitor sees a React application that fetches data via API. Classic headless.

  • One backend serves the website, mobile app, and Telegram bot — through the same endpoints
  • Scaling: React bundle on CloudFront/CDN, Bitrix on a single server. Even at 50k unique visitors, the frontend doesn't load the backend directly
  • Pitfall: the standard Bitrix visual editor (BXEditor) stops working for visitors. Content managers will have to work only through the admin panel, without inline editing

Inertia.js — A Bridge Without REST API

Inertia passes data from the PHP controller directly into the React component as props. No need to write a separate API, no response serializer, no Swagger. Server-side routing, but client-side rendering.

  • Forms: useForm() from Inertia instead of fetch + manual error handling. Server-side validation arrives automatically
  • Authorization via standard Bitrix sessions — $USER->IsAuthorized() works as usual
  • Downside: tight coupling. The frontend doesn't work without the backend, and you can't connect a separate mobile app

The Stack We Actually Use

Technology Why Specifically
React 18+ Suspense, useTransition — the UI doesn't block during heavy catalog updates
TypeScript Typing Bitrix API responses — IBlockElement, BasketItem, Order. Without this, refactoring turns into Russian roulette
Vite HMR in 50ms vs 3-5 seconds on webpack. On a project with 200 components, the difference is noticeable
React Query useQuery(['catalog', sectionId]) — automatic caching, revalidation, retry on 503 from an overloaded Bitrix
React Hook Form + Zod Checkout: 15-20 fields, conditional validation (legal entity — one set of fields, individual — another). RHF doesn't re-render the form on every keystroke
Tailwind CSS Utility classes. No fighting with the cascade from Bitrix's template_styles.css
Radix UI / Shadcn Accessible primitives. Modals, dropdowns, tabs — with ARIA out of the box

Component Approach: Where the Pitfalls Are

Project Component Library

Every project starts with a design system. Not out of love for order, but because without one, by the third month three developers will have written three different button components.

  • Typography, colors, spacing — via CSS variables and Tailwind config
  • Forms: inputs with masks (phone, tax ID), selects with search, file uploads with preview and MIME validation
  • Product card — a story of its own. Price factoring in discounts from CCatalogProduct::GetOptimalPrice(), "Bestseller"/"New" labels from information block properties, "Add to cart" button with loading/success/error states
  • Tables with virtualization (react-window) for price lists with 5,000+ rows

Typing: Not a Formality, But a Lifesaver

We type everything that comes from Bitrix. Because the REST API returns string where you expect number, "Y"/"N" instead of boolean, and null instead of an empty array.

// The actual response type from CIBlockElement via REST — surprises everywhere
interface BitrixProduct {
  ID: string;          // yes, string, not number
  ACTIVE: "Y" | "N";  // not boolean
  PRICE: string;       // also string
  QUANTITY: string;    // and this is string too
}

A Zod schema at the input parses and transforms — components receive proper types.

Performance: Where Bitrix + React Slows Down

The Main Pain Point — Number of Requests

A standard catalog page: product list, filters, breadcrumbs, banner, SEO text. If you make a separate REST API request for each block — you get 6-8 requests at 200-500ms each. Total: 2-3 seconds.

The solution — aggregating endpoints. A single ajax.php or custom controller on \Bitrix\Main\Engine\Controller gathers all data for the page in one request. React Query caches the response; a repeat visit comes from cache.

Virtualization — Not Optional, But Essential

A catalog with a faceted filter can return 500 products per page (it happens when the SEO specialist "optimizes" pagination). React-window or react-virtuoso renders only the visible 20-30 cards. The DOM doesn't bloat, scrolling stays smooth.

Core Web Vitals — Specific Numbers

  • LCP < 2.5s — lazy loading images via loading="lazy", critical CSS inline, preloading the LCP image via <link rel="preload">
  • INP (replaced FID) < 200ms — useTransition for heavy filtering, useDeferredValue for the search input
  • CLS < 0.1 — fixed dimensions for skeletons and images. Skeleton placeholders instead of spinners

Integration with Bitrix API: The Reality

Standard REST — Covers 30% of Tasks

Out of the box via /rest/, you get: information blocks (iblock.element.get), cart (sale.basket.*), orders (sale.order.*), users (user.*). For a simple catalog — it's enough.

The Other 70% — Custom Controllers

\Bitrix\Main\Engine\Controller — the standard way to create your own endpoints in D7. Write a controller, register via registerAction, and get an endpoint with CSRF protection and authorization out of the box.

  • Aggregation: one request = catalog data + filters + cart + user
  • WebSocket via Bitrix Push & Pull (CPullStack::AddByTag) — order status updates in real time, no polling
  • GraphQL layer (webonyx/graphql-php) on top of D7 ORM — the frontend requests exactly the fields it needs. Traffic savings on mobile

Typical Projects

  • An online store with 30,000 SKUs with a faceted filter via \Bitrix\Iblock\PropertyIndex\Facet — SPA, React Query, catalog virtualization
  • B2B portal: personalized prices from CCatalogGroup, reconciliation reports from 1C via \Bitrix\Sale\Compatible\OrderCompatibility, order history with filtering
  • Corporate portal: dashboards on Recharts, real-time via Push & Pull, integration with internal APIs through middleware
  • Marketplace: two React applications (buyer + seller), shared backend, data separation via CUser::GetUserGroup()

Timelines

Project Type Timeline
Landing page on React + Bitrix 2-4 weeks
SPA online store 8-16 weeks
Corporate portal 10-20 weeks
Frontend migration to React (phased) 6-12 weeks

Exact figures — after reviewing the requirements. Estimation is phased, with a fixed budget per sprint.

Why React, Not Vue or Bitrix Templates

  • Ecosystem. For any UI task, there's a ready-made library: tables, charts, drag-and-drop, virtualization
  • Talent. Finding a React developer is 3x easier than finding a Bitrix template developer who knows D7 and template.php
  • React Native. Components are reused in the mobile app — not one-to-one, but business logic and types are shared
  • Gradual adoption. You can start with one section (/catalog/) on React, leaving the rest on Bitrix templates. component_epilog.php loads the React bundle, data is passed via window.__INITIAL_DATA__

1C-Bitrix + React is not a theoretical architecture, but a proven combination that already powers catalogs with tens of thousands of SKUs and B2B portals with complex business logic.