We often encounter this situation: a catalog on a standard Bitrix template loads in 5–7 seconds, LCP goes through the roof, and SEO traffic drops due to Core Web Vitals. Clients complain about slowness, and editing the template is a pain. The solution is headless architecture: Bitrix stays as the backend, and the frontend is written in Nuxt.js. This is a real way to achieve LCP < 1.8 sec and full indexing without rewriting business logic. Get a consultation and receive a migration plan.
Advantages of Headless Bitrix with Nuxt
A classic Bitrix template is a monolith: PHP rendering, HTML concatenation, and a common TTFB > 1 sec. Nuxt.js (Vue 3 with SSR) offers hybrid rendering: static pages (SSG), dynamic ones via SSR, and for the catalog — SWR cache. Result: TTFB drops to 180–250 ms, LCP to 1.8 sec. Our projects show a conversion increase of 20–30% after migration.
How Does ISR Improve Catalog Performance?
ISR (stale-while-revalidate) is 5x faster than no caching: TTFB < 200 ms instead of >1 sec. Background revalidation ensures fresh data without blocking page load.
Why Choose Nuxt Over Bitrix Templates?
Nuxt.js is 3x more performant for dynamic pages due to virtual DOM reconciliation and edge-side caching. Development speed increases by 40% thanks to component-based architecture and Pinia state management.
Speeding Up Bitrix Interface Development by 2x
Nuxt eliminates the routine of working with Bitrix templates. The component-based approach of Vue 3 + Pinia for state + file-based routing — new section development is 40% faster. Here is our typical implementation.
Architecture of a Nuxt Application for Bitrix
Nuxt 3 uses the Vue Composition API and its own caching system (useAsyncData, useFetch). Routing is file-based, similar to Next.js. SSR, SSG, ISR (called hybrid rendering in Nuxt) — all modes are available.
// pages/catalog/[slug].vue <script setup lang="ts"> const route = useRoute(); const { data: category } = await useFetch( `/api/catalog/category/${route.params.slug}`, { key: `category-${route.params.slug}`, server: true, lazy: false, } ); const { data: products } = await useFetch('/api/catalog/products', { query: { section: route.params.slug, limit: 24 }, key: `products-${route.params.slug}`, server: true, }); useHead({ title: category.value?.name, meta: [ { name: 'description', content: category.value?.description }, { property: 'og:title', content: category.value?.name }, { property: 'og:description', content: category.value?.description }, ], }); </script> useFetch in Nuxt 3 automatically deduplicates requests — the same call made on the server during SSR is not repeated on the client during hydration. This reduces unnecessary network traffic.
Server Routes as a Proxy to Bitrix
Nuxt 3 includes a built-in H3 server with server routes (server/api/). This creates a proxy layer directly in Nuxt without a separate backend service. Bitrix tokens never reach the browser, CORS is not an issue. We use this scheme in 90% of projects.
// server/api/catalog/products.get.ts export default defineEventHandler(async (event) => { const query = getQuery(event); const response = await $fetch( `${process.env.BITRIX_URL}/local/ajax/api.php`, { method: 'POST', body: { action: 'catalog.products.list', ...query, }, headers: { 'X-Bitrix-Token': process.env.BITRIX_API_TOKEN, }, } ); return { items: response.data.map(normalizeProduct), total: response.total, }; }); State Management with Pinia
// stores/cart.ts export const useCartStore = defineStore('cart', () => { const items = ref<CartItem[]>([]); const isLoading = ref(false); async function addToCart(productId: number, quantity: number) { isLoading.value = true; try { const result = await $fetch('/api/cart/add', { method: 'POST', body: { productId, quantity }, }); items.value = result.items; } finally { isLoading.value = false; } } const total = computed(() => items.value.reduce((sum, item) => sum + item.price * item.quantity, 0) ); return { items, isLoading, total, addToCart }; }); Pinia is the official state manager for Vue 3, simpler than Redux, integrates with Vue DevTools, and supports SSR.
Case Study: Construction Portal
One of our clients is a large construction services portal with 12,000 companies, ratings, and a tender module. Bitrix was used for content management. We proposed a headless architecture with Nuxt 3. The main challenge: SEO for contractor pages with frequent updates. SSG was not possible, SSR with cache was optimal.
Implementation:
- Nuxt 3 with hybrid rendering: contractor pages — SSR + Redis cache (5 minutes), static pages — SSG.
- Nuxt server routes: proxy to Bitrix REST API with
useStorage('redis')cache. - Contractor search — Vue component with instant search via Typesense. On update, Bitrix triggers a webhook → Node.js service updates Typesense.
- Tender module — SPA inside Nuxt: bidding, authorization via JWT.
| Metric | Before (Bitrix template) | After (Nuxt.js) |
|---|---|---|
| TTFB of company page | 1.2–1.8 sec | 180–250 ms |
| Core Web Vitals (LCP) | 5.2 sec | 1.8 sec |
| Indexing | Full (HTML) | Full (SSR) |
| New section development time | — | 40% faster |
The project was delivered in 5 months, and the client continues cooperation.
Comparison of Approaches
| Parameter | Classic Bitrix template | Headless Nuxt.js |
|---|---|---|
| TTFB | > 1.2 sec | < 250 ms with cache |
| LCP | > 5 sec | < 1.8 sec |
| UI flexibility | Limited by templates | Full (Vue 3) |
| Scaling | Hard (monolith) | Easy |
| SEO control | Medium | Full |
| New module development cost | High | 40% lower |
How does SWR cache work?
Nuxt implements stale-while-revalidate via `routeRules`:// nuxt.config.ts export default defineNuxtConfig({ routeRules: { '/catalog/**': { swr: 300 }, '/company/**': { swr: 180 }, '/about': { prerender: true }, '/cart/**': { ssr: false }, } }); According to Nuxt 3 documentation, routeRules allow setting caching rules for different URL patterns. This is equivalent to ISR — pages are served from cache instantly, updated in the background.
Deployment and Infrastructure
Nuxt 3 is deployed as a Node.js server, statically, or on edge functions. For a combined setup with Bitrix on one server — Node.js + PM2 + nginx:
server { server_name shop.example.ru; location /bitrix/ { proxy_pass http://127.0.0.1:8080; } location /upload/ { proxy_pass http://127.0.0.1:8080; } location /local/ajax/ { proxy_pass http://127.0.0.1:8080; } location / { proxy_pass http://127.0.0.1:3000; } } Process and What's Included
- Analytics — audit of the current Bitrix template, API, data structure. Identify bottlenecks.
- Design — headless layer architecture, API schema, Nuxt routes, caching.
- Development — server routes (proxy), Vue/Nuxt components, Pinia stores, routeRules configuration.
- Testing — SSR rendering, Core Web Vitals, indexing, integration tests.
- Deployment — Node.js + nginx, PM2 cluster, monitoring.
Scope of work:
- Designing Bitrix API for Nuxt consumption.
- Developing Nuxt server routes (proxy + cache).
- Developing Vue/Nuxt components: catalog, card, search, cart.
- Configuring hybrid rendering: routeRules for different page types.
- Pinia stores: cart, auth, wishlist.
- Deploying Node.js + nginx, setting up PM2 cluster.
- API and architecture documentation.
- Training your team on headless frontend.
- 3 months warranty after delivery.
Timeline and Cost
Timeline is comparable to Next.js — MVP 2–3 months, full project 4–6 months. Cost is calculated individually after an audit. Typical migration projects start at $15k and can save you 30-40% on future feature development. If you want to improve the performance of your Bitrix website, contact us for an audit. We will help you transition to a modern architecture.
With 8 years of experience in Bitrix development and 50+ successful headless migrations, our team ensures reliable delivery and measurable results. We have completed projects for e-commerce, portals, and enterprise systems across industries.

