Developing a Vue.js Shopping Cart 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.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1173
  • 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
    745
  • 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

Shopping Cart Development with Vue.js for 1C-Bitrix

The cart is the most UX-sensitive component of any store. The standard bitrix:sale.basket.basket performs a full page reload on every quantity change or item removal. A Vue cart with optimistic updates eliminates this: visually everything happens instantly, while synchronization with the server runs in the background.

Bitrix API for Cart Operations

Core methods of the sale module:

// Add to cart
\Bitrix\Sale\Basket::create(SITE_ID);
$basketItem = $basket->createItem('catalog', $productId);
$basketItem->setFields(['QUANTITY' => 1, 'CURRENCY' => 'RUB']);
$basket->save();

// AJAX controller for Vue:
// POST /basket/add { productId, quantity, props }
// POST /basket/update { itemId, quantity }
// POST /basket/remove { itemId }
// GET  /basket — current state

Or via REST API: sale.basketitem.add, sale.basketitem.update, sale.basketitem.delete.

Vue Cart Structure

CartApp.vue              — root, reads cartStore
├── CartDrawer.vue       — side panel (slide-over)
├── CartIcon.vue         — icon with counter in the header
├── CartItem.vue         — product row (image, name, quantity, price)
├── CartSummary.vue      — total, promo code, checkout button
└── EmptyCart.vue        — empty cart placeholder

Pinia Cart Store

export const useCartStore = defineStore('cart', {
    state: () => ({
        items: [],
        totalPrice: 0,
        discounts: [],
        isLoading: false,
    }),
    getters: {
        itemCount: (state) => state.items.reduce((sum, i) => sum + i.quantity, 0),
    },
    actions: {
        async addItem(productId, quantity = 1) {
            // Optimistic update: add locally immediately
            this.items.push({ productId, quantity, pending: true });
            try {
                const result = await cartApi.add(productId, quantity);
                // Update with server data (real ID, price)
                this.syncFromServer(result.basket);
            } catch {
                // Rollback on error
                this.items = this.items.filter(i => !i.pending);
            }
        }
    }
});

Tab Synchronization

The user has the store open in two tabs. A product is added in one — the cart in the other is stale. The solution:

// Listen for localStorage events (BroadcastChannel — the modern approach)
const channel = new BroadcastChannel('cart-sync');
channel.onmessage = (e) => {
    if (e.data.type === 'CART_UPDATED') cartStore.fetchCart();
};

// On cart change:
channel.postMessage({ type: 'CART_UPDATED' });

Real-World Case

An electronics store with the standard Bitrix AJAX cart. Problem: when adding a product via the button on the product card (sale.basket.basket.ajax), the page would "flicker" — the entire cart block in the header was re-rendered. On mobile devices this was perceived as a freeze. A Vue cart with CartIcon (counter updated instantly via Pinia) and CartDrawer (sliding panel opens without page reload) — adding a product is visually instant, the server request runs asynchronously.

Delivery Timelines

Option Timeline
Drawer cart with basic operations 4 to 6 business days
With promo codes, discounts, saved lists 8 to 12 business days
Integration with Vue catalog and checkout 3 to 5 additional business days