TypeScript Frontend Development 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.
Showing 1 of 1All 1626 services
TypeScript Frontend Development for 1C-Bitrix
Medium
~1-2 weeks
Frequently Asked Questions

Our competencies:

Development stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1356
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    943
  • 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
    693
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    828
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    731
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    1073

A Bitrix project with a 50,000-item catalog is a constant battle against type mismatches. When passing data from PHP to JavaScript, bugs often surface: undefined is not an object, wrong price types, broken filters. We regularly faced this on projects of any complexity. TypeScript solves this: static typing catches errors at compile time, not in the user's browser. Our team's experience — 8 years in Bitrix and over 50 projects with TypeScript architecture. Result: bugfix cost reduction of 30–50% and integration debugging time cut significantly. On one project, bugfix savings amounted to a substantial sum in the first year after migration.

Why TypeScript instead of vanilla JavaScript for Bitrix?

According to TypeScript Handbook (on Wikipedia), static typing prevents up to 15% of errors at compile time. In the Bitrix context this is critical: a wrong price type or product ID can break the cart. On a project with a 100,000-item catalog we completely eliminated filter bugs after switching to strict typing. TypeScript frontend is 2–3 times more reliable than a similar solution on plain JS: type errors, incorrect data transfer between PHP and JS, caching issues — all caught before production.

How is TypeScript integrated with PHP components?

We use a step-by-step approach to minimize downtime:

  • Audit of current JS code: identify type mismatches, global variables, weak spots.
  • Design types for all integration points with PHP (infoblocks, REST, components).
  • Set up build tool (Vite or Webpack) with TypeScript support.
  • Develop fully typed components — catalog, cart, filter.
  • Test and deploy with stability guarantee.

TypeScript architecture in a Bitrix template

Two main approaches we apply:

Approach Description When to choose
MPA with TypeScript modules Classic PHP page generation, JavaScript is interactive islands. Each component is an isolated module with its own types. Medium-sized projects where SEO and first-load speed are critical.
SPA/Headless React or Vue on TypeScript fully control UI, Bitrix acts as API (REST/GraphQL). Complex user interfaces: client cabinet, CRM widgets, multi-step forms.

Most of our projects use the first approach with elements of the second in the most interactive parts (catalog, cart, personal account).

Example component structure
/local/templates/my_site/
├── src/
│   ├── components/
│   │   ├── catalog/
│   │   │   ├── CatalogFilter.ts
│   │   │   ├── ProductCard.ts
│   │   │   └── CartButton.ts
│   │   ├── cart/
│   │   │   ├── CartDrawer.ts
│   │   │   └── CartCounter.ts
│   │   └── common/
│   │       ├── Modal.ts
│   │       └── Tooltip.ts
│   ├── api/
│   │   ├── catalog.ts
│   │   ├── cart.ts
│   │   └── user.ts
│   ├── types/
│   │   ├── bitrix.d.ts
│   │   └── api.ts
│   ├── utils/
│   │   ├── http.ts
│   │   └── format.ts
│   └── main.ts
├── dist/
├── package.json
├── tsconfig.json
└── vite.config.ts

TypeScript cart component

Example of a typed add-to-cart component:

// api/cart.ts
interface CartItem {
    id:       number;
    name:     string;
    price:    number;
    quantity: number;
    img:      string | null;
}

interface CartState {
    items:      CartItem[];
    totalPrice: number;
    totalCount: number;
    currency:   string;
}

interface AddToCartPayload {
    productId: number;
    quantity:  number;
    properties?: Record<string, string>;
}

export async function addToCart(payload: AddToCartPayload): Promise<CartState> {
    const formData = new FormData();
    formData.append('sessid',     BX.bitrix_sessid());
    formData.append('action',     'addItem');
    formData.append('product_id', String(payload.productId));
    formData.append('quantity',   String(payload.quantity));

    if (payload.properties) {
        Object.entries(payload.properties).forEach(([k, v]) => {
            formData.append(`props[${k}]`, v);
        });
    }

    const res = await fetch('/local/ajax/cart.php', {
        method: 'POST',
        body:   formData,
    });

    if (!res.ok) throw new Error(`Cart error: ${res.status}`);

    const json = await res.json();
    if (json.status !== 'success') throw new Error(json.error ?? 'Cart error');

    return json.cart as CartState;
}

Integration with PHP components via data-attributes

Pass data from template to TypeScript without global variables:

// template.php of catalog component
<div
    id="catalog-app"
    data-section-id="<?= (int)$arResult['SECTION']['ID'] ?>"
    data-iblock-id="<?= (int)$arParams['IBLOCK_ID'] ?>"
    data-initial-filter='<?= htmlspecialchars(
        json_encode($arResult['FILTER_PARAMS']), ENT_QUOTES
    ) ?>'
>
    <?php // SSR markup for initial load ?>
</div>
// TypeScript reads data with types
const appEl = document.getElementById('catalog-app');
if (!appEl) throw new Error('#catalog-app not found');

const sectionId  = Number(appEl.dataset['sectionId']);
const iblockId   = Number(appEl.dataset['iblockId']);
const rawFilter  = appEl.dataset['initialFilter'] ?? '{}';
const initFilter = JSON.parse(rawFilter) as FilterState;

How Vite speeds up TypeScript frontend build?

For multi-module projects we use Vite — it provides fast builds and code splitting.

// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
    root:  'src',
    build: {
        outDir:          '../dist',
        emptyOutDir:     true,
        rollupOptions: {
            input: {
                main:    'src/main.ts',
                catalog: 'src/pages/catalog.ts',
                cart:    'src/pages/cart.ts',
            },
        },
    },
    resolve: {
        alias: { '@': '/src' },
    },
});

Separate entrypoints for each section — only the needed JavaScript loads on the page, improving load speed.

Real case: catalog with 100,000 products

Our client — an e-commerce store with a 100,000-item catalog. Features: dynamic filters, cart with many options, integration with 1C via CommerceML. The original vanilla JS code suffered from type errors during 1C exchange. We performed an audit, designed types for all entities and migrated the frontend to TypeScript in three weeks. Result: cart errors decreased by 60%, filter load time by 30%. The client got a stability guarantee for the next two years, and bugfix savings amounted to a significant sum in the first year.

What is included in our TypeScript frontend development work

  • Audit of current architecture: identify JavaScript issues, estimate migration volume.
  • Set up TypeScript + build tool (Vite/Webpack) considering Bitrix environment.
  • Create types for all integration points with PHP (infoblocks, REST, components).
  • Develop new components (catalog, cart, filter, personal account) with full typing.
  • Migrate existing code from vanilla JS to TypeScript preserving functionality.
  • Architecture documentation and type description.
  • Testing and debugging in production with stability guarantee.

Estimated timeline

Stage Duration
Audit and architecture design 1–2 days
Set up TypeScript + Vite infrastructure 1 day
Develop catalog components (filter, list, card) 3–5 days
Develop cart and mini-cart in header 2–3 days
Migrate existing JS code (depends on volume) 2–5 days
Testing and deployment 1–2 days

Exact timeline and cost are calculated individually after getting to know your project. Order an audit of your project — we will analyze your code and offer the best solution. Get a consultation to understand how TypeScript will reduce your frontend maintenance costs.

Why does website layout for 1C-Bitrix require professionalism?

Open template.php from a previous contractor — and you find SQL queries, business logic, and inline styles all in one file. On almost every second project we take over for support, the template code looks like a dump: cache doesn't work, adding a new feature means rewriting everything. Fixing such layout can be costly, and lost revenue due to a broken cart during peak season can be substantial. Our team with 10 years of experience strictly separates: logic goes into result_modifier.php or component_epilog.php, presentation into template.php. No CIBlockElement::GetList in templates. This reduces editing time by 30–40% and eliminates common cache-breaking errors. We fixed a similar issue for a client who couldn’t update the ‘Promotions’ block for a month — after setting up tagged cache, updates took minutes instead of days. Want the same results? Get a free audit of your current layout.

How to properly organize component templates?

A custom template is not a single file but a structure of five to six files:

  • template.php — only HTML and output of $arResult
  • result_modifier.php — data preparation, additional queries
  • component_epilog.php — code after caching (counters, dynamic content)
  • style.css and script.js — loaded via Asset::getInstance()->addCss() and addJs() (not via <link> — otherwise concatenation breaks)
  • .parameters.php — visual editor parameters

Example structure for a catalog:

local/templates/your_template/components/bitrix/catalog.section/.default/
├── template.php
├── result_modifier.php
├── component_epilog.php
├── style.css
├── script.js
└── .parameters.php

Typical templates we develop turnkey:

Component What we do
catalog.section and catalog.element View switching (grid/list/table), lazy load for images, srcset for retina
sale.basket.basket AJAX update without reload, mini-cart via sale.basket.basket.line
menu Mega menu with caching by sections, lazy loading of submenus
search.title Autosuggest with 300ms debounce, product previews in dropdown
breadcrumb Microdata BreadcrumbList according to Schema.org

Caching: why does it break and how do we fix it?

Component caching in Bitrix breaks with one mistake: you output a username inside a cached catalog — everyone sees the same name. Solution — use component_epilog.php for dynamic inserts.

Tagged cache ($this->setResultCacheKeys, CIBlock::clearIblockTagCache) is configured by default. Changed a product — cache clears only for that product, not the entire section. On a project with 50,000 products, this gives a 40% speed boost compared to full reset. Official Bitrix documentation recommends using component_epilog.php for dynamic inserts. Real case. A client complained that everyone saw the same cart on the catalog page. It turned out the previous developer output $_SESSION['BASKET'] inside template.php of the catalog.section component. The component was cached for an hour — the cart was frozen. We moved the output to component_epilog.php and configured tagged cache on sale.basket.basket.line. The page didn’t lose speed, the cart became up-to-date. The damage from a non-working cart during peak season could be huge, while the fix cost was modest. Tagged cache reduces page rebuild time by 50× compared to full reset.

CSS approaches: BEM, Tailwind, or hybrid?

For large projects (30+ templates) we use BEM — .product-card__price, .product-card--featured. Styles are isolated, no conflicts. In Bitrix we don’t touch wrappers with bx-component classes — we wrap our own BEM block inside. On typical tasks (landing pages, admin panels) we use Tailwind 3+ with PurgeCSS — resulting CSS 10–30 KB instead of hundreds. Design tokens in tailwind.config.js lock colors, fonts, spacing in one place. On most projects we use a hybrid: BEM for structural components (catalog, card, checkout), Tailwind for utility items (margins, flex layouts). We agree on the boundary with the team in advance.

How do we achieve Core Web Vitals?

Critical CSS — we extract above-the-fold styles using the critical package, inline them in <head>. The rest loads asynchronously via media="print" onload="this.media='all'". LCP on mobile decreases by 1–1.5 seconds.

Images — the main bottleneck. We use <picture> with WebP and JPEG fallback. loading="lazy" for everything below the fold. width and height explicitly set — CLS = 0. A handler in urlrewrite.php generates WebP on the fly.

Minification and compression. CSS and JS via Vite or Bitrix built-in concatenation. Brotli on nginx (brotli_comp_level 6) — 15–20% more efficient than gzip. Static caching: expires 1y + versioning via query string.

For a catalog of 10,000 products, LCP went from 4.2 s to 2.1 s. Conversions improved by 12% after the speed fix. Want similar results? Order a free audit — we’ll evaluate your current layout and propose specific steps.

Deliverables after layout completion

When you order template development or adaptation, you receive:

  • Source files of component templates with separation into template.php, result_modifier.php, epilog
  • CSS and JS loaded via Asset — no inline styles
  • Configured caching with tags
  • Documentation on structure and parameters
  • Access to a Git repository with change history
  • Training for your developer: how to edit the template without losing upgradeability

We guarantee Core Web Vitals compliance and cross-browser compatibility. Each project is assigned a lead engineer with 10+ years of Bitrix experience.

Process:

  1. Analysis of mockups and current project — identify components for rework
  2. Structure design — break the page into BEM blocks
  3. Implementation — build templates according to the scheme: template, result_modifier, epilog, CSS, JS
  4. Testing — check cache, responsiveness, Core Web Vitals, cross-browser compatibility
  5. Deployment — staging, acceptance, production

At each stage you get intermediate results and can make corrections. Contact our team for a project estimate — we’ll provide a timeline and cost within 1–2 days after receiving mockups.

Common mistakes in Bitrix layout

  • SQL queries inside template.php — breaks caching and creates heavy load
  • Inline <style> and <script> — breaks Asset concatenation and slows loading
  • Missing result_modifier.php — logic mixed with presentation
  • Direct $_REQUEST in cached components — user-specific data leaks
  • Not using component_epilog.php for dynamic content — entire cache invalidated on each user action

Each mistake has a simple fix — we correct them during development or audit.

Timelines

Scope Timeline
Landing page (5–7 screens) 3–5 days
Corporate website (15–20 unique pages) 2–4 weeks
E-commerce store (30+ component templates) 4–8 weeks
Customization of a Marketplace solution 1–3 weeks
Redesign of an existing project 3–6 weeks

Ready to improve your layout? Order a preliminary consultation — we’ll calculate timelines and budget individually.