Product Catalog Development with Vue.js for 1C-Bitrix
The standard bitrix:catalog.section component works great for simple catalogs, but as soon as requirements for dynamic filtering, infinite scroll, or instant view-switching appear — server-side rendering starts to lag. A Vue catalog solves these challenges through client-side reactivity while preserving server-side rendering for SEO.
Data Structure: API for the Catalog
Bitrix provides data via CIBlockElement::GetList() or the D7 ORM. We wrap it in a custom controller:
// local/components/vendor/catalog.api/ajax.php
use Bitrix\Main\Engine\Controller;
use Bitrix\Iblock\Elements\ElementProductTable;
class CatalogController extends Controller
{
public function getProductsAction(array $filter = [], int $page = 1, int $pageSize = 24): array
{
$offset = ($page - 1) * $pageSize;
// Retrieval via D7 ORM ElementProductTable
// Returns JSON: items, pagination, facets
}
}
Responds to POST /bitrix/services/main/ajax.php?action=catalog.getProducts.
Vue Catalog Components
Minimal component structure:
-
CatalogApp.vue— root component, manages state -
ProductGrid.vue/ProductList.vue— grid and list views, switchable without page reload -
ProductCard.vue— product card with quick view -
Pagination.vueorInfiniteScroll.vue— page navigation -
SortBar.vue— sort order switcher
SEO: Hybrid Rendering
The first screen, which matters for SEO, is rendered server-side by Bitrix. Vue takes control after hydration:
// In the component template
$initialProducts = json_encode($arResult['ITEMS']);
echo '<div id="catalog-app"
data-initial-products="' . htmlspecialchars($initialProducts) . '"
data-iblock-id="' . $arResult['IBLOCK_ID'] . '"
></div>';
Vue reads data-initial-products and renders the first screen without AJAX. Subsequent requests (pagination, filtering) go through the API.
Working with Prices and Availability
Prices in Bitrix come from b_catalog_price via price type. Stock is from b_catalog_store_product. For real-time availability (up-to-date stock at the moment of viewing), add a separate fast endpoint:
// Request availability for an array of products
async function getAvailability(productIds) {
return await api.post('/catalog/availability', { ids: productIds });
}
Call this after rendering the product cards, without blocking the initial load.
Real-World Case
An online store for building materials: a catalog with 80,000 items, filtering by 20+ parameters. The standard Bitrix AJAX filter took 3–6 seconds per request on each parameter change (full server-side section re-render). A Vue catalog with debounced requests (300 ms) and optimistic UI (skeleton shown immediately) — subjectively feels like an instant response. The initial section page load uses Bitrix server-side rendering for correct indexing.
Delivery Timelines
| Complexity | Timeline |
|---|---|
| Basic catalog (grid, list, pagination) | 5 to 8 business days |
| With faceted filter and quick view | 10 to 15 business days |
| With infinite scroll and SEO hybrid | 15 to 20 business days |







